Skip to content

Commit 379ec29

Browse files
committed
refactor(announcements): Move duplicate markdown code into utils/markdown.js
1 parent 9077162 commit 379ec29

File tree

14 files changed

+67
-189
lines changed

14 files changed

+67
-189
lines changed

web/app/package-lock.json

Lines changed: 10 additions & 40 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

web/app/src/components/AnnouncementBanner.vue

Lines changed: 1 addition & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,8 @@
130130

131131
<script setup>
132132
import { computed, ref } from 'vue'
133-
import { marked } from 'marked'
134-
import DOMPurify from 'dompurify'
135133
import { XCircle, AlertTriangle, Info, CheckCircle, Circle, ChevronDown } from 'lucide-vue-next'
134+
import { formatAnnouncementMessage } from '@/utils/markdown'
136135
137136
// Props
138137
const props = defineProps({
@@ -237,55 +236,6 @@ const getTypeClasses = (type) => {
237236
return typeConfigs[type] || typeConfigs.none
238237
}
239238
240-
const escapeHtml = (value) => {
241-
if (value === null || value === undefined) {
242-
return ''
243-
}
244-
245-
return String(value)
246-
.replace(/&/g, '&amp;')
247-
.replace(/</g, '&lt;')
248-
.replace(/>/g, '&gt;')
249-
.replace(/"/g, '&quot;')
250-
.replace(/'/g, '&#39;')
251-
}
252-
253-
const renderer = new marked.Renderer()
254-
255-
renderer.link = (tokenOrHref, title, text) => {
256-
const tokenObject = typeof tokenOrHref === 'object' && tokenOrHref !== null
257-
? tokenOrHref
258-
: null
259-
260-
const href = tokenObject ? tokenObject.href : tokenOrHref
261-
const resolvedTitle = tokenObject ? tokenObject.title : title
262-
const resolvedText = tokenObject ? tokenObject.text : text
263-
264-
const url = escapeHtml(href || '')
265-
const titleAttribute = resolvedTitle ? ` title="${escapeHtml(resolvedTitle)}"` : ''
266-
const linkText = resolvedText || ''
267-
268-
return `<a href="${url}" target="_blank" rel="noopener noreferrer"${titleAttribute}>${linkText}</a>`
269-
}
270-
271-
marked.use({
272-
renderer,
273-
breaks: true,
274-
gfm: true,
275-
headerIds: false,
276-
mangle: false
277-
})
278-
279-
const formatAnnouncementMessage = (message) => {
280-
if (!message) {
281-
return ''
282-
}
283-
284-
const markdown = String(message)
285-
const html = marked.parse(markdown)
286-
return DOMPurify.sanitize(html, { ADD_ATTR: ['target', 'rel'] })
287-
}
288-
289239
const formatDate = (dateString) => {
290240
const date = new Date(dateString)
291241
const today = new Date()
@@ -349,22 +299,4 @@ const formatFullTimestamp = (timestamp) => {
349299
margin-left: 1.5rem;
350300
}
351301
}
352-
353-
.announcement-content :deep(a) {
354-
color: #1d4ed8;
355-
text-decoration: underline;
356-
font-weight: 500;
357-
}
358-
359-
.announcement-content :deep(a:hover) {
360-
color: #1e40af;
361-
}
362-
363-
.dark .announcement-content :deep(a) {
364-
color: #60a5fa;
365-
}
366-
367-
.dark .announcement-content :deep(a:hover) {
368-
color: #93c5fd;
369-
}
370302
</style>

0 commit comments

Comments
 (0)