build: improve dts rollup output

This commit is contained in:
Evan You 2023-02-04 11:59:42 +08:00
parent 2774ba5f0f
commit dbe7109c8f
4 changed files with 132 additions and 8 deletions

View File

@ -77,6 +77,7 @@
"esbuild": "^0.17.4",
"eslint": "^8.33.0",
"eslint-plugin-jest": "^27.2.1",
"estree-walker": "^2.0.2",
"execa": "^4.0.2",
"jsdom": "^21.1.0",
"lint-staged": "^10.2.10",

View File

@ -26,6 +26,7 @@ importers:
esbuild: ^0.17.4
eslint: ^8.33.0
eslint-plugin-jest: ^27.2.1
estree-walker: ^2.0.2
execa: ^4.0.2
jsdom: ^21.1.0
lint-staged: ^10.2.10
@ -75,6 +76,7 @@ importers:
esbuild: 0.17.5
eslint: 8.33.0
eslint-plugin-jest: 27.2.1_4vsywjlpuriuw3tl5oq6zy5a64
estree-walker: 2.0.2
execa: 4.1.0
jsdom: 21.1.0
lint-staged: 10.5.4

View File

@ -1,6 +1,9 @@
// @ts-check
import { parse } from '@babel/parser'
import { existsSync, readdirSync, readFileSync } from 'fs'
import MagicString from 'magic-string'
import dts from 'rollup-plugin-dts'
import { walk } from 'estree-walker'
if (!existsSync('temp/packages')) {
console.warn(
@ -31,14 +34,132 @@ export default readdirSync('temp/packages').map(pkg => {
})
/**
* Patch the dts generated by rollup-plugin-dts
* 1. remove exports marked as @internal
* 2. Convert all types to inline exports
* and remove them from the big export {} declaration
* otherwise it gets weird in vitepress `defineComponent` call with
* "the inferred type cannot be named without a reference"
* 3. Append custom agumentations (jsx, macros)
* @returns {import('rollup').Plugin}
*/
function patchTypes(pkg) {
return {
name: 'patch-types',
renderChunk(code) {
// 1. TODO remove entries marked with @private
// 2. append pkg specific types
const s = new MagicString(code)
const ast = parse(code, {
plugins: ['typescript'],
sourceType: 'module'
})
/**
* @param {import('@babel/types').Node} node
* @returns {boolean}
*/
function removeInternal(node) {
if (
node.leadingComments &&
node.leadingComments.some(c => {
return c.type === 'CommentBlock' && /@internal\b/.test(c.value)
})
) {
/** @type {any} */
const n = node
let id
if (n.id && n.id.type === 'Identifier') {
id = n.id.name
} else if (n.key && n.key.type === 'Identifier') {
id = n.key.name
}
if (id) {
s.overwrite(
// @ts-ignore
node.leadingComments[0].start,
node.end,
`/* removed internal: ${id} */`
)
} else {
// @ts-ignore
s.remove(node.leadingComments[0].start, node.end)
}
return true
}
return false
}
const shouldRemoveExport = new Set()
// pass 1: remove internals + add exports
for (const node of ast.program.body) {
if (
(node.type === 'TSTypeAliasDeclaration' ||
node.type === 'TSInterfaceDeclaration') &&
!node.id.name.startsWith(`_`)
) {
shouldRemoveExport.add(node.id.name)
if (!removeInternal(node)) {
// @ts-ignore
s.prependLeft(node.start, `export `)
// traverse further for internal properties
if (node.type === 'TSInterfaceDeclaration') {
node.body.body.forEach(removeInternal)
} else if (node.type === 'TSTypeAliasDeclaration') {
// @ts-ignore
walk(node.typeAnnotation, {
enter(node) {
// @ts-ignore
if (removeInternal(node)) this.skip()
}
})
}
}
} else if (removeInternal(node)) {
if (node.type === 'VariableDeclaration') {
// declare const x
for (const decl of node.declarations) {
// @ts-ignore
shouldRemoveExport.add(decl.id.name)
}
} else if (
node.type === 'TSDeclareFunction' ||
node.type === 'TSEnumDeclaration'
) {
// declare function
// @ts-ignore
shouldRemoveExport.add(node.id.name)
} else {
throw new Error(
`unhandled export type marked as @internal: ${node.type}`
)
}
}
}
// pass 2: remove exports
for (const node of ast.program.body) {
if (node.type === 'ExportNamedDeclaration' && !node.source) {
for (let i = 0; i < node.specifiers.length; i++) {
const spec = node.specifiers[i]
if (
spec.type === 'ExportSpecifier' &&
shouldRemoveExport.has(spec.local.name)
) {
const next = node.specifiers[i + 1]
if (next) {
// @ts-ignore
s.remove(spec.start, next.start)
} else {
// last one
const prev = node.specifiers[i - 1]
// @ts-ignore
s.remove(prev ? prev.end : spec.start, spec.end)
}
}
}
}
}
code = s.toString()
// append pkg specific types
const additionalTypeDir = `packages/${pkg}/types`
if (existsSync(additionalTypeDir)) {
code +=

View File

@ -192,15 +192,15 @@ export async function constEnum() {
spec.exportKind !== 'type' &&
knowEnums.has(spec.local.name)
) {
if (i === 0) {
// first
const next = node.specifiers[i + 1]
const next = node.specifiers[i + 1]
if (next) {
// @ts-ignore
s.remove(spec.start, next ? next.start : spec.end)
s.remove(spec.start, next.start)
} else {
// locate the end of prev
// last one
const prev = node.specifiers[i - 1]
// @ts-ignore
s.remove(node.specifiers[i - 1].end, spec.end)
s.remove(prev ? prev.end : spec.start, spec.end)
}
}
}