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:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-07-13 18:09:14 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-07-13 18:09:14 +0300
commita88c31d0ea1a79ca93fad357c3eb536b5e013e44 (patch)
treeb38023b2be7478fa706c7a95d08cdfad13f8d8c1 /app/assets/javascripts/vue_shared/components/source_viewer
parentaffec3ced2d85697d9a21d83e811285b030705f2 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared/components/source_viewer')
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/constants.js2
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/index.js6
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js25
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js15
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js46
-rw-r--r--app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue2
6 files changed, 94 insertions, 2 deletions
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 94ebbccb014..3ac35abcf3a 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/constants.js
@@ -145,3 +145,5 @@ export const BIDI_CHAR_TOOLTIP = __(
export const HLJS_COMMENT_SELECTOR = 'hljs-comment';
export const HLJS_ON_AFTER_HIGHLIGHT = 'after:highlight';
+
+export const NPM_URL = 'https://npmjs.com/package';
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 c9f7e5508be..5d24a3d110b 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,5 +1,6 @@
import { HLJS_ON_AFTER_HIGHLIGHT } from '../constants';
import wrapComments from './wrap_comments';
+import linkDependencies from './link_dependencies';
/**
* Registers our plugins for Highlight.js
@@ -8,6 +9,9 @@ import wrapComments from './wrap_comments';
*
* @param {Object} hljs - the Highlight.js instance.
*/
-export const registerPlugins = (hljs) => {
+export const registerPlugins = (hljs, fileType, rawContent) => {
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/link_dependencies.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js
new file mode 100644
index 00000000000..5b7650c56ae
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/link_dependencies.js
@@ -0,0 +1,25 @@
+import packageJsonLinker from './utils/package_json_linker';
+
+const DEPENDENCY_LINKERS = {
+ package_json: packageJsonLinker,
+};
+
+/**
+ * Highlight.js plugin for generating links to dependencies when viewing dependency files.
+ *
+ * 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
+ * @param {String} fileType - a string containing the file type
+ * @param {String} rawContent - raw (non-highlighted) file content
+ */
+export default (result, fileType, rawContent) => {
+ if (DEPENDENCY_LINKERS[fileType]) {
+ try {
+ // eslint-disable-next-line no-param-reassign
+ result.value = DEPENDENCY_LINKERS[fileType](result, rawContent);
+ } catch (e) {
+ // Shallowed (do nothing), in this case the original unlinked dependencies will be rendered.
+ }
+ }
+};
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js
new file mode 100644
index 00000000000..56ad55ef553
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/dependency_linker_util.js
@@ -0,0 +1,15 @@
+import { escape } from 'lodash';
+import { setAttributes } from '~/lib/utils/dom_utils';
+
+export const createLink = (href, innerText) => {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ const rel = 'nofollow noreferrer noopener';
+ const link = document.createElement('a');
+
+ setAttributes(link, { href: escape(href), rel });
+ link.innerText = escape(innerText);
+
+ return link.outerHTML;
+};
+
+export const generateHLJSOpenTag = (type) => `<span class="hljs-${escape(type)}">&quot;`;
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js
new file mode 100644
index 00000000000..d013d077ba3
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/plugins/utils/package_json_linker.js
@@ -0,0 +1,46 @@
+import { joinPaths } from '~/lib/utils/url_utility';
+import { NPM_URL } from '../../constants';
+import { createLink, generateHLJSOpenTag } from './dependency_linker_util';
+
+const attrOpenTag = generateHLJSOpenTag('attr');
+const stringOpenTag = generateHLJSOpenTag('string');
+const closeTag = '&quot;</span>';
+const DEPENDENCY_REGEX = new RegExp(
+ /*
+ * Detects dependencies inside of content that is highlighted by Highlight.js
+ * Example: <span class="hljs-attr">&quot;@babel/core&quot;</span><span class="hljs-punctuation">:</span> <span class="hljs-string">&quot;^7.18.5&quot;</span>
+ * Group 1: @babel/core
+ * Group 2: ^7.18.5
+ */
+ `${attrOpenTag}(.*)${closeTag}.*${stringOpenTag}(.*[0-9].*)(${closeTag})`,
+ 'gm',
+);
+
+const handleReplace = (original, packageName, version, dependenciesToLink) => {
+ const href = joinPaths(NPM_URL, packageName);
+ const packageLink = createLink(href, packageName);
+ const versionLink = createLink(href, version);
+ const closeAndOpenTag = `${closeTag}: ${attrOpenTag}`;
+ const dependencyToLink = dependenciesToLink[packageName];
+
+ if (dependencyToLink && dependencyToLink === version) {
+ return `${attrOpenTag}${packageLink}${closeAndOpenTag}${versionLink}${closeTag}`;
+ }
+
+ return original;
+};
+
+export default (result, raw) => {
+ const { dependencies, devDependencies, peerDependencies, optionalDependencies } = JSON.parse(raw);
+
+ const dependenciesToLink = {
+ ...dependencies,
+ ...devDependencies,
+ ...peerDependencies,
+ ...optionalDependencies,
+ };
+
+ return result.value.replace(DEPENDENCY_REGEX, (original, packageName, version) =>
+ handleReplace(original, packageName, version, dependenciesToLink),
+ );
+};
diff --git a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
index 4ef37b1d059..ccc8b44942a 100644
--- a/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
+++ b/app/assets/javascripts/vue_shared/components/source_viewer/source_viewer.vue
@@ -141,7 +141,7 @@ export default {
let detectedLanguage = language;
let highlightedContent;
if (this.hljs) {
- registerPlugins(this.hljs);
+ registerPlugins(this.hljs, this.blob.fileType, this.content);
if (!detectedLanguage) {
const hljsHighlightAuto = this.hljs.highlightAuto(content);
highlightedContent = hljsHighlightAuto.value;