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-04-08 21:08:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-04-08 21:08:29 +0300
commit842ac3526cba09feb4b9ccefd0aeeb6edc02035d (patch)
tree2b73dca2be277685aefdc4f775c211049b4dae7c /app/assets/javascripts/code_navigation
parent9f9dc2bc412632e6b459d0bb9e1ac205c8cf34af (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/code_navigation')
-rw-r--r--app/assets/javascripts/code_navigation/components/app.vue6
-rw-r--r--app/assets/javascripts/code_navigation/store/actions.js6
-rw-r--r--app/assets/javascripts/code_navigation/store/mutations.js3
-rw-r--r--app/assets/javascripts/code_navigation/store/state.js1
-rw-r--r--app/assets/javascripts/code_navigation/utils/dom_utils.js31
-rw-r--r--app/assets/javascripts/code_navigation/utils/index.js17
6 files changed, 59 insertions, 5 deletions
diff --git a/app/assets/javascripts/code_navigation/components/app.vue b/app/assets/javascripts/code_navigation/components/app.vue
index d65b9a71288..81edbb4182e 100644
--- a/app/assets/javascripts/code_navigation/components/app.vue
+++ b/app/assets/javascripts/code_navigation/components/app.vue
@@ -23,6 +23,11 @@ export default {
required: false,
default: null,
},
+ wrapTextNodes: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
...mapState([
@@ -37,6 +42,7 @@ export default {
const initialData = {
blobs: [{ path: this.blobPath, codeNavigationPath: this.codeNavigationPath }],
definitionPathPrefix: this.pathPrefix,
+ wrapTextNodes: this.wrapTextNodes,
};
this.setInitialData(initialData);
}
diff --git a/app/assets/javascripts/code_navigation/store/actions.js b/app/assets/javascripts/code_navigation/store/actions.js
index 0b6b8437db5..562b78a891a 100644
--- a/app/assets/javascripts/code_navigation/store/actions.js
+++ b/app/assets/javascripts/code_navigation/store/actions.js
@@ -22,7 +22,7 @@ export default {
...d,
definitionLineNumber: parseInt(d.definition_path?.split('#L').pop() || 0, 10),
};
- addInteractionClass(path, d);
+ addInteractionClass({ path, d, wrapTextNodes: state.wrapTextNodes });
}
return acc;
}, {});
@@ -34,7 +34,9 @@ export default {
},
showBlobInteractionZones({ state }, path) {
if (state.data && state.data[path]) {
- Object.values(state.data[path]).forEach((d) => addInteractionClass(path, d));
+ Object.values(state.data[path]).forEach((d) =>
+ addInteractionClass({ path, d, wrapTextNodes: state.wrapTextNodes }),
+ );
}
},
showDefinition({ commit, state }, { target: el }) {
diff --git a/app/assets/javascripts/code_navigation/store/mutations.js b/app/assets/javascripts/code_navigation/store/mutations.js
index 07b190c7476..98beffe231c 100644
--- a/app/assets/javascripts/code_navigation/store/mutations.js
+++ b/app/assets/javascripts/code_navigation/store/mutations.js
@@ -1,9 +1,10 @@
import * as types from './mutation_types';
export default {
- [types.SET_INITIAL_DATA](state, { blobs, definitionPathPrefix }) {
+ [types.SET_INITIAL_DATA](state, { blobs, definitionPathPrefix, wrapTextNodes }) {
state.blobs = blobs;
state.definitionPathPrefix = definitionPathPrefix;
+ state.wrapTextNodes = wrapTextNodes;
},
[types.REQUEST_DATA](state) {
state.loading = true;
diff --git a/app/assets/javascripts/code_navigation/store/state.js b/app/assets/javascripts/code_navigation/store/state.js
index 569d2f7b319..17505b8392c 100644
--- a/app/assets/javascripts/code_navigation/store/state.js
+++ b/app/assets/javascripts/code_navigation/store/state.js
@@ -2,6 +2,7 @@ export default () => ({
blobs: [],
loading: false,
data: null,
+ wrapTextNodes: false,
currentDefinition: null,
currentDefinitionPosition: null,
currentBlobPath: null,
diff --git a/app/assets/javascripts/code_navigation/utils/dom_utils.js b/app/assets/javascripts/code_navigation/utils/dom_utils.js
new file mode 100644
index 00000000000..1a65c1a64a2
--- /dev/null
+++ b/app/assets/javascripts/code_navigation/utils/dom_utils.js
@@ -0,0 +1,31 @@
+const TEXT_NODE = 3;
+
+const isTextNode = ({ nodeType }) => nodeType === TEXT_NODE;
+
+const isBlank = (str) => !str || /^\s*$/.test(str);
+
+const isMatch = (s1, s2) => !isBlank(s1) && s1.trim() === s2.trim();
+
+const createSpan = (content) => {
+ const span = document.createElement('span');
+ span.innerText = content;
+ return span;
+};
+
+const wrapSpacesWithSpans = (text) => text.replace(/ /g, createSpan(' ').outerHTML);
+
+const wrapTextWithSpan = (el, text) => {
+ if (isTextNode(el) && isMatch(el.textContent, text)) {
+ const newEl = createSpan(text.trim());
+ el.replaceWith(newEl);
+ }
+};
+
+const wrapNodes = (text) => {
+ const wrapper = createSpan();
+ wrapper.innerHTML = wrapSpacesWithSpans(text);
+ wrapper.childNodes.forEach((el) => wrapTextWithSpan(el, text));
+ return wrapper.childNodes;
+};
+
+export { wrapNodes, isTextNode };
diff --git a/app/assets/javascripts/code_navigation/utils/index.js b/app/assets/javascripts/code_navigation/utils/index.js
index 6c078891ed4..0d72153d8fe 100644
--- a/app/assets/javascripts/code_navigation/utils/index.js
+++ b/app/assets/javascripts/code_navigation/utils/index.js
@@ -1,9 +1,11 @@
+import { wrapNodes, isTextNode } from './dom_utils';
+
export const cachedData = new Map();
export const getCurrentHoverElement = () => cachedData.get('current');
export const setCurrentHoverElement = (el) => cachedData.set('current', el);
-export const addInteractionClass = (path, d) => {
+export const addInteractionClass = ({ path, d, wrapTextNodes }) => {
const lineNumber = d.start_line + 1;
const lines = document
.querySelector(`[data-path="${path}"]`)
@@ -12,13 +14,24 @@ export const addInteractionClass = (path, d) => {
lines.forEach((line) => {
let charCount = 0;
+
+ if (wrapTextNodes) {
+ line.childNodes.forEach((elm) => {
+ if (isTextNode(elm)) {
+ // Highlight.js does not wrap all text nodes by default
+ // We need all text nodes to be wrapped in order to append code nav attributes
+ elm.replaceWith(...wrapNodes(elm.textContent));
+ }
+ });
+ }
+
const el = [...line.childNodes].find(({ textContent }) => {
if (charCount === d.start_char) return true;
charCount += textContent.length;
return false;
});
- if (el) {
+ if (el && !isTextNode(el)) {
el.setAttribute('data-char-index', d.start_char);
el.setAttribute('data-line-index', d.start_line);
el.classList.add('cursor-pointer', 'code-navigation', 'js-code-navigation');