Skip to content

Commit d5482fe

Browse files
fix(processors): improve code block processing to remove extra lines not present in twoslash output (#91)
1 parent 6160023 commit d5482fe

3 files changed

Lines changed: 20 additions & 6 deletions

File tree

.changeset/easy-stars-go.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"expressive-code-twoslash": patch
3+
---
4+
5+
Improves codeblock processing to ensure extra lines that don't exist in the twoslash output do not make it to the final output.

packages/expressive-code-twoslash/src/helpers/processors.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ export function processTwoslashCodeBlock(
4040

4141
// Remove any extra lines from the EC code block
4242
if (twoslashCodeBlock.length < ecCodeBlock.length) {
43-
for (let i = twoslashCodeBlock.length; i < ecCodeBlock.length; i++) {
44-
codeBlock.deleteLine(twoslashCodeBlock.length);
43+
for (let i = ecCodeBlock.length - 1; i >= twoslashCodeBlock.length; i--) {
44+
const exists = codeBlock.getLine(i);
45+
if (exists) codeBlock.deleteLine(i);
4546
}
4647
}
4748
}

packages/expressive-code-twoslash/src/index.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,13 @@ export default function ecTwoSlash(options: PluginTwoslashOptions = {}): Express
105105
...twoslashEslintOptions,
106106
});
107107

108-
const snippetTsconfigPath = resolveTsconfigPath(cwd, tsConfigPath);
109-
const { options: baseCompilerOptions } = parseSnippetTsconfig(snippetTsconfigPath);
108+
// Get the TSConfig path for getting the default library files for Twoslash
109+
const _TsConfigPath = resolveTsconfigPath(cwd, tsConfigPath);
110110

111+
// Get the default compiler options from the parsed TSConfig, which includes the default library files for Twoslash
112+
const { options: baseCompilerOptions } = parseSnippetTsconfig(_TsConfigPath);
113+
114+
// Get the directory of the default library files for Twoslash, which is needed for proper module resolution in Twoslash
111115
const tsLibDirectory = path.dirname(ts.getDefaultLibFilePath(baseCompilerOptions));
112116

113117
return definePlugin({
@@ -138,8 +142,10 @@ export default function ecTwoSlash(options: PluginTwoslashOptions = {}): Express
138142
// Add the include to the includes map if it exists
139143
if (include) includes.add(include, codeWithIncludes);
140144

145+
// If the trigger is "eslint", we want to set a full filename with extension instead of just the language identifier,
146+
// because ESLint's Twoslasher needs the full filename to properly parse the code block and provide accurate completions.
141147
const extension =
142-
trigger === "twoslash" ? codeBlock.language : `index.${codeBlock.language}`;
148+
trigger === "eslint" ? `index.${codeBlock.language}` : codeBlock.language;
143149

144150
// Twoslash the code block
145151
const twoslash = twoslasher(codeWithIncludes, extension, {
@@ -153,7 +159,9 @@ export default function ecTwoSlash(options: PluginTwoslashOptions = {}): Express
153159
},
154160
});
155161

156-
// Update EC code block with the twoslash information
162+
// Update EC code block with the twoslash information this is important to ensure that if the end user
163+
// is using the @showEmit functionality, the emitted code is properly displayed in the code block.
164+
// Twoslash output code, could be TypeScript, but could also be a JS/JSON/d.ts representation of the code.
157165
if (twoslash.extension) {
158166
codeBlock.language = twoslash.extension;
159167
}

0 commit comments

Comments
 (0)