Commit 8b0f6331 authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch '243758-indent-two-spaced-lists' into 'master'

Resolve "Static Site Editor Flattens Mixed Lists"

Closes #243758

See merge request gitlab-org/gitlab!41599
parents 05e15c27 c6842c06
import { repeat } from 'lodash';
const topLevelOrderedRegexp = /^\d{1,3}/;
const nestedLineRegexp = /^\s+/;
/**
* DISCLAIMER: This is a temporary fix that corrects the indentation
* spaces of list items. This workaround originates in the usage of
* the Static Site Editor to edit the Handbook. The Handbook uses a
* Markdown parser called Kramdown interprets lines indented
* with two spaces as content within a list. For example:
*
* 1. ordered list
* - nested unordered list
*
* The Static Site Editor uses a different Markdown parser based on the
* CommonMark specification (official Markdown spec) called ToastMark.
* When the SSE encounters a nested list with only two spaces, it flattens
* the list:
*
* 1. ordered list
* - nested unordered list
*
* This function attempts to correct this problem before the content is loaded
* by Toast UI.
*/
const correctNestedContentIndenation = source => {
const lines = source.split('\n');
let topLevelOrderedListDetected = false;
return lines
.reduce((result, line) => {
if (topLevelOrderedListDetected && nestedLineRegexp.test(line)) {
return [...result, line.replace(nestedLineRegexp, repeat(' ', 4))];
}
topLevelOrderedListDetected = topLevelOrderedRegexp.test(line);
return [...result, line];
}, [])
.join('\n');
};
const removeOrphanedBrTags = source => { const removeOrphanedBrTags = source => {
/* Until the underlying Squire editor of Toast UI Editor resolves duplicate `<br>` tags, this /* Until the underlying Squire editor of Toast UI Editor resolves duplicate `<br>` tags, this
`replace` solution will clear out orphaned `<br>` tags that it generates. Additionally, `replace` solution will clear out orphaned `<br>` tags that it generates. Additionally,
...@@ -8,7 +50,7 @@ const removeOrphanedBrTags = source => { ...@@ -8,7 +50,7 @@ const removeOrphanedBrTags = source => {
}; };
const format = source => { const format = source => {
return removeOrphanedBrTags(source); return correctNestedContentIndenation(removeOrphanedBrTags(source));
}; };
export default format; export default format;
...@@ -96,7 +96,7 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) => ...@@ -96,7 +96,7 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
const isReferenceDefinition = Boolean(node.dataset.sseReferenceDefinition); const isReferenceDefinition = Boolean(node.dataset.sseReferenceDefinition);
return isReferenceDefinition return isReferenceDefinition
? `\n\n${node.innerText}\n` ? `\n\n${node.innerText}\n\n`
: baseRenderer.convert(node, subContent); : baseRenderer.convert(node, subContent);
}, },
}; };
......
---
title: Resolve Static Site Editor Flattens Mixed Lists
merge_request: 41599
author:
type: fixed
import formatter from '~/static_site_editor/services/formatter'; import formatter from '~/static_site_editor/services/formatter';
describe('formatter', () => { describe('static_site_editor/services/formatter', () => {
const source = `Some text const source = `Some text
<br> <br>
...@@ -23,4 +23,17 @@ And even more text`; ...@@ -23,4 +23,17 @@ And even more text`;
it('removes extraneous <br> tags', () => { it('removes extraneous <br> tags', () => {
expect(formatter(source)).toMatch(sourceWithoutBrTags); expect(formatter(source)).toMatch(sourceWithoutBrTags);
}); });
describe('ordered lists with incorrect content indentation', () => {
it.each`
input | result
${'12. ordered list item\n13.Next ordered list item'} | ${'12. ordered list item\n13.Next ordered list item'}
${'12. ordered list item\n - Next ordered list item'} | ${'12. ordered list item\n - Next ordered list item'}
${'12. ordered list item\n - Next ordered list item'} | ${'12. ordered list item\n - Next ordered list item'}
${'12. ordered list item\n Next ordered list item'} | ${'12. ordered list item\n Next ordered list item'}
${'1. ordered list item\n Next ordered list item'} | ${'1. ordered list item\n Next ordered list item'}
`('\ntransforms\n$input \nto\n$result', ({ input, result }) => {
expect(formatter(input)).toBe(result);
});
});
}); });
...@@ -178,7 +178,9 @@ describe('rich_content_editor/services/html_to_markdown_renderer', () => { ...@@ -178,7 +178,9 @@ describe('rich_content_editor/services/html_to_markdown_renderer', () => {
}); });
it('returns raw text when pre node has sse-reference-definitions class', () => { it('returns raw text when pre node has sse-reference-definitions class', () => {
expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(`\n\n${node.innerText}\n`); expect(htmlToMarkdownRenderer['PRE CODE'](node, subContent)).toBe(
`\n\n${node.innerText}\n\n`,
);
}); });
it('returns base result when pre node does not have sse-reference-definitions class', () => { it('returns base result when pre node does not have sse-reference-definitions class', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment