Skip to content

Commit 974d8c2

Browse files
authored
fix smart quotes (#770)
fix smart quotes - closes #470
1 parent ee14eb4 commit 974d8c2

File tree

2 files changed

+30
-29
lines changed

2 files changed

+30
-29
lines changed

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

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -281,34 +281,33 @@ export async function render_content_markdown(
281281
snippets.save(token.text, html);
282282
}
283283

284-
// ensure that `foo`/`bar` is transformed to `foo` / `bar`
285-
// https://github.com/sveltejs/svelte.dev/pull/577
286-
const slash_index =
287-
// @ts-expect-error
288-
token.tokens?.findIndex((token) => token.type === 'text' && token.text === '/') ?? -1;
289-
290-
if (slash_index !== -1) {
291-
// @ts-expect-error
292-
const before = token.tokens[slash_index - 1];
293-
// @ts-expect-error
294-
const after = token.tokens[slash_index + 1];
295-
296-
if (before?.type === 'codespan' && after?.type === 'codespan') {
297-
// @ts-expect-error
298-
token.tokens[slash_index].raw = token.tokens[slash_index].text = ' / ';
284+
const tokens = 'tokens' in token ? token.tokens : undefined;
285+
286+
if (tokens) {
287+
// ensure that `foo`/`bar` is transformed to `foo` / `bar`
288+
// https://github.com/sveltejs/svelte.dev/pull/577
289+
const slash_index =
290+
tokens.findIndex((token) => token.type === 'text' && token.text === '/') ?? -1;
291+
292+
if (slash_index !== -1) {
293+
const before = tokens[slash_index - 1];
294+
const after = tokens[slash_index + 1];
295+
296+
if (before?.type === 'codespan' && after?.type === 'codespan') {
297+
// @ts-expect-error
298+
tokens[slash_index].raw = tokens[slash_index].text = ' / ';
299+
}
299300
}
300-
}
301-
},
302-
text(token) {
303-
// @ts-expect-error I think this is a bug in marked — some text tokens have children,
304-
// but that's not reflected in the types. In these cases we can't just use `token.tokens`
305-
// because that will result in e.g. `<code>` elements not being generated
306-
if (token.tokens) {
307-
// @ts-expect-error
308-
return this.parser!.parseInline(token.tokens);
309-
}
310301

311-
return smart_quotes(token.text, true);
302+
// smart quotes
303+
for (let i = 0; i < tokens.length; i += 1) {
304+
const token = tokens[i];
305+
306+
if (token.type === 'text') {
307+
token.text = smart_quotes(token.text, { first: i === 0, html: true });
308+
}
309+
}
310+
}
312311
},
313312
heading({ tokens, depth }) {
314313
const text = this.parser!.parseInline(tokens);

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,18 @@ export const slugify = (str: string) => {
4242
.replace(/-$/, '');
4343
};
4444

45-
export function smart_quotes(str: string, html: boolean = false) {
45+
export function smart_quotes(
46+
str: string,
47+
{ first = true, html = false }: { first?: boolean; html?: boolean } = {}
48+
) {
4649
// replace dumb quotes with smart quotes. This isn't a perfect algorithm — it
4750
// wouldn't correctly handle `That '70s show` or `My country 'tis of thee`
4851
// but a) it's very unlikely they'll occur in our docs, and
4952
// b) they can be dealt with manually
5053
return str.replace(
5154
html ? /(.|^)(&#39;|&quot;)(.|$)/g : /(.|^)('|")(.|$)/g,
5255
(m, before, quote, after) => {
53-
const trimmed = before.trim();
54-
const left = trimmed === '' || trimmed === '(';
56+
const left = (first && before === '') || [' ', '\n', '('].includes(before);
5557
let replacement = '';
5658

5759
if (html) {

0 commit comments

Comments
 (0)