Skip to content

Commit

Permalink
build: improve dts rollup output
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Feb 4, 2023
1 parent 2774ba5 commit dbe7109
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 8 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

125 changes: 123 additions & 2 deletions rollup.dts.config.js
@@ -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(
Expand Down Expand Up @@ -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 +=
Expand Down
12 changes: 6 additions & 6 deletions scripts/const-enum.js
Expand Up @@ -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)
}
}
}
Expand Down

0 comments on commit dbe7109

Please sign in to comment.