Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

116 строки
3.0 KiB

  1. import { existsSync, readFileSync } from 'node:fs'
  2. import { extname, join } from 'node:path'
  3. import process from 'node:process'
  4. import { parse as VueParser } from 'vue/compiler-sfc'
  5. import { normalizePath } from 'vite'
  6. function stripJsonComments(jsonText) {
  7. return jsonText
  8. .replace(/\/\*[\s\S]*?\*\//g, '')
  9. .replace(/(^|[^:\\])\/\/.*$/gm, '$1')
  10. }
  11. function parseJsonc(jsonText) {
  12. const withoutComments = stripJsonComments(jsonText)
  13. const withoutTrailingComma = withoutComments.replace(/,\s*([}\]])/g, '$1')
  14. return JSON.parse(withoutTrailingComma)
  15. }
  16. export async function parseSFC(code) {
  17. try {
  18. return VueParser(code, { pad: 'space' }).descriptor
  19. } catch {
  20. throw new Error('[@up-root] Vue version must support compiler-sfc parser.')
  21. }
  22. }
  23. const PAGE_FILE_EXTS = ['.vue', '.nvue', '.uvue']
  24. export function formatPagePath(root, path) {
  25. const joinedPath = join(root, path)
  26. const pathExt = extname(joinedPath)
  27. if (pathExt) {
  28. return normalizePath(joinedPath)
  29. }
  30. const pageFilePath = PAGE_FILE_EXTS
  31. .map(fileExt => `${joinedPath}${fileExt}`)
  32. .find(filePath => existsSync(filePath))
  33. return normalizePath(pageFilePath || `${joinedPath}.vue`)
  34. }
  35. export function loadPagesJson(path, rootPath) {
  36. const pagesJsonRaw = readFileSync(path, 'utf-8')
  37. const parsed = parseJsonc(pagesJsonRaw) || {}
  38. const pages = parsed.pages || []
  39. const subPackages = parsed.subPackages || []
  40. return [
  41. ...pages.map((page) => formatPagePath(rootPath, page.path)),
  42. ...subPackages
  43. .map(({ pages: subPages = [], root = '' }) => {
  44. return subPages.map((page) => formatPagePath(join(rootPath, root), page.path))
  45. })
  46. .flat(),
  47. ]
  48. }
  49. export function toKebabCase(str) {
  50. return str
  51. .replace(/([a-z])([A-Z])/g, '$1-$2')
  52. .replace(/[_\s]+/g, '-')
  53. .toLowerCase()
  54. }
  55. export function toPascalCase(str) {
  56. return str
  57. .replace(/(^\w|-+\w)/g, (match) => match.toUpperCase().replace(/-/g, ''))
  58. }
  59. export function findNode(sfc, rawTagName) {
  60. const templateSource = sfc.template?.content
  61. if (!templateSource) return
  62. let tagName = ''
  63. if (templateSource.includes(`<${toKebabCase(rawTagName)}`)) {
  64. tagName = toKebabCase(rawTagName)
  65. } else if (templateSource.includes(`<${toPascalCase(rawTagName)}`)) {
  66. tagName = toPascalCase(rawTagName)
  67. }
  68. if (!tagName) return
  69. const nodeAst = sfc.template?.ast
  70. if (!nodeAst) return
  71. const traverse = (nodes) => {
  72. for (const node of nodes) {
  73. if (node.type === 1) {
  74. if (node.tag === tagName) return node
  75. if (node.children?.length) {
  76. const found = traverse(node.children)
  77. if (found) return found
  78. }
  79. }
  80. }
  81. }
  82. return traverse(nodeAst.children)
  83. }
  84. const platform = process.env.UNI_PLATFORM
  85. export function normalizePlatformPath(id) {
  86. const idExt = extname(id)
  87. if (idExt !== '.vue') return id
  88. if (!id.includes(`.${platform}.`)) return id
  89. return id.replace(`.${platform}.`, '.')
  90. }
  91. export function toArray(value) {
  92. if (!value) return []
  93. return Array.isArray(value) ? value : [value]
  94. }