may 14, 2014
• added help • fixed some issues for fonts with space in family name
may 14, 2014
• added help • fixed some issues for fonts with space in family name
#!/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(); | |
} |