utils.ts 5.2 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1
import fs from 'fs'
fxy060608's avatar
fxy060608 已提交
2 3
import os from 'os'
import path from 'path'
fxy060608's avatar
fxy060608 已提交
4
import colors from 'picocolors'
fxy060608's avatar
fxy060608 已提交
5
import { camelize, capitalize } from '@vue/shared'
fxy060608's avatar
fxy060608 已提交
6
export { default as hash } from 'hash-sum'
fxy060608's avatar
fxy060608 已提交
7 8 9 10 11 12 13
import {
  EXTNAME_TS_RE,
  PAGE_EXTNAME,
  PAGE_EXTNAME_APP,
  X_PAGE_EXTNAME,
  X_PAGE_EXTNAME_APP,
} from './constants'
fxy060608's avatar
fxy060608 已提交
14

15 16 17 18 19 20
import {
  NodeTypes,
  ElementNode,
  RootNode,
  TemplateChildNode,
} from '@vue/compiler-core'
fxy060608's avatar
fxy060608 已提交
21
import { ParserPlugin } from '@babel/parser'
fxy060608's avatar
fxy060608 已提交
22
import { getPlatformDir } from './platform'
fxy060608's avatar
fxy060608 已提交
23
import { isInHBuilderX } from './hbx'
fxy060608's avatar
fxy060608 已提交
24

fxy060608's avatar
fxy060608 已提交
25 26
export const version = require('../package.json').version

fxy060608's avatar
fxy060608 已提交
27 28 29
// 专为 uts.ts 服务
export { camelize, capitalize, isArray } from '@vue/shared'

fxy060608's avatar
fxy060608 已提交
30 31 32 33 34
export let isRunningWithYarnPnp: boolean
try {
  isRunningWithYarnPnp = Boolean(require('pnpapi'))
} catch {}

35
export const isWindows = os.platform() === 'win32'
fxy060608's avatar
fxy060608 已提交
36
export function normalizePath(id: string): string {
37
  return isWindows ? id.replace(/\\/g, '/') : id
fxy060608's avatar
fxy060608 已提交
38
}
fxy060608's avatar
fxy060608 已提交
39

雪洛's avatar
雪洛 已提交
40
export function checkElementNodeTag(
41
  node: RootNode | TemplateChildNode | null | undefined,
雪洛's avatar
雪洛 已提交
42 43
  tag: string
): node is ElementNode {
44
  return !!node && node.type === NodeTypes.ELEMENT && node.tag === tag
雪洛's avatar
雪洛 已提交
45 46
}

