2016-06-14 18:22:47 +00:00
|
|
|
/* generate-octicons
|
|
|
|
*
|
|
|
|
* Utility script for generating a strongly typed representation of all
|
2017-11-04 00:54:19 +00:00
|
|
|
* octicons distributed by the octicons NPM package. Enumerates the icons
|
|
|
|
* and generates the TypeScript class containing just what Desktop needs.
|
2016-06-14 18:22:47 +00:00
|
|
|
*/
|
|
|
|
|
2017-11-04 01:05:05 +00:00
|
|
|
import * as fs from 'fs'
|
|
|
|
import * as Path from 'path'
|
|
|
|
import * as cp from 'child_process'
|
|
|
|
|
2017-09-23 22:13:57 +00:00
|
|
|
import xml2js = require('xml2js')
|
|
|
|
import toCamelCase = require('to-camel-case')
|
2017-11-04 00:54:19 +00:00
|
|
|
|
|
|
|
interface IXML2JSNode {
|
|
|
|
path: {
|
|
|
|
$: {
|
|
|
|
d: string
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-06-13 14:28:16 +00:00
|
|
|
|
2017-11-04 00:54:19 +00:00
|
|
|
interface IOcticonData {
|
|
|
|
readonly jsFriendlyName: string
|
|
|
|
readonly pathData: string
|
|
|
|
readonly width: string
|
|
|
|
readonly height: string
|
|
|
|
}
|
2016-06-13 14:28:16 +00:00
|
|
|
|
2017-11-04 00:54:19 +00:00
|
|
|
const viewBoxRe = /0 0 (\d+) (\d+)/
|
2016-06-13 14:28:16 +00:00
|
|
|
|
2017-11-04 00:54:19 +00:00
|
|
|
function readXml(xml: string): Promise<IXML2JSNode> {
|
|
|
|
return new Promise((resolve, reject) => {
|
2020-06-24 18:28:06 +00:00
|
|
|
xml2js.parseString(xml, function (err, result: IXML2JSNode) {
|
2017-11-04 00:54:19 +00:00
|
|
|
if (err) {
|
|
|
|
reject(err)
|
|
|
|
} else {
|
|
|
|
resolve(result)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
})
|
2017-09-23 22:13:57 +00:00
|
|
|
}
|
2017-11-04 00:54:19 +00:00
|
|
|
|
|
|
|
async function generateIconData(): Promise<ReadonlyArray<IOcticonData>> {
|
2019-09-25 18:24:58 +00:00
|
|
|
const octicons = require('@primer/octicons')
|
2017-11-04 00:54:19 +00:00
|
|
|
|
|
|
|
const results = new Array<IOcticonData>()
|
|
|
|
|
2018-12-29 12:59:47 +00:00
|
|
|
for (const name of Object.keys(octicons).sort()) {
|
2017-11-04 00:54:19 +00:00
|
|
|
const octicon = octicons[name]
|
|
|
|
|
|
|
|
const viewBox = octicon.options.viewBox
|
|
|
|
const viewBoxMatch = viewBoxRe.exec(viewBox)
|
|
|
|
|
|
|
|
if (!viewBoxMatch) {
|
2017-11-04 01:05:05 +00:00
|
|
|
throw new Error(
|
2017-11-04 02:47:59 +00:00
|
|
|
`Unexpected viewBox format for ${octicon.symbol} - '${viewBox}'`
|
2017-11-04 01:05:05 +00:00
|
|
|
)
|
2017-11-04 00:54:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const [, width, height] = viewBoxMatch
|
|
|
|
|
2017-11-04 01:05:05 +00:00
|
|
|
const result = await readXml(octicon.path)
|
2017-11-04 00:54:19 +00:00
|
|
|
const pathData = result.path.$.d
|
2017-11-04 01:05:05 +00:00
|
|
|
const jsFriendlyName = toCamelCase(octicon.symbol)
|
2017-11-04 00:54:19 +00:00
|
|
|
|
|
|
|
results.push({ jsFriendlyName, width, height, pathData })
|
|
|
|
}
|
|
|
|
|
|
|
|
return results
|
2017-09-23 22:13:57 +00:00
|
|
|
}
|
|
|
|
|
2017-11-04 00:54:19 +00:00
|
|
|
generateIconData().then(result => {
|
2017-11-04 01:28:11 +00:00
|
|
|
console.log(`Writing ${result.length} octicons...`)
|
|
|
|
|
2017-08-18 04:37:45 +00:00
|
|
|
const out = fs.createWriteStream(
|
2017-11-04 01:05:05 +00:00
|
|
|
Path.resolve(__dirname, '../app/src/ui/octicons/octicons.generated.ts'),
|
2017-09-25 10:45:44 +00:00
|
|
|
{
|
2017-09-25 16:49:22 +00:00
|
|
|
encoding: 'utf-8',
|
2017-09-25 10:45:44 +00:00
|
|
|
}
|
2017-08-18 04:37:45 +00:00
|
|
|
)
|
2016-06-15 17:47:16 +00:00
|
|
|
|
2017-08-18 04:37:45 +00:00
|
|
|
out.write('/*\n')
|
|
|
|
out.write(
|
|
|
|
' * This file is automatically generated by the generate-octicons tool.\n'
|
|
|
|
)
|
|
|
|
out.write(' * Manually changing this file will only lead to sadness.\n')
|
|
|
|
out.write(' */\n\n')
|
2016-06-13 14:28:16 +00:00
|
|
|
|
2017-08-18 04:37:45 +00:00
|
|
|
out.write('export class OcticonSymbol {\n')
|
2016-06-13 18:40:13 +00:00
|
|
|
|
2017-08-18 04:37:45 +00:00
|
|
|
out.write(
|
|
|
|
'\n public constructor(public w: number, public h: number, public d: string) { }\n\n'
|
|
|
|
)
|
2016-06-13 14:28:16 +00:00
|
|
|
|
2020-06-24 18:28:06 +00:00
|
|
|
result.forEach(function (symbol) {
|
2017-11-04 00:54:19 +00:00
|
|
|
const { jsFriendlyName, pathData, width, height } = symbol
|
2017-08-18 04:37:45 +00:00
|
|
|
out.write(
|
2017-12-12 05:21:47 +00:00
|
|
|
` public static get ${jsFriendlyName}() { return new OcticonSymbol(${width}, ${height}, '${pathData}') }\n`
|
2017-08-18 04:37:45 +00:00
|
|
|
)
|
2016-06-14 18:20:11 +00:00
|
|
|
})
|
2017-08-18 04:37:45 +00:00
|
|
|
|
|
|
|
out.write('}\n')
|
|
|
|
out.end()
|
|
|
|
|
2017-11-04 01:28:11 +00:00
|
|
|
console.log('Ensuring generated file is formatted correctly...')
|
|
|
|
const root = Path.dirname(__dirname)
|
2018-03-25 23:23:35 +00:00
|
|
|
const yarnExecutable = process.platform === 'win32' ? 'yarn.cmd' : 'yarn'
|
|
|
|
return cp.spawn(yarnExecutable, ['lint:fix'], { cwd: root, stdio: 'inherit' })
|
2017-08-18 04:37:45 +00:00
|
|
|
})
|