diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-13 18:09:32 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-13 18:09:32 +0300 |
commit | bd25f1d9c685039381df23e49bc52cdcf4ec1b4a (patch) | |
tree | 33b3b16ae2ef653f74828f69742154122ff0ac2d /app/assets/javascripts/vue_shared/components/source_viewer | |
parent | 70ce746bd011b101605e6d84f141d1f0c3175831 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/source_viewer')
5 files changed, 48 insertions, 46 deletions
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue index 6395dbdac50..ffd0eea63a1 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue +++ b/app/assets/javascripts/vue_shared/components/source_viewer/components/chunk_line.vue @@ -48,7 +48,7 @@ export default { </div> <pre - class="gl-p-0! gl-w-full gl-overflow-visible! gl-border-none! code highlight gl-line-height-normal" + class="gl-p-0! gl-w-full gl-overflow-visible! gl-border-none! code highlight gl-line-height-0" ><code><span :id="`LC${number}`" v-safe-html="content" :lang="language" class="line" data-testid="content"></span></code></pre> </div> </template> diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js index 10489a4eff3..a28460dd58e 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js +++ b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js @@ -139,6 +139,4 @@ export const BIDI_CHARS_CLASS_LIST = 'unicode-bidi has-tooltip'; export const BIDI_CHAR_TOOLTIP = 'Potentially unwanted character detected: Unicode BiDi Control'; -export const HLJS_COMMENT_SELECTOR = 'hljs-comment'; - export const HLJS_ON_AFTER_HIGHLIGHT = 'after:highlight'; diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js index e38c9b8f66f..d694adf7147 100644 --- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js +++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js @@ -1,4 +1,4 @@ -import wrapComments from './wrap_comments'; +import wrapChildNodes from './wrap_child_nodes'; import linkDependencies from './link_dependencies'; import wrapBidiChars from './wrap_bidi_chars'; @@ -12,8 +12,8 @@ export const HLJS_ON_AFTER_HIGHLIGHT = 'after:highlight'; * @param {Object} hljs - the Highlight.js instance. */ export const registerPlugins = (hljs, fileType, rawContent) => { + hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapChildNodes }); hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapBidiChars }); - hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: wrapComments }); hljs.addPlugin({ [HLJS_ON_AFTER_HIGHLIGHT]: (result) => linkDependencies(result, fileType, rawContent), }); diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js new file mode 100644 index 00000000000..e0ba4b730a7 --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_child_nodes.js @@ -0,0 +1,45 @@ +import { escape } from 'lodash'; + +/** + * Highlight.js plugin for wrapping nodes with the correct selectors to ensure + * child-elements are highlighted correctly after we split up the result into chunks and lines. + * + * Plugin API: https://github.com/highlightjs/highlight.js/blob/main/docs/plugin-api.rst + * + * @param {Object} Result - an object that represents the highlighted result from Highlight.js + */ +const newlineRegex = /\r?\n/; +const generateClassName = (suffix) => (suffix ? `hljs-${escape(suffix)}` : ''); +const generateCloseTag = (includeClose) => (includeClose ? '</span>' : ''); +const generateHLJSTag = (kind, content = '', includeClose) => + `<span class="${generateClassName(kind)}">${escape(content)}${generateCloseTag(includeClose)}`; + +const format = (node, kind = '') => { + let buffer = ''; + + if (typeof node === 'string') { + buffer += node + .split(newlineRegex) + .map((newline) => generateHLJSTag(kind, newline, true)) + .join('\n'); + } else if (node.kind) { + const { children } = node; + if (children.length && children.length === 1) { + buffer += format(children[0], node.kind); + } else { + buffer += generateHLJSTag(node.kind); + children.forEach((subChild) => { + buffer += format(subChild, node.kind); + }); + buffer += `</span>`; + } + } + + return buffer; +}; + +export default (result) => { + // NOTE: We're using the private Emitter API here as we expect the Emitter API to be publicly available soon (https://github.com/highlightjs/highlight.js/issues/3621) + // eslint-disable-next-line no-param-reassign, no-underscore-dangle + result.value = result._emitter.rootNode.children.reduce((val, node) => val + format(node), ''); // Highlight.js expects the result param to be mutated for plugins to work +}; diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js deleted file mode 100644 index 8b52df83fdf..00000000000 --- a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/wrap_comments.js +++ /dev/null @@ -1,41 +0,0 @@ -import { HLJS_COMMENT_SELECTOR } from '../constants'; - -const createWrapper = (content) => { - const span = document.createElement('span'); - span.className = HLJS_COMMENT_SELECTOR; - - // eslint-disable-next-line no-unsanitized/property - span.innerHTML = content; - return span.outerHTML; -}; - -/** - * Highlight.js plugin for wrapping multi-line comments in the `hljs-comment` class. - * This ensures that multi-line comments are rendered correctly in the GitLab UI. - * - * Plugin API: https://github.com/highlightjs/highlight.js/blob/main/docs/plugin-api.rst - * - * @param {Object} Result - an object that represents the highlighted result from Highlight.js - */ -export default (result) => { - if (!result.value.includes(HLJS_COMMENT_SELECTOR)) return; - - let wrapComment = false; - - // eslint-disable-next-line no-param-reassign - result.value = result.value // Highlight.js expects the result param to be mutated for plugins to work - .split('\n') - .map((lineContent) => { - const includesClosingTag = lineContent.includes('</span>'); - if (lineContent.includes(HLJS_COMMENT_SELECTOR) && !includesClosingTag) { - wrapComment = true; - return lineContent; - } - const line = wrapComment ? createWrapper(lineContent) : lineContent; - if (includesClosingTag) { - wrapComment = false; - } - return line; - }) - .join('\n'); -}; |