@brillout/docpress 0.15.10-commit-317b144 → 0.15.10-commit-05c2883

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/detypePlugin.ts DELETED
@@ -1,179 +0,0 @@
1
- export { detypePlugin }
2
-
3
- import type { PluginOption } from 'vite'
4
- import module from 'node:module'
5
- import { assertUsage } from './utils/assert.js'
6
- import pc from '@brillout/picocolors'
7
- import { getMagicString } from './utils/getMagicString.js'
8
- // Cannot use `import { transform } from 'detype'` as it results in errors,
9
- // and the package has no default export. Using `module.createRequire` instead.
10
- const { transform: detype } = module.createRequire(import.meta.url)('detype') as typeof import('detype')
11
-
12
- const prettierOptions: NonNullable<Parameters<typeof detype>[2]>['prettierOptions'] = {
13
- semi: false,
14
- singleQuote: true,
15
- printWidth: 100,
16
- trailingComma: 'none',
17
- }
18
- // RegExp to find TypeScript code blocks.
19
- //
20
- // For example:
21
- // ~~~mdx
22
- // ```ts
23
- // const hello: string = 'world'
24
- // ```
25
- // ~~~
26
- //
27
- // But also indented code blocks:
28
- // ~~~mdx
29
- // > Also works:
30
- // > - In blockquotes
31
- // > - In bullet points
32
- // > ```ts
33
- // > const hello: string = 'world'
34
- // > ```
35
- // ~~~
36
- const codeBlockRE = /^(.*)```(tsx?|vue|yaml)[^\n]*\n([\s\S]*?)```/gm
37
-
38
- function detypePlugin(): PluginOption {
39
- return {
40
- name: '@brillout/docpress:detypePlugin',
41
- enforce: 'pre',
42
- transform: async (code: string, moduleId: string) => {
43
- if (!moduleId.endsWith('.mdx')) return
44
- return await transformCode(code, moduleId)
45
- },
46
- }
47
- }
48
-
49
- async function transformCode(code: string, moduleId: string) {
50
- const matches = Array.from(code.matchAll(codeBlockRE))
51
- if (matches.length === 0) return
52
-
53
- const { magicString, getMagicStringResult } = getMagicString(code, moduleId)
54
-
55
- magicString.prepend(`import { CodeSnippets, CodeSnippet } from '@brillout/docpress';\n\n`)
56
-
57
- // [Claude AI] Process matches in reverse order to avoid offset issues
58
- for (let i = matches.length - 1; i >= 0; i--) {
59
- const match = matches[i]
60
- const [codeBlockOuterStr, codeBlockIndent, codeBlockLang, codeBlockContentWithIndent] = match
61
- const isYaml = codeBlockLang === 'yaml'
62
-
63
- // Remove indentation
64
- const codeBlockOpen = codeBlockOuterStr.split('\n')[0].slice(codeBlockIndent.length)
65
- const codeBlockContent = removeCodeBlockIndent(codeBlockContentWithIndent, codeBlockIndent, moduleId)
66
-
67
- let replacement: string
68
- if (codeBlockOpen.includes('ts-only') && !isYaml) {
69
- replacement = `${codeBlockIndent}<CodeSnippet codeLang="ts" tsOnly>\n${codeBlockOuterStr}\n${codeBlockIndent}</CodeSnippet>`
70
- } else {
71
- // someFileName.ts => someFileName.js
72
- let codeBlockContentJs = codeBlockContent.replaceAll('.ts', '.js')
73
- const codeBlockClose = '```'
74
- if (isYaml && codeBlockContentJs === codeBlockContent) {
75
- continue
76
- }
77
-
78
- // Remove TypeScript
79
- if (!isYaml) {
80
- codeBlockContentJs = await detype(codeBlockContentJs, `some-dummy-filename.${codeBlockLang}`, {
81
- customizeBabelConfig(config) {
82
- // Add `onlyRemoveTypeImports: true` to the internal `@babel/preset-typescript` config
83
- // See https://github.com/cyco130/detype/blob/main/src/transform.ts#L206
84
- assertUsage(config.presets && config.presets.length === 1, 'Unexpected Babel config presets')
85
- config.presets = [[config.presets[0], { onlyRemoveTypeImports: true }]]
86
- },
87
- removeTsComments: true,
88
- prettierOptions,
89
- })
90
- // Correct code diff comments
91
- codeBlockContentJs = correctCodeDiffComments(codeBlockContentJs)
92
- }
93
-
94
- // Update code block open delimiter
95
- const codeBlockLangJs =
96
- codeBlockLang === 'vue'
97
- ? 'vue'
98
- : // ts => js | tsx => jsx
99
- codeBlockLang.replace('t', 'j')
100
- const codeBlockOpenJs = codeBlockOpen.replace(codeBlockLang, codeBlockLangJs)
101
-
102
- // Wrap each with <CodeSnippet>
103
- let codeSnippets = [
104
- wrapCodeSnippet('ts', `${codeBlockOpen}\n${codeBlockContent}${codeBlockClose}`),
105
- wrapCodeSnippet('js', `${codeBlockOpenJs}\n${codeBlockContentJs}${codeBlockClose}`),
106
- ].join('\n')
107
-
108
- // Wrap with <CodeSnippets> (if not YAML)
109
- codeSnippets = isYaml
110
- ? codeSnippets
111
- : // Rename/Replace Words via Custom Magic Comments
112
- processMagicComments(`<CodeSnippets>\n${codeSnippets}\n</CodeSnippets>`)
113
-
114
- // Restore indentation
115
- codeSnippets = restoreCodeBlockIndent(codeSnippets, codeBlockIndent)
116
-
117
- // Done
118
- replacement = codeSnippets
119
- }
120
-
121
- const blockStartIndex = match.index!
122
- const blockEndIndex = blockStartIndex + codeBlockOuterStr.length
123
- magicString.overwrite(blockStartIndex, blockEndIndex, replacement)
124
- }
125
-
126
- return getMagicStringResult()
127
- }
128
-
129
- function wrapCodeSnippet(lang: string, content: string) {
130
- return `<CodeSnippet codeLang="${lang}">\n${content}\n</CodeSnippet>`
131
- }
132
- function removeCodeBlockIndent(code: string, codeBlockIndent: string, moduleId: string) {
133
- if (!codeBlockIndent.length) return code
134
- return code
135
- .split('\n')
136
- .map((line) => {
137
- const lineStart = codeBlockIndent.trimEnd()
138
- assertUsage(
139
- line.startsWith(lineStart),
140
- `In ${pc.bold(pc.blue(moduleId))} the line '${pc.bold(line)}' must start with '${pc.bold(lineStart)}'`,
141
- )
142
- return line.slice(codeBlockIndent.length)
143
- })
144
- .join('\n')
145
- }
146
- function restoreCodeBlockIndent(code: string, codeBlockIndent: string) {
147
- if (!codeBlockIndent.length) return code
148
- return code
149
- .split('\n')
150
- .map((line) => `${codeBlockIndent}${line}`)
151
- .join('\n')
152
- }
153
- function processMagicComments(code: string) {
154
- // @detype-rename DummyLayout>Layout
155
- const renameCommentRE = /^\/\/\s@detype-rename\s(\w+)>(\w+)\n/gm
156
- const matches = Array.from(code.matchAll(renameCommentRE))
157
-
158
- if (matches.length) {
159
- for (let i = 0; i < matches.length / 2; i++) {
160
- const match = matches[i]
161
- const [fullMatch, renameFrom, renameTo] = match
162
- code = code.split(fullMatch).join('').replaceAll(renameFrom, renameTo)
163
- }
164
- }
165
-
166
- return code.replaceAll('//~', '')
167
- }
168
- /**
169
- * Correct code diff comments that detype() unexpectedly reformatted (using Prettier and Babel internally)
170
- * after removing TypeScript.
171
- * See https://github.com/brillout/docpress/pull/47#issuecomment-3263953899
172
- * @param code Transformed Javascript code.
173
- * @returns The corrected code.
174
- */
175
- function correctCodeDiffComments(code: string) {
176
- // Expected to match the code diff comments: `// [!code ++]` and `// [!code --]` started with newline and optional spaces
177
- const codeDiffRE = /\n\s*\/\/\s\[!code.+\]/g
178
- return code.replaceAll(codeDiffRE, (codeDiff) => codeDiff.trimStart())
179
- }
@@ -1,3 +0,0 @@
1
- export { detypePlugin };
2
- import type { PluginOption } from 'vite';
3
- declare function detypePlugin(): PluginOption;
@@ -1,159 +0,0 @@
1
- export { detypePlugin };
2
- import module from 'node:module';
3
- import { assertUsage } from './utils/assert.js';
4
- import pc from '@brillout/picocolors';
5
- import { getMagicString } from './utils/getMagicString.js';
6
- // Cannot use `import { transform } from 'detype'` as it results in errors,
7
- // and the package has no default export. Using `module.createRequire` instead.
8
- const { transform: detype } = module.createRequire(import.meta.url)('detype');
9
- const prettierOptions = {
10
- semi: false,
11
- singleQuote: true,
12
- printWidth: 100,
13
- trailingComma: 'none',
14
- };
15
- // RegExp to find TypeScript code blocks.
16
- //
17
- // For example:
18
- // ~~~mdx
19
- // ```ts
20
- // const hello: string = 'world'
21
- // ```
22
- // ~~~
23
- //
24
- // But also indented code blocks:
25
- // ~~~mdx
26
- // > Also works:
27
- // > - In blockquotes
28
- // > - In bullet points
29
- // > ```ts
30
- // > const hello: string = 'world'
31
- // > ```
32
- // ~~~
33
- const codeBlockRE = /^(.*)```(tsx?|vue|yaml)[^\n]*\n([\s\S]*?)```/gm;
34
- function detypePlugin() {
35
- return {
36
- name: '@brillout/docpress:detypePlugin',
37
- enforce: 'pre',
38
- transform: async (code, moduleId) => {
39
- if (!moduleId.endsWith('.mdx'))
40
- return;
41
- return await transformCode(code, moduleId);
42
- },
43
- };
44
- }
45
- async function transformCode(code, moduleId) {
46
- const matches = Array.from(code.matchAll(codeBlockRE));
47
- if (matches.length === 0)
48
- return;
49
- const { magicString, getMagicStringResult } = getMagicString(code, moduleId);
50
- magicString.prepend(`import { CodeSnippets, CodeSnippet } from '@brillout/docpress';\n\n`);
51
- // [Claude AI] Process matches in reverse order to avoid offset issues
52
- for (let i = matches.length - 1; i >= 0; i--) {
53
- const match = matches[i];
54
- const [codeBlockOuterStr, codeBlockIndent, codeBlockLang, codeBlockContentWithIndent] = match;
55
- const isYaml = codeBlockLang === 'yaml';
56
- // Remove indentation
57
- const codeBlockOpen = codeBlockOuterStr.split('\n')[0].slice(codeBlockIndent.length);
58
- const codeBlockContent = removeCodeBlockIndent(codeBlockContentWithIndent, codeBlockIndent, moduleId);
59
- let replacement;
60
- if (codeBlockOpen.includes('ts-only') && !isYaml) {
61
- replacement = `${codeBlockIndent}<CodeSnippet codeLang="ts" tsOnly>\n${codeBlockOuterStr}\n${codeBlockIndent}</CodeSnippet>`;
62
- }
63
- else {
64
- // someFileName.ts => someFileName.js
65
- let codeBlockContentJs = codeBlockContent.replaceAll('.ts', '.js');
66
- const codeBlockClose = '```';
67
- if (isYaml && codeBlockContentJs === codeBlockContent) {
68
- continue;
69
- }
70
- // Remove TypeScript
71
- if (!isYaml) {
72
- codeBlockContentJs = await detype(codeBlockContentJs, `some-dummy-filename.${codeBlockLang}`, {
73
- customizeBabelConfig(config) {
74
- // Add `onlyRemoveTypeImports: true` to the internal `@babel/preset-typescript` config
75
- // See https://github.com/cyco130/detype/blob/main/src/transform.ts#L206
76
- assertUsage(config.presets && config.presets.length === 1, 'Unexpected Babel config presets');
77
- config.presets = [[config.presets[0], { onlyRemoveTypeImports: true }]];
78
- },
79
- removeTsComments: true,
80
- prettierOptions,
81
- });
82
- // Correct code diff comments
83
- codeBlockContentJs = correctCodeDiffComments(codeBlockContentJs);
84
- }
85
- // Update code block open delimiter
86
- const codeBlockLangJs = codeBlockLang === 'vue'
87
- ? 'vue'
88
- : // ts => js | tsx => jsx
89
- codeBlockLang.replace('t', 'j');
90
- const codeBlockOpenJs = codeBlockOpen.replace(codeBlockLang, codeBlockLangJs);
91
- // Wrap each with <CodeSnippet>
92
- let codeSnippets = [
93
- wrapCodeSnippet('ts', `${codeBlockOpen}\n${codeBlockContent}${codeBlockClose}`),
94
- wrapCodeSnippet('js', `${codeBlockOpenJs}\n${codeBlockContentJs}${codeBlockClose}`),
95
- ].join('\n');
96
- // Wrap with <CodeSnippets> (if not YAML)
97
- codeSnippets = isYaml
98
- ? codeSnippets
99
- : // Rename/Replace Words via Custom Magic Comments
100
- processMagicComments(`<CodeSnippets>\n${codeSnippets}\n</CodeSnippets>`);
101
- // Restore indentation
102
- codeSnippets = restoreCodeBlockIndent(codeSnippets, codeBlockIndent);
103
- // Done
104
- replacement = codeSnippets;
105
- }
106
- const blockStartIndex = match.index;
107
- const blockEndIndex = blockStartIndex + codeBlockOuterStr.length;
108
- magicString.overwrite(blockStartIndex, blockEndIndex, replacement);
109
- }
110
- return getMagicStringResult();
111
- }
112
- function wrapCodeSnippet(lang, content) {
113
- return `<CodeSnippet codeLang="${lang}">\n${content}\n</CodeSnippet>`;
114
- }
115
- function removeCodeBlockIndent(code, codeBlockIndent, moduleId) {
116
- if (!codeBlockIndent.length)
117
- return code;
118
- return code
119
- .split('\n')
120
- .map((line) => {
121
- const lineStart = codeBlockIndent.trimEnd();
122
- assertUsage(line.startsWith(lineStart), `In ${pc.bold(pc.blue(moduleId))} the line '${pc.bold(line)}' must start with '${pc.bold(lineStart)}'`);
123
- return line.slice(codeBlockIndent.length);
124
- })
125
- .join('\n');
126
- }
127
- function restoreCodeBlockIndent(code, codeBlockIndent) {
128
- if (!codeBlockIndent.length)
129
- return code;
130
- return code
131
- .split('\n')
132
- .map((line) => `${codeBlockIndent}${line}`)
133
- .join('\n');
134
- }
135
- function processMagicComments(code) {
136
- // @detype-rename DummyLayout>Layout
137
- const renameCommentRE = /^\/\/\s@detype-rename\s(\w+)>(\w+)\n/gm;
138
- const matches = Array.from(code.matchAll(renameCommentRE));
139
- if (matches.length) {
140
- for (let i = 0; i < matches.length / 2; i++) {
141
- const match = matches[i];
142
- const [fullMatch, renameFrom, renameTo] = match;
143
- code = code.split(fullMatch).join('').replaceAll(renameFrom, renameTo);
144
- }
145
- }
146
- return code.replaceAll('//~', '');
147
- }
148
- /**
149
- * Correct code diff comments that detype() unexpectedly reformatted (using Prettier and Babel internally)
150
- * after removing TypeScript.
151
- * See https://github.com/brillout/docpress/pull/47#issuecomment-3263953899
152
- * @param code Transformed Javascript code.
153
- * @returns The corrected code.
154
- */
155
- function correctCodeDiffComments(code) {
156
- // Expected to match the code diff comments: `// [!code ++]` and `// [!code --]` started with newline and optional spaces
157
- const codeDiffRE = /\n\s*\/\/\s\[!code.+\]/g;
158
- return code.replaceAll(codeDiffRE, (codeDiff) => codeDiff.trimStart());
159
- }
@@ -1,9 +0,0 @@
1
- export { getMagicString };
2
- import MagicString from 'magic-string';
3
- declare function getMagicString(code: string, id: string): {
4
- magicString: MagicString;
5
- getMagicStringResult: () => {
6
- code: string;
7
- map: import("magic-string").SourceMap;
8
- };
9
- };
@@ -1,13 +0,0 @@
1
- export { getMagicString };
2
- import MagicString from 'magic-string';
3
- // Used everywhere instead of `new MagicString()` for consistent source map generation
4
- function getMagicString(code, id) {
5
- const magicString = new MagicString(code);
6
- const getMagicStringResult = () => {
7
- return {
8
- code: magicString.toString(),
9
- map: magicString.generateMap({ hires: true, source: id }),
10
- };
11
- };
12
- return { magicString, getMagicStringResult };
13
- }
@@ -1,17 +0,0 @@
1
- export { getMagicString }
2
-
3
- import MagicString from 'magic-string'
4
-
5
- // Used everywhere instead of `new MagicString()` for consistent source map generation
6
- function getMagicString(code: string, id: string) {
7
- const magicString = new MagicString(code)
8
-
9
- const getMagicStringResult = () => {
10
- return {
11
- code: magicString.toString(),
12
- map: magicString.generateMap({ hires: true, source: id }),
13
- }
14
- }
15
-
16
- return { magicString, getMagicStringResult }
17
- }