Skip to content

Commit 313923a

Browse files
committed
oops
1 parent beb0f8a commit 313923a

File tree

1 file changed

+63
-2
lines changed

1 file changed

+63
-2
lines changed

packages/site-kit/src/lib/markdown/renderer.ts

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { createHash, Hash } from 'node:crypto';
33
import fs from 'node:fs';
44
import path from 'node:path';
55
import ts from 'typescript';
6+
import * as marked from 'marked';
67
import { codeToHtml, createCssVariablesTheme } from 'shiki';
78
import { transformerTwoslash } from '@shikijs/twoslash';
89
import { SHIKI_LANGUAGE_MAP, slugify, smart_quotes, transform } from './utils';
@@ -185,11 +186,11 @@ const snippets = await create_snippet_cache();
185186
export async function render_content_markdown(
186187
filename: string,
187188
body: string,
188-
options: { check?: boolean },
189+
options?: { check?: boolean },
189190
twoslashBanner?: TwoslashBanner
190191
) {
191192
const headings: string[] = [];
192-
const { check = true } = options;
193+
const { check = true } = options ?? {};
193194

194195
return await transform(body, {
195196
async walkTokens(token) {
@@ -675,6 +676,66 @@ async function syntax_highlight({
675676
});
676677

677678
html = html.replace(/ {27,}/g, () => redactions.shift()!);
679+
680+
if (check) {
681+
// munge the twoslash output so that it renders sensibly. the order of operations
682+
// here is important — we need to work backwards, to avoid corrupting the offsets
683+
const replacements: Array<{ start: number; end: number; content: string }> = [];
684+
685+
for (const match of html.matchAll(/<div class="twoslash-popup-docs">([^]+?)<\/div>/g)) {
686+
const content = await render_content_markdown('<twoslash>', match[1], { check: false });
687+
688+
replacements.push({
689+
start: match.index,
690+
end: match.index + match[0].length,
691+
content: '<div class="twoslash-popup-docs">' + content + '</div>'
692+
});
693+
}
694+
695+
while (replacements.length > 0) {
696+
const { start, end, content } = replacements.pop()!;
697+
html = html.slice(0, start) + content + html.slice(end);
698+
}
699+
700+
for (const match of html.matchAll(
701+
/<span class="twoslash-popup-docs-tag"><span class="twoslash-popup-docs-tag-name">([^]+?)<\/span><span class="twoslash-popup-docs-tag-value">([^]+?)<\/span><\/span>/g
702+
)) {
703+
const tag = match[1];
704+
let value = match[2];
705+
706+
let content = `<span class="tag">${tag}</span><span class="value">`;
707+
708+
if (tag === '@param' || tag === '@throws') {
709+
const words = value.split(' ');
710+
let param = words.shift()!;
711+
value = words.join(' ');
712+
713+
if (tag === '@throws') {
714+
if (param[0] !== '{' || param[param.length - 1] !== '}') {
715+
throw new Error('TODO robustify @throws handling');
716+
}
717+
718+
param = param.slice(1, -1);
719+
}
720+
721+
content += `<span class="param">${param}</span> `;
722+
}
723+
724+
content += marked.parseInline(value);
725+
content += '</span>';
726+
727+
replacements.push({
728+
start: match.index,
729+
end: match.index + match[0].length,
730+
content: '<div class="tags">' + content + '</div>'
731+
});
732+
}
733+
734+
while (replacements.length > 0) {
735+
const { start, end, content } = replacements.pop()!;
736+
html = html.slice(0, start) + content + html.slice(end);
737+
}
738+
}
678739
} catch (e) {
679740
console.error((e as Error).message);
680741
console.warn(prelude + redacted);

0 commit comments

Comments
 (0)