diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-20 12:16:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-20 12:16:11 +0300 |
commit | edaa33dee2ff2f7ea3fac488d41558eb5f86d68c (patch) | |
tree | 11f143effbfeba52329fb7afbd05e6e2a3790241 /app/assets/javascripts/content_editor | |
parent | d8a5691316400a0f7ec4f83832698f1988eb27c1 (diff) |
Add latest changes from gitlab-org/gitlab@14-7-stable-eev14.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/content_editor')
9 files changed, 82 insertions, 30 deletions
diff --git a/app/assets/javascripts/content_editor/components/wrappers/frontmatter.vue b/app/assets/javascripts/content_editor/components/wrappers/frontmatter.vue index 97b69afd12e..e8829d00986 100644 --- a/app/assets/javascripts/content_editor/components/wrappers/frontmatter.vue +++ b/app/assets/javascripts/content_editor/components/wrappers/frontmatter.vue @@ -20,7 +20,7 @@ export default { }; </script> <template> - <node-view-wrapper class="gl-relative code highlight" as="pre"> + <node-view-wrapper class="content-editor-code-block gl-relative code highlight" as="pre"> <span data-testid="frontmatter-label" class="gl-absolute gl-top-0 gl-right-3" diff --git a/app/assets/javascripts/content_editor/constants.js b/app/assets/javascripts/content_editor/constants.js index 4af9dc8e405..5e56078df01 100644 --- a/app/assets/javascripts/content_editor/constants.js +++ b/app/assets/javascripts/content_editor/constants.js @@ -49,3 +49,10 @@ export const LOADING_ERROR_EVENT = 'loadingError'; export const PARSE_HTML_PRIORITY_LOWEST = 1; export const PARSE_HTML_PRIORITY_DEFAULT = 50; export const PARSE_HTML_PRIORITY_HIGHEST = 100; + +export const EXTENSION_PRIORITY_LOWER = 75; +/** + * 100 is the default priority in Tiptap + * https://tiptap.dev/guide/custom-extensions/#priority + */ +export const EXTENSION_PRIORITY_DEFAULT = 100; diff --git a/app/assets/javascripts/content_editor/extensions/code.js b/app/assets/javascripts/content_editor/extensions/code.js index f93c22ad10e..53f6d9b995c 100644 --- a/app/assets/javascripts/content_editor/extensions/code.js +++ b/app/assets/javascripts/content_editor/extensions/code.js @@ -1 +1,12 @@ -export { Code as default } from '@tiptap/extension-code'; +import Code from '@tiptap/extension-code'; +import { EXTENSION_PRIORITY_LOWER } from '../constants'; + +export default Code.extend({ + excludes: null, + /** + * Reduce the rendering priority of the code mark to + * ensure the bold, italic, and strikethrough marks + * are rendered first. + */ + priority: EXTENSION_PRIORITY_LOWER, +}); diff --git a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js index ea51bee3ba9..9dc17fcd570 100644 --- a/app/assets/javascripts/content_editor/extensions/code_block_highlight.js +++ b/app/assets/javascripts/content_editor/extensions/code_block_highlight.js @@ -19,7 +19,14 @@ export default CodeBlockLowlight.extend({ }; }, renderHTML({ HTMLAttributes }) { - return ['div', ['pre', HTMLAttributes, ['code', {}, 0]]]; + return [ + 'pre', + { + ...HTMLAttributes, + class: `content-editor-code-block ${HTMLAttributes.class}`, + }, + ['code', {}, 0], + ]; }, }).configure({ lowlight, diff --git a/app/assets/javascripts/content_editor/extensions/frontmatter.js b/app/assets/javascripts/content_editor/extensions/frontmatter.js index c09c10bc524..9842027e192 100644 --- a/app/assets/javascripts/content_editor/extensions/frontmatter.js +++ b/app/assets/javascripts/content_editor/extensions/frontmatter.js @@ -14,9 +14,20 @@ export default CodeBlockHighlight.extend({ }, ]; }, + addCommands() { + return { + setFrontmatter: (attributes) => ({ commands }) => { + return commands.setNode(this.name, attributes); + }, + toggleFrontmatter: (attributes) => ({ commands }) => { + return commands.toggleNode(this.name, 'paragraph', attributes); + }, + }; + }, addNodeView() { return new VueNodeViewRenderer(FrontmatterWrapper); }, + addInputRules() { return []; }, diff --git a/app/assets/javascripts/content_editor/extensions/image.js b/app/assets/javascripts/content_editor/extensions/image.js index d7fb617f7ee..519f7f168ce 100644 --- a/app/assets/javascripts/content_editor/extensions/image.js +++ b/app/assets/javascripts/content_editor/extensions/image.js @@ -66,6 +66,17 @@ export default Image.extend({ }, ]; }, + renderHTML({ HTMLAttributes }) { + return [ + 'img', + { + src: HTMLAttributes.src, + alt: HTMLAttributes.alt, + title: HTMLAttributes.title, + 'data-canonical-src': HTMLAttributes.canonicalSrc, + }, + ]; + }, addNodeView() { return VueNodeViewRenderer(ImageWrapper); }, diff --git a/app/assets/javascripts/content_editor/services/markdown_serializer.js b/app/assets/javascripts/content_editor/services/markdown_serializer.js index 278ef326c7a..d54fb7cded2 100644 --- a/app/assets/javascripts/content_editor/services/markdown_serializer.js +++ b/app/assets/javascripts/content_editor/services/markdown_serializer.js @@ -65,8 +65,8 @@ import { const defaultSerializerConfig = { marks: { [Bold.name]: defaultMarkdownSerializer.marks.strong, - [Code.name]: defaultMarkdownSerializer.marks.code, [Italic.name]: { open: '_', close: '_', mixable: true, expelEnclosingWhitespace: true }, + [Code.name]: defaultMarkdownSerializer.marks.code, [Subscript.name]: { open: '<sub>', close: '</sub>', mixable: true }, [Superscript.name]: { open: '<sup>', close: '</sup>', mixable: true }, [InlineDiff.name]: { diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js index ed5910fca18..4d5a54c0347 100644 --- a/app/assets/javascripts/content_editor/services/serialization_helpers.js +++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js @@ -1,4 +1,4 @@ -import { uniq } from 'lodash'; +import { uniq, isString } from 'lodash'; const defaultAttrs = { td: { colspan: 1, rowspan: 1, colwidth: null }, @@ -325,9 +325,12 @@ export function renderHardBreak(state, node, parent, index) { export function renderImage(state, node) { const { alt, canonicalSrc, src, title } = node.attrs; - const quotedTitle = title ? ` ${state.quote(title)}` : ''; - state.write(`![${state.esc(alt || '')}](${state.esc(canonicalSrc || src)}${quotedTitle})`); + if (isString(src) || isString(canonicalSrc)) { + const quotedTitle = title ? ` ${state.quote(title)}` : ''; + + state.write(`![${state.esc(alt || '')}](${state.esc(canonicalSrc || src)}${quotedTitle})`); + } } export function renderPlayable(state, node) { diff --git a/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js b/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js index 9b1cb76f845..eb1e4885ba6 100644 --- a/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js +++ b/app/assets/javascripts/content_editor/services/track_input_rules_and_shortcuts.js @@ -35,31 +35,33 @@ const trackInputRule = (contentType, inputRule) => { }; const trackInputRulesAndShortcuts = (tiptapExtension) => { - return tiptapExtension.extend({ - addKeyboardShortcuts() { - const shortcuts = this.parent?.() || {}; - const { name } = this; - /** - * We don’t want to track keyboard shortcuts - * that are not deliberately executed to create - * new types of content - */ - const dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY]; - const decorated = mapValues(shortcuts, (commandFn, shortcut) => - dotNotTrackKeys.includes(shortcut) - ? commandFn - : trackKeyboardShortcut(name, commandFn, shortcut), - ); + return tiptapExtension + .extend({ + addKeyboardShortcuts() { + const shortcuts = this.parent?.() || {}; + const { name } = this; + /** + * We don’t want to track keyboard shortcuts + * that are not deliberately executed to create + * new types of content + */ + const dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY]; + const decorated = mapValues(shortcuts, (commandFn, shortcut) => + dotNotTrackKeys.includes(shortcut) + ? commandFn + : trackKeyboardShortcut(name, commandFn, shortcut), + ); - return decorated; - }, - addInputRules() { - const inputRules = this.parent?.() || []; - const { name } = this; + return decorated; + }, + addInputRules() { + const inputRules = this.parent?.() || []; + const { name } = this; - return inputRules.map((inputRule) => trackInputRule(name, inputRule)); - }, - }); + return inputRules.map((inputRule) => trackInputRule(name, inputRule)); + }, + }) + .configure(tiptapExtension.options); }; export default trackInputRulesAndShortcuts; |