#!/usr/bin/env node /* jshint node: true */ ( function () { var i, count, group, symbol, symbols, symbolObject, symbolsData, cssData, cssLines, index, cssRules = [], cssClasses = [], symbolList = [], symbolsFile = '../symbols.json', cssFile = '../ve.ui.MWMathSymbols.css', cssPrefix = '.ve-ui-mwMathSymbol-', fs = require( 'fs' ), http = require( 'http' ), querystring = require( 'querystring' ), SVGO = require( 'svgo' ), svgo = new SVGO( { plugins: [ { convertTransform: false } ] } ), mathoidMaxConnections = 5; symbolsData = fs.readFileSync( symbolsFile ).toString(); try { cssData = fs.readFileSync( cssFile ).toString(); } catch ( e ) {} function encodeURIComponentForCSS( str ) { return encodeURIComponent( str ) .replace( /[!'\(\)\*]/g, function ( chr ) { return '%' + chr.charCodeAt( 0 ).toString( 16 ); } ); } function texToClass( tex ) { // Make the className, replacing any non-alphanumerics with their character code return tex.replace( /[^\w]/g, function ( c ) { return '_' + c.charCodeAt( 0 ) + '_'; } ); } function makeRequest( symbol ) { var request, data = querystring.stringify( { q: symbol } ), // API call to mathoid options = { host: '192.168.37.177', port: '10044', path: '/', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': Buffer.byteLength( data ) } }; // Populate and make the API call request = http.request( options, function ( res ) { var body = ''; res.setEncoding( 'utf8' ); res.on( 'data', function ( data ) { body += data; } ); res.on( 'end', function () { var className = texToClass( symbol ), svg = JSON.parse( body ).svg; if ( !svg ) { console.log( symbol + ' FAILED: ' + body ); onEnd(); return; } svgo.optimize( svg, function ( result ) { // write to the css file cssRules.push( cssPrefix + className + ' {\n' + '\tbackground-image: url(data:image/svg+xml,' + encodeURIComponentForCSS( result.data ) + ');\n' + '}' ); console.log( symbol + ' -> ' + className ); } ); onEnd(); } ); } ); request.setTimeout( 10000 ); request.write( data ); request.end(); runNext(); } function onEnd() { count--; runNext(); } function runNext() { if ( count < mathoidMaxConnections && symbolList.length ) { count++; makeRequest( symbolList.shift() ); } if ( !symbolList.length && !count ) { cssRules.sort(); fs.writeFileSync( cssFile, '/*!\n' + ' * This file is GENERATED by tools/makeSvgsAndCss.js\n' + ' * DO NOT EDIT\n' + ' */\n' + '\n' + cssRules.join( '\n\n' ) + '\n' ); } } if ( cssData ) { cssLines = cssData.split( '\n' ); for ( i = 0; i < cssLines.length; i++ ) { if ( cssLines[ i ].indexOf( cssPrefix ) === 0 ) { cssRules.push( cssLines.slice( i, i + 3 ).join( '\n' ) ); cssClasses.push( cssLines[ i ].slice( cssPrefix.length, -2 ) ); } } } symbolObject = JSON.parse( symbolsData ); for ( group in symbolObject ) { symbols = symbolObject[ group ]; for ( i = 0; i < symbols.length; i++ ) { symbol = symbols[ i ]; if ( symbol.duplicate || symbol.notWorking ) { continue; } index = cssClasses.indexOf( texToClass( symbol.tex ) ); if ( index === -1 ) { symbolList.push( symbol.tex ); } else { // Remove CSS classes we found in the symbol list so that // and the end of this loop, cssClasses contains classes // that have been deleted from the symbol list cssClasses.splice( index, 1 ); } } } // Remove classes that are no longer in the JSON cssRules = cssRules.filter( function ( rule ) { return cssClasses.indexOf( rule.split( '\n' )[ 0 ].slice( cssPrefix.length, -2 ) ) === -1; } ); count = 0; runNext(); } )();