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

JavaScript: New Publish Script

10/15/15

I gots me a newly made publish.js script. This new one can be required in other node scripts.

It doesn't, however, check for TODOs and such and refuse to publish a post if it sees something wrong with it.

One step forward, and two steps back, as they say.

In any case, here's the script:

/*jslint node: true */
'use strict';

// Modules used in this file
var argparse = require('argparse'),
    fs = require('fs'),
    path = require('path');

var updateDatabase = function (area, posts) {
    var databaseAppend,
        database = path.join('database', area + '.txt');

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

    fs.appendFile(database, databaseAppend, 'utf-8', function (err) {
        if (err) {
            throw err;
        }
    });
};

/*jslint unparam: true */
var moveToArea = function (area, callback) {
    var newDirectory = path.join('public', area),
        count = 0;

    return function (filename, index, files) {
        var basename = path.basename(filename),
            newPath = path.join(newDirectory, basename);

        fs.rename(filename, newPath, function (err) {
            if (err) {
                throw err;
            }

            count += 1;

            if (count === files.length) {
                callback(area, files);
            }
        });
    };
};
/*jslint unparam: false */

var publishArea = function (posts, area) {
    // Move filenames to published area, append database with basenames
    posts.forEach(moveToArea(area, updateDatabase));
};

var publish = exports;

publish.blog = function (posts) {
    // TODO: Add description item to RSS
    // TODO: Need to actually generate html instead of just moving html files
    publishArea(posts, 'blog');
};

publish.diary = function (posts) {
    // Append basenames to "database" blog list
    // Move filenames to published area
    // If anything goes wrong, none of these files should change
    publishArea(posts, 'diary');
};

publish.main = function (rawArgs) {
    var args,
        diaryPosts,
        blogPosts;

    args = (function () {
        var parser;

        parser = new argparse.ArgumentParser({
            version: '0.0.1',
            addHelp: true,
            description: 'Publish file into blog or diary area',
            epilog: 'Area to publish in is deduced from the input path'
                + '(defaults to "blog")'
        });

        parser.addArgument(
            ['file'],
            {
                nargs: '+',
                help: 'File to publish'
            }
        );

        if (rawArgs) {
            return parser.parseArgs(rawArgs);
        }

        return parser.parseArgs();
    }());

    // Separate the input filenames into the blog and diary posts
    blogPosts = args.file.filter(function (filename) {
        return path.dirname(filename).search('diary') === -1;
    });
    publish.blog(blogPosts);

    diaryPosts = args.file.filter(function (filename) {
        return path.dirname(filename).search('diary') !== -1;
    });
    publish.diary(diaryPosts);
};

if (require.main === module) {
    publish.main();
}

Gone is the anonymous function closure that made sure the script didn't pollute the global namespace. I've decided that for node scripts, this is unnecessary, as the require module does that for me. For scripts loaded in a browser, I will continue the habit. Though, I might also look up using require browser-side. Last time I looked into it, the library was capable of generating un-require'd (that's a pun) javascript during the minify process.

Best to live in the require'd world and let the computer make it un-require'd.

In any case, the publish script should play nicely with other scripts now. Time to do the same for the other scripts. From there, I can start amassing a proper blog script library, have running publish.js generate the html from the view files, and then generate the index file, and I can stop running the various scripts manually from the terminal, and just run one script.