-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathgenerator.js
More file actions
120 lines (99 loc) · 3.33 KB
/
Copy pathgenerator.js
File metadata and controls
120 lines (99 loc) · 3.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import fs from 'fs'
import path from 'path'
import axios from 'axios'
const GOOGLE_FONTS_URL =
'https://fonts.google.com/metadata/icons?key=material_symbols&incomplete=true'
const ICON_FAMILIES = [
{ id: 'materialsymbolsoutlined', postfix: 'Outlined' },
{ id: 'materialsymbolsrounded', postfix: 'Rounded' },
{ id: 'materialsymbolssharp', postfix: 'Sharp' },
]
const getIncludedFamilies = (unsupportedFamilies) => {
const unsupportedFamilyIds = unsupportedFamilies.map((family) =>
family.replace(/\s+/g, '').toLowerCase(),
)
return ICON_FAMILIES.filter(
(family) => !unsupportedFamilyIds.includes(family.id),
)
}
;(async () => {
generatePropsFile()
const res = await axios.get(GOOGLE_FONTS_URL)
// remove )]}' from the response
const data = res.data.substring(4)
const icons = await JSON.parse(data)
for (let i = 0; i < icons.icons.length; i++) {
await generateComponentsForAllFamilies(icons.icons[i])
}
})()
function generatePropsFile() {
const typesFile = `
import React from 'react'
export interface IconProps extends React.SVGProps<SVGSVGElement> {
title?: string
}
`
fs.writeFileSync(path.join(import.meta.dirname, 'src', 'types.ts'), typesFile)
}
async function generateComponentsForAllFamilies(icon) {
const families = getIncludedFamilies(icon.unsupported_families)
for (let i = 0; i < families.length; i++) {
await Promise.all([
generateComponent(icon, families[i]),
generateComponent(icon, families[i], true),
])
}
}
async function generateComponent(icon, family, filled = false) {
try {
const name = formatName(icon.name, family.postfix, filled)
const svg = await downloadSVG(icon.name, family.id, filled)
console.log(`Downloading ${name}`)
await fs.writeFileSync(
path.join(import.meta.dirname, 'src', `${name}.tsx`),
mapSVGToTemplate(name, svg),
)
} catch {
console.log('Error generating component for', icon.name)
//process.abort()
}
}
function formatName(string, familyPostfix, filled) {
const formattedString = string
.replace(/_/g, ' ')
.replace(/\w\S*/g, (txt) => {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase()
})
.replace(/ /g, '')
return 'Icon' + formattedString + familyPostfix + (filled ? 'Filled' : '')
}
async function downloadSVG(icon, familyId, filled) {
const filledConfig = filled ? 'fill1' : 'default'
const svg = await axios
.get(
`https://fonts.gstatic.com/s/i/short-term/release/${familyId}/${icon}/${filledConfig}/24px.svg`,
)
.catch((err) => console.log(err))
return svg.data
.replace('height="24"', '')
.replace('width="24"', '{...props}')
.replace(/class/g, 'className')
.replace(/enable-background/g, 'enableBackground')
.replace(/clip-rule/g, 'clipRule')
.replace(/fill-rule/g, 'fillRule')
.replace('>', '>{props.title && <title>{props.title}</title>}')
.replace(/style="enableBackground:(.*?);?"/g, 'enableBackground="$1"')
.replace(/style="fill:(.*?);?"/g, 'fill="$1"')
.replace(/xmlns:xlink/g, 'xmlnsXlink')
.replace(/xlink:href/g, 'xlinkHref')
}
function mapSVGToTemplate(name, svg) {
return `
import React from 'react'
import { IconProps } from './types'
const ${name}: React.FC<IconProps> = ({ ...props }) => (
${svg}
)
export default ${name}
`
}