|
1 | 1 | // @ts-check
|
| 2 | +import { parse } from '@babel/parser' |
2 | 3 | import { existsSync, readdirSync, readFileSync } from 'fs'
|
| 4 | +import MagicString from 'magic-string' |
3 | 5 | import dts from 'rollup-plugin-dts'
|
| 6 | +import { walk } from 'estree-walker' |
4 | 7 |
|
5 | 8 | if (!existsSync('temp/packages')) {
|
6 | 9 | console.warn(
|
@@ -31,14 +34,132 @@ export default readdirSync('temp/packages').map(pkg => {
|
31 | 34 | })
|
32 | 35 |
|
33 | 36 | /**
|
| 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) |
34 | 44 | * @returns {import('rollup').Plugin}
|
35 | 45 | */
|
36 | 46 | function patchTypes(pkg) {
|
37 | 47 | return {
|
38 | 48 | name: 'patch-types',
|
39 | 49 | 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 |
42 | 163 | const additionalTypeDir = `packages/${pkg}/types`
|
43 | 164 | if (existsSync(additionalTypeDir)) {
|
44 | 165 | code +=
|
|
0 commit comments