|
1 | 1 | import fs from 'fs-extra'
|
2 |
| -import { BUNDLED_LANGUAGES, BUNDLED_THEMES } from 'shiki' |
3 |
| -import fg from 'fast-glob' |
4 |
| - |
5 |
| -const allLangFiles = await fg('*.json', { |
6 |
| - cwd: './node_modules/shiki/languages', |
7 |
| - absolute: true, |
8 |
| - onlyFiles: true, |
9 |
| -}) |
10 |
| - |
11 |
| -const comments = ` |
12 |
| -/** |
13 |
| - * Generated by scripts/prepare.ts |
14 |
| - */ |
15 |
| -`.trim() |
| 2 | +import { prepareLangs } from './prepare/langs' |
| 3 | +import { prepareTheme } from './prepare/themes' |
16 | 4 |
|
17 | 5 | await fs.ensureDir('./src/assets/langs')
|
18 | 6 | await fs.emptyDir('./src/assets/langs')
|
19 |
| - |
20 |
| -allLangFiles.sort() |
21 |
| -for (const file of allLangFiles) { |
22 |
| - const content = await fs.readJSON(file) |
23 |
| - const lang = BUNDLED_LANGUAGES.find(i => i.id === content.name) |
24 |
| - if (!lang) { |
25 |
| - console.warn(`unknown ${content.name}`) |
26 |
| - continue |
27 |
| - } |
28 |
| - |
29 |
| - const json = { |
30 |
| - ...content, |
31 |
| - name: content.name || lang.id, |
32 |
| - scopeName: content.scopeName || lang.scopeName, |
33 |
| - displayName: lang.displayName, |
34 |
| - aliases: lang.aliases, |
35 |
| - embeddedLangs: lang.embeddedLangs, |
36 |
| - balancedBracketSelectors: lang.balancedBracketSelectors, |
37 |
| - unbalancedBracketSelectors: lang.unbalancedBracketSelectors, |
38 |
| - } |
39 |
| - |
40 |
| - // F# and Markdown has circular dependency |
41 |
| - if (lang.id === 'fsharp') |
42 |
| - json.embeddedLangs = json.embeddedLangs.filter((i: string) => i !== 'markdown') |
43 |
| - |
44 |
| - const embedded = (json.embeddedLangs || []) as string[] |
45 |
| - |
46 |
| - await fs.writeFile(`./src/assets/langs/${lang.id}.ts`, `${comments} |
47 |
| -import type { LanguageRegistration } from 'shikiji-core' |
48 |
| -
|
49 |
| -${embedded.map(i => `import ${i.replace(/[^\w]/g, '_')} from './${i}'`).join('\n')} |
50 |
| -
|
51 |
| -const lang = Object.freeze(${JSON.stringify(json)}) as unknown as LanguageRegistration |
52 |
| -
|
53 |
| -export default [ |
54 |
| -${[ |
55 |
| - ...embedded.map(i => ` ...${i.replace(/[^\w]/g, '_')}`), |
56 |
| - ' lang', |
57 |
| -].join(',\n') || ''} |
58 |
| -] |
59 |
| -`, 'utf-8') |
60 |
| -} |
61 |
| - |
62 |
| -async function writeLanguageBundleIndex(fileName: string, ids: string[]) { |
63 |
| - const bundled = ids.map(id => BUNDLED_LANGUAGES.find(i => i.id === id)!) |
64 |
| - |
65 |
| - const info = bundled.map(i => ({ |
66 |
| - id: i.id, |
67 |
| - name: i.displayName, |
68 |
| - aliases: i.aliases, |
69 |
| - import: `__(() => import('./langs/${i.id}')) as DynamicLangReg__`, |
70 |
| - }) as const) |
71 |
| - .sort((a, b) => a.id.localeCompare(b.id)) |
72 |
| - |
73 |
| - const type = info.flatMap(i => [...i.aliases || [], i.id]).sort().map(i => `'${i}'`).join(' | ') |
74 |
| - |
75 |
| - await fs.writeFile( |
76 |
| - `src/assets/${fileName}.ts`, |
77 |
| - `${comments} |
78 |
| -import type { LanguageRegistration } from 'shikiji-core' |
79 |
| -
|
80 |
| -type DynamicLangReg = () => Promise<{ default: LanguageRegistration[] }> |
81 |
| -
|
82 |
| -export interface BundledLanguageInfo { |
83 |
| - id: string |
84 |
| - name: string |
85 |
| - import: DynamicLangReg |
86 |
| - aliases?: string[] |
87 |
| -} |
88 |
| -
|
89 |
| -export const bundledLanguagesInfo: BundledLanguageInfo[] = ${JSON.stringify(info, null, 2).replace(/"__|__"/g, '').replace(/"/g, '\'')} |
90 |
| -
|
91 |
| -export const bundledLanguagesBase = Object.fromEntries(bundledLanguagesInfo.map(i => [i.id, i.import])) |
92 |
| -
|
93 |
| -export const bundledLanguagesAlias = Object.fromEntries(bundledLanguagesInfo.flatMap(i => i.aliases?.map(a => [a, i.import]) || [])) |
94 |
| -
|
95 |
| -export type BuiltinLanguage = ${type} |
96 |
| -
|
97 |
| -export const bundledLanguages = { |
98 |
| - ...bundledLanguagesBase, |
99 |
| - ...bundledLanguagesAlias, |
100 |
| -} as Record<BuiltinLanguage, DynamicLangReg> |
101 |
| -`, |
102 |
| - 'utf-8', |
103 |
| - ) |
104 |
| - |
105 |
| - await fs.writeJSON( |
106 |
| - `src/assets/${fileName}.json`, |
107 |
| - BUNDLED_LANGUAGES.map(i => ({ |
108 |
| - id: i.id, |
109 |
| - name: i.displayName, |
110 |
| - aliases: i.aliases, |
111 |
| - })), |
112 |
| - { spaces: 2 }, |
113 |
| - ) |
114 |
| -} |
115 |
| - |
116 |
| -await writeLanguageBundleIndex('langs', BUNDLED_LANGUAGES.map(i => i.id)) |
117 |
| -// await writeLanguageBundleIndex('langs-common', BundleCommonLangs) |
118 |
| - |
119 |
| -const themes = BUNDLED_THEMES.sort() |
120 |
| - .filter(i => i !== 'css-variables') |
121 |
| - .map((id) => { |
122 |
| - const theme = fs.readJSONSync(`./node_modules/shiki/themes/${id}.json`) |
123 |
| - |
124 |
| - return { |
125 |
| - id, |
126 |
| - name: guessThemeName(id, theme), |
127 |
| - type: guessThemeType(id, theme), |
128 |
| - import: `__(() => import('shiki/themes/${id}.json')) as unknown as DynamicThemeReg__`, |
129 |
| - } |
130 |
| - }) |
131 |
| - |
132 |
| -await fs.writeFile( |
133 |
| - 'src/assets/themes.ts', |
134 |
| - `${comments} |
135 |
| -import type { ThemeRegistrationRaw } from 'shikiji-core' |
136 |
| -
|
137 |
| -type DynamicThemeReg = () => Promise<{ default: ThemeRegistrationRaw }> |
138 |
| -
|
139 |
| -export interface BundledThemeInfo { |
140 |
| - id: string |
141 |
| - name: string |
142 |
| - type: 'light' | 'dark' |
143 |
| - import: DynamicThemeReg |
144 |
| -} |
145 |
| -
|
146 |
| -export const bundledThemesInfo: BundledThemeInfo[] = ${JSON.stringify(themes, null, 2).replace(/"__|__"/g, '')} |
147 |
| -
|
148 |
| -export type BuiltinTheme = ${themes.map(i => `'${i.id}'`).join(' | ')} |
149 |
| -
|
150 |
| -export const bundledThemes = Object.fromEntries(bundledThemesInfo.map(i => [i.id, i.import])) as Record<BuiltinTheme, DynamicThemeReg> |
151 |
| -`, |
152 |
| - 'utf-8', |
153 |
| -) |
154 |
| - |
155 |
| -await fs.writeJSON( |
156 |
| - 'src/assets/themes.json', |
157 |
| - BUNDLED_THEMES |
158 |
| - .filter(i => i !== 'css-variables') |
159 |
| - .map(i => ({ |
160 |
| - id: i, |
161 |
| - })), |
162 |
| - { spaces: 2 }, |
163 |
| -) |
164 |
| - |
165 |
| -function isLightColor(hex: string) { |
166 |
| - const [r, g, b] = hex.slice(1).match(/.{2}/g)!.map(i => Number.parseInt(i, 16)) |
167 |
| - return (r * 299 + g * 587 + b * 114) / 1000 > 128 |
168 |
| -} |
169 |
| - |
170 |
| -function guessThemeType(id: string, theme: any) { |
171 |
| - let color |
172 |
| - if (id.includes('dark') || id.includes('dimmed') || id.includes('black')) |
173 |
| - color = 'dark' |
174 |
| - else if (id.includes('light') || id.includes('white') || id === 'slack-ochin') |
175 |
| - color = 'light' |
176 |
| - else if (theme.colors.background) |
177 |
| - color = isLightColor(theme.colors.background) ? 'light' : 'dark' |
178 |
| - else if (theme.colors['editor.background']) |
179 |
| - color = isLightColor(theme.colors['editor.background']) ? 'light' : 'dark' |
180 |
| - else if (theme.colors.foreground) |
181 |
| - color = isLightColor(theme.colors.foreground) ? 'dark' : 'light' |
182 |
| - else |
183 |
| - color = 'light' |
184 |
| - return color |
185 |
| -} |
186 |
| - |
187 |
| -function guessThemeName(id: string, theme: any) { |
188 |
| - if (theme.displayName) |
189 |
| - return theme.displayName |
190 |
| - let name: string = theme.name || id |
191 |
| - name = name.split(/[_-]/).map(i => i[0].toUpperCase() + i.slice(1)).join(' ') |
192 |
| - name = name.replace(/github/ig, 'GitHub') |
193 |
| - return name |
194 |
| -} |
| 7 | +await prepareLangs() |
| 8 | +await prepareTheme() |
0 commit comments