[Notebook] Links, Restricted Notebook Links, Search links (#6344)

* big simplification and enhancement to highlight component and added formatting for locked notebooks as well

* fix typo, fix logic
This commit is contained in:
Jamie V 2023-02-15 11:05:28 -08:00 committed by GitHub
parent 64f300d466
commit d4496cba41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 95 deletions

View File

@ -64,7 +64,7 @@
tabindex="0" tabindex="0"
> >
<TextHighlight <TextHighlight
:text="entryText" :text="formatValidUrls(entry.text)"
:highlight="highlightText" :highlight="highlightText"
:highlight-class="'search-highlight'" :highlight-class="'search-highlight'"
/> />
@ -94,7 +94,7 @@
class="c-ne__text" class="c-ne__text"
contenteditable="false" contenteditable="false"
tabindex="0" tabindex="0"
v-html="formattedText" v-bind.prop="formattedText"
> >
</div> </div>
</template> </template>
@ -228,7 +228,9 @@ export default {
}, },
selectedEntryId: { selectedEntryId: {
type: String, type: String,
required: true default() {
return '';
}
} }
}, },
data() { data() {
@ -236,7 +238,7 @@ export default {
editMode: false, editMode: false,
canEdit: true, canEdit: true,
enableEmbedsWrapperScroll: false, enableEmbedsWrapperScroll: false,
urlWhitelist: null urlWhitelist: []
}; };
}, },
computed: { computed: {
@ -248,28 +250,15 @@ export default {
}, },
formattedText() { formattedText() {
// remove ANY tags // remove ANY tags
let text = sanitizeHtml(this.entry.text, SANITIZATION_SCHEMA); const text = sanitizeHtml(this.entry.text, SANITIZATION_SCHEMA);
if (this.editMode || !this.urlWhitelist) { if (this.editMode || this.urlWhitelist.length === 0) {
return { innerText: text }; return { innerText: text };
} }
text = text.replace(URL_REGEX, (match) => { const html = this.formatValidUrls(text);
const url = new URL(match);
const domain = url.hostname;
let result = match;
let isMatch = this.urlWhitelist.find((partialDomain) => {
return domain.endsWith(partialDomain);
});
if (isMatch) { return { innerHTML: html };
result = `<a class="c-hyperlink" target="_blank" href="${match}">${match}</a>`;
}
return result;
});
return { innerHTML: text };
}, },
isSelectedEntry() { isSelectedEntry() {
return this.selectedEntryId === this.entry.id; return this.selectedEntryId === this.entry.id;
@ -355,6 +344,22 @@ export default {
deleteEntry() { deleteEntry() {
this.$emit('deleteEntry', this.entry.id); this.$emit('deleteEntry', this.entry.id);
}, },
formatValidUrls(text) {
return text.replace(URL_REGEX, (match) => {
const url = new URL(match);
const domain = url.hostname;
let result = match;
let isMatch = this.urlWhitelist.find((partialDomain) => {
return domain.endsWith(partialDomain);
});
if (isMatch) {
result = `<a class="c-hyperlink" target="_blank" href="${match}">${match}</a>`;
}
return result;
});
},
manageEmbedLayout() { manageEmbedLayout() {
if (this.$refs.embeds) { if (this.$refs.embeds) {
const embedsWrapperLength = this.$refs.embedsWrapper.clientWidth; const embedsWrapperLength = this.$refs.embedsWrapper.clientWidth;

View File

@ -21,24 +21,13 @@
*****************************************************************************/ *****************************************************************************/
<template> <template>
<!-- eslint-disable-next-line vue/no-v-html -->
<span> <span v-html="highlightedText"></span>
<span
v-for="segment in segments"
:key="segment.id"
:style="getStyles(segment)"
:class="{ [highlightClass] : segment.type === 'highlight' }"
>
{{ segment.text }}
</span>
</span>
</template> </template>
<script> <script>
import { v4 as uuid } from 'uuid';
export default { export default {
props: { props: {
text: { text: {
@ -58,68 +47,11 @@ export default {
} }
} }
}, },
data() { computed: {
return { highlightedText() {
segments: [] let regex = new RegExp(`(?<!<[^>]*)(${this.highlight})`, 'gi');
};
},
watch: {
highlight() {
this.highlightText();
},
text() {
this.highlightText();
}
},
mounted() {
this.highlightText();
},
methods: {
addHighlightSegment(segment) {
this.segments.push({
id: uuid(),
text: segment,
type: 'highlight',
spaceBefore: segment.startsWith(' '),
spaceAfter: segment.endsWith(' ')
});
},
addTextSegment(segment) {
this.segments.push({
id: uuid(),
text: segment,
type: 'text',
spaceBefore: segment.startsWith(' '),
spaceAfter: segment.endsWith(' ')
});
},
getStyles(segment) {
let styles = {
display: 'inline-block'
};
if (segment.spaceBefore) { return this.text.replace(regex, `<span class="${this.highlightClass}">${this.highlight}</span>`);
styles.paddingLeft = '.33em';
}
if (segment.spaceAfter) {
styles.paddingRight = '.33em';
}
return styles;
},
highlightText() {
this.segments = [];
let regex = new RegExp('(' + this.highlight + ')', 'gi');
let textSegments = this.text.split(regex);
for (let i = 0; i < textSegments.length; i++) {
if (textSegments[i].toLowerCase() === this.highlight.toLowerCase()) {
this.addHighlightSegment(textSegments[i]);
} else {
this.addTextSegment(textSegments[i]);
}
}
} }
} }
}; };