svgicons2svgfont
Advanced tools
Comparing version 2.0.2 to 3.0.0
@@ -22,3 +22,4 @@ #! /usr/bin/env node | ||
.option('-s, --startunicode [value]', 'the start unicode codepoint for unprefixed files [0xEA01].', parseInt) | ||
.option('-a, --appendunicode', 'prefix files with their allocated unicode codepoint.', parseInt) | ||
.option('-a, --appendunicode', 'prefix files with their automatically allocated unicode codepoint.', parseInt) | ||
.option('-m, --metadata', 'content of the metadata tag.') | ||
.parse(process.argv); | ||
@@ -44,4 +45,5 @@ | ||
descent: program.descent, | ||
metadata: program.metadata, | ||
log: program.v ? console.log : function() {} | ||
})) | ||
.pipe(program.output ? fs.createWriteStream(program.output) : process.stdout); |
{ | ||
"name": "svgicons2svgfont", | ||
"version": "2.0.2", | ||
"version": "3.0.0", | ||
"description": "Read a set of SVG icons and ouput a SVG font", | ||
@@ -33,4 +33,3 @@ "homepage": "https://github.com/nfroidure/svgicons2svgfont", | ||
"coveralls": "~2.11.2", | ||
"istanbul": "~0.3.14", | ||
"sax": "~1.1.1" | ||
"istanbul": "~0.3.14" | ||
}, | ||
@@ -37,0 +36,0 @@ "author": { |
@@ -40,3 +40,3 @@ # svgicons2svgfont | ||
glyph1.metadata = { | ||
unicode: '\uE001\uE002', | ||
unicode: ['\uE001\uE002'], | ||
name: 'icon1' | ||
@@ -55,3 +55,3 @@ }; | ||
glyph3.metadata = { | ||
unicode: '\uE001\uE002', | ||
unicode: ['\uE001\uE002'], | ||
name: 'icon1-icon2' | ||
@@ -65,3 +65,3 @@ }; | ||
# CLI interface | ||
## CLI interface | ||
All options are available except the `log` one by using this pattern: | ||
@@ -75,3 +75,3 @@ `--{LOWER_CASE(optionName)}={optionValue}`. | ||
`${icon.unicode}-${icon.name}.svg` where `icon.unicode` is a comma separated | ||
list of unicode strings (ex: 'uEA01,uE001,uEOO1uEOO2', note that the last | ||
list of unicode strings (ex: 'uEA01,uE001,uE001uE002', note that the last | ||
string is in fact a ligature). | ||
@@ -98,3 +98,4 @@ | ||
# -s, --startunicode [value] the start unicode codepoint for unprefixed files [0xEA01]. | ||
# -a, --appendunicode prefix files with their allocated unicode codepoint. | ||
# -a, --appendunicode prefix files with their automatically allocated unicode codepoint. | ||
# -m, --metadata content of the metadata tag. | ||
``` | ||
@@ -156,2 +157,9 @@ | ||
#### options.metadata | ||
Type: `String` | ||
Default value: `undefined` | ||
The font [metadata](http://www.w3.org/TR/SVG/metadata.html). You can set any | ||
character data in but it is the be suited place for a copyright mention. | ||
#### options.log | ||
@@ -158,0 +166,0 @@ Type: `Function` |
@@ -14,3 +14,3 @@ var fs = require('fs'); | ||
var _this = this; | ||
var files; | ||
var filesInfos; | ||
@@ -23,16 +23,69 @@ // Ensure new were used | ||
if(dir instanceof Array) { | ||
files = dir; | ||
var dirCopy = dir; | ||
dir = ''; | ||
_getFilesInfos(dirCopy); | ||
} | ||
function _getFilesInfos(files) { | ||
var filesProcessed = 0; | ||
filesInfos = []; | ||
// Ensure prefixed files come first | ||
files = files.slice(0).sort(function(fileA, fileB) { | ||
var result = 0; | ||
if((/(^|\/)(?:((?:u[0-9a-f]{4,6},?)+)\-)(.+)\.svg$/i).test(fileA)) { | ||
if((/(^|\/)(?:((?:u[0-9a-f]{4,6},?)+)\-)(.+)\.svg$/i).test(fileB)) { | ||
if(fileA < fileB) { | ||
result = -1; | ||
} else { | ||
result = 1; | ||
} | ||
} else { | ||
result = -1; | ||
} | ||
} else { | ||
if((/(^|\/)(?:((?:u[0-9a-f]{4,6},?)+)\-)(.+)\.svg$/i).test(fileB)) { | ||
result = 1; | ||
} else if(fileA < fileB) { | ||
result = -1; | ||
} else { | ||
result = 1; | ||
} | ||
} | ||
return result; | ||
}); | ||
files.forEach(function(file) { | ||
getMetadata((dir ? dir + '/' : '') + file, function(err, metadata) { | ||
filesProcessed++; | ||
if(err) { | ||
_this.emit('error', err); | ||
} else { | ||
if(metadata.renamed) { | ||
options.log('Saved codepoint: ' + | ||
'u' + metadata.unicode[0].charCodeAt(0).toString(16).toUpperCase() + | ||
' for the glyph "' + metadata.name + '"'); | ||
} | ||
filesInfos.push(metadata); | ||
} | ||
if(files.length === filesProcessed) { | ||
// Reorder files | ||
filesInfos = filesInfos.sort(function(infosA, infosB) { | ||
return infosA.unicode[0] > infosB.unicode[0] ? 1 : -1; | ||
}); | ||
_pushSVGIcons(); | ||
} | ||
}); | ||
}); | ||
} | ||
function _pushSVGIcons() { | ||
var file; | ||
var fileInfo; | ||
var matches; | ||
var svgIconStream; | ||
while(files.length) { | ||
file = files.shift(); | ||
svgIconStream = fs.createReadStream(file); | ||
var metadata = getMetadata(file); | ||
svgIconStream.metadata = metadata; | ||
while(filesInfos.length) { | ||
fileInfo = filesInfos.shift(); | ||
svgIconStream = fs.createReadStream(fileInfo.path); | ||
svgIconStream.metadata = { | ||
name: fileInfo.name, | ||
unicode: fileInfo.unicode | ||
}; | ||
if(!_this.push(svgIconStream)) { | ||
@@ -51,18 +104,13 @@ return; | ||
this._read = function() { | ||
if(files) { | ||
_pushSVGIcons(); | ||
return; | ||
if(!filesInfos) { | ||
fs.readdir( | ||
dir, | ||
function(err, files) { | ||
if(err) { | ||
_this.emit('error', err); | ||
} | ||
_getFilesInfos(files); | ||
} | ||
); | ||
} | ||
fs.readdir( | ||
dir, | ||
function(err, theFiles) { | ||
if(err) { | ||
_this.emit('error', err); | ||
} | ||
files = theFiles.map(function(file) { | ||
return dir + '/' + file; | ||
}); | ||
_pushSVGIcons(); | ||
} | ||
); | ||
@@ -69,0 +117,0 @@ }; |
@@ -189,2 +189,3 @@ /* | ||
options.round = options.round || 10e12; | ||
options.metadata = options.metadata || ''; | ||
@@ -348,3 +349,5 @@ log = (options.log || console.log.bind(console)); | ||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >\n\ | ||
<svg xmlns="http://www.w3.org/2000/svg">\n\ | ||
<svg xmlns="http://www.w3.org/2000/svg">\n' + ( | ||
options.metadata ? '<metadata>' + options.metadata + '</metadata>\n' : '' | ||
) + '\ | ||
<defs>\n\ | ||
@@ -351,0 +354,0 @@ <font id="' + options.fontName + '" horiz-adv-x="' + fontWidth + '">\n\ |
@@ -15,10 +15,14 @@ var path = require('path'); | ||
return function getMetadataFromFile(file) { | ||
return function getMetadataFromFile(file, cb) { | ||
var basename = path.basename(file); | ||
var metadata = { | ||
path: file, | ||
name: '', | ||
unicode: [] | ||
unicode: [], | ||
renamed: false | ||
}; | ||
matches = basename.match(/^(?:((?:u[0-9a-f]{4,6},?)+)\-)?(.*).svg$/i); | ||
metadata.name = matches[2]; | ||
matches = basename.match(/^(?:((?:u[0-9a-f]{4,6},?)+)\-)?(.+)\.svg$/i); | ||
metadata.name = matches && matches[2] ? | ||
matches[2] : | ||
'icon' + options.startUnicode; | ||
if(matches && matches[1]) { | ||
@@ -31,2 +35,6 @@ metadata.unicode = matches[1].split(',').map(function(match) { | ||
}); | ||
if(-1 !== usedUnicodes.indexOf(metadata.unicode[0])) { | ||
return cb(new Error('The unicode codepoint of the glyph ' + metadata.name + | ||
' seems to be already used by another glyph.')); | ||
} | ||
usedUnicodes = usedUnicodes.concat(metadata.unicode); | ||
@@ -39,15 +47,14 @@ } else { | ||
if(options.appendUnicode) { | ||
fs.rename(file, path.dirname(file) + '/' + | ||
metadata.renamed = true; | ||
metadata.path = path.dirname(file) + '/' + | ||
'u' + metadata.unicode[0].charCodeAt(0).toString(16).toUpperCase() + | ||
'-' + basename, | ||
'-' + basename; | ||
fs.rename(file, metadata.path, | ||
function(err) { | ||
if(err) { | ||
options.error(new Error('Could not save codepoint: ' + | ||
return cb(new Error('Could not save codepoint: ' + | ||
'u' + metadata.unicode[0].charCodeAt(0).toString(16).toUpperCase() + | ||
' for ' + basename)); | ||
} else { | ||
options.log('Saved codepoint: ' + | ||
'u' + metadata.unicode[0].charCodeAt(0).toString(16).toUpperCase() + | ||
' for ' + basename); | ||
} | ||
cb(null, metadata); | ||
} | ||
@@ -57,3 +64,7 @@ ); | ||
} | ||
return metadata; | ||
if(!metadata.renamed) { | ||
setImmediate(function() { | ||
cb(null, metadata); | ||
}); | ||
} | ||
}; | ||
@@ -60,0 +71,0 @@ |
@@ -18,5 +18,5 @@ var svgicons2svgfont = require(__dirname + '/../src/index.js'); | ||
assert.equal( | ||
fs.readFileSync(__dirname + '/results/originalicons-cli.svg', | ||
{encoding: 'utf8'}), | ||
fs.readFileSync(__dirname + '/expected/originalicons-cli.svg', | ||
{encoding: 'utf8'}), | ||
fs.readFileSync(__dirname + '/results/originalicons-cli.svg', | ||
{encoding: 'utf8'}) | ||
@@ -29,2 +29,27 @@ ); | ||
describe("with nested icons", function(done) { | ||
it("should work", function(done) { | ||
(require('child_process').exec)( | ||
'node ' + __dirname + '/../bin/svgicons2svgfont.js' + | ||
' -o ' + __dirname + '/results/nestedicons-cli.svg' + | ||
' ' + __dirname + '/fixtures/nestedicons/*.svg ', | ||
function(err) { | ||
if(err) { | ||
throw err; | ||
} | ||
assert.equal( | ||
fs.readFileSync(__dirname + '/results/nestedicons-cli.svg', | ||
{encoding: 'utf8'}), | ||
fs.readFileSync(__dirname + '/expected/nestedicons-cli.svg', | ||
{encoding: 'utf8'}) | ||
); | ||
done(); | ||
} | ||
); | ||
}); | ||
}); | ||
}); |
@@ -9,5 +9,6 @@ var assert = require('assert'); | ||
// Helpers | ||
function generateFontToFile(options, done, fileSuffix) { | ||
function generateFontToFile(options, done, fileSuffix, startUnicode) { | ||
var dest = __dirname + '/results/' + options.fontName + | ||
(fileSuffix || '') + '.svg'; | ||
options.log = function() {}; | ||
var svgFontStream = SVGIcons2SVGFontStream(options); | ||
@@ -27,3 +28,3 @@ | ||
SVGIconsDirStream(__dirname + '/fixtures/' + options.fontName, { | ||
startUnicode: 0xE001 | ||
startUnicode: startUnicode || 0xE001 | ||
}) | ||
@@ -33,5 +34,6 @@ .pipe(svgFontStream); | ||
function generateFontToMemory(options, done) { | ||
function generateFontToMemory(options, done, fileSuffix, startUnicode) { | ||
var content = ''; | ||
var decoder = new StringDecoder('utf8'); | ||
options.log = function() {}; | ||
var svgFontStream = SVGIcons2SVGFontStream(options); | ||
@@ -53,3 +55,3 @@ | ||
SVGIconsDirStream(__dirname + '/fixtures/' + options.fontName, { | ||
startUnicode: 0xE001 | ||
startUnicode: startUnicode || 0xE001 | ||
}) | ||
@@ -264,2 +266,8 @@ .pipe(svgFontStream); | ||
it("should work with nested icons", function(done) { | ||
generateFontToFile({ | ||
fontName: 'nestedicons' | ||
}, done, '', 0xEA01); | ||
}); | ||
}); | ||
@@ -266,0 +274,0 @@ |
@@ -11,8 +11,15 @@ var metadata = require(__dirname + '/../src/metadata.js'); | ||
var metadataService = metadata(); | ||
assert.deepEqual( | ||
metadataService('/var/plop/hello.svg'), { | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0xEA01)] | ||
metadataService('/var/plop/hello.svg', function(err, infos) { | ||
if(err) { | ||
return done(err); | ||
} | ||
); | ||
assert.deepEqual( | ||
infos, { | ||
path: '/var/plop/hello.svg', | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0xEA01)], | ||
renamed: false | ||
} | ||
); | ||
}); | ||
}); | ||
@@ -24,16 +31,24 @@ | ||
appendUnicode: true, | ||
log: function() { | ||
assert(fs.existsSync(__dirname + '/results/uEA01-plop.svg')); | ||
assert(!fs.existsSync(__dirname + '/results/plop.svg')); | ||
fs.unlinkSync(__dirname + '/results/uEA01-plop.svg'); | ||
done(); | ||
}, | ||
error: done | ||
log: function() {}, | ||
error: function() { | ||
done(new Error('Not supposed to be here')); | ||
} | ||
}); | ||
assert.deepEqual( | ||
metadataService(__dirname + '/results/plop.svg'), { | ||
name: 'plop', | ||
unicode: [String.fromCharCode(0xEA01)] | ||
metadataService(__dirname + '/results/plop.svg', function(err, infos) { | ||
if(err) { | ||
return done(err); | ||
} | ||
); | ||
assert.deepEqual( | ||
infos, { | ||
path: __dirname + '/results/uEA01-plop.svg', | ||
name: 'plop', | ||
unicode: [String.fromCharCode(0xEA01)], | ||
renamed: true | ||
} | ||
); | ||
assert(fs.existsSync(__dirname + '/results/uEA01-plop.svg')); | ||
assert(!fs.existsSync(__dirname + '/results/plop.svg')); | ||
fs.unlinkSync(__dirname + '/results/uEA01-plop.svg'); | ||
done(); | ||
}); | ||
}); | ||
@@ -45,7 +60,3 @@ | ||
startUnicode: 0xEA02, | ||
error: function(err) { | ||
assert(!fs.existsSync(__dirname + '/results/uEA02-plop.svg')); | ||
assert(err); | ||
done(); | ||
}, | ||
error: function(err) {}, | ||
log: function() { | ||
@@ -55,8 +66,8 @@ done(new Error('Not supposed to be here')); | ||
}); | ||
assert.deepEqual( | ||
metadataService(__dirname + '/results/plop.svg'), { | ||
name: 'plop', | ||
unicode: [String.fromCharCode(0xEA02)] | ||
} | ||
); | ||
metadataService(__dirname + '/results/plop.svg', function(err, infos) { | ||
assert(!infos); | ||
assert(err); | ||
assert(!fs.existsSync(__dirname + '/results/uEA02-plop.svg')); | ||
done(); | ||
}); | ||
}); | ||
@@ -68,43 +79,63 @@ | ||
it("should work for simple codes", function() { | ||
it("should work for simple codes", function(done) { | ||
var metadataService = metadata(); | ||
assert.deepEqual( | ||
metadataService('/var/plop/u0001-hello.svg'), { | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0x0001)] | ||
} | ||
); | ||
metadataService('/var/plop/u0001-hello.svg', function(err, infos) { | ||
assert(!err); | ||
assert.deepEqual(infos, { | ||
path: '/var/plop/u0001-hello.svg', | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0x0001)], | ||
renamed: false | ||
} | ||
); | ||
done(); | ||
}); | ||
}); | ||
it("should work for several codes", function() { | ||
it("should work for several codes", function(done) { | ||
var metadataService = metadata(); | ||
assert.deepEqual( | ||
metadataService('/var/plop/u0001,u0002-hello.svg'), { | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0x0001), String.fromCharCode(0x0002)] | ||
} | ||
); | ||
metadataService('/var/plop/u0001,u0002-hello.svg', function(err, infos) { | ||
assert(!err); | ||
assert.deepEqual(infos, { | ||
path: '/var/plop/u0001,u0002-hello.svg', | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0x0001), String.fromCharCode(0x0002)], | ||
renamed: false | ||
} | ||
); | ||
done(); | ||
}); | ||
}); | ||
it("should work for ligature codes", function() { | ||
it("should work for ligature codes", function(done) { | ||
var metadataService = metadata(); | ||
assert.deepEqual( | ||
metadataService('/var/plop/u0001u0002-hello.svg'), { | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0x0001) + String.fromCharCode(0x0002)] | ||
} | ||
); | ||
metadataService('/var/plop/u0001u0002-hello.svg', function(err, infos) { | ||
assert(!err); | ||
assert.deepEqual(infos, { | ||
path: '/var/plop/u0001u0002-hello.svg', | ||
name: 'hello', | ||
unicode: [String.fromCharCode(0x0001) + String.fromCharCode(0x0002)], | ||
renamed: false | ||
} | ||
); | ||
done(); | ||
}); | ||
}); | ||
it("should work for nested codes", function() { | ||
it("should work for nested codes", function(done) { | ||
var metadataService = metadata(); | ||
assert.deepEqual( | ||
metadataService('/var/plop/u0001u0002,u0001-hello.svg'), { | ||
name: 'hello', | ||
unicode: [ | ||
String.fromCharCode(0x0001) + String.fromCharCode(0x0002), | ||
String.fromCharCode(0x0001) | ||
] | ||
} | ||
); | ||
metadataService('/var/plop/u0001u0002,u0001-hello.svg', function(err, infos) { | ||
assert(!err); | ||
assert.deepEqual(infos, { | ||
path: '/var/plop/u0001u0002,u0001-hello.svg', | ||
name: 'hello', | ||
unicode: [ | ||
String.fromCharCode(0x0001) + String.fromCharCode(0x0002), | ||
String.fromCharCode(0x0001) | ||
], | ||
renamed: false | ||
} | ||
); | ||
done(); | ||
}); | ||
}); | ||
@@ -111,0 +142,0 @@ |
4
210
156908
102
1130
2