@brillout/docpress 0.15.10-commit-af2d9bc → 0.15.10-commit-317b144
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/components/CodeSnippets.css +15 -1
- package/components/CodeSnippets.tsx +2 -2
- package/detypePlugin.ts +86 -29
- package/dist/components/CodeSnippets.js +2 -2
- package/dist/detypePlugin.js +79 -24
- package/dist/utils/getMagicString.d.ts +9 -0
- package/dist/utils/getMagicString.js +13 -0
- package/package.json +2 -1
- package/utils/getMagicString.ts +17 -0
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/* Wrapper */
|
|
2
|
+
.code-snippet,
|
|
3
|
+
.code-snippets {
|
|
4
|
+
position: relative;
|
|
5
|
+
&:hover {
|
|
6
|
+
button,
|
|
7
|
+
select {
|
|
8
|
+
opacity: 1;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
1
13
|
/* Language select */
|
|
2
14
|
.code-lang-select {
|
|
3
15
|
right: 42px;
|
|
@@ -41,7 +53,9 @@
|
|
|
41
53
|
border: 1px solid #ccc;
|
|
42
54
|
border-radius: 5px;
|
|
43
55
|
background-color: #f7f7f7;
|
|
44
|
-
|
|
56
|
+
opacity: 0;
|
|
57
|
+
transition: opacity 0.8s ease-in-out, background-color 0.4s ease-in-out;
|
|
58
|
+
&:not(:hover) {
|
|
45
59
|
background-color: #eee;
|
|
46
60
|
}
|
|
47
61
|
}
|
|
@@ -18,7 +18,7 @@ function TypescriptOnly({ children }: { children: React.ReactNode }) {
|
|
|
18
18
|
function CodeSnippets({ children }: { children: React.ReactNode }) {
|
|
19
19
|
const [codeLangSelected, selectCodeLang] = useSelectCodeLang()
|
|
20
20
|
return (
|
|
21
|
-
<div>
|
|
21
|
+
<div className="code-snippets">
|
|
22
22
|
<form style={{ position: 'relative' }}>
|
|
23
23
|
<select className="code-lang-select" onChange={onChange} value={codeLangSelected}>
|
|
24
24
|
<option value="js">JavaScript</option>
|
|
@@ -43,7 +43,7 @@ function CodeSnippet({
|
|
|
43
43
|
const displayStyle = tsOnly ? {} : { display: codeLangSelected === codeLang ? 'block' : 'none' }
|
|
44
44
|
|
|
45
45
|
return (
|
|
46
|
-
<div style={{ ...displayStyle
|
|
46
|
+
<div className="code-snippet" style={{ ...displayStyle }}>
|
|
47
47
|
<CopyButton />
|
|
48
48
|
{children}
|
|
49
49
|
</div>
|
package/detypePlugin.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { PluginOption } from 'vite'
|
|
|
4
4
|
import module from 'node:module'
|
|
5
5
|
import { assertUsage } from './utils/assert.js'
|
|
6
6
|
import pc from '@brillout/picocolors'
|
|
7
|
+
import { getMagicString } from './utils/getMagicString.js'
|
|
7
8
|
// Cannot use `import { transform } from 'detype'` as it results in errors,
|
|
8
9
|
// and the package has no default export. Using `module.createRequire` instead.
|
|
9
10
|
const { transform: detype } = module.createRequire(import.meta.url)('detype') as typeof import('detype')
|
|
@@ -32,7 +33,7 @@ const prettierOptions: NonNullable<Parameters<typeof detype>[2]>['prettierOption
|
|
|
32
33
|
// > const hello: string = 'world'
|
|
33
34
|
// > ```
|
|
34
35
|
// ~~~
|
|
35
|
-
const codeBlockRE = /^(.*)```(tsx?|vue)[^\n]*\n([\s\S]*?)```/gm
|
|
36
|
+
const codeBlockRE = /^(.*)```(tsx?|vue|yaml)[^\n]*\n([\s\S]*?)```/gm
|
|
36
37
|
|
|
37
38
|
function detypePlugin(): PluginOption {
|
|
38
39
|
return {
|
|
@@ -40,8 +41,7 @@ function detypePlugin(): PluginOption {
|
|
|
40
41
|
enforce: 'pre',
|
|
41
42
|
transform: async (code: string, moduleId: string) => {
|
|
42
43
|
if (!moduleId.endsWith('.mdx')) return
|
|
43
|
-
|
|
44
|
-
return codeNew
|
|
44
|
+
return await transformCode(code, moduleId)
|
|
45
45
|
},
|
|
46
46
|
}
|
|
47
47
|
}
|
|
@@ -50,64 +50,94 @@ async function transformCode(code: string, moduleId: string) {
|
|
|
50
50
|
const matches = Array.from(code.matchAll(codeBlockRE))
|
|
51
51
|
if (matches.length === 0) return
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
let lastIndex = 0
|
|
53
|
+
const { magicString, getMagicStringResult } = getMagicString(code, moduleId)
|
|
55
54
|
|
|
56
|
-
|
|
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]
|
|
57
60
|
const [codeBlockOuterStr, codeBlockIndent, codeBlockLang, codeBlockContentWithIndent] = match
|
|
61
|
+
const isYaml = codeBlockLang === 'yaml'
|
|
58
62
|
|
|
59
63
|
// Remove indentation
|
|
60
64
|
const codeBlockOpen = codeBlockOuterStr.split('\n')[0].slice(codeBlockIndent.length)
|
|
61
65
|
const codeBlockContent = removeCodeBlockIndent(codeBlockContentWithIndent, codeBlockIndent, moduleId)
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (codeBlockOpen.includes('ts-only')) {
|
|
68
|
-
codeNew += `${codeBlockIndent}<CodeSnippet codeLang="ts" tsOnly>\n${codeBlockOuterStr}\n${codeBlockIndent}</CodeSnippet>`
|
|
67
|
+
let replacement: string
|
|
68
|
+
if (codeBlockOpen.includes('ts-only') && !isYaml) {
|
|
69
|
+
replacement = `${codeBlockIndent}<CodeSnippet codeLang="ts" tsOnly>\n${codeBlockOuterStr}\n${codeBlockIndent}</CodeSnippet>`
|
|
69
70
|
} else {
|
|
70
71
|
// someFileName.ts => someFileName.js
|
|
71
72
|
let codeBlockContentJs = codeBlockContent.replaceAll('.ts', '.js')
|
|
73
|
+
const codeBlockClose = '```'
|
|
74
|
+
if (isYaml && codeBlockContentJs === codeBlockContent) {
|
|
75
|
+
continue
|
|
76
|
+
}
|
|
77
|
+
|
|
72
78
|
// Remove TypeScript
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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
|
+
}
|
|
77
93
|
|
|
94
|
+
// Update code block open delimiter
|
|
78
95
|
const codeBlockLangJs =
|
|
79
96
|
codeBlockLang === 'vue'
|
|
80
97
|
? 'vue'
|
|
81
98
|
: // ts => js | tsx => jsx
|
|
82
99
|
codeBlockLang.replace('t', 'j')
|
|
83
100
|
const codeBlockOpenJs = codeBlockOpen.replace(codeBlockLang, codeBlockLangJs)
|
|
84
|
-
const codeBlockClose = '```'
|
|
85
101
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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)
|
|
92
116
|
|
|
93
|
-
|
|
117
|
+
// Done
|
|
118
|
+
replacement = codeSnippets
|
|
94
119
|
}
|
|
95
120
|
|
|
96
|
-
|
|
121
|
+
const blockStartIndex = match.index!
|
|
122
|
+
const blockEndIndex = blockStartIndex + codeBlockOuterStr.length
|
|
123
|
+
magicString.overwrite(blockStartIndex, blockEndIndex, replacement)
|
|
97
124
|
}
|
|
98
|
-
codeNew += code.slice(lastIndex)
|
|
99
125
|
|
|
100
|
-
return
|
|
126
|
+
return getMagicStringResult()
|
|
101
127
|
}
|
|
102
128
|
|
|
129
|
+
function wrapCodeSnippet(lang: string, content: string) {
|
|
130
|
+
return `<CodeSnippet codeLang="${lang}">\n${content}\n</CodeSnippet>`
|
|
131
|
+
}
|
|
103
132
|
function removeCodeBlockIndent(code: string, codeBlockIndent: string, moduleId: string) {
|
|
104
133
|
if (!codeBlockIndent.length) return code
|
|
105
134
|
return code
|
|
106
135
|
.split('\n')
|
|
107
136
|
.map((line) => {
|
|
137
|
+
const lineStart = codeBlockIndent.trimEnd()
|
|
108
138
|
assertUsage(
|
|
109
|
-
line.startsWith(
|
|
110
|
-
`In ${pc.bold(pc.blue(moduleId))} the line ${pc.bold(line)} must start with ${pc.bold(
|
|
139
|
+
line.startsWith(lineStart),
|
|
140
|
+
`In ${pc.bold(pc.blue(moduleId))} the line '${pc.bold(line)}' must start with '${pc.bold(lineStart)}'`,
|
|
111
141
|
)
|
|
112
142
|
return line.slice(codeBlockIndent.length)
|
|
113
143
|
})
|
|
@@ -120,3 +150,30 @@ function restoreCodeBlockIndent(code: string, codeBlockIndent: string) {
|
|
|
120
150
|
.map((line) => `${codeBlockIndent}${line}`)
|
|
121
151
|
.join('\n')
|
|
122
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
|
+
}
|
|
@@ -13,7 +13,7 @@ function TypescriptOnly({ children }) {
|
|
|
13
13
|
}
|
|
14
14
|
function CodeSnippets({ children }) {
|
|
15
15
|
const [codeLangSelected, selectCodeLang] = useSelectCodeLang();
|
|
16
|
-
return (React.createElement("div",
|
|
16
|
+
return (React.createElement("div", { className: "code-snippets" },
|
|
17
17
|
React.createElement("form", { style: { position: 'relative' } },
|
|
18
18
|
React.createElement("select", { className: "code-lang-select", onChange: onChange, value: codeLangSelected },
|
|
19
19
|
React.createElement("option", { value: "js" }, "JavaScript"),
|
|
@@ -26,7 +26,7 @@ function CodeSnippets({ children }) {
|
|
|
26
26
|
function CodeSnippet({ children, codeLang, tsOnly = false, }) {
|
|
27
27
|
const [codeLangSelected] = useSelectCodeLang();
|
|
28
28
|
const displayStyle = tsOnly ? {} : { display: codeLangSelected === codeLang ? 'block' : 'none' };
|
|
29
|
-
return (React.createElement("div", { style: { ...displayStyle
|
|
29
|
+
return (React.createElement("div", { className: "code-snippet", style: { ...displayStyle } },
|
|
30
30
|
React.createElement(CopyButton, null),
|
|
31
31
|
children));
|
|
32
32
|
}
|
package/dist/detypePlugin.js
CHANGED
|
@@ -2,6 +2,7 @@ export { detypePlugin };
|
|
|
2
2
|
import module from 'node:module';
|
|
3
3
|
import { assertUsage } from './utils/assert.js';
|
|
4
4
|
import pc from '@brillout/picocolors';
|
|
5
|
+
import { getMagicString } from './utils/getMagicString.js';
|
|
5
6
|
// Cannot use `import { transform } from 'detype'` as it results in errors,
|
|
6
7
|
// and the package has no default export. Using `module.createRequire` instead.
|
|
7
8
|
const { transform: detype } = module.createRequire(import.meta.url)('detype');
|
|
@@ -29,7 +30,7 @@ const prettierOptions = {
|
|
|
29
30
|
// > const hello: string = 'world'
|
|
30
31
|
// > ```
|
|
31
32
|
// ~~~
|
|
32
|
-
const codeBlockRE = /^(.*)```(tsx?|vue)[^\n]*\n([\s\S]*?)```/gm;
|
|
33
|
+
const codeBlockRE = /^(.*)```(tsx?|vue|yaml)[^\n]*\n([\s\S]*?)```/gm;
|
|
33
34
|
function detypePlugin() {
|
|
34
35
|
return {
|
|
35
36
|
name: '@brillout/docpress:detypePlugin',
|
|
@@ -37,8 +38,7 @@ function detypePlugin() {
|
|
|
37
38
|
transform: async (code, moduleId) => {
|
|
38
39
|
if (!moduleId.endsWith('.mdx'))
|
|
39
40
|
return;
|
|
40
|
-
|
|
41
|
-
return codeNew;
|
|
41
|
+
return await transformCode(code, moduleId);
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
}
|
|
@@ -46,42 +46,71 @@ async function transformCode(code, moduleId) {
|
|
|
46
46
|
const matches = Array.from(code.matchAll(codeBlockRE));
|
|
47
47
|
if (matches.length === 0)
|
|
48
48
|
return;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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];
|
|
52
54
|
const [codeBlockOuterStr, codeBlockIndent, codeBlockLang, codeBlockContentWithIndent] = match;
|
|
55
|
+
const isYaml = codeBlockLang === 'yaml';
|
|
53
56
|
// Remove indentation
|
|
54
57
|
const codeBlockOpen = codeBlockOuterStr.split('\n')[0].slice(codeBlockIndent.length);
|
|
55
58
|
const codeBlockContent = removeCodeBlockIndent(codeBlockContentWithIndent, codeBlockIndent, moduleId);
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
if (codeBlockOpen.includes('ts-only')) {
|
|
60
|
-
codeNew += `${codeBlockIndent}<CodeSnippet codeLang="ts" tsOnly>\n${codeBlockOuterStr}\n${codeBlockIndent}</CodeSnippet>`;
|
|
59
|
+
let replacement;
|
|
60
|
+
if (codeBlockOpen.includes('ts-only') && !isYaml) {
|
|
61
|
+
replacement = `${codeBlockIndent}<CodeSnippet codeLang="ts" tsOnly>\n${codeBlockOuterStr}\n${codeBlockIndent}</CodeSnippet>`;
|
|
61
62
|
}
|
|
62
63
|
else {
|
|
63
64
|
// someFileName.ts => someFileName.js
|
|
64
65
|
let codeBlockContentJs = codeBlockContent.replaceAll('.ts', '.js');
|
|
66
|
+
const codeBlockClose = '```';
|
|
67
|
+
if (isYaml && codeBlockContentJs === codeBlockContent) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
65
70
|
// Remove TypeScript
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
|
70
86
|
const codeBlockLangJs = codeBlockLang === 'vue'
|
|
71
87
|
? 'vue'
|
|
72
88
|
: // ts => js | tsx => jsx
|
|
73
89
|
codeBlockLang.replace('t', 'j');
|
|
74
90
|
const codeBlockOpenJs = codeBlockOpen.replace(codeBlockLang, codeBlockLangJs);
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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;
|
|
80
105
|
}
|
|
81
|
-
|
|
106
|
+
const blockStartIndex = match.index;
|
|
107
|
+
const blockEndIndex = blockStartIndex + codeBlockOuterStr.length;
|
|
108
|
+
magicString.overwrite(blockStartIndex, blockEndIndex, replacement);
|
|
82
109
|
}
|
|
83
|
-
|
|
84
|
-
|
|
110
|
+
return getMagicStringResult();
|
|
111
|
+
}
|
|
112
|
+
function wrapCodeSnippet(lang, content) {
|
|
113
|
+
return `<CodeSnippet codeLang="${lang}">\n${content}\n</CodeSnippet>`;
|
|
85
114
|
}
|
|
86
115
|
function removeCodeBlockIndent(code, codeBlockIndent, moduleId) {
|
|
87
116
|
if (!codeBlockIndent.length)
|
|
@@ -89,7 +118,8 @@ function removeCodeBlockIndent(code, codeBlockIndent, moduleId) {
|
|
|
89
118
|
return code
|
|
90
119
|
.split('\n')
|
|
91
120
|
.map((line) => {
|
|
92
|
-
|
|
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)}'`);
|
|
93
123
|
return line.slice(codeBlockIndent.length);
|
|
94
124
|
})
|
|
95
125
|
.join('\n');
|
|
@@ -102,3 +132,28 @@ function restoreCodeBlockIndent(code, codeBlockIndent) {
|
|
|
102
132
|
.map((line) => `${codeBlockIndent}${line}`)
|
|
103
133
|
.join('\n');
|
|
104
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
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@brillout/docpress",
|
|
3
|
-
"version": "0.15.10-commit-
|
|
3
|
+
"version": "0.15.10-commit-317b144",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@brillout/picocolors": "^1.0.10",
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"@shikijs/transformers": "1.2.0",
|
|
13
13
|
"@vitejs/plugin-react-swc": "^3.10.2",
|
|
14
14
|
"detype": "^1.1.2",
|
|
15
|
+
"magic-string": "^0.30.18",
|
|
15
16
|
"rehype-pretty-code": "0.13.0",
|
|
16
17
|
"remark-gfm": "4.0.0",
|
|
17
18
|
"shiki": "1.2.0",
|
|
@@ -0,0 +1,17 @@
|
|
|
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
|
+
}
|