@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.
@@ -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
- &:hover {
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, position: 'relative' }}>
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
- const codeNew = await transformCode(code, moduleId)
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
- let codeNew = `import { CodeSnippets, CodeSnippet } from '@brillout/docpress';\n\n`
54
- let lastIndex = 0
53
+ const { magicString, getMagicStringResult } = getMagicString(code, moduleId)
55
54
 
56
- for (const match of matches) {
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
- const blockStartIndex = match.index
64
- const blockEndIndex = blockStartIndex + codeBlockOuterStr.length
65
- codeNew += code.slice(lastIndex, blockStartIndex)
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
- codeBlockContentJs = await detype(codeBlockContentJs, `some-dummy-filename.${codeBlockLang}`, {
74
- removeTsComments: true,
75
- prettierOptions,
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
- const codeSnippetTs = `<CodeSnippet codeLang="ts">\n${codeBlockOpen}\n${codeBlockContent}${codeBlockClose}\n</CodeSnippet>`
87
- const codeSnippetJs = `<CodeSnippet codeLang="js">\n${codeBlockOpenJs}\n${codeBlockContentJs}${codeBlockClose}\n</CodeSnippet>`
88
- const codeSnippets = restoreCodeBlockIndent(
89
- `<CodeSnippets>\n${codeSnippetJs}\n${codeSnippetTs}\n</CodeSnippets>`,
90
- codeBlockIndent,
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
- codeNew += codeSnippets
117
+ // Done
118
+ replacement = codeSnippets
94
119
  }
95
120
 
96
- lastIndex = blockEndIndex
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 codeNew
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(codeBlockIndent.trimEnd()),
110
- `In ${pc.bold(pc.blue(moduleId))} the line ${pc.bold(line)} must start with ${pc.bold(codeBlockIndent)}`,
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", null,
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, position: 'relative' } },
29
+ return (React.createElement("div", { className: "code-snippet", style: { ...displayStyle } },
30
30
  React.createElement(CopyButton, null),
31
31
  children));
32
32
  }
@@ -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
- const codeNew = await transformCode(code, moduleId);
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
- let codeNew = `import { CodeSnippets, CodeSnippet } from '@brillout/docpress';\n\n`;
50
- let lastIndex = 0;
51
- for (const match of matches) {
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
- const blockStartIndex = match.index;
57
- const blockEndIndex = blockStartIndex + codeBlockOuterStr.length;
58
- codeNew += code.slice(lastIndex, blockStartIndex);
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
- codeBlockContentJs = await detype(codeBlockContentJs, `some-dummy-filename.${codeBlockLang}`, {
67
- removeTsComments: true,
68
- prettierOptions,
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
- const codeBlockClose = '```';
76
- const codeSnippetTs = `<CodeSnippet codeLang="ts">\n${codeBlockOpen}\n${codeBlockContent}${codeBlockClose}\n</CodeSnippet>`;
77
- const codeSnippetJs = `<CodeSnippet codeLang="js">\n${codeBlockOpenJs}\n${codeBlockContentJs}${codeBlockClose}\n</CodeSnippet>`;
78
- const codeSnippets = restoreCodeBlockIndent(`<CodeSnippets>\n${codeSnippetJs}\n${codeSnippetTs}\n</CodeSnippets>`, codeBlockIndent);
79
- codeNew += codeSnippets;
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
- lastIndex = blockEndIndex;
106
+ const blockStartIndex = match.index;
107
+ const blockEndIndex = blockStartIndex + codeBlockOuterStr.length;
108
+ magicString.overwrite(blockStartIndex, blockEndIndex, replacement);
82
109
  }
83
- codeNew += code.slice(lastIndex);
84
- return codeNew;
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
- assertUsage(line.startsWith(codeBlockIndent.trimEnd()), `In ${pc.bold(pc.blue(moduleId))} the line ${pc.bold(line)} must start with ${pc.bold(codeBlockIndent)}`);
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,9 @@
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
+ };
@@ -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-af2d9bc",
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
+ }