Skip to content

Commit d82db06

Browse files
authored
Merge pull request #5891 from rtibbles/markdown_edit
fix(texteditor): align markdown output with Perseus grammar
2 parents 892566d + 3e15eff commit d82db06

5 files changed

Lines changed: 35 additions & 5 deletions

File tree

contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/components/EditorToolbar.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,9 @@
386386
// Categories that can overflow (in order of overflow priority)
387387
const OVERFLOW_CATEGORIES = [
388388
'insert',
389-
'script',
389+
// Perseus flavoured markdown does not support super and sub script,
390+
// so we disable this for now until we stop using markdown as the primary target
391+
// 'script',
390392
'lists',
391393
'clearFormat',
392394
'align',

contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/utils/markdown.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ export const paramsToImageMd = ({ src, alt, width, height, permanentSrc, textAli
3939
return `![${alt || ''}](${IMAGE_PLACEHOLDER}/${fileName}${alignSuffix})`;
4040
};
4141

42+
// --- Underline Translation ---
43+
// Perseus simple-markdown treats __text__ as <u>; marked treats it as <strong>.
44+
// Rewrite before marked runs so the round-trip preserves underline.
45+
export const UNDERLINE_REGEX = /__([\s\S]+?)__(?!_)/g;
46+
4247
// --- Math/Formula Translation ---
4348
export const MATH_REGEX = /\$\$([^$]+)\$\$/g;
4449

@@ -151,5 +156,7 @@ export function preprocessMarkdown(markdown) {
151156
return `<span data-latex="${params.latex}"></span>`;
152157
});
153158

159+
processedMarkdown = processedMarkdown.replace(UNDERLINE_REGEX, '<u>$1</u>');
160+
154161
return marked(processedMarkdown);
155162
}

contentcuration/contentcuration/frontend/shared/views/TipTapEditor/TipTapEditor/utils/markdownSerializer.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export const createCustomMarkdownSerializer = editor => {
2424
trimmedText = `*${trimmedText}*`;
2525
break;
2626
case 'underline':
27-
trimmedText = `<u>${trimmedText}</u>`;
27+
trimmedText = `__${trimmedText}__`;
2828
break;
2929
case 'strike':
3030
trimmedText = `~~${trimmedText}~~`;

contentcuration/contentcuration/frontend/shared/views/TipTapEditor/__tests__/markdown.spec.js

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,28 @@ describe('preprocessMarkdown', () => {
7070
});
7171
});
7272

73-
// 4: Standard Markdown Passthrough
73+
// 4: Perseus Underline Handling
74+
// Perseus's simple-markdown treats __text__ as <u>, but `marked` (CommonMark)
75+
// treats it as <strong>. We must rewrite __text__ -> <u>text</u> before marked
76+
// sees it, so the round-trip preserves underline instead of turning it into bold.
77+
describe('Perseus Underline Handling', () => {
78+
it('should rewrite __text__ to <u>text</u> before passing to marked', () => {
79+
preprocessMarkdown('This is __underlined__ text.');
80+
expect(marked).toHaveBeenCalledWith('This is <u>underlined</u> text.');
81+
});
82+
83+
it('should rewrite multiple __ runs on the same line independently', () => {
84+
preprocessMarkdown('__one__ and __two__');
85+
expect(marked).toHaveBeenCalledWith('<u>one</u> and <u>two</u>');
86+
});
87+
88+
it('should rewrite __ spanning multiple words', () => {
89+
preprocessMarkdown('__multi word underline__');
90+
expect(marked).toHaveBeenCalledWith('<u>multi word underline</u>');
91+
});
92+
});
93+
94+
// 5: Standard Markdown Passthrough
7495
describe('Standard Markdown Passthrough', () => {
7596
it('should pass non-custom syntax through to the marked library', () => {
7697
const standardMd = 'Here is **bold** and a [link](url).';

contentcuration/contentcuration/frontend/shared/views/TipTapEditor/__tests__/markdownSerializer.spec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ describe('createCustomMarkdownSerializer', () => {
209209
expect(getMarkdown()).toBe('*' + '**bold and italic**' + '*');
210210
});
211211

212-
it('should serialize an underlined node with a <u> tag', () => {
212+
it('should serialize an underlined node with __ delimiters (Perseus syntax)', () => {
213213
const docContent = [
214214
{
215215
type: 'paragraph',
@@ -224,7 +224,7 @@ describe('createCustomMarkdownSerializer', () => {
224224
];
225225
const mockEditor = createMockEditor(docContent);
226226
const getMarkdown = createCustomMarkdownSerializer(mockEditor);
227-
expect(getMarkdown()).toBe('<u>underlined</u>');
227+
expect(getMarkdown()).toBe('__underlined__');
228228
});
229229

230230
it('should serialize a link node correctly', () => {

0 commit comments

Comments
 (0)