fxy060608's avatar
fxy060608 已提交
47 48 49
export function normalizeIdentifier(str: string) {
  return capitalize(camelize(str.replace(/\//g, '-')))
}
fxy060608's avatar
fxy060608 已提交
50 51

export function normalizePagePath(pagePath: string, platform: UniApp.PLATFORM) {
fxy060608's avatar
fxy060608 已提交
52
  const absolutePagePath = path.resolve(process.env.UNI_INPUT_DIR, pagePath)
fxy060608's avatar
fxy060608 已提交
53 54
  const isX = process.env.UNI_APP_X === 'true'
  let extensions = isX ? X_PAGE_EXTNAME : PAGE_EXTNAME
fxy060608's avatar
fxy060608 已提交
55
  if (platform === 'app') {
fxy060608's avatar
fxy060608 已提交
56
    extensions = isX ? X_PAGE_EXTNAME_APP : PAGE_EXTNAME_APP
fxy060608's avatar
fxy060608 已提交
57
  }
fxy060608's avatar
fxy060608 已提交
58 59 60
  for (let i = 0; i < extensions.length; i++) {
    const extname = extensions[i]
    if (fs.existsSync(absolutePagePath + extname)) {
fxy060608's avatar
fxy060608 已提交
61 62 63 64 65
      return pagePath + extname
    }
  }
  console.error(`${pagePath} not found`)
}
fxy060608's avatar
fxy060608 已提交
66

fxy060608's avatar
fxy060608 已提交
67 68
export function removeExt(str: string) {
  return str.split('?')[0].replace(/\.\w+$/g, '')
fxy060608's avatar
fxy060608 已提交
69
}
fxy060608's avatar
fxy060608 已提交
70 71 72 73 74 75

const NODE_MODULES_REGEX = /(\.\.\/)?node_modules/g

export function normalizeNodeModules(str: string) {
  str = normalizePath(str).replace(NODE_MODULES_REGEX, 'node-modules')
  // HBuilderX 内置模块路径转换
fxy060608's avatar
fxy060608 已提交
76 77 78 79
  str = str.replace(
    /.*\/plugins\/uniapp-cli-vite\/node[-_]modules/,
    'node-modules'
  )
fxy060608's avatar
fxy060608 已提交
80 81 82 83 84 85 86 87 88 89
  if (!isInHBuilderX()) {
    // 内部测试
    if (str.includes('uni-app-next/packages/')) {
      str = str.replace(
        /.*\/uni-app-next\/packages\//,
        'node-modules/@dcloudio/'
      )
    }
  }

fxy060608's avatar
fxy060608 已提交
90 91 92 93 94
  if (process.env.UNI_PLATFORM === 'mp-alipay') {
    str = str.replace('node-modules/@', 'node-modules/npm-scope-')
  }
  return str
}
fxy060608's avatar
fxy060608 已提交
95 96 97 98 99

export function normalizeMiniProgramFilename(
  filename: string,
  inputDir?: string
) {
fxy060608's avatar
fxy060608 已提交
100
  if (!inputDir || !path.isAbsolute(filename)) {
fxy060608's avatar
fxy060608 已提交
101 102 103 104
    return normalizeNodeModules(filename)
  }
  return normalizeNodeModules(path.relative(inputDir, filename))
}
fxy060608's avatar
fxy060608 已提交
105 106 107 108 109 110 111 112 113 114 115 116 117 118

export function normalizeParsePlugins(
  importer: string,
  babelParserPlugins?: ParserPlugin[]
) {
  const isTS = EXTNAME_TS_RE.test(importer.split('?')[0])
  const plugins: ParserPlugin[] = []
  if (isTS) {
    plugins.push('jsx')
  }
  if (babelParserPlugins) plugins.push(...babelParserPlugins)
  if (isTS) plugins.push('typescript', 'decorators-legacy')
  return plugins
}
Q
qiang 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134

export function pathToGlob(
  pathString: string,
  glob: string,
  options: { windows?: boolean; escape?: boolean } = {}
): string {
  const isWindows =
    'windows' in options ? options.windows : /^win/.test(process.platform)
  const useEscape = options.escape
  const str = isWindows ? pathString.replace(/\\/g, '/') : pathString
  let safeStr = str.replace(
    /[\\*?[\]{}()!]/g,
    isWindows || !useEscape ? '[$&]' : '\\$&'
  )
  return path.posix.join(safeStr, glob)
}
fxy060608's avatar
fxy060608 已提交
135

fxy060608's avatar
fxy060608 已提交
136 137 138 139
export function resolveSourceMapPath(
  outputDir?: string,
  platform?: UniApp.PLATFORM
) {
fxy060608's avatar
fxy060608 已提交
140
  return path.resolve(
fxy060608's avatar
fxy060608 已提交
141 142
    outputDir || process.env.UNI_OUTPUT_DIR,
    '../.sourcemap/' + (platform || getPlatformDir())
fxy060608's avatar
fxy060608 已提交
143
  )
fxy060608's avatar
fxy060608 已提交
144
}
fxy060608's avatar
fxy060608 已提交
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

function hasProjectYarn(cwd: string) {
  return fs.existsSync(path.join(cwd, 'yarn.lock'))
}

function hasProjectPnpm(cwd: string) {
  return fs.existsSync(path.join(cwd, 'pnpm-lock.yaml'))
}

function getInstallCommand(cwd: string) {
  return hasProjectYarn(cwd)
    ? 'yarn add'
    : hasProjectPnpm(cwd)
    ? 'pnpm i'
    : 'npm i'
}

export function installDepTips(
  type: 'dependencies' | 'devDependencies',
  module: string,
  version?: string
) {
  return `Cannot find module: ${module}
Please run \`${colors.cyan(
    `${getInstallCommand(process.cwd())} ${
      module + (version ? '@' + version : '')
    }${type === 'devDependencies' ? ' -D' : ''}`
  )}\` and try again.`
}
fxy060608's avatar
fxy060608 已提交
174 175 176 177 178 179 180 181 182 183 184 185

export function isAppVue(filename: string) {
  return filename.endsWith('App.vue') || filename.endsWith('App.uvue')
}

export function resolveAppVue(inputDir: string) {
  const appUVue = path.resolve(inputDir, 'App.uvue')
  if (fs.existsSync(appUVue)) {
    return normalizePath(appUVue)
  }
  return normalizePath(path.resolve(inputDir, 'App.vue'))
}
186 187 188 189 190 191 192 193 194 195 196 197

export function parseImporter(importer: string) {
  importer = importer.split('?')[0]
  if (path.isAbsolute(importer)) {
    return normalizePath(path.relative(process.env.UNI_INPUT_DIR, importer))
  }
  return importer
}

export function createResolveErrorMsg(source: string, importer: string) {
  return `Could not resolve "${source}" from "${parseImporter(importer)}"`
}