CI / docs-check (push) Canceled after 0s
CI / backend-test (push) Canceled after 0s
CI / service-test (push) Canceled after 0s
CI / frontend-test (push) Canceled after 0s
CI / rust-core (push) Canceled after 0s
CI / docs-check (pull_request) Canceled after 0s
CI / backend-test (pull_request) Canceled after 0s
CI / service-test (pull_request) Canceled after 0s
CI / frontend-test (pull_request) Canceled after 0s
CI / rust-core (pull_request) Canceled after 0s
46 lines
2.9 KiB
JavaScript
46 lines
2.9 KiB
JavaScript
// 用法:node scripts/generate-language-icons.mjs /path/to/@iconify-json/vscode-icons
|
||
// 来源:@iconify-json/vscode-icons 1.2.76(MIT);运行时不会发起网络请求。
|
||
import { readFileSync, writeFileSync } from 'node:fs'
|
||
import { resolve } from 'node:path'
|
||
import { bundledLanguagesInfo } from 'shiki/langs'
|
||
|
||
const source = process.argv[2]
|
||
if (!source) throw new Error('Provide the extracted vscode-icons package directory')
|
||
const data = JSON.parse(readFileSync(resolve(source, 'icons.json'), 'utf8'))
|
||
const overrides = {
|
||
ahk: 'autohotkey', ahk2: 'autohotkey', asm: 'assembly', bat: 'bat',
|
||
'angular-html': 'angular', 'angular-ts': 'angular',
|
||
'common-lisp': 'lisp', 'emacs-lisp': 'lisp',
|
||
'fortran-fixed-form': 'fortran', 'fortran-free-form': 'fortran',
|
||
'git-commit': 'git', 'git-rebase': 'git',
|
||
jsonc: 'json', jsonl: 'json', shellscript: 'shell', shellsession: 'shell',
|
||
jsx: 'reactjs', tsx: 'reactts', latex: 'tex', bibtex: 'bibtex',
|
||
'objective-c': 'objectivec', 'objective-cpp': 'objectivecpp',
|
||
dart: 'dartlang', d: 'dlang', v: 'vlang', gdshader: 'godot',
|
||
fish: 'shell', 'ssh-config': 'shell', 'vue-html': 'vue', 'vue-vine': 'vue',
|
||
'html-derivative': 'html', qss: 'qt', rbs: 'ruby',
|
||
}
|
||
const groups = new Map()
|
||
const unmatched = []
|
||
for (const info of [...bundledLanguagesInfo, { id: 'text', name: 'Text' }]) {
|
||
const candidates = [overrides[info.id], info.id, ...(info.aliases ?? []), info.name.toLowerCase().replace(/\s+/g, '')].filter(Boolean)
|
||
const icon = candidates.map(name => `file-type-${name}`).find(name => data.icons[name])
|
||
if (!icon) { unmatched.push(info.id); continue }
|
||
const ids = groups.get(icon) ?? []
|
||
ids.push(info.id)
|
||
groups.set(icon, ids)
|
||
}
|
||
const base = '.milkdown-host .language-list-item[data-language]'
|
||
const svgUrl = icon => {
|
||
const item = data.icons[icon]
|
||
const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${item.width ?? data.width ?? 32} ${item.height ?? data.height ?? 32}">${item.body}</svg>`
|
||
return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`
|
||
}
|
||
let css = `/* 由 scripts/generate-language-icons.mjs 自动生成。VSCode Icons 采用 MIT 许可证;详情见 language-icons-LICENSE.txt。 */\n${base} { display: flex; align-items: center; gap: 8px; }\n${base}::before { content: ''; flex: 0 0 20px; width: 20px; height: 20px; background: center / contain no-repeat ${svgUrl('default-file')}; }\n`
|
||
for (const [icon, ids] of groups) {
|
||
css += ids.map(id => `${base}[data-language="${id}"]::before`).join(',\n') + ` { background-image: ${svgUrl(icon)}; }\n`
|
||
}
|
||
writeFileSync(new URL('../src/features/editor/language-icons.css', import.meta.url), css)
|
||
writeFileSync(new URL('../src/features/editor/language-icons-LICENSE.txt', import.meta.url), readFileSync(resolve(source, 'license.txt')))
|
||
console.log(`${bundledLanguagesInfo.length + 1 - unmatched.length} languages mapped; generic file icon for: ${unmatched.join(', ')}`)
|