Rory's Diary
Home
Blog
Projects
Facebook
Google+
Github
RSS

Post Publishing Script

04/13/15

Okay, now that I have a means of generating my blog and diary areas, I think it might be good to have a means of updating what is published to each area. I'm thinking using it should be something like:

node publish.js diary post_publishing_script_150413.html

So, I'll feed the area I'm pusblishing and the file I want to publish.

Now, in all honesty, publishing isn't a particularly complicated thing, and I got a vim macro that does it for me. The problem is, however, that it limits the design of this site to publish more-or-less manually. Further, I have this tendency to forget things that I should do before publishing, like make sure my links actually go somewhere. So a script will help me improve the system, and also be another step towards doing it all dynamically from the node server.

All right, let's start, as I tend to do, with a blank javascript file.

/*jslint node: true */
(function () {
    'use strict';
    // TODO:
    var args;

    args = (function () {
        var processArgs = process.argv.slice(2);
        return processArgs;
    }());
}());

That's how I usually like to start a node script right now. The args function is still something I want to improve in general, though, but right now it's a good way to start.

Okay, I got carried away, and now I've got something I more-or-less like:

/*jslint node: true */
(function () {
    'use strict';
    var args,
        usage,
        errorCount,
        publishCount,
        publishPosts;

    errorCount = 0;
    usage = function (err) {
        if (errorCount === 0) {
            console.log('USAGE: publish <area> <file> [<file>] [...]');
            console.log('    area: diary or blog');
            console.log('    file: html file containing post to publish');
            console.log();
        }

        if (err) {
            console.log('Error: ' + err);
        }

        errorCount += 1;
        return false;
    };

    args = (function () {
        var processArgs,
            area,
            validAreas,
            files;

        processArgs = process.argv.slice(2);

        if (processArgs.length < 2) {
            return usage();
        }

        area = processArgs[0];
        validAreas = ['diary', 'blog', 'test'];
        if (validAreas.indexOf(area) === -1) {
            return usage('area must be diary or blog');
        }

        files = processArgs.slice(1);

        return {
            area: area,
            files: files
        };
    }());

    if (!args) {
        return;
    }

    publishPosts = function (area, filenames) {
        var path,
            database,
            fs,
            publishedPosts;

        path = require('path');
        database = path.join('database', area + '.txt');
        fs = require('fs');

        // Move posts to published area
        filenames.forEach(function (filename) {
            var publishedPath;

            publishedPath = path.join(
                'public',
                area,
                path.basename(filename)
            );
            fs.rename(filename, publishedPath, function (err) {
                if (err) {
                    console.log(
                        'Error moving ' + filename  + ' to ' + area
                    );
                }
            });
        });

        publishedPosts = '\n'
            + filenames.map(function (filename) {
                return path.basename(filename);
            }).join('\n');

        // Add to the database of published posts
        fs.appendFile(database, publishedPosts, 'utf-8', function (err) {
            if (err) {
                return console.log('Failed to publish to ' + area);
            }
        });
    };

    publishCount = 0;
    args.files.forEach(function (filename) {
        var fs;

        fs = require('fs');
        fs.readFile(filename, 'utf-8', function (err, data) {
            if (err) {
                return usage('could not open ' + filename);
            }

            // Verify no empty strings in file to be published
            if (data.indexOf('""') !== -1) {
                return usage('Empty string "" in ' + filename);
            }

            // TODO: Verify there's actually a post to publish

            publishCount += 1;
            if (publishCount === args.files.length) {
                publishPosts(args.area, args.files);
            }
        });
    });
}());

It works! Time to write a proper blog post about this.

Realization... putting '""' into this post flags it.... I'll just change the search string used instead of smarter verification. Smarter verifcation can happen later.