diff --git a/app/src/components/v-form/form-field.vue b/app/src/components/v-form/form-field.vue
index b4143f1faa..b49a14b00d 100644
--- a/app/src/components/v-form/form-field.vue
+++ b/app/src/components/v-form/form-field.vue
@@ -54,7 +54,7 @@
-
+
{{ validationMessage }}
@@ -65,7 +65,7 @@
diff --git a/app/src/modules/activity/routes/collection.vue b/app/src/modules/activity/routes/collection.vue
index ba5e65a604..311b83e11f 100644
--- a/app/src/modules/activity/routes/collection.vue
+++ b/app/src/modules/activity/routes/collection.vue
@@ -32,7 +32,7 @@
-
+
@@ -45,7 +45,7 @@ import { defineComponent, computed, ref } from '@vue/composition-api';
import ActivityNavigation from '../components/navigation.vue';
import { i18n } from '@/lang';
import usePreset from '@/composables/use-preset';
-import marked from 'marked';
+import { md } from '@/utils/md';
import FilterSidebarDetail from '@/views/private/components/filter-sidebar-detail';
import LayoutSidebarDetail from '@/views/private/components/layout-sidebar-detail';
import SearchInput from '@/views/private/components/search-input';
@@ -65,7 +65,7 @@ export default defineComponent({
return {
breadcrumb,
- marked,
+ md,
layout,
layoutOptions,
layoutQuery,
diff --git a/app/src/modules/collections/routes/collection.vue b/app/src/modules/collections/routes/collection.vue
index d04ccde37d..800db3902f 100644
--- a/app/src/modules/collections/routes/collection.vue
+++ b/app/src/modules/collections/routes/collection.vue
@@ -211,7 +211,7 @@
-
+
-
+
@@ -53,7 +53,7 @@ import useNavigation, { NavItem } from '../composables/use-navigation';
import router from '@/router';
import { useUserStore } from '@/stores';
-import marked from 'marked';
+import { md } from '@/utils/md';
export default defineComponent({
name: 'collections-overview',
@@ -93,7 +93,7 @@ export default defineComponent({
navItems,
navigateToCollection,
isAdmin,
- marked,
+ md,
};
function navigateToCollection(navItem: NavItem) {
diff --git a/app/src/modules/docs/routes/static.vue b/app/src/modules/docs/routes/static.vue
index dfbe40cae9..4a2cdd2607 100644
--- a/app/src/modules/docs/routes/static.vue
+++ b/app/src/modules/docs/routes/static.vue
@@ -20,7 +20,7 @@
-
+
@@ -30,7 +30,7 @@
import { AsyncComponent } from 'vue';
import { defineComponent, ref, computed } from '@vue/composition-api';
import DocsNavigation from '../components/navigation.vue';
-import marked from 'marked';
+import { md } from '@/utils/md';
const Markdown = () => import(/* webpackChunkName: 'markdown', webpackPrefetch: true */ '../components/markdown.vue');
@@ -97,7 +97,7 @@ export default defineComponent({
return lines.join('\n');
});
- return { markdown, title, markdownWithoutTitle, marked, path };
+ return { markdown, title, markdownWithoutTitle, md, path };
},
});
diff --git a/app/src/modules/files/components/file-info-sidebar-detail.vue b/app/src/modules/files/components/file-info-sidebar-detail.vue
index 72d30353a0..ca3f70fc40 100644
--- a/app/src/modules/files/components/file-info-sidebar-detail.vue
+++ b/app/src/modules/files/components/file-info-sidebar-detail.vue
@@ -112,7 +112,7 @@
-
+
@@ -121,7 +121,7 @@ import { defineComponent, computed, ref, watch } from '@vue/composition-api';
import readableMimeType from '@/utils/readable-mime-type';
import bytes from 'bytes';
import i18n from '@/lang';
-import marked from 'marked';
+import { md } from '@/utils/md';
import localizedFormat from '@/utils/localized-format';
import api, { addTokenToURL } from '@/api';
import { getRootPath } from '@/utils/get-root-path';
@@ -164,7 +164,7 @@ export default defineComponent({
userCreated,
userModified,
folder,
- marked,
+ md,
folderLink,
getRootPath,
fileLink,
diff --git a/app/src/modules/files/routes/collection.vue b/app/src/modules/files/routes/collection.vue
index a323297ab2..ee18973311 100644
--- a/app/src/modules/files/routes/collection.vue
+++ b/app/src/modules/files/routes/collection.vue
@@ -145,7 +145,7 @@
-
+
@@ -171,7 +171,7 @@ import FilterSidebarDetail from '@/views/private/components/filter-sidebar-detai
import LayoutSidebarDetail from '@/views/private/components/layout-sidebar-detail';
import AddFolder from '../components/add-folder.vue';
import SearchInput from '@/views/private/components/search-input';
-import marked from 'marked';
+import { md } from '@/utils/md';
import FolderPicker from '../components/folder-picker.vue';
import emitter, { Events } from '@/events';
import router from '@/router';
@@ -300,7 +300,7 @@ export default defineComponent({
layout,
filtersWithFolderAndType,
searchQuery,
- marked,
+ md,
moveToDialogActive,
moveToFolder,
moving,
diff --git a/app/src/modules/settings/routes/data-model/collections/collections.vue b/app/src/modules/settings/routes/data-model/collections/collections.vue
index 2dcb0fb298..3214d7bad7 100644
--- a/app/src/modules/settings/routes/data-model/collections/collections.vue
+++ b/app/src/modules/settings/routes/data-model/collections/collections.vue
@@ -86,7 +86,7 @@
-
+
@@ -104,7 +104,7 @@ import router from '@/router';
import { sortBy } from 'lodash';
import CollectionOptions from './components/collection-options.vue';
import CollectionsFilter from './components/collections-filter.vue';
-import marked from 'marked';
+import { md } from '@/utils/md';
const activeTypes = ref(['visible', 'hidden', 'unmanaged']);
@@ -143,7 +143,7 @@ export default defineComponent({
items,
openCollection,
activeTypes,
- marked,
+ md,
};
function useItems() {
diff --git a/app/src/modules/settings/routes/data-model/fields/fields.vue b/app/src/modules/settings/routes/data-model/fields/fields.vue
index 72fcf73a30..4b679484af 100644
--- a/app/src/modules/settings/routes/data-model/fields/fields.vue
+++ b/app/src/modules/settings/routes/data-model/fields/fields.vue
@@ -77,7 +77,7 @@
-
+
@@ -92,7 +92,7 @@ import FieldsManagement from './components/fields-management.vue';
import useItem from '@/composables/use-item';
import router from '@/router';
import { useCollectionsStore, useFieldsStore } from '@/stores';
-import marked from 'marked';
+import { md } from '@/utils/md';
export default defineComponent({
components: { SettingsNavigation, FieldsManagement },
@@ -145,7 +145,7 @@ export default defineComponent({
deleteAndQuit,
saveAndQuit,
hasEdits,
- marked,
+ md,
};
async function deleteAndQuit() {
diff --git a/app/src/modules/settings/routes/presets/collection/components/presets-info-sidebar-detail.vue b/app/src/modules/settings/routes/presets/collection/components/presets-info-sidebar-detail.vue
index 9a05286406..628313d633 100644
--- a/app/src/modules/settings/routes/presets/collection/components/presets-info-sidebar-detail.vue
+++ b/app/src/modules/settings/routes/presets/collection/components/presets-info-sidebar-detail.vue
@@ -13,14 +13,14 @@
-
+
diff --git a/app/src/modules/settings/routes/roles/collection.vue b/app/src/modules/settings/routes/roles/collection.vue
index 1a94e7b0bd..50e0048279 100644
--- a/app/src/modules/settings/routes/roles/collection.vue
+++ b/app/src/modules/settings/routes/roles/collection.vue
@@ -20,7 +20,7 @@
-
+
@@ -62,7 +62,7 @@ import SettingsNavigation from '../../components/navigation.vue';
import { i18n } from '@/lang';
import api from '@/api';
-import marked from 'marked';
+import { md } from '@/utils/md';
import { Header as TableHeader } from '@/components/v-table/types';
import ValueNull from '@/views/private/components/value-null';
import router from '@/router';
@@ -120,7 +120,7 @@ export default defineComponent({
return `/settings/roles/+`;
});
- return { marked, loading, roles, tableHeaders, addNewLink, navigateToRole };
+ return { md, loading, roles, tableHeaders, addNewLink, navigateToRole };
async function fetchRoles() {
loading.value = true;
diff --git a/app/src/modules/settings/routes/roles/item/components/role-info-sidebar-detail.vue b/app/src/modules/settings/routes/roles/item/components/role-info-sidebar-detail.vue
index 750edb87da..9b3f7be3f4 100644
--- a/app/src/modules/settings/routes/roles/item/components/role-info-sidebar-detail.vue
+++ b/app/src/modules/settings/routes/roles/item/components/role-info-sidebar-detail.vue
@@ -9,13 +9,13 @@
-
+
diff --git a/app/src/modules/settings/routes/webhooks/collection.vue b/app/src/modules/settings/routes/webhooks/collection.vue
index 197cac1b36..ceab849120 100644
--- a/app/src/modules/settings/routes/webhooks/collection.vue
+++ b/app/src/modules/settings/routes/webhooks/collection.vue
@@ -87,7 +87,7 @@
-
+
@@ -99,7 +99,7 @@
import { defineComponent, computed, ref } from '@vue/composition-api';
import SettingsNavigation from '../../components/navigation.vue';
import LayoutSidebarDetail from '@/views/private/components/layout-sidebar-detail';
-import marked from 'marked';
+import { md } from '@/utils/md';
import { LayoutComponent } from '@/layouts/types';
import { usePreset } from '@/composables/use-preset';
import api from '@/api';
@@ -134,7 +134,7 @@ export default defineComponent({
layoutQuery,
layout,
searchQuery,
- marked,
+ md,
clearFilters,
};
diff --git a/app/src/modules/settings/routes/webhooks/item.vue b/app/src/modules/settings/routes/webhooks/item.vue
index 0889fbde39..730eb0bf6b 100644
--- a/app/src/modules/settings/routes/webhooks/item.vue
+++ b/app/src/modules/settings/routes/webhooks/item.vue
@@ -60,7 +60,7 @@
-
+
@@ -75,7 +75,7 @@ import router from '@/router';
import RevisionsDrawerDetail from '@/views/private/components/revisions-drawer-detail';
import useItem from '@/composables/use-item';
import SaveOptions from '@/views/private/components/save-options';
-import marked from 'marked';
+import { md } from '@/utils/md';
import i18n from '@/lang';
export default defineComponent({
@@ -130,7 +130,7 @@ export default defineComponent({
saveAndAddNew,
saveAsCopyAndNavigate,
isBatch,
- marked,
+ md,
title,
validationErrors,
};
diff --git a/app/src/modules/users/components/user-info-sidebar-detail.vue b/app/src/modules/users/components/user-info-sidebar-detail.vue
index 39f0ed6c7f..13c422aa40 100644
--- a/app/src/modules/users/components/user-info-sidebar-detail.vue
+++ b/app/src/modules/users/components/user-info-sidebar-detail.vue
@@ -31,13 +31,13 @@
-
+
diff --git a/app/src/modules/users/routes/collection.vue b/app/src/modules/users/routes/collection.vue
index 3a80671db2..05383c48b5 100644
--- a/app/src/modules/users/routes/collection.vue
+++ b/app/src/modules/users/routes/collection.vue
@@ -128,7 +128,7 @@
-
+
@@ -148,7 +148,7 @@ import usePreset from '@/composables/use-preset';
import LayoutSidebarDetail from '@/views/private/components/layout-sidebar-detail';
import SearchInput from '@/views/private/components/search-input';
import { useUserStore, usePermissionsStore } from '@/stores';
-import marked from 'marked';
+import { md } from '@/utils/md';
import useNavigation from '../composables/use-navigation';
import DrawerBatch from '@/views/private/components/drawer-batch';
import { Role } from '@/types';
@@ -231,7 +231,7 @@ export default defineComponent({
layoutQuery,
layout,
searchQuery,
- marked,
+ md,
clearFilters,
userInviteModalActive,
refresh,
diff --git a/app/src/utils/md.ts b/app/src/utils/md.ts
new file mode 100644
index 0000000000..727c77b703
--- /dev/null
+++ b/app/src/utils/md.ts
@@ -0,0 +1,9 @@
+import marked from 'marked';
+import { sanitize } from 'dompurify';
+
+/**
+ * Render and sanitize a markdown string
+ */
+export function md(str: string) {
+ return sanitize(marked(str));
+}
diff --git a/app/src/views/private/components/comments-sidebar-detail/comment-item.vue b/app/src/views/private/components/comments-sidebar-detail/comment-item.vue
index 43cff4fcfd..55dad138c4 100644
--- a/app/src/views/private/components/comments-sidebar-detail/comment-item.vue
+++ b/app/src/views/private/components/comments-sidebar-detail/comment-item.vue
@@ -37,7 +37,7 @@
import { defineComponent, PropType, ref, computed, watch } from '@vue/composition-api';
import { Activity } from './types';
import CommentItemHeader from './comment-item-header.vue';
-import marked from 'marked';
+import { md } from '@/utils/md';
import useShortcut from '@/composables/use-shortcut';
import api from '@/api';
@@ -57,7 +57,7 @@ export default defineComponent({
},
setup(props) {
const textarea = ref();
- const htmlContent = computed(() => (props.activity.comment ? marked(props.activity.comment) : null));
+ const htmlContent = computed(() => (props.activity.comment ? md(props.activity.comment) : null));
const { edits, editing, savingEdits, saveEdits, cancelEditing } = useEdits();
diff --git a/app/src/views/public/public-view.vue b/app/src/views/public/public-view.vue
index 17ef355234..01adfa0b41 100644
--- a/app/src/views/public/public-view.vue
+++ b/app/src/views/public/public-view.vue
@@ -26,7 +26,7 @@
@@ -36,7 +36,7 @@
import { version } from '../../../package.json';
import { defineComponent, computed } from '@vue/composition-api';
import { useServerStore } from '@/stores';
-import marked from 'marked';
+import { md } from '@/utils/md';
import { getRootPath } from '@/utils/get-root-path';
export default defineComponent({
@@ -83,7 +83,7 @@ export default defineComponent({
return {
version,
artStyles,
- marked,
+ md,
branding: serverStore.state.info?.project,
foregroundURL,
logoURL,