Skip to content

Commit 45e3452

Browse files
authored
Merge pull request #1618 from privy-open-source/feat/sync-icon
chore: sync with figma
2 parents 19515ac + f32bc4d commit 45e3452

38 files changed

+18449
-13975
lines changed

packages/persona-icon/font/persona-icon.css

Lines changed: 472 additions & 472 deletions
Large diffs are not rendered by default.
-28.1 KB
Binary file not shown.

packages/persona-icon/font/persona-icon.json

Lines changed: 5411 additions & 0 deletions
Large diffs are not rendered by default.

packages/persona-icon/font/persona-icon.svg

Lines changed: 934 additions & 2737 deletions
Loading
-28.1 KB
Binary file not shown.
-67.3 KB
Binary file not shown.
-159 KB
Binary file not shown.

packages/persona-icon/package.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,15 @@
4646
},
4747
"devDependencies": {
4848
"@nuxt/module-builder": "1.0.1",
49+
"@tsconfig/node22": "^22.0.1",
4950
"@types/fs-extra": "11.0.4",
5051
"@types/minimist": "1.2.5",
52+
"@types/svg2ttf": "^5.0.3",
53+
"@types/ttf2eot": "^2.0.2",
54+
"@types/ttf2woff": "^2.0.4",
55+
"@types/ttf2woff2": "^6.0.0",
5156
"dotenv": "16.5.0",
57+
"fast-glob": "^3.3.3",
5258
"figma-api": "1.12.0",
5359
"fs-extra": "11.3.0",
5460
"jiti": "2.4.2",
@@ -58,8 +64,12 @@
5864
"ora": "8.2.0",
5965
"p-all": "5.0.0",
6066
"svg-path-commander": "2.1.10",
67+
"svg2ttf": "^6.0.3",
68+
"svgicons2svgfont": "^15.0.1",
6169
"svgo": "3.3.2",
62-
"webfont": "11.2.26"
70+
"ttf2eot": "^3.1.0",
71+
"ttf2woff": "^3.0.0",
72+
"ttf2woff2": "^6.0.1"
6373
},
6474
"dependencies": {
6575
"@nuxt/kit": "3.16.2"

packages/persona-icon/scripts/changelog.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
import { resolve } from 'node:path'
66
import { readJSON } from 'fs-extra'
77
import { name } from '../package.json'
8-
import type { MetaData } from './types'
8+
import type { MetaData } from './types.js'
99
import { ofetch } from 'ofetch'
10-
import * as ohash from 'ohash'
10+
import { diff } from 'ohash/utils'
1111
import minimist from 'minimist'
1212
import {
1313
groupBy,
@@ -42,7 +42,7 @@ async function getMeta (version: string): Promise<MetaData[]> {
4242
async function main () {
4343
const sourceMeta = getFilesData(await getMeta(argv.from ?? 'latest'))
4444
const targetMeta = getFilesData(await getMeta(argv.to ?? 'local'))
45-
const diffs = ohash.diff(sourceMeta, targetMeta)
45+
const diffs = diff(sourceMeta, targetMeta)
4646
const changelogs = groupBy(sortBy(diffs, ['type', 'key']), 'type')
4747

4848
if (Object.keys(changelogs).length > 0) {
@@ -56,7 +56,7 @@ async function main () {
5656
console.log(`- ${group}`)
5757
else {
5858
for (const item of items)
59-
console.log(`- ${item.key.replace('.hash', '')}`)
59+
console.log(`- ${(item.key as string).replace('.hash', '')}`)
6060
}
6161
}
6262
}

packages/persona-icon/scripts/create-font.ts

Lines changed: 135 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
/* eslint-disable unicorn/prefer-module */
2-
import { webfont } from 'webfont'
31
import {
42
writeFile,
53
ensureFile,
4+
createWriteStream,
5+
createReadStream,
6+
readFile,
67
} from 'fs-extra'
78
import {
89
resolve,
@@ -11,74 +12,157 @@ import {
1112
basename,
1213
} from 'node:path'
1314
import { createHash } from 'node:crypto'
14-
import type { Result } from 'webfont/dist/src/types/Result'
1515
import { EOL } from 'node:os'
16+
import { fileURLToPath } from 'node:url'
17+
import glob from 'fast-glob'
18+
import type { Glyph, SVGIconStream } from 'svgicons2svgfont'
19+
import { SVGIcons2SVGFontStream } from 'svgicons2svgfont'
20+
import svg2ttf from 'svg2ttf'
21+
import ttf2woff from 'ttf2woff'
22+
import ttf2woff2 from 'ttf2woff2'
23+
import ttf2eot from 'ttf2eot'
24+
25+
const SVG_DIR = fileURLToPath(new URL('../svg/', import.meta.url))
26+
const FONT_DIR = fileURLToPath(new URL('../font/', import.meta.url))
27+
28+
function withDirname (a: string, b: string) {
29+
const dirA = basename(dirname(a))
30+
const dirB = basename(dirname(b))
31+
32+
return dirA.localeCompare(dirB)
33+
}
1634

17-
const SVG_DIR = resolve(__dirname, '../svg/')
18-
const FONT_DIR = resolve(__dirname, '../font/')
19-
20-
export async function createFont () {
21-
const result = await webfont({
22-
files : join(SVG_DIR, '**', '16.svg'),
23-
fontName : 'Persona Icon',
24-
templateClassName: 'pi',
25-
fixedWidth : true,
26-
normalize : true,
27-
fontHeight : 1000,
28-
round : 10e12,
29-
sort : true,
30-
glyphTransformFn (obj) {
31-
return Object.assign(obj, { name: basename(dirname((obj as any).path)) })
32-
},
35+
async function createSVG () {
36+
await ensureFile(join(FONT_DIR, 'persona-icon.svg'))
37+
38+
const icons = await glob('./**/16.svg', { cwd: SVG_DIR })
39+
const glyphs = await new Promise<Glyph[]>((resolve, reject) => {
40+
const fontStream = new SVGIcons2SVGFontStream({
41+
fontName : 'Persona Icon',
42+
fixedWidth: true,
43+
normalize : true,
44+
fontHeight: 1000,
45+
round : 10e12,
46+
})
47+
48+
fontStream.pipe(createWriteStream(join(FONT_DIR, 'persona-icon.svg')))
49+
.on('finish', () => {
50+
resolve(fontStream.glyphs)
51+
})
52+
.on('error', (error) => {
53+
reject(error)
54+
})
55+
56+
let unicode = 0xEA_00
57+
58+
for (const icon of icons.toSorted(withDirname)) {
59+
const glyph: SVGIconStream = createReadStream(join(SVG_DIR, icon)) as any
60+
61+
glyph.metadata = {
62+
name : basename(dirname(icon)),
63+
unicode: [String.fromCodePoint(++unicode)],
64+
}
65+
66+
fontStream.write(glyph)
67+
}
68+
69+
fontStream.end()
3370
})
3471

35-
if (result.ttf) {
36-
await ensureFile(resolve(FONT_DIR, 'persona-icon.ttf'))
37-
await writeFile(resolve(FONT_DIR, 'persona-icon.ttf'), result.ttf.toString())
38-
}
72+
await ensureFile(join(FONT_DIR, 'persona-icon.json'))
73+
await writeFile(join(FONT_DIR, 'persona-icon.json'), JSON.stringify(glyphs, undefined, 2))
3974

40-
if (result.woff) {
41-
await ensureFile(resolve(FONT_DIR, 'persona-icon.woff'))
42-
await writeFile(resolve(FONT_DIR, 'persona-icon.woff'), result.woff.toString())
43-
}
75+
const buffer = await readFile(join(FONT_DIR, 'persona-icon.svg'))
4476

45-
if (result.woff2) {
46-
await ensureFile(resolve(FONT_DIR, 'persona-icon.woff2'))
47-
await writeFile(resolve(FONT_DIR, 'persona-icon.woff2'), result.woff2.toString())
48-
}
77+
return { glyphs, buffer }
78+
}
4979

50-
if (result.eot) {
51-
await ensureFile(resolve(FONT_DIR, 'persona-icon.eot'))
52-
await writeFile(resolve(FONT_DIR, 'persona-icon.eot'), result.eot.toString())
53-
}
80+
async function createTtf (svg: Buffer) {
81+
const result = svg2ttf(svg.toString('utf8'))
82+
const output = Buffer.from(result.buffer)
5483

55-
if (result.svg) {
56-
await ensureFile(resolve(FONT_DIR, 'persona-icon.svg'))
57-
await writeFile(resolve(FONT_DIR, 'persona-icon.svg'), result.svg.toString())
58-
}
84+
await ensureFile(resolve(FONT_DIR, 'persona-icon.ttf'))
85+
await writeFile(resolve(FONT_DIR, 'persona-icon.ttf'), output)
5986

60-
await createCss(result)
87+
return output
88+
}
89+
90+
async function createWoff (ttf: Buffer) {
91+
const result = ttf2woff(ttf)
92+
93+
await ensureFile(resolve(FONT_DIR, 'persona-icon.woff'))
94+
await writeFile(resolve(FONT_DIR, 'persona-icon.woff'), result)
95+
96+
return result
97+
}
98+
99+
async function createWoff2 (ttf: Buffer) {
100+
const result = ttf2woff2(ttf)
101+
102+
await ensureFile(resolve(FONT_DIR, 'persona-icon.woff2'))
103+
await writeFile(resolve(FONT_DIR, 'persona-icon.woff2'), result)
104+
105+
return result
106+
}
107+
108+
async function createEot (ttf: Buffer) {
109+
const result = ttf2eot(ttf)
110+
111+
await ensureFile(resolve(FONT_DIR, 'persona-icon.eot'))
112+
await writeFile(resolve(FONT_DIR, 'persona-icon.eot'), result)
113+
114+
return result
115+
}
116+
117+
export async function createFont () {
118+
const {
119+
glyphs,
120+
buffer: svg,
121+
} = await createSVG()
122+
123+
const ttf = await createTtf(svg)
124+
const woff = await createWoff(ttf)
125+
const woff2 = await createWoff2(ttf)
126+
const eot = await createEot(ttf)
127+
128+
await createCss({
129+
glyphs,
130+
svg,
131+
ttf,
132+
eot,
133+
woff,
134+
woff2,
135+
})
61136
}
62137

63138
function hash (buffer: Buffer | string, length = 4) {
64139
return createHash('shake256', { outputLength: length })
65-
.update(buffer.toString())
140+
.update(buffer)
66141
.digest('hex')
67142
}
68143

69144
function toCode (unicode: string) {
70145
return unicode.codePointAt(0)?.toString(16).padStart(4, '0') ?? ''
71146
}
72147

73-
async function createCss (result: Result) {
148+
interface CreateCSS {
149+
glyphs: Glyph[],
150+
svg: Buffer,
151+
ttf: Buffer,
152+
eot: Buffer,
153+
woff: Buffer,
154+
woff2: Buffer,
155+
}
156+
157+
async function createCss (input: CreateCSS) {
74158
let css = `@font-face {
75159
font-family: 'Persona Icon';
76-
src: url('../font/persona-icon.eot?${hash(result.eot ?? '')}');
77-
src: url('../font/persona-icon.eot?${hash(result.eot ?? '')}#iefix') format('embedded-opentype'),
78-
url('../font/persona-icon.woff2?${hash(result.woff2 ?? '')}') format('woff2'),
79-
url('../font/persona-icon.woff?${hash(result.woff ?? '')}') format('woff'),
80-
url('../font/persona-icon.ttf?${hash(result.ttf ?? '')}') format('truetype'),
81-
url('../font/persona-icon.svg?${hash(result.svg ?? '')}#${encodeURIComponent('Persona Icon')}') format('svg');
160+
src: url('../font/persona-icon.eot?${hash(input.eot)}');
161+
src: url('../font/persona-icon.eot?${hash(input.eot)}#iefix') format('embedded-opentype'),
162+
url('../font/persona-icon.woff2?${hash(input.woff2)}') format('woff2'),
163+
url('../font/persona-icon.woff?${hash(input.woff)}') format('woff'),
164+
url('../font/persona-icon.ttf?${hash(input.ttf)}') format('truetype'),
165+
url('../font/persona-icon.svg?${hash(input.svg ?? '')}#${encodeURIComponent('Persona Icon')}') format('svg');
82166
font-weight: normal;
83167
font-style: normal;
84168
}
@@ -99,9 +183,9 @@ async function createCss (result: Result) {
99183
-moz-osx-font-smoothing: grayscale;
100184
}${EOL}${EOL}`
101185

102-
for (const glyph of (result.glyphsData ?? [])) {
103-
const name = glyph.metadata?.name
104-
const content = glyph.metadata?.unicode?.at(0)
186+
for (const glyph of (input.glyphs ?? [])) {
187+
const name = glyph.name
188+
const content = glyph.unicode?.at(0)
105189

106190
if (name && content)
107191
css += `.pi-${name}::before { content: '\\${toCode(content)}' }${EOL}`

packages/persona-icon/scripts/lint.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/* eslint-disable unicorn/prefer-top-level-await */
44
import { readJSON } from 'fs-extra'
55
import { resolve } from 'node:path'
6-
import type { MetaData } from './types'
6+
import type { MetaData } from './types.js'
77

88
const META_FILE = resolve(__dirname, '../svg/meta.json')
99

packages/persona-icon/scripts/sync.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import 'dotenv/config'
77
import { EOL } from 'node:os'
88
import { createHash } from 'node:crypto'
99
import { Api } from 'figma-api'
10-
import type { ComponentMetadata } from 'figma-api/lib/api-types'
10+
import type { ComponentMetadata } from 'figma-api/lib/api-types.js'
1111
import {
1212
writeFile,
1313
ensureFile,
@@ -25,9 +25,9 @@ import type { Config } from 'svgo'
2525
import { optimize } from 'svgo'
2626
import ora from 'ora'
2727
import { ESLint } from 'eslint'
28-
import type { ObjectData, MetaData } from './types'
29-
import { fixPath } from './fix-svg'
30-
import { createFont } from './create-font'
28+
import type { ObjectData, MetaData } from './types.js'
29+
import { fixPath } from './fix-svg.js'
30+
import { createFont } from './create-font.js'
3131
import pAll from 'p-all'
3232
import * as ohash from 'ohash'
3333
import minimist from 'minimist'
@@ -195,7 +195,7 @@ function getMetadata (objects: Iterable<ObjectData>): MetaData[] {
195195
map.set(object.folder, metadata)
196196
}
197197

198-
return [...map.values()]
198+
return [...map.values()].sort((a, b) => a.name.localeCompare(b.name))
199199
}
200200

201201
function toVue (svg: string): string {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": "@tsconfig/node22/tsconfig.json",
3+
"compilerOptions": {
4+
"resolveJsonModule": true
5+
}
6+
}

packages/persona-icon/scripts/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ComponentMetadata } from 'figma-api/lib/api-types'
1+
import type { ComponentMetadata } from 'figma-api/lib/api-types.js'
22

33
export interface MetaData {
44
name: string,
Lines changed: 1 addition & 1 deletion
Loading
Lines changed: 1 addition & 1 deletion
Loading
Lines changed: 1 addition & 1 deletion
Loading
Lines changed: 1 addition & 1 deletion
Loading

0 commit comments

Comments
 (0)