iconfont
Version:
CLI that converts Icon Font CSS StyleSheets into CommonJS modules exporting the unicodes by name.
192 lines (140 loc) • 4.12 kB
JavaScript
;
var
fs = require('fs'),
path = require('path'),
util = require('util');
var
program = require('commander'),
updateNotifier = require('update-notifier'),
chalk = require('chalk'),
css = require('css'),
_ = require('underscore');
var
pkg = require('./package.json');
updateNotifier({
packageName: pkg.name,
packageVersion: pkg.version
}).notify();
css.stringifyRule = function(rule, options) {
options = options || {};
options.compress = options.compress !== false;
return this.stringify({
stylesheet: {
rules: [rule]
}
}, options);
};
program
.version(pkg.version, '-v, --version')
.option('-t, --tss', 'export to Titanium Alloy Style Sheet(tss)')
.description(pkg.description)
.usage('<stylesheet> [js]')
.parse(process.argv);
var ln = program.args.length;
if (ln === 0) {
program.help();
}
if (ln > 2) {
console.error(chalk.red('Just one stylesheet please'));
process.exit(1);
}
var stylesheet = path.normalize(program.args[0]);
var js;
if (ln === 2) {
js = path.normalize(program.args[1]);
if (js.match(/\.tss$/)) {
program.tss = true;
}
} else {
js = stylesheet.replace(/\.css$/, program.tss ? '.tss' : '.js');
}
fs.readFile(stylesheet, function(err, data) {
if (err) {
console.error(chalk.red(err));
process.exit(1);
}
var code = data.toString();
var obj = css.parse(code, stylesheet);
if (!obj.stylesheet || !obj.stylesheet.rules) {
console.error(chalk.red('Cannot find rules in the root'));
process.exit(1);
}
var icons = {};
var prefixes = [];
var fontFamily = '';
_.each(obj.stylesheet.rules, function(rule) {
if (!rule.selectors || !rule.declarations) {
if (rule.type == 'font-face') {
fontFamily = _.findWhere(rule.declarations, {
property: 'font-family'
}).value.replace(/["']/g, '');
}
return;
}
var declaration = _.findWhere(rule.declarations, {
property: 'content'
});
if (!declaration) {
return;
}
var content = declaration.value;
var matches = content.match(/^("|')(.+)\1$/i);
if (!matches) {
console.warn(chalk.yellow('Skipping content without string value: ') + chalk.blue(css.stringifyRule(rule)));
return;
}
var string = matches[2];
if (string.match(/^\\[a-z0-9]{1,4}$/i)) {
string = '\\u' + (new Array(4 + 2 - string.length)).join('0') + string.substr(1);
}
_.each(rule.selectors, function(selector) {
var matches2 = selector.match(/^\.(([a-z0-9]+-)?[a-z0-9]+(?:[_-][a-z0-9]+)*):before$/i);
if (!matches2) {
return;
}
var name = matches2[1];
var prefix = matches2[2];
if (prefixes.indexOf(prefix) === -1) {
prefixes.push(prefix);
}
icons[name] = string;
});
});
var ln = _.size(icons);
if (ln === 0) {
console.error(chalk.red('Found no icons'));
process.exit(1);
}
var prefix = (prefixes.length === 1) ? prefixes[0] : null;
if (program.tss) {
data = '/* ' + fontFamily + ' Styles (Generated by IconFont) */\n';
_.each(_.keys(icons), function(name, i) {
var unicode = icons[name];
data += util.format('".%s": { font: { fontFamily: "%s"}, text: "%s", title: "%s"}\n',
name, fontFamily, unicode, unicode);
});
} else {
data = 'module.exports = {\n';
_.each(_.keys(icons), function(name, i) {
var unicode = icons[name];
if (prefix) {
name = name.substr(prefix.length);
}
if (name.indexOf('-') !== -1 || name.indexOf('_') !== -1) {
name = name.replace(/[_-]([a-z0-9])([^_-]*)/gi, function(match, p1, p2) {
return p1.toUpperCase() + p2.toLowerCase();
});
}
data += ' "' + name + '": "' + unicode + '"' + ((i === ln - 1) ? '' : ',') + '\n';
});
data += '};';
}
fs.writeFile(js, data, null, function(err) {
if (err) {
console.error(chalk.red(err));
process.exit(1);
}
console.info(chalk.green('Written ' + ln + ' icons to: ' + js));
});
});