diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-11 18:07:26 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-05-11 18:07:26 +0300 |
commit | 6282dd78339f98cbc5624e7fdf744a342d3d8b73 (patch) | |
tree | 50952cb7a6f9ead4c805c20227871d3be845cc98 /app/assets/javascripts/content_editor | |
parent | b9ab87c14ce9ebe8284aeffa32c1cee934156e58 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/content_editor')
-rw-r--r-- | app/assets/javascripts/content_editor/services/markdown_serializer.js | 28 | ||||
-rw-r--r-- | app/assets/javascripts/content_editor/services/serialization_helpers.js | 117 |
2 files changed, 127 insertions, 18 deletions
diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js index 6c8c562af8e..d665f24bba1 100644 --- a/app/assets/javascripts/content_editor/services/markdown_serializer.js +++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js @@ -48,7 +48,6 @@ import Text from '../extensions/text'; import Video from '../extensions/video'; import WordBreak from '../extensions/word_break'; import { - isPlainURL, renderCodeBlock, renderHardBreak, renderTable, @@ -62,36 +61,29 @@ import { renderHTMLNode, renderContent, preserveUnchanged, + bold, + italic, + link, + code, } from './serialization_helpers'; const defaultSerializerConfig = { marks: { - [Bold.name]: defaultMarkdownSerializer.marks.strong, - [Italic.name]: { open: '_', close: '_', mixable: true, expelEnclosingWhitespace: true }, - [Code.name]: defaultMarkdownSerializer.marks.code, + [Bold.name]: bold, + [Italic.name]: italic, + [Code.name]: code, [Subscript.name]: { open: '<sub>', close: '</sub>', mixable: true }, [Superscript.name]: { open: '<sup>', close: '</sup>', mixable: true }, [InlineDiff.name]: { mixable: true, - open(state, mark) { + open(_, mark) { return mark.attrs.type === 'addition' ? '{+' : '{-'; }, - close(state, mark) { + close(_, mark) { return mark.attrs.type === 'addition' ? '+}' : '-}'; }, }, - [Link.name]: { - open(state, mark, parent, index) { - return isPlainURL(mark, parent, index, 1) ? '<' : '['; - }, - close(state, mark, parent, index) { - const href = mark.attrs.canonicalSrc || mark.attrs.href; - - return isPlainURL(mark, parent, index, -1) - ? '>' - : `](${state.esc(href)}${mark.attrs.title ? ` ${state.quote(mark.attrs.title)}` : ''})`; - }, - }, + [Link.name]: link, [MathInline.name]: { open: (...args) => `$${defaultMarkdownSerializer.marks.code.open(...args)}`, close: (...args) => `${defaultMarkdownSerializer.marks.code.close(...args)}$`, diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js index 99aaee8f312..089d30edec7 100644 --- a/app/assets/javascripts/content_editor/services/serialization_helpers.js +++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js @@ -363,3 +363,120 @@ export function preserveUnchanged(render) { } }; } + +const generateBoldTags = (open = true) => { + return (_, mark) => { + const type = /^(\*\*|__|<strong|<b).*/.exec(mark.attrs.sourceMarkdown)?.[1]; + + switch (type) { + case '**': + case '__': + return type; + // eslint-disable-next-line @gitlab/require-i18n-strings + case '<strong': + case '<b': + return (open ? openTag : closeTag)(type.substring(1)); + default: + return '**'; + } + }; +}; + +export const bold = { + open: generateBoldTags(), + close: generateBoldTags(false), + mixable: true, + expelEnclosingWhitespace: true, +}; + +const generateItalicTag = (open = true) => { + return (_, mark) => { + const type = /^(\*|_|<em|<i).*/.exec(mark.attrs.sourceMarkdown)?.[1]; + + switch (type) { + case '*': + case '_': + return type; + // eslint-disable-next-line @gitlab/require-i18n-strings + case '<em': + case '<i': + return (open ? openTag : closeTag)(type.substring(1)); + default: + return '_'; + } + }; +}; + +export const italic = { + open: generateItalicTag(), + close: generateItalicTag(false), + mixable: true, + expelEnclosingWhitespace: true, +}; + +const generateCodeTag = (open = true) => { + return (_, mark) => { + const type = /^(`|<code).*/.exec(mark.attrs.sourceMarkdown)?.[1]; + + if (type === '<code') { + return (open ? openTag : closeTag)(type.substring(1)); + } + + return '`'; + }; +}; + +export const code = { + open: generateCodeTag(), + close: generateCodeTag(false), + mixable: true, + expelEnclosingWhitespace: true, +}; + +const LINK_HTML = 'linkHtml'; +const LINK_MARKDOWN = 'linkMarkdown'; + +const linkType = (sourceMarkdown) => { + const expression = /^(\[|<a).*/.exec(sourceMarkdown)?.[1]; + + if (!expression || expression === '[') { + return LINK_MARKDOWN; + } + + return LINK_HTML; +}; + +export const link = { + open(state, mark, parent, index) { + if (isPlainURL(mark, parent, index, 1)) { + return '<'; + } + + const { canonicalSrc, href, title, sourceMarkdown } = mark.attrs; + + if (linkType(sourceMarkdown) === LINK_MARKDOWN) { + return '['; + } + + const attrs = { href: state.esc(href || canonicalSrc) }; + + if (title) { + attrs.title = title; + } + + return openTag('a', attrs); + }, + close(state, mark, parent, index) { + if (isPlainURL(mark, parent, index, -1)) { + return '>'; + } + + const { canonicalSrc, href, title, sourceMarkdown } = mark.attrs; + + if (linkType(sourceMarkdown) === LINK_HTML) { + return closeTag('a'); + } + + return `](${state.esc(canonicalSrc || href)}${title ? ` ${state.quote(title)}` : ''})`; + }, +}; |