generate.icons.ts 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { spawn } from 'node:child_process'
  2. import path from 'node:path'
  3. import process from 'node:process'
  4. import * as p from '@clack/prompts'
  5. import { lookupCollection, lookupCollections } from '@iconify/json'
  6. import fs from 'fs-extra'
  7. // 拿到全部图标集的原始数据
  8. const raw = await lookupCollections()
  9. let lastChoose = fs.readFileSync(path.resolve(process.cwd(), 'src/iconify/index.json'), 'utf-8')
  10. lastChoose = JSON.parse(lastChoose)
  11. // 取出可使用的图标集数据用于选择,并按名称排序
  12. const collections = Object.entries(raw).map(([id, item]) => ({
  13. ...item,
  14. id,
  15. })).sort((a, b) => a.name.localeCompare(b.name))
  16. p.intro('图标集生成工具')
  17. /**
  18. * 分别会在对应目录下生成以下文件,其中(1)(3)用于离线下载并安装图标,(2)用于图标选择器使用
  19. * (1) src/iconify/index.json 记录用户交互信息
  20. * (2) src/iconify/data.json 包含多个图标集数据,仅记录图标名
  21. * (3) public/icons/*-raw.json 多个图标集的原始数据,独立存放,用于离线使用
  22. */
  23. const answers = await p.group(
  24. {
  25. collections: () =>
  26. p.multiselect({
  27. message: '请选择需要生成的图标集',
  28. options: collections.map(item => ({
  29. label: item.name,
  30. value: item.id,
  31. hint: `${item.total} 个图标`,
  32. })),
  33. initialValues: lastChoose.collections,
  34. }),
  35. isOfflineUse: () =>
  36. p.confirm({
  37. message: '是否需要离线使用',
  38. initialValue: false,
  39. }),
  40. },
  41. {
  42. onCancel: () => {
  43. p.cancel('操作已取消')
  44. process.exit(0)
  45. },
  46. },
  47. )
  48. const spinner = p.spinner()
  49. spinner.start('正在生成图标集...')
  50. await fs.writeJSON(
  51. path.resolve(process.cwd(), 'src/iconify/index.json'),
  52. {
  53. collections: answers.collections,
  54. isOfflineUse: answers.isOfflineUse,
  55. },
  56. )
  57. const outputDir = path.resolve(process.cwd(), 'public/icons')
  58. await fs.ensureDir(outputDir)
  59. await fs.emptyDir(outputDir)
  60. const collectionsMeta: object[] = []
  61. for (const info of answers.collections) {
  62. const setData = await lookupCollection(info)
  63. collectionsMeta.push({
  64. prefix: setData.prefix,
  65. info: setData.info,
  66. icons: Object.keys(setData.icons),
  67. })
  68. const offlineFilePath = path.join(outputDir, `${info}-raw.json`)
  69. if (answers.isOfflineUse) {
  70. await fs.writeJSON(offlineFilePath, setData)
  71. }
  72. }
  73. await fs.writeJSON(
  74. path.resolve(process.cwd(), 'src/iconify/data.json'),
  75. collectionsMeta,
  76. )
  77. // 使用 spawn 运行 eslint
  78. const eslint = spawn('eslint', ['src/iconify/data.json', 'src/iconify/index.json', '--cache', '--fix'], {
  79. stdio: 'inherit',
  80. shell: true,
  81. })
  82. eslint.on('error', (err) => {
  83. p.log.error(`ESLint 执行失败: ${err.message}`)
  84. process.exit(1)
  85. })
  86. eslint.on('close', (code) => {
  87. if (code !== 0) {
  88. p.log.error(`ESLint 执行失败,退出码: ${code}`)
  89. process.exit(code)
  90. }
  91. spinner.stop('图标集生成完成!')
  92. })