1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-08-02 19:55:18 +02:00

feat: Add file type validation and sanitize markdown input in adventure components

This commit is contained in:
Sean Morley 2025-03-15 12:29:12 -04:00
parent 50a732b4d7
commit 7fbcf170d0
6 changed files with 84 additions and 8 deletions

View file

@ -40,6 +40,7 @@
"dependencies": {
"@lukulent/svelte-umami": "^0.0.3",
"@mapbox/togeojson": "^0.16.2",
"dompurify": "^3.2.4",
"emoji-picker-element": "^1.26.0",
"gsap": "^3.12.7",
"marked": "^15.0.4",

View file

@ -14,6 +14,9 @@ importers:
'@mapbox/togeojson':
specifier: ^0.16.2
version: 0.16.2
dompurify:
specifier: ^3.2.4
version: 3.2.4
emoji-picker-element:
specifier: ^1.26.0
version: 1.26.0
@ -816,6 +819,9 @@ packages:
'@types/supercluster@7.1.3':
resolution: {integrity: sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==}
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
'@vercel/nft@0.27.2':
resolution: {integrity: sha512-7LeioS1yE5hwPpQfD3DdH04tuugKjo5KrJk3yK5kAI3Lh76iSsK/ezoFQfzuT08X3ZASQOd1y9ePjLNI9+TxTQ==}
engines: {node: '>=16'}
@ -1093,6 +1099,9 @@ packages:
dlv@1.1.3:
resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==}
dompurify@3.2.4:
resolution: {integrity: sha512-ysFSFEDVduQpyhzAob/kkuJjf5zWkZD8/A9ywSp1byueyuCfHamrCBa14/Oc2iiB0e51B+NpxSl5gmzn+Ms/mg==}
earcut@2.2.4:
resolution: {integrity: sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==}
@ -2828,6 +2837,9 @@ snapshots:
dependencies:
'@types/geojson': 7946.0.14
'@types/trusted-types@2.0.7':
optional: true
'@vercel/nft@0.27.2':
dependencies:
'@mapbox/node-pre-gyp': 1.0.11
@ -3094,6 +3106,10 @@ snapshots:
dlv@1.1.3: {}
dompurify@3.2.4:
optionalDependencies:
'@types/trusted-types': 2.0.7
earcut@2.2.4: {}
eastasianwidth@0.2.0: {}

View file

@ -14,6 +14,57 @@
let categories: Category[] = [];
const allowedFileTypes = [
'.pdf',
'.doc',
'.docx',
'.xls',
'.xlsx',
'.ppt',
'.pptx',
'.txt',
'.png',
'.jpg',
'.jpeg',
'.gif',
'.webp',
'.mp4',
'.mov',
'.avi',
'.mkv',
'.mp3',
'.wav',
'.flac',
'.ogg',
'.m4a',
'.wma',
'.aac',
'.opus',
'.zip',
'.rar',
'.7z',
'.tar',
'.gz',
'.bz2',
'.xz',
'.zst',
'.lz4',
'.lzma',
'.lzo',
'.z',
'.tar.gz',
'.tar.bz2',
'.tar.xz',
'.tar.zst',
'.tar.lz4',
'.tar.lzma',
'.tar.lzo',
'.tar.z',
'gpx',
'md',
'pdf'
];
export let initialLatLng: { lat: number; lng: number } | null = null; // Used to pass the location from the map selection to the modal
let fileInput: HTMLInputElement;
@ -783,7 +834,7 @@
type="file"
id="fileInput"
class="file-input file-input-bordered w-full max-w-xs"
accept="image/*,video/*,audio/*,application/pdf,.gpx"
accept={allowedFileTypes.join(',')}
on:change={handleFileChange}
/>

View file

@ -1,6 +1,7 @@
<script lang="ts">
import { marked } from 'marked'; // Import the markdown parser
import { t } from 'svelte-i18n';
import DOMPurify from 'dompurify'; // Import DOMPurify to sanitize HTML
export let text: string | null | undefined = ''; // Markdown text
export let editor_height: string = 'h-64'; // Editor height
@ -8,7 +9,7 @@
// Function to parse markdown to HTML
const renderMarkdown = (markdown: string) => {
return marked(markdown);
return marked(markdown) as string;
};
// References for scroll syncing
@ -61,7 +62,7 @@
class="prose overflow-auto h-96 max-w-full w-full p-4 border border-base-300 rounded-lg bg-base-300"
bind:this={previewRef}
>
{@html renderMarkdown(text || '')}
{@html DOMPurify.sanitize(renderMarkdown(text || ''))}
</article>
{/if}
</div>

View file

@ -7,7 +7,7 @@
import { DefaultMarker, MapLibre, Popup, GeoJSON, LineLayer } from 'svelte-maplibre';
import { t } from 'svelte-i18n';
import { marked } from 'marked'; // Import the markdown parser
import DOMPurify from 'dompurify';
// @ts-ignore
import toGeoJSON from '@mapbox/togeojson';
@ -16,7 +16,7 @@
let geojson: any;
const renderMarkdown = (markdown: string) => {
return marked(markdown);
return marked(markdown) as string;
};
async function getGpxFiles() {
@ -369,7 +369,7 @@
<article
class="prose overflow-auto h-full max-w-full p-4 border border-base-300 rounded-lg"
>
{@html renderMarkdown(adventure.description)}
{@html DOMPurify.sanitize(renderMarkdown(adventure.description))}
</article>
{/if}
</div>