Skip to content

Commit dbe7109

Browse files
committed
build: improve dts rollup output
1 parent 2774ba5 commit dbe7109

File tree

4 files changed

+132
-8
lines changed

4 files changed

+132
-8
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
"esbuild": "^0.17.4",
7878
"eslint": "^8.33.0",
7979
"eslint-plugin-jest": "^27.2.1",
80+
"estree-walker": "^2.0.2",
8081
"execa": "^4.0.2",
8182
"jsdom": "^21.1.0",
8283
"lint-staged": "^10.2.10",

pnpm-lock.yaml

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rollup.dts.config.js

Lines changed: 123 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// @ts-check
2+
import { parse } from '@babel/parser'
23
import { existsSync, readdirSync, readFileSync } from 'fs'
4+
import MagicString from 'magic-string'
35
import dts from 'rollup-plugin-dts'
6+
import { walk } from 'estree-walker'
47

58
if (!existsSync('temp/packages')) {
69
console.warn(
@@ -31,14 +34,132 @@ export default readdirSync('temp/packages').map(pkg => {
3134
})
3235

3336
/**
37+
* Patch the dts generated by rollup-plugin-dts
38+
* 1. remove exports marked as @internal
39+
* 2. Convert all types to inline exports
40+
* and remove them from the big export {} declaration
41+
* otherwise it gets weird in vitepress `defineComponent` call with
42+
* "the inferred type cannot be named without a reference"
43+
* 3. Append custom agumentations (jsx, macros)
3444
* @returns {import('rollup').Plugin}
3545
*/
3646
function patchTypes(pkg) {
3747
return {
3848
name: 'patch-types',
3949
renderChunk(code) {
40-
// 1. TODO remove entries marked with @private
41-
// 2. append pkg specific types
50+
const s = new MagicString(code)
51+
const ast = parse(code, {
52+
plugins: ['typescript'],
53+
sourceType: 'module'
54+
})
55+
56+
/**
57+
* @param {import('@babel/types').Node} node
58+
* @returns {boolean}
59+
*/
60+
function removeInternal(node) {
61+
if (
62+
node.leadingComments &&
63+
node.leadingComments.some(c => {
64+
return c.type === 'CommentBlock' && /@internal\b/.test(c.value)
65+
})
66+
) {
67+
/** @type {any} */
68+
const n = node
69+
let id
70+
if (n.id && n.id.type === 'Identifier') {
71+
id = n.id.name
72+
} else if (n.key && n.key.type === 'Identifier') {
73+
id = n.key.name
74+
}
75+
if (id) {
76+
s.overwrite(
77+
// @ts-ignore
78+
node.leadingComments[0].start,
79+
node.end,
80+
`/* removed internal: ${id} */`
81+
)
82+
} else {
83+
// @ts-ignore
84+
s.remove(node.leadingComments[0].start, node.end)
85+
}
86+
return true
87+
}
88+
return false
89+
}
90+
91+
const shouldRemoveExport = new Set()
92+
// pass 1: remove internals + add exports
93+
for (const node of ast.program.body) {
94+
if (
95+
(node.type === 'TSTypeAliasDeclaration' ||
96+
node.type === 'TSInterfaceDeclaration') &&
97+
!node.id.name.startsWith(`_`)
98+
) {
99+
shouldRemoveExport.add(node.id.name)
100+
if (!removeInternal(node)) {
101+
// @ts-ignore
102+
s.prependLeft(node.start, `export `)
103+
// traverse further for internal properties
104+
if (node.type === 'TSInterfaceDeclaration') {
105+
node.body.body.forEach(removeInternal)
106+
} else if (node.type === 'TSTypeAliasDeclaration') {
107+
// @ts-ignore
108+
walk(node.typeAnnotation, {
109+
enter(node) {
110+
// @ts-ignore
111+
if (removeInternal(node)) this.skip()
112+
}
113+
})
114+
}
115+
}
116+
} else if (removeInternal(node)) {
117+
if (node.type === 'VariableDeclaration') {
118+
// declare const x
119+
for (const decl of node.declarations) {
120+
// @ts-ignore
121+
shouldRemoveExport.add(decl.id.name)
122+
}
123+
} else if (
124+
node.type === 'TSDeclareFunction' ||
125+
node.type === 'TSEnumDeclaration'
126+
) {
127+
// declare function
128+
// @ts-ignore
129+
shouldRemoveExport.add(node.id.name)
130+
} else {
131+
throw new Error(
132+
`unhandled export type marked as @internal: ${node.type}`
133+
)
134+
}
135+
}
136+
}
137+
// pass 2: remove exports
138+
for (const node of ast.program.body) {
139+
if (node.type === 'ExportNamedDeclaration' && !node.source) {
140+
for (let i = 0; i < node.specifiers.length; i++) {
141+
const spec = node.specifiers[i]
142+
if (
143+
spec.type === 'ExportSpecifier' &&
144+
shouldRemoveExport.has(spec.local.name)
145+
) {
146+
const next = node.specifiers[i + 1]
147+
if (next) {
148+
// @ts-ignore
149+
s.remove(spec.start, next.start)
150+
} else {
151+
// last one
152+
const prev = node.specifiers[i - 1]
153+
// @ts-ignore
154+
s.remove(prev ? prev.end : spec.start, spec.end)
155+
}
156+
}
157+
}
158+
}
159+
}
160+
code = s.toString()
161+
162+
// append pkg specific types
42163
const additionalTypeDir = `packages/${pkg}/types`
43164
if (existsSync(additionalTypeDir)) {
44165
code +=

scripts/const-enum.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,15 @@ export async function constEnum() {
192192
spec.exportKind !== 'type' &&
193193
knowEnums.has(spec.local.name)
194194
) {
195-
if (i === 0) {
196-
// first
197-
const next = node.specifiers[i + 1]
195+
const next = node.specifiers[i + 1]
196+
if (next) {
198197
// @ts-ignore
199-
s.remove(spec.start, next ? next.start : spec.end)
198+
s.remove(spec.start, next.start)
200199
} else {
201-
// locate the end of prev
200+
// last one
201+
const prev = node.specifiers[i - 1]
202202
// @ts-ignore
203-
s.remove(node.specifiers[i - 1].end, spec.end)
203+
s.remove(prev ? prev.end : spec.start, spec.end)
204204
}
205205
}
206206
}

0 commit comments

Comments
 (0)