mirror of
https://github.com/desktop/desktop
synced 2024-09-14 05:41:46 +00:00
128 lines
3.2 KiB
TypeScript
128 lines
3.2 KiB
TypeScript
/* generate-octicons
|
|
*
|
|
* Utility script for generating a strongly typed representation of all
|
|
* octicons distributed by the octicons NPM package. Enumerates the icons
|
|
* and generates the TypeScript class containing just what Desktop needs.
|
|
*/
|
|
|
|
import * as fs from 'fs'
|
|
import * as Path from 'path'
|
|
import * as cp from 'child_process'
|
|
import { check } from 'reserved-words'
|
|
import toCamelCase from 'to-camel-case'
|
|
|
|
// Basic type for the @primer/octicons package.
|
|
type OcticonsLib = Record<
|
|
string,
|
|
{
|
|
readonly symbol: string
|
|
readonly heights: Record<
|
|
string,
|
|
{
|
|
readonly ast: {
|
|
readonly children: ReadonlyArray<{
|
|
readonly attributes: {
|
|
readonly d: string
|
|
}
|
|
}>
|
|
}
|
|
readonly options: {
|
|
readonly height: string
|
|
readonly width: string
|
|
}
|
|
}
|
|
>
|
|
}
|
|
>
|
|
|
|
interface IOcticonVariant {
|
|
p: string[]
|
|
h: number
|
|
w: number
|
|
}
|
|
|
|
interface IOcticon {
|
|
/** JS friendly name of the icon. */
|
|
readonly name: string
|
|
|
|
/** Size variants of the icon. */
|
|
readonly variants: Record<PropertyKey, IOcticonVariant>
|
|
}
|
|
|
|
function getJsFriendlyName(name: string) {
|
|
const sanitizedName = toCamelCase(name)
|
|
return check(sanitizedName, 'es6', true) ? sanitizedName + '_' : sanitizedName
|
|
}
|
|
|
|
async function generateIconData(): Promise<ReadonlyArray<IOcticon>> {
|
|
const octicons: OcticonsLib = require('@primer/octicons')
|
|
|
|
return Object.keys(octicons)
|
|
.sort()
|
|
.map(name => {
|
|
const octicon = octicons[name]
|
|
|
|
if (Object.keys(octicon.heights).length === 0) {
|
|
throw new Error(`Unexpected empty sizes array for ${octicon.symbol}`)
|
|
}
|
|
|
|
const variants: Record<PropertyKey, IOcticonVariant> = {}
|
|
|
|
Object.entries(octicon.heights).forEach(([height, data]) => {
|
|
variants[height] = {
|
|
p: data.ast.children.map(c => c.attributes.d),
|
|
h: parseInt(data.options.height, 10),
|
|
w: parseInt(data.options.width, 10),
|
|
}
|
|
})
|
|
|
|
return { name: getJsFriendlyName(name), variants }
|
|
})
|
|
}
|
|
|
|
generateIconData().then(results => {
|
|
console.log(`Writing ${results.length} octicons...`)
|
|
|
|
const out = fs.createWriteStream(
|
|
Path.resolve(__dirname, '../app/src/ui/octicons/octicons.generated.ts'),
|
|
{
|
|
encoding: 'utf-8',
|
|
}
|
|
)
|
|
|
|
out.write(`/*
|
|
* This file is automatically generated by the generate-octicons tool.
|
|
* Manually changing this file will only lead to sadness.
|
|
*/
|
|
|
|
export type OcticonSymbolVariant = {
|
|
/** SVG path element data */
|
|
readonly p: string[]
|
|
|
|
/** The width of the symbol */
|
|
readonly w: number
|
|
|
|
/** The height of the symbol */
|
|
readonly h: number
|
|
}
|
|
|
|
export type OcticonSymbolVariants = Record<PropertyKey, OcticonSymbolVariant>
|
|
|
|
export type OcticonSymbol = OcticonSymbolVariant | OcticonSymbolVariants\n\n`)
|
|
|
|
results.forEach(icon => {
|
|
out.write(
|
|
`export const ${icon.name}: OcticonSymbolVariants = ${JSON.stringify(
|
|
icon.variants
|
|
)}\n`
|
|
)
|
|
})
|
|
|
|
out.end()
|
|
|
|
console.log('Ensuring generated file is formatted correctly...')
|
|
const root = Path.dirname(__dirname)
|
|
const yarnExecutable = process.platform === 'win32' ? 'yarn.cmd' : 'yarn'
|
|
return cp.spawn(yarnExecutable, ['lint:fix'], { cwd: root, stdio: 'inherit' })
|
|
})
|