imports.ts 1.8 KB
Newer Older
1 2 3 4
import path from 'path'
import { PluginContext } from 'rollup'
import { init, parse as parseImports, ImportSpecifier } from 'es-module-lexer'
import { extend } from '@vue/shared'
5 6
import { isImportDeclaration, isImportDefaultSpecifier } from '@babel/types'
import { parse } from '@babel/parser'
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
import { EXTNAME_VUE, EXTNAME_VUE_RE } from '../constants'

export async function findVueComponentImports(
  source: string,
  importer: string,
  resolve: PluginContext['resolve']
) {
  await init
  let imports: readonly ImportSpecifier[] = []
  // strip UTF-8 BOM
  if (source.charCodeAt(0) === 0xfeff) {
    source = source.slice(1)
  }
  try {
    imports = parseImports(source)[0]
  } catch (e: any) {
    console.error(e)
  }
  if (!imports.length) {
    return []
  }

29
  const rewriteImports: (ImportSpecifier & { i: string })[] = []
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
  for (let i = 0; i < imports.length; i++) {
    const importSpecifier = imports[i]
    const { n } = importSpecifier
    if (!n) {
      continue
    }
    const extname = path.extname(n)
    // 仅处理没有后缀,或后缀是.vue,.nvue的文件
    if (extname && !EXTNAME_VUE.includes(extname)) {
      continue
    }
    const res = await resolve(n, importer)
    if (!res) {
      continue
    }
    if (EXTNAME_VUE_RE.test(res.id)) {
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
      const expr = parse(source.slice(importSpecifier.ss, importSpecifier.se), {
        sourceType: 'module',
      }).program.body[0]
      if (isImportDeclaration(expr) && expr.specifiers.length === 1) {
        const importDefaultSpecifier = expr.specifiers[0]
        if (!isImportDefaultSpecifier(importDefaultSpecifier)) {
          continue
        }
        rewriteImports.push(
          extend(importSpecifier, {
            n: res.id,
            i: importDefaultSpecifier.local.name,
          })
        )
      }
61 62 63 64
    }
  }
  return rewriteImports
}