diff --git a/frontend/src/utils/index.js b/frontend/src/utils/index.js index 2261349c..f560d061 100644 --- a/frontend/src/utils/index.js +++ b/frontend/src/utils/index.js @@ -162,20 +162,21 @@ export function getEditorTools() { config: { services: { youtube: { - regex: /(?:https?:\/\/)?(?:www\.)?(?:(?:youtu\.be\/)|(?:youtube\.com)\/(?:v\/|u\/\w\/|embed\/|watch))(?:(?:\?v=)?([^#&?=]*))?((?:[?&]\w*=\w*)*)/, + regex: /^(?:https?:\/\/)?(?:www\.)?(?:(?:youtu\.be\/)|(?:youtube\.com)\/(?:v\/|u\/\w\/|embed\/|watch))(?:(?:\?v=)?([^#&?=]*))?((?:[?&]\w*=\w*)*)$/, embedUrl: '<%= remote_id %>', /* 'https://www.youtube.com/embed/<%= remote_id %>?origin=https://plyr.io&iv_load_policy=3&modestbranding=1&playsinline=1&showinfo=0&rel=0&enablejsapi=1' */ html: `
`, id: ([id]) => id, }, vimeo: { - regex: /(?:http[s]?:\/\/)?(?:www\.)?vimeo\.com\/(\d+)/, - embedUrl: '<%= remote_id %>', + regex: /^(?:http[s]?:\/\/)?(?:www\.)?vimeo\.com\/(\d+)(?:\/([a-zA-Z0-9]+))?(?:\?[^\s]*)?$/, + embedUrl: + 'https://player.vimeo.com/video/<%= remote_id %>', html: `
`, - id: ([id]) => id, + id: ([id, hash]) => (hash ? `${id}?h=${hash}` : id), }, cloudflareStream: { - regex: /https:\/\/customer-[a-z0-9]+\.cloudflarestream\.com\/([a-f0-9]{32})\/watch/, + regex: /^https:\/\/customer-[a-z0-9]+\.cloudflarestream\.com\/([a-f0-9]{32})\/watch$/, embedUrl: 'https://iframe.videodelivery.net/<%= remote_id %>', html: ``, }, bunnyStream: { - regex: /https:\/\/(?:iframe\.mediadelivery\.net|video\.bunnycdn\.com)\/play\/([a-zA-Z0-9]+\/[a-zA-Z0-9-]+)/, + regex: /^https:\/\/(?:iframe\.mediadelivery\.net|video\.bunnycdn\.com)\/play\/([a-zA-Z0-9]+\/[a-zA-Z0-9-]+)$/, embedUrl: 'https://iframe.mediadelivery.net/embed/<%= remote_id %>', html: ``, }, drive: { - regex: /https:\/\/drive\.google\.com\/file\/d\/([A-Za-z0-9_-]+)\/view(\?.+)?/, + regex: /^https:\/\/drive\.google\.com\/file\/d\/([A-Za-z0-9_-]+)\/view(\?.+)?$/, embedUrl: 'https://drive.google.com/file/d/<%= remote_id %>/preview', html: ``, }, docsPublic: { - regex: /https:\/\/docs\.google\.com\/document\/d\/([A-Za-z0-9_-]+)\/edit(\?.+)?/, + regex: /^https:\/\/docs\.google\.com\/document\/d\/([A-Za-z0-9_-]+)\/edit(\?.+)?$/, embedUrl: 'https://docs.google.com/document/d/<%= remote_id %>/preview', html: "", }, sheetsPublic: { - regex: /https:\/\/docs\.google\.com\/spreadsheets\/d\/([A-Za-z0-9_-]+)\/edit(\?.+)?/, + regex: /^https:\/\/docs\.google\.com\/spreadsheets\/d\/([A-Za-z0-9_-]+)\/edit(\?.+)?$/, embedUrl: 'https://docs.google.com/spreadsheets/d/<%= remote_id %>/preview', html: "", }, slidesPublic: { - regex: /https:\/\/docs\.google\.com\/presentation\/d\/([A-Za-z0-9_-]+)\/edit(\?.+)?/, + regex: /^https:\/\/docs\.google\.com\/presentation\/d\/([A-Za-z0-9_-]+)\/edit(\?.+)?$/, embedUrl: 'https://docs.google.com/presentation/d/<%= remote_id %>/embed', html: "", diff --git a/frontend/src/utils/markdownParser.js b/frontend/src/utils/markdownParser.js index 493bcb47..1e3cf6dd 100644 --- a/frontend/src/utils/markdownParser.js +++ b/frontend/src/utils/markdownParser.js @@ -1,5 +1,6 @@ import { CodeXml } from 'lucide-vue-next' import { createApp, h } from 'vue' +import { escapeHTML } from '@/utils' export class Markdown { constructor({ data, api, readOnly, config }) { @@ -301,7 +302,7 @@ export class Markdown { _parseInlineMarkdown(text) { if (!text) return '' - let html = this._escapeHtml(text) + let html = escapeHTML(text) html = html.replace(/`([^`]+)`/g, '$1') @@ -316,15 +317,6 @@ export class Markdown { return html } - _escapeHtml(text) { - return text - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, ''') - } - _togglePlaceholder() { const blocks = document.querySelectorAll( '.cdx-block.ce-paragraph[data-placeholder]' @@ -429,16 +421,6 @@ export class Markdown { return { alt: '', url: '' } } - _isLink(text) { - return /\[.+?\]\(.+?\)/.test(text) - } - - _extractLink(text) { - const match = text.match(/\[(.+?)\]\((.+?)\)/) - if (match) return { text: match[1], url: match[2] } - return { text: '', url: '' } - } - _isEmbed(text) { return /^https?:\/\/.+/.test(text.trim()) }