diff --git a/client/index.html b/client/index.html index f418ffb15..91fe2e89f 100644 --- a/client/index.html +++ b/client/index.html @@ -6,16 +6,7 @@ Projectx - +
diff --git a/client/package.json b/client/package.json index 67a0302b9..107e0ad1d 100644 --- a/client/package.json +++ b/client/package.json @@ -31,6 +31,7 @@ "@vueuse/core": "^14.2.1", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "dompurify": "^3.3.3", "echarts": "^6.0.0", "howler": "^2.2.4", "lucide-vue-next": "^1.0.0", @@ -49,6 +50,7 @@ }, "devDependencies": { "@tsconfig/node24": "^24.0.4", + "@types/dompurify": "^3.2.0", "@types/jsdom": "^28.0.1", "@types/node": "^25.6.0", "@vitejs/plugin-vue": "^6.0.5", diff --git a/client/public/theme-init.js b/client/public/theme-init.js new file mode 100644 index 000000000..d25e609b8 --- /dev/null +++ b/client/public/theme-init.js @@ -0,0 +1,8 @@ +;(function () { + var theme = localStorage.getItem('theme') || (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light') + var accent = localStorage.getItem('accent') || 'neutral' + var radius = localStorage.getItem('radius') || 'default' + if (theme === 'dark') document.documentElement.classList.add('dark') + if (accent !== 'neutral') document.documentElement.classList.add('accent-' + accent) + if (radius !== 'default') document.documentElement.classList.add('radius-' + radius) +})() diff --git a/client/src/features/book/components/BookQuickView.vue b/client/src/features/book/components/BookQuickView.vue index bd3760712..9139b03e8 100644 --- a/client/src/features/book/components/BookQuickView.vue +++ b/client/src/features/book/components/BookQuickView.vue @@ -15,6 +15,7 @@ import { getFormatColor } from '../lib/format-colors' import { FORMAT_TO_GROUP } from '@projectx/types' import { COVER_ASPECT_RATIO_KEY, DEFAULT_COVER_ASPECT_RATIO } from '../lib/cover-aspect-ratio' import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip' +import { useSafeHtml } from '@/features/book/composables/useSafeHtml' const props = defineProps<{ bookId: number | null; open: boolean }>() const { hasPermission } = usePermissions() @@ -131,6 +132,7 @@ const providerLinks = computed(() => { const descriptionExpanded = ref(false) const genresExpanded = ref(false) const coverLightboxOpen = ref(false) +const safeDescription = useSafeHtml(() => detail.value?.description) const coverAspectRatio = inject(COVER_ASPECT_RATIO_KEY, ref(DEFAULT_COVER_ASPECT_RATIO)) @@ -373,7 +375,7 @@ function toggleGenres() {