greglamb
11/30/2013 - 11:07 PM

script to retrieve whole pack of formats for one google font

script to retrieve whole pack of formats for one google font

#!/usr/bin/env node

var http = require ('http');
var url  = require ('url');
var fs   = require ('fs');
var path = require ('path');

/*

usage: script family variants subset
for example: node get-google-fonts.js Roboto 100,400,700,100italic latin,cyrillic

*/

var argv = process.argv;

if (argv.length < 3) {
	console.log ("usage: script family variants subset");
	console.log ("for example:\n", argv[0], argv[1], "\"Roboto\" 100,400,700,100italic latin,cyrillic");
	process.kill ();
}

var family   = argv[2];
var variants = argv[3] || '400';
var subset   = argv[4] || 'latin';

family = family.replace (/\s/g, "+");

var reqUrl = 'http://fonts.googleapis.com/css?family='+family+':'+variants+'&subset='+subset;

console.log (reqUrl);

var uaTTF  = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/534.54.16 (KHTML, like Gecko) Version/5.1.4 Safari/534.54.16';
var uaEOT  = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)';
var uaWOFF = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9) AppleWebKit/537.71 (KHTML, like Gecko) Version/7.0 Safari/537.71';

remoteResource (reqUrl, uaTTF, cssLoaded, die);
remoteResource (reqUrl, uaEOT, cssLoaded, die);
remoteResource (reqUrl, uaWOFF, cssLoaded, die);

var cssChunks = [];

var cssData = {};

function die (e) {
	console.error (e);
	process.terminate ();
}

function fontLoaded (fileName, reqParams, res, fontDataBuffer) {
	
	fs.writeFile (fileName, fontDataBuffer);
	return fileName;
}

function cssLoaded (reqParams, res, bodyBuffer) {
	var body = bodyBuffer.toString();
	
	var regexp = "font-family: ([^;]+)[^]+?font-style: ([^;]+)[^]+?font-weight: ([^;]+)[^]+?local\\(\\'([^\\']+)\\'\\), local\\(\\'([^\\s\\']+)\\'\\), url\\(([^\\)]+)\\) format\\(\\'([^\\']+)\\'\\)";
	var gRegexp = new RegExp (regexp, "g");
	var matches = body.match (gRegexp);
	
	matches.forEach (function (item) {
		var iRegexp = new RegExp (regexp, "");

		var fontItem = item.match (iRegexp);
		console.log ('font name: ' + fontItem[5] + ' font url: ' + fontItem[6]);

		var fileName = fontItem[5] + path.extname (url.parse(fontItem[6]).pathname);

		var fontVariant = fontItem[1] + "-" + fontItem[2] + "-" + fontItem[3];
		if (!cssData[fontVariant]) {
			cssData[fontVariant] = {
				"font-family": fontItem[1],
				"font-style":  fontItem[2],
				"font-weight": fontItem[3],
				src: {
					local: fontItem[4],
					local2: fontItem[5]
				}
			};
		}

		cssData[fontVariant].src[fontItem[7]] = fileName;

		remoteResource (fontItem[6], null, function (reqParams, res, bodyBuffer) {
			var newName = fontLoaded (fileName, reqParams, res, bodyBuffer);
			
		}, die);

		body = body.replace (fontItem[6], fileName);
	});

	cssDone (body);
}

function cssDone (cssChunk) {
	cssChunks.push (cssChunk);
	if (cssChunks.length == 3) {
		var buf = '';
		var keys = Object.keys(cssData);
		keys.forEach (function (k) {
			item = cssData[k];
			buf += "@font-face {\n";
			buf += "\tfont-family: "+item["font-family"]+";\n";
			buf += "\tfont-style:  "+item["font-style"]+";\n";
			buf += "\tfont-weight: "+item["font-weight"]+";\n";
			buf += "\tsrc: url("+item.src["embedded-opentype"]+");\n";
			buf += "\tsrc: local("+item.src.local+"), local("+item.src.local2+"), ";
			buf += "url("+item.src["truetype"]+") format('truetype'), ";
			buf += "url("+item.src["embedded-opentype"]+") format('embedded-opentype'), ";
			buf += "url("+item.src["woff"]+") format('woff');\n}\n\n";
			// fs.write ();
		});
		fs.writeFile (family.replace (/\+/g, '-') + '-font.css', buf);
		// console.log (JSON.stringify (cssData));
	}
}

function remoteResource (reqUrl, ua, success, failure) {
	
	// console.log ("ua:", ua);

	var reqParams = url.parse (reqUrl);

	var req = http.request(reqUrl, function(res) {
		// console.log("Got response: " + res.statusCode);
		var bodyBuffer = new Buffer (0);
		res.on('data', function (chunk) {
			// console.log('BODY: ' + chunk);
			bodyBuffer += chunk;
		});
		res.on ('end', function () {
			// console.log (body);
			// var body = bodyBuffer.toString();
			success (reqParams, res, bodyBuffer);
		});
	});
	req.on('error', function(e) {
		console.log("Got error: " + e.message);
		failure (e);
	});

	
	req.setTimeout (10000);
	req.setHeader ('User-Agent', ua);

	req.end();

}

may 14, 2014

• added help • fixed some issues for fonts with space in family name