Skip to content
This repository has been archived by the owner on Jan 19, 2021. It is now read-only.

Commit

Permalink
Organized everything
Browse files Browse the repository at this point in the history
- We're now using commander with a stylish CLI API
- A few algorythms were moved to their own functions
- demo.html and config.json are now being extracted with the font
- Added possibility of changing the font name
  • Loading branch information
Gustavo Henke committed Apr 10, 2014
1 parent 57aac1d commit 07e057c
Show file tree
Hide file tree
Showing 9 changed files with 33,408 additions and 2,213 deletions.
189 changes: 117 additions & 72 deletions build/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,12 @@
var FONTELLO_HOST = "http://fontello.com/";

// Requires
var path = require( "path" );
var fs = require( "fs" );
var path = require( "path" );
var xml2js = require( "xml2js" );
var ent = require( "ent" );
var restler = require( "restler" );
var AdmZip = require( "adm-zip" );
var SvgPath = require( "svgpath" );
var wrench = require( "wrench" );
var stripJsonComments = require( "strip-json-comments" );

// Initialize program options
var options = initOptions();

// Initialize fontello config
var fontelloCfg = {};
Expand All @@ -29,18 +26,22 @@ svg = svg.replace( /glyph-name="uni[a-f0-9]{4}" unicode="(.+?)"/gi, "glyph-name=

xml2js.parseString( svg, function( err, result ) {
var json;
var restler = require( "restler" );
var cfgFile = path.join( __dirname, "config.json" );
var font = result.svg.defs[ 0 ].font[ 0 ];
var fontFace = font[ "font-face" ][ 0 ].$;
var unicodeStart = parseInt( "0xE000", 16 );

fontelloCfg.name = "webhostinghub-glyphs";
if ( options.name ) {
console.log( "Using font name %s", options.name );
}

fontelloCfg.name = options.name || "webhostinghub-glyphs";
fontelloCfg.ascent = +fontFace[ "ascent" ];
fontelloCfg.units_per_em = +fontFace[ "units-per-em" ];
fontelloCfg.css_use_suffix = false;
fontelloCfg.css_prefix_text = "icon-";
fontelloCfg.hinting = true;
fontelloCfg.glyphs = font.glyph.map( getGlyphParser( fontFace, unicodeStart ) ).filter(function( glyph ) {
fontelloCfg.glyphs = font.glyph.map( getGlyphParser( fontFace ) ).filter(function( glyph ) {
return glyph;
});

Expand Down Expand Up @@ -69,90 +70,73 @@ xml2js.parseString( svg, function( err, result ) {
restler.get( FONTELLO_HOST + id + "/get", {
// Decoding must be buffer in order to zip download correctly
decoding: "buffer"
}).on( "complete", function( zip ) {
var dir;
var zipOutput = path.join( __dirname, "font" );

// Create the zip file locally
var zipFile = path.join( __dirname, "font.zip" );
fs.writeFileSync( zipFile, zip );
console.log( "Downloaded and saved zip file" );

// Unzip contents and delete zip file
new AdmZip( zipFile ).extractAllTo( zipOutput, true );
fs.unlinkSync( zipFile );

// Get the fontello directory
dir = fs.readdirSync( zipOutput );
dir = path.join( zipOutput, dir[ 0 ] );

// Copy things
console.log( "Copying files" );
wrench.copyDirSyncRecursive(
path.join( dir, "font" ),
path.resolve( process.cwd(), "font" ),
{ forceDelete: true }
);
wrench.copyDirSyncRecursive(
path.join( dir, "css" ),
path.resolve( process.cwd(), "css" ),
{ forceDelete: true }
);

wrench.rmdirSyncRecursive( zipOutput );
console.log( "Finished installation." );
});
}).on( "complete", extractZip );
});
});

// -------------------------------------------------------------------------------------------------

/**
* Get CLI args
*
* @returns {*}
*/
function initOptions() {
var program = require( "commander" );
program
.version( require( "../package.json" ).version )
.option( "-i, --icons <value>", "use specified icons mapping" )
.option( "-n, --name <value>", "use specified font name" );

program._name = "whhglyphs";
return program.parse( process.argv );
}

/**
* Read a file passed via argv and return selected icons.
* If the file does not exist, or the format is unsupported, no icon is selected.
*
* @returns {String[]|void}
*/
function getSelectedIcons() {
var ret, content, file, ext;
var ret, content, ext;
var stripJsonComments = require( "strip-json-comments" );
var file = options.icons;

// If there's more than 2 argvs (node script.js), we'll slice it and try to read as a file
if ( process.argv.length > 2 ) {
file = process.argv[ 2 ];
if ( file ) {
ext = file.split( "." ).pop().toLowerCase();

ret = {};

try {
content = fs.readFileSync( path.resolve( process.cwd(), file ), "utf8" );
if ( ext === "txt" ) {
content = content.split( "\n" ).map(function( ln ) {
content = content.split( "\n" ).map( function ( ln ) {
// Trim and split by spaces each line.
// 1st item will be the original name, and the 2nd item will be the new name
ln = ln.trim().split( /\s+/ );
return ln;
});
} );
} else if ( ext === "json" ) {
content = JSON.parse( stripJsonComments( content ) );

if ( !Array.isArray( content ) ) {
// We'll use keys as original name, and values as renamed icons
content = Object.keys( content ).map(function( key ) {
content = Object.keys( content ).map( function ( key ) {
return [ key, content[ key ] ];
});
} );
}
} else {
content = [];
console.log( "Unsupported file type: " + ext );
}

content.forEach(function( item ) {
content.forEach( function ( item ) {
if ( typeof item === "string" ) {
item = [ item, item ];
}

ret[ item[ 0 ] ] = item[ 1 ] || item[ 0 ];
});
} );
} catch ( e ) {}
}

Expand All @@ -162,22 +146,36 @@ function getSelectedIcons() {
/**
* Return a parser for glyphs
*
* @param {Number} unicodeStart The unicode char to start from
* @param {Object} root
* @returns {Function}
*/
function getGlyphParser( root, unicodeStart ) {
function getGlyphParser( root ) {
var ent = require( "ent" );
var SvgPath = require( "svgpath" );

// Fontello uses ascent = 850, WHHGlyphs uses 819. This makes the font look disaligned.
var ascent = 850;
var proportion = ( +root.ascent * 100 ) / ascent / 100;

// Init externally selected icons
// This will be used to filter out the icons by their name
var selected = getSelectedIcons();
var hasSelection = selected && Object.keys( selected ).length;
var iconNames = [];
var findAvailableName = function( name ) {

// Hold available/used icons after they were renamed
var availableIcons = [];
var usedIcons = [];

// Declare the PUA starting point
var unicodeStart = parseInt( "0xE000", 16 );
var findAvailableName = function( arr, name ) {
var orig = name;
var i = 0;

do {
name = name + ( i || "" );
name = orig + ( i || "" );
i++;
} while ( iconNames.indexOf( name ) > -1 );
} while ( arr.indexOf( name ) > -1 );

return name;
};
Expand All @@ -187,7 +185,7 @@ function getGlyphParser( root, unicodeStart ) {
}

return function parseGlyphObject( glyph, i ) {
var name, d, unicodeAttr, isSelected;
var name, originalName, d, unicodeAttr, isSelected;

glyph = glyph.$;
d = glyph.d;
Expand All @@ -205,33 +203,36 @@ function getGlyphParser( root, unicodeStart ) {
}

// Uses glyph-name, unless it's so stupid.
name = glyph[ "glyph-name" ];
if ( /^uni[a-f0-9]{4}$/.test( name ) || name.indexOf( "NameMe" ) > -1 ) {
name = unicodeAttr;
originalName = glyph[ "glyph-name" ];
if ( /^uni[a-f0-9]{4}$/.test( originalName ) || originalName.indexOf( "NameMe" ) > -1 ) {
originalName = unicodeAttr;
}

// Add some index after the icon name
name = findAvailableName( name );
name = findAvailableName( availableIcons, originalName );
availableIcons.push( name );

// Initially, the icon will be selected, but...
// Initially, the icon will be selected...
isSelected = true;

// ...when a selection is available, let's analyze it to determine if we're going to use.
// And, if so, what will be its name.
// ...but when a selection is available, let's analyze it to determine if we're going to
// use, and, if so, what will be its name.
if ( hasSelection ) {
name = selected[ name ];
name = name ? findAvailableName( name ) : false;
name = name ? findAvailableName( usedIcons, name ) : false;

isSelected = !!name;
} else {
name = findAvailableName( usedIcons, originalName );
}

// Add the current icon name in the list of used names
iconNames.push( name );
usedIcons.push( name );

// Unshift and unmirror the icon
d = new SvgPath( d.replace( /\r?\n/g, " " ) )
.scale( 1, -1 )
.translate( 0, +root.ascent )
.scale( proportion, -proportion )
.translate( 0, ascent )
.abs()
.round( 1 )
.toString();
Expand All @@ -249,4 +250,48 @@ function getGlyphParser( root, unicodeStart ) {
search: [ name ]
};
};
}

/**
* Extract zip contents to the output directory.
*
* @param zip
* @returns void
*/
function extractZip( zip ) {
var dir;
var AdmZip = require( "adm-zip" );
var wrench = require( "wrench" );
var zipOutput = path.join( __dirname, "font" );

// Create the zip file locally
var zipFile = path.join( __dirname, "font.zip" );
fs.writeFileSync( zipFile, zip );
console.log( "Downloaded and saved zip file" );

// Unzip contents and delete zip file
new AdmZip( zipFile ).extractAllTo( zipOutput, true );
fs.unlinkSync( zipFile );

// Get the fontello directory
dir = fs.readdirSync( zipOutput );
dir = path.join( zipOutput, dir[ 0 ] );

// Copy things
console.log( "Copying files" );
fs.rename( path.join( dir, "demo.html" ), path.resolve( "demo.html" ) );
fs.rename( path.join( dir, "config.json" ), path.resolve( "config.json" ) );
wrench.copyDirSyncRecursive(
path.join( dir, "font" ),
path.resolve( "font" ),
{ forceDelete: true }
);
wrench.copyDirSyncRecursive(
path.join( dir, "css" ),
path.resolve( "css" ),
{ forceDelete: true }
);

wrench.rmdirSyncRecursive( zipOutput );
console.log( "Finished installation." );
}
Loading

0 comments on commit 07e057c

Please sign in to comment.