feat(geschichten): frontend foundation — canBlogWrite, sanitize util, nav, i18n
- Derives canBlogWrite in +layout.server.ts the same way as canAnnotate. - Adds Geschichten link to AppNav (desktop + mobile, between Stammbaum and Admin). - Adds error_geschichte_not_found mapping to errors.ts and translation keys for the Geschichten index, detail, editor, and confirmation copy in de/en/es. - Adds isomorphic-dompurify-backed safeHtml() helper with allow-list matching the backend OWASP policy (p/br/strong/em/h2/h3/ul/ol/li), plus Vitest spec. - Updates legacy spec test data so the new required canBlogWrite layout prop type-checks. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
17
frontend/src/lib/utils/sanitize.ts
Normal file
17
frontend/src/lib/utils/sanitize.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import DOMPurify from 'isomorphic-dompurify';
|
||||
|
||||
const ALLOWED_TAGS = ['p', 'br', 'strong', 'em', 'h2', 'h3', 'ul', 'ol', 'li'];
|
||||
|
||||
/**
|
||||
* Render-side sanitiser for Geschichte body HTML. The backend already
|
||||
* sanitises with the OWASP allow-list on save, but we re-run on render
|
||||
* because the API can be called directly and stored content can pre-date
|
||||
* a tightening of the allow-list.
|
||||
*/
|
||||
export function safeHtml(raw: string | null | undefined): string {
|
||||
if (!raw) return '';
|
||||
return DOMPurify.sanitize(raw, {
|
||||
ALLOWED_TAGS,
|
||||
ALLOWED_ATTR: []
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user