Source: apc-static/task/worker/link_theme_image_files.js

/**
 * Link theme image files.
 * @function task.worker.linkThemeImageFiles.
 * @param {object} config - Task configuration.
 * @param {string} config.srcDir - Source files directory.
 * @param {string} config.destDir - Destination directory.
 * @param {string} config.settingFile - Setting file name.
 * @param {string} config.themeName - Theme name. ('a', 'b' or 'c'...)
 * @param {function} callback - Callback when done.
 * @author Taka Okunishi
 */
var path = require('path'),
    util = require('util'),
    fs = require('fs'),
    format = util.format,
    debug = require('./_debug'),
    lib = require('../../lib'),
    file = lib.file,
    string = lib.string,
    camelize = string.camelize,
    relativeSymlink = file.relativeSymlink;

module.exports = function (config, callback) {
    var srcDir = path.resolve(config.srcDir),
        destDir = path.resolve(config.destDir),
        settingFile = path.resolve(config.settingFile),
        setting = require(settingFile);
    fs.readdir(srcDir, function (err, dirnames) {
        if (err) {
            callback(err);
            return;
        }
        var async = require('async');
        async.series(
            dirnames
                .map(function (dirname) {
                    return {
                        dirname: path.resolve(srcDir, dirname),
                        themeName: setting[camelize(dirname)]
                    };
                })
                .filter(function (data) {
                    return fs.statSync(data.dirname).isDirectory();
                })
                .filter(function (data) {
                    return !!data.themeName;
                })
                .map(function (data) {
                    return function (callback) {
                        var srcSubDir = data.dirname,
                            themeName = data.themeName;
                        if (!themeName.match(/^theme\-/)) themeName = ['theme', themeName].join('-');
                        fs.readdir(srcSubDir, function (err, filenames) {
                            if (err) {
                                callback(err);
                                return;
                            }
                            var srcNames = filenames.filter(function (filename) {
                                return !!filename.match(themeName);
                            });
                            if (!srcNames.length) {
                                var errMsg = format('Image for theme %s is not found in %s.',
                                    themeName, srcSubDir);
                                callback(new Error(errMsg));
                                return;
                            }
                            async.parallel(
                                srcNames.map(function (srcName) {
                                    return function (callback) {
                                        var destName = srcName.replace(themeName, '')
                                            .replace(/\-\./g, '.')
                                            .replace(/\-\-/g, '-');
                                        var src = path.resolve(srcSubDir, srcName),
                                            dest = path.resolve(destDir, destName);
                                        relativeSymlink(src, dest, function (err) {
                                            if (!err) {
                                                debug.didCreateLink(dest, src);
                                            }
                                            callback(err);
                                        });
                                    }
                                }),
                                function (err) {
                                    callback(err);
                                }
                            );

                        });
                    }
                }),
            function (err) {
                callback(err);
            }
        )
    });
};