Add URL parsing to the HighlightSidebar component

Resolves MS-881 #Complete
This commit is contained in:
Ramon Wenger 2024-02-13 16:48:22 +01:00
parent f0018e2e56
commit 376f2c5f82
3 changed files with 32 additions and 7 deletions

View File

@ -217,12 +217,15 @@ describe('Highlights', () => {
markText(); markText();
cy.getByDataCy('highlight-note').click(); cy.getByDataCy('highlight-note').click();
cy.wait('@AddHighlight'); cy.wait('@AddHighlight');
const note = 'Some noteworthy stuff'; const textPart = 'Some noteworthy stuff with a link to ';
const urlPart = 'https://hep.ch';
const note = `${textPart}${urlPart}`;
cy.getByDataCy('highlight-note-input').should('have.value', '').type(note); cy.getByDataCy('highlight-note-input').should('have.value', '').type(note);
cy.getByDataCy('highlight-note-save').click(); cy.getByDataCy('highlight-note-save').click();
cy.wait('@UpdateHighlight'); cy.wait('@UpdateHighlight');
cy.getByDataCy('highlight-note-save').should('not.exist'); cy.getByDataCy('highlight-note-save').should('not.exist');
cy.getByDataCy('highlight-note-text').should('have.text', note); cy.getByDataCy('highlight-note-text').should('contain.text', textPart);
cy.get(`[href="${urlPart}"]`).should('exist');
}); });
}); });

View File

@ -41,14 +41,16 @@
> >
</div> </div>
<div v-else> <div v-else>
<!-- .stop to prevent the click handler to close the sidebar (as the element won't be a child of the <!-- todo: is there any safety concern here? Should not be, as the user can only enter URLs, and also gets only
sidebar anymore once the event handler checks) --> their own content to be displayed -->
<!-- eslint-disable vue/no-v-html -->
<p <p
data-cy="highlight-note-text" data-cy="highlight-note-text"
class="highlight-sidebar__note" class="highlight-sidebar__note"
> v-html="noteWithUrls"
{{ note }} />
</p> <!-- .stop to prevent the click handler to close the sidebar (as the element won't be a child of the
sidebar anymore once the event handler checks) -->
<a <a
class="inline-title highlight-sidebar__edit-note" class="inline-title highlight-sidebar__edit-note"
@click.stop="enableEditMode" @click.stop="enableEditMode"
@ -67,6 +69,7 @@ export interface Props {
} }
import vAutoGrow from '@/directives/auto-grow'; import vAutoGrow from '@/directives/auto-grow';
import { computed } from '@vue/reactivity';
const emits = defineEmits(['close', 'update-text']); const emits = defineEmits(['close', 'update-text']);
const close = () => emits('close'); const close = () => emits('close');
@ -94,6 +97,21 @@ const save = () => {
emits('update-text', note.value); emits('update-text', note.value);
inEditMode.value = false; inEditMode.value = false;
}; };
const parseUrls = (text: string) => {
/* todo: is this correct (enough)? There are more complete regex patterns to find URLs, but we're not interested in all valid
* URLs (e.g. with protocol FTP, with an IP instead of a hostname, with usernames and ports, etc) */
const urls = text.match(/((((https?):\/\/)|(w{3}\.))[-\w@:%_+.~#?,&//=]+)/g) || []; // taken from https://codepen.io/zuhairtaha/pen/NmbGKJ
let parsedText = text;
for (const url of urls) {
parsedText = parsedText.replace(url, `<a class="text-link" target="_blank" href="${url}">${url}</a>`);
}
return parsedText;
};
const noteWithUrls = computed(() => {
return parseUrls(note.value);
});
</script> </script>
<style scoped lang="postcss"> <style scoped lang="postcss">

View File

@ -47,3 +47,7 @@
@reuse .regular-text; @reuse .regular-text;
color: var(--color-silver-dark); color: var(--color-silver-dark);
} }
.text-link {
text-decoration: underline;
}