Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/rich_content_editor/services')
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js61
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js39
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js10
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js7
-rw-r--r--app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js10
10 files changed, 85 insertions, 66 deletions
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
index 70d29b5b3df..a9c5d442f62 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_custom_renderer.js
@@ -1,16 +1,18 @@
+import { union, mapValues } from 'lodash';
import renderBlockHtml from './renderers/render_html_block';
import renderKramdownList from './renderers/render_kramdown_list';
import renderKramdownText from './renderers/render_kramdown_text';
import renderIdentifierInstanceText from './renderers/render_identifier_instance_text';
import renderIdentifierParagraph from './renderers/render_identifier_paragraph';
-import renderEmbeddedRubyText from './renderers/render_embedded_ruby_text';
import renderFontAwesomeHtmlInline from './renderers/render_font_awesome_html_inline';
+import renderSoftbreak from './renderers/render_softbreak';
const htmlInlineRenderers = [renderFontAwesomeHtmlInline];
const htmlBlockRenderers = [renderBlockHtml];
const listRenderers = [renderKramdownList];
const paragraphRenderers = [renderIdentifierParagraph];
-const textRenderers = [renderKramdownText, renderEmbeddedRubyText, renderIdentifierInstanceText];
+const textRenderers = [renderKramdownText, renderIdentifierInstanceText];
+const softbreakRenderers = [renderSoftbreak];
const executeRenderer = (renderers, node, context) => {
const availableRenderer = renderers.find(renderer => renderer.canRender(node, context));
@@ -18,51 +20,20 @@ const executeRenderer = (renderers, node, context) => {
return availableRenderer ? availableRenderer.render(node, context) : context.origin();
};
-const buildCustomRendererFunctions = (customRenderers, defaults) => {
- const customTypes = Object.keys(customRenderers).filter(type => !defaults[type]);
- const customEntries = customTypes.map(type => {
- const fn = (node, context) => executeRenderer(customRenderers[type], node, context);
- return [type, fn];
- });
-
- return Object.fromEntries(customEntries);
-};
-
-const buildCustomHTMLRenderer = (
- customRenderers = { htmlBlock: [], htmlInline: [], list: [], paragraph: [], text: [] },
-) => {
- const defaults = {
- htmlBlock(node, context) {
- const allHtmlBlockRenderers = [...customRenderers.htmlBlock, ...htmlBlockRenderers];
-
- return executeRenderer(allHtmlBlockRenderers, node, context);
- },
- htmlInline(node, context) {
- const allHtmlInlineRenderers = [...customRenderers.htmlInline, ...htmlInlineRenderers];
-
- return executeRenderer(allHtmlInlineRenderers, node, context);
- },
- list(node, context) {
- const allListRenderers = [...customRenderers.list, ...listRenderers];
-
- return executeRenderer(allListRenderers, node, context);
- },
- paragraph(node, context) {
- const allParagraphRenderers = [...customRenderers.paragraph, ...paragraphRenderers];
-
- return executeRenderer(allParagraphRenderers, node, context);
- },
- text(node, context) {
- const allTextRenderers = [...customRenderers.text, ...textRenderers];
-
- return executeRenderer(allTextRenderers, node, context);
- },
+const buildCustomHTMLRenderer = customRenderers => {
+ const renderersByType = {
+ ...customRenderers,
+ htmlBlock: union(htmlBlockRenderers, customRenderers?.htmlBlock),
+ htmlInline: union(htmlInlineRenderers, customRenderers?.htmlInline),
+ list: union(listRenderers, customRenderers?.list),
+ paragraph: union(paragraphRenderers, customRenderers?.paragraph),
+ text: union(textRenderers, customRenderers?.text),
+ softbreak: union(softbreakRenderers, customRenderers?.softbreak),
};
- return {
- ...buildCustomRendererFunctions(customRenderers, defaults),
- ...defaults,
- };
+ return mapValues(renderersByType, renderers => {
+ return (node, context) => executeRenderer(renderers, node, context);
+ });
};
export default buildCustomHTMLRenderer;
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
index ed04765c871..868ede9426e 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/build_html_to_markdown_renderer.js
@@ -1,7 +1,12 @@
+/* eslint-disable @gitlab/require-i18n-strings */
import { defaults, repeat } from 'lodash';
const DEFAULTS = {
subListIndentSpaces: 4,
+ unorderedListBulletChar: '-',
+ incrementListMarker: false,
+ strong: '*',
+ emphasis: '_',
};
const countIndentSpaces = text => {
@@ -11,9 +16,18 @@ const countIndentSpaces = text => {
};
const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) => {
- const { subListIndentSpaces } = defaults(formattingPreferences, DEFAULTS);
- // eslint-disable-next-line @gitlab/require-i18n-strings
+ const {
+ subListIndentSpaces,
+ unorderedListBulletChar,
+ incrementListMarker,
+ strong,
+ emphasis,
+ } = defaults(formattingPreferences, DEFAULTS);
const sublistNode = 'LI OL, LI UL';
+ const unorderedListItemNode = 'UL LI';
+ const orderedListItemNode = 'OL LI';
+ const emphasisNode = 'EM, I';
+ const strongNode = 'STRONG, B';
return {
TEXT_NODE(node) {
@@ -47,6 +61,27 @@ const buildHTMLToMarkdownRender = (baseRenderer, formattingPreferences = {}) =>
return reindentedList;
},
+ [unorderedListItemNode](node, subContent) {
+ const baseResult = baseRenderer.convert(node, subContent);
+
+ return baseResult.replace(/^(\s*)([*|-])/, `$1${unorderedListBulletChar}`);
+ },
+ [orderedListItemNode](node, subContent) {
+ const baseResult = baseRenderer.convert(node, subContent);
+
+ return incrementListMarker ? baseResult : baseResult.replace(/^(\s*)\d+?\./, '$11.');
+ },
+ [emphasisNode](node, subContent) {
+ const result = baseRenderer.convert(node, subContent);
+
+ return result.replace(/(^[*_]{1}|[*_]{1}$)/g, emphasis);
+ },
+ [strongNode](node, subContent) {
+ const result = baseRenderer.convert(node, subContent);
+ const strongSyntax = repeat(strong, 2);
+
+ return result.replace(/^[*_]{2}/, strongSyntax).replace(/[*_]{2}$/, strongSyntax);
+ },
};
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
index 6436dcaae64..51ba033dff0 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/editor_service.js
@@ -1,6 +1,9 @@
import Vue from 'vue';
+import { defaults } from 'lodash';
import ToolbarItem from '../toolbar_item.vue';
import buildHtmlToMarkdownRenderer from './build_html_to_markdown_renderer';
+import buildCustomHTMLRenderer from './build_custom_renderer';
+import { TOOLBAR_ITEM_CONFIGS } from '../constants';
const buildWrapper = propsData => {
const instance = new Vue({
@@ -54,3 +57,10 @@ export const registerHTMLToMarkdownRenderer = editorApi => {
renderer: renderer.constructor.factory(renderer, buildHtmlToMarkdownRenderer(renderer)),
});
};
+
+export const getEditorOptions = externalOptions => {
+ return defaults({
+ customHTMLRenderer: buildCustomHTMLRenderer(externalOptions?.customRenderers),
+ toolbarItems: TOOLBAR_ITEM_CONFIGS.map(toolbarItem => generateToolbarItem(toolbarItem)),
+ });
+};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
index d96cadafdbb..1dcecd5fb8c 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/build_uneditable_token.js
@@ -34,7 +34,7 @@ export const buildUneditableCloseTokens = (token, tagType = TAG_TYPES.block) =>
export const buildTextToken = content => buildToken('text', null, { content });
-export const buildUneditableTokens = token => {
+export const buildUneditableBlockTokens = token => {
return [...buildUneditableOpenTokens(token), buildUneditableCloseToken()];
};
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js
index 494057fc75b..0e122f598e5 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_embedded_ruby_text.js
@@ -1,4 +1,4 @@
-import { buildUneditableTokens } from './build_uneditable_token';
+import { renderUneditableLeaf as render } from './render_utils';
const embeddedRubyRegex = /(^<%.+%>$)/;
@@ -6,8 +6,4 @@ const canRender = ({ literal }) => {
return embeddedRubyRegex.test(literal);
};
-const render = (_, { origin }) => {
- return buildUneditableTokens(origin());
-};
-
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
index f5b4502ea3c..4ec45ecd3a7 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_identifier_paragraph.js
@@ -1,4 +1,4 @@
-import { buildUneditableOpenTokens, buildUneditableCloseToken } from './build_uneditable_token';
+import { renderUneditableBranch as render } from './render_utils';
const identifierRegex = /(^\[.+\]: .+)/;
@@ -10,7 +10,4 @@ const canRender = (node, context) => {
return isIdentifier(context.getChildrenText(node));
};
-const render = (_, { entering, origin }) =>
- entering ? buildUneditableOpenTokens(origin()) : buildUneditableCloseToken();
-
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js
index 491a26c81d0..949ca0e5c2a 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_list.js
@@ -1,4 +1,4 @@
-import { buildUneditableOpenTokens, buildUneditableCloseToken } from './build_uneditable_token';
+import { renderUneditableBranch as render } from './render_utils';
const isKramdownTOC = ({ type, literal }) => type === 'text' && literal === 'TOC';
@@ -21,7 +21,4 @@ const canRender = node => {
return false;
};
-const render = (_, { entering, origin }) =>
- entering ? buildUneditableOpenTokens(origin()) : buildUneditableCloseToken();
-
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js
index 01384699e4f..0551894918c 100644
--- a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_kramdown_text.js
@@ -1,4 +1,4 @@
-import { buildUneditableTokens } from './build_uneditable_token';
+import { renderUneditableLeaf as render } from './render_utils';
const kramdownRegex = /(^{:.+}$)/;
@@ -6,8 +6,4 @@ const canRender = ({ literal }) => {
return kramdownRegex.test(literal);
};
-const render = (_, { origin }) => {
- return buildUneditableTokens(origin());
-};
-
export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
new file mode 100644
index 00000000000..389ade5f27a
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_softbreak.js
@@ -0,0 +1,7 @@
+const canRender = node => ['emph', 'strong'].includes(node.parent?.type);
+const render = () => ({
+ type: 'text',
+ content: ' ',
+});
+
+export default { canRender, render };
diff --git a/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
new file mode 100644
index 00000000000..cec6491557b
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/rich_content_editor/services/renderers/render_utils.js
@@ -0,0 +1,10 @@
+import {
+ buildUneditableBlockTokens,
+ buildUneditableOpenTokens,
+ buildUneditableCloseToken,
+} from './build_uneditable_token';
+
+export const renderUneditableLeaf = (_, { origin }) => buildUneditableBlockTokens(origin());
+
+export const renderUneditableBranch = (_, { entering, origin }) =>
+ entering ? buildUneditableOpenTokens(origin()) : buildUneditableCloseToken();