<< Previous | Home | Next >>

Using NodeJS to Build a Firefox XPI (Zip) File

I have been a long time JavaScript programmer, but of course this is mainly for development of client-side code running in a web-browser.  Node.js, the server-side JavaScript engine, has been around for a few years now, but I have only had limited opportunity to put it to use.  I really like the idea of using JavaScript to write utilities and automate desktop tasks.  In the past I have turned to shell scripts or Python for these kind of tasks, but Node.js has become quite robust, and it is nice to be able to use the same, familiar language everywhere.

Below is a nifty little build script I wrote in JavaScript using Node.js which creates a zip file named "mine.xpi" for use as a Firefox extension.  It leverages the archiver package available using the npm package manager...

var archiver = require('archiver'),
    fs = require('fs'),
    path = require('path'),

    basePath = path.resolve('mine'),

    walk = function(dir, done) {
        var results = [];
        fs.readdir(dir, function(err, list) {
            if (err) return done(err);
            var pending = list.length;
            if (!pending) return done(null, results);
            list.forEach(function(file) {
                file = path.resolve(dir, file);
                fs.stat(file, function(err, stat) {
                    if (stat && stat.isDirectory()) {
                        walk(file, function(err, res) {
                            results = results.concat(res);
                            if (!--pending) done(null, results);
                        });
                    } else {
                        results.push(file);
                        if (!--pending) done(null, results);
                    }
                });
            });
        });
    };

walk(basePath, function(err, results) {
    var archive = archiver.create('zip', {}),
        backslashRegex = /\\/g,
        baseRegex = new RegExp('^' + basePath.replace(backslashRegex, '\\\\')),
        ignoreRegex = /\.bak$/,
        output = fs.createWriteStream('mine.xpi');

    output.on('close', function() {
        console.log(archive.pointer() + ' total bytes');
        console.log('archiver has been finalized and the output file descriptor has closed.');
    });

    archive.on('error', function(err) {
        throw err;
    });

    archive.pipe(output);

    if (err) throw err;
    results.forEach(function(result) {
        if (!result.match(ignoreRegex)) {
            console.log('ADDING:', result.replace(baseRegex, '').replace(backslashRegex, '/'));
            archive.append(fs.createReadStream(result), {name:result.replace(baseRegex, '').replace(backslashRegex, '/')});
        }
    });
    console.log('FINALIZING');
    archive.finalize();
});
Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!

Export this post as PDF document  Export this post to PDF document

HTML5Test and CSS3Test

These two sites do a great job of testing your web browser and telling you what HTML5 and CSS3 features it supports...

Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!

Export this post as PDF document  Export this post to PDF document

Calculate Size of Files Within a Zip File

package co.wlv.apputil;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.filefilter.TrueFileFilter;

public class CalculateFileSizeInDir {

    public static void main(String args[]) throws Exception {

        String zipFileName = "C:\\path\\to\\my.zip";
        File initialFile = new File(zipFileName);
        InputStream targetStream = new FileInputStream(initialFile);
        File extractDir = new File("output");
        FileUtils.deleteDirectory(extractDir);
        unZipImportData(targetStream, extractDir);

        List files = (List) FileUtils.listFiles(extractDir, TrueFileFilter.INSTANCE, TrueFileFilter.INSTANCE);
        for (File file : files) {
            System.out.println("file: " + file.getCanonicalPath() + " - file Size: " + readableFileSize(file.length()));
        }
    }

    public static String readableFileSize(long size) {
        if (size <= 0)
            return "0";
        final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(size / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    public static double fileSize(long size) {
        if (size <= 0)
            return 0;
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return size / Math.pow(1024, digitGroups);
    }

    public static String getUnits(long size) {
        if (size <= 0)
            return "0";
        final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return units[digitGroups];
    }

    public static void unZipImportData(InputStream zip, File extractTo) throws Exception {
        ZipInputStream zipInputStream = new ZipInputStream(zip);
        ZipEntry zipEntry;
        try {
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                File file = new File(extractTo, zipEntry.getName());
                if (zipEntry.isDirectory() && !file.exists())
                    file.mkdirs();
                else {
                    if (!file.getParentFile().exists())
                        file.getParentFile().mkdirs();

                    BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(file));
                    byte[] buffer = new byte[8192];
                    int read;

                    while (-1 != (read = zipInputStream.read(buffer)))
                        out.write(buffer, 0, read);

                    zipInputStream.closeEntry();
                    out.close();
                }
            }
            zipInputStream.close();
            zipInputStream = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!

Export this post as PDF document  Export this post to PDF document

Subclipse 1.10 + Maven (M2E)

I had a tricky time getting the Eclipse Maven tool (m2e) to work in Eclipse Luna with the latest version of Subclipse 1.10.6.  It turns out that the Maven SCM Handler for Subclipse (m2e-subclipse)  linked to in the Luna Marketplace on the Sonatype site is no longer supported.  The gory details and a .zip file containing an updated m2e-subclipse plugin are available at subclipse.tigris.org/issues/show_bug.cgi.

Tags : , ,
Social Bookmarks :  Add this post to Slashdot    Add this post to Digg    Add this post to Reddit    Add this post to Delicious    Add this post to Stumble it    Add this post to Google    Add this post to Technorati    Add this post to Bloglines    Add this post to Facebook    Add this post to Furl    Add this post to Windows Live    Add this post to Yahoo!

Export this post as PDF document  Export this post to PDF document