Skip to content

Commit

Permalink
fix: don't escape markdown underscores (#4896)
Browse files Browse the repository at this point in the history
  • Loading branch information
bigint authored May 7, 2024
2 parents 0bc0d31 + f99e6aa commit 83846fa
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 22,500 deletions.
4 changes: 3 additions & 1 deletion apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"prettier": "prettier --check \"**/*.{js,ts,tsx,md}\" --cache",
"prettier:fix": "prettier --write \"**/*.{js,ts,tsx,md}\" --cache",
"start": "next start --port 4783",
"test:dev": "vitest run",
"typecheck": "tsc --pretty"
},
"dependencies": {
Expand Down Expand Up @@ -92,6 +93,7 @@
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"tailwindcss": "^3.4.3",
"typescript": "^5.4.5"
"typescript": "^5.4.5",
"vitest": "^1.6.0"
}
}
53 changes: 53 additions & 0 deletions apps/web/src/helpers/prosekit/markdown.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { describe, expect, test } from 'vitest';

import { htmlFromMarkdown, markdownFromHTML } from './markdown';

describe('markdownFromHTML', () => {
test('should convert HTML to markdown', () => {
const html = '<p>Text <strong>Bold</strong> <em>italic</em></p>';
const markdown = markdownFromHTML(html);
expect(markdown).toMatchInlineSnapshot(`
"Text **Bold** *italic*
"
`);
});

test('should not escape mention handles with _', () => {
const html =
'<p>A normal handle: <span>@lens/foo</span></p>' +
'<p>A handle with underscore: <span>@lens/foo_bar</span></p>';
const markdown = markdownFromHTML(html);
expect(markdown).toContain('@lens/foo');
expect(markdown).toContain('@lens/foo_bar');
expect(markdown).toMatchInlineSnapshot(`
"A normal handle: @lens/foo
A handle with underscore: @lens/foo_bar
"
`);
});
});

describe('htmlFromMarkdown', () => {
test('should convert markdown to HTML', () => {
const markdown = 'Text **Bold** _italic_';
const html = htmlFromMarkdown(markdown);
expect(html).toMatchInlineSnapshot(`
"<p>Text <strong>Bold</strong> <em>italic</em></p>
"
`);
});

test('should not escape mention handles with _', () => {
const markdown = [
'A normal handle: @lens/foo',
'A handle with underscore: @lens/foo_bar'
].join('\n\n');
const html = htmlFromMarkdown(markdown);
expect(html).toMatchInlineSnapshot(`
"<p>A normal handle: @lens/foo</p>
<p>A handle with underscore: @lens/foo_bar</p>
"
`);
});
});
10 changes: 9 additions & 1 deletion apps/web/src/helpers/prosekit/markdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,22 @@ import remarkParse from 'remark-parse';
import remarkStringify from 'remark-stringify';
import { unified } from 'unified';

// By default, remark-stringify escapes underscores (i.e. "_" => "\_"). We want
// to disable this behavior so that we can have underscores in mention handles.
const unescapeUnderscore = (str: string) => {
return str.replace(/(^|[^\\])\\_/g, '$1_');
};

export const markdownFromHTML = (html: string): string => {
return unified()
const markdown = unified()
.use(rehypeParse)
.use(rehypeRemark)
.use(remarkLinkProtocol)
.use(remarkStringify)
.processSync(html)
.toString();

return unescapeUnderscore(markdown);
};

export const htmlFromMarkdown = (markdown: string): string => {
Expand Down
9 changes: 9 additions & 0 deletions apps/web/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
alias: { '@helpers': '/src/helpers' },
globals: true,
testTimeout: 30000
}
});
Loading

0 comments on commit 83846fa

Please sign in to comment.