chore: migrate svelte-markdown-preprocess (#655)

This commit is contained in:
Jason Rasmussen
2026-03-31 16:37:28 -04:00
committed by GitHub
parent 0f0ff38b0a
commit 0af8e4986d
32 changed files with 19 additions and 786 deletions
+1 -2
View File
@@ -1,4 +1,3 @@
{
"packages/ui": "0.70.0",
"packages/svelte-markdown-preprocess": "0.3.0"
"packages/ui": "0.70.0"
}
@@ -1,2 +0,0 @@
src/
tsconfig.json
@@ -1,147 +0,0 @@
# Changelog
## [0.3.0](https://github.com/immich-app/ui/compare/svelte-markdown-preprocess-v0.2.1...svelte-markdown-preprocess-v0.3.0) (2026-03-31)
### Features
* markdown image caption ([#654](https://github.com/immich-app/ui/issues/654)) ([fb7e9ae](https://github.com/immich-app/ui/commit/fb7e9aea1f29dbdc20ed49e8d288ab705b6c3254))
## 0.2.1 (2026-01-30)
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### 🐛 Bug fixes
* fix: dependencies by @jrasm91 in https://github.com/immich-app/ui/pull/563
**Full Changelog**: https://github.com/immich-app/ui/compare/svelte-markdown-preprocess-v0.2.0...svelte-markdown-preprocess-v0.2.1
## 0.2.0 (2026-01-30)
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### 🚀 Features
* feat: context menu by @jrasm91 in https://github.com/immich-app/ui/pull/368
* feat: required indicator by @bwees in https://github.com/immich-app/ui/pull/404
* feat: form modal by @danieldietzler in https://github.com/immich-app/ui/pull/402
* feat: badge by @jrasm91 in https://github.com/immich-app/ui/pull/412
* feat: date picker by @bwees in https://github.com/immich-app/ui/pull/413
* feat: progress bar by @insertish in https://github.com/immich-app/ui/pull/425
* feat: context menu button by @danieldietzler in https://github.com/immich-app/ui/pull/435
* feat: breadcrumbs by @jrasm91 in https://github.com/immich-app/ui/pull/438
* feat: tooltip by @alextran1502 in https://github.com/immich-app/ui/pull/467
* feat: image carousel by @jrasm91 in https://github.com/immich-app/ui/pull/499
* feat: basic modal by @jrasm91 in https://github.com/immich-app/ui/pull/505
* feat: tables by @jrasm91 in https://github.com/immich-app/ui/pull/511
* feat: list button by @danieldietzler in https://github.com/immich-app/ui/pull/527
* feat: control bar by @jrasm91 in https://github.com/immich-app/ui/pull/550
* feat: markdown improvements by @jrasm91 in https://github.com/immich-app/ui/pull/561
### 🌟 Enhancements
* feat: layer-aware command palette by @danieldietzler in https://github.com/immich-app/ui/pull/376
* feat: command palette shortcuts by @danieldietzler in https://github.com/immich-app/ui/pull/379
* feat: command palette shortcut visualization by @danieldietzler in https://github.com/immich-app/ui/pull/382
* feat: command palette $if by @danieldietzler in https://github.com/immich-app/ui/pull/394
* feat: context menu $if by @danieldietzler in https://github.com/immich-app/ui/pull/396
* feat: show all shortcuts for command by @danieldietzler in https://github.com/immich-app/ui/pull/420
* feat: open menu translation by @jrasm91 in https://github.com/immich-app/ui/pull/451
* feat: form onreset support by @jrasm91 in https://github.com/immich-app/ui/pull/504
* feat: remove prompt snippet by @jrasm91 in https://github.com/immich-app/ui/pull/506
* feat: add cancel text property by @jrasm91 in https://github.com/immich-app/ui/pull/508
* feat: text improvements by @jrasm91 in https://github.com/immich-app/ui/pull/529
* chore: stricter types for select components by @danieldietzler in https://github.com/immich-app/ui/pull/530
* chore: improve nested modal handling by @danieldietzler in https://github.com/immich-app/ui/pull/532
* feat: navbar improvements by @jrasm91 in https://github.com/immich-app/ui/pull/543
* fix: improve progress bar design by @meesfrensel in https://github.com/immich-app/ui/pull/544
### 🐛 Bug fixes
* fix: inconsistent card width by @danieldietzler in https://github.com/immich-app/ui/pull/375
* fix: dropdown options z-index on modal by @bwees in https://github.com/immich-app/ui/pull/377
* fix: modal manager export by @jrasm91 in https://github.com/immich-app/ui/pull/380
* fix: command shortcuts by @jrasm91 in https://github.com/immich-app/ui/pull/384
* fix: command palette reactivity by @danieldietzler in https://github.com/immich-app/ui/pull/387
* fix: menu manager interface by @jrasm91 in https://github.com/immich-app/ui/pull/392
* fix: button wrap text by @meesfrensel in https://github.com/immich-app/ui/pull/400
* fix: remove field top padding by @bwees in https://github.com/immich-app/ui/pull/414
* fix: revert field background color changes by @bwees in https://github.com/immich-app/ui/pull/415
* fix: remove modal open count by @danieldietzler in https://github.com/immich-app/ui/pull/417
* fix: modal scroll by @jrasm91 in https://github.com/immich-app/ui/pull/427
* fix: card scroll in modals by @jrasm91 in https://github.com/immich-app/ui/pull/436
* fix: exports by @jrasm91 in https://github.com/immich-app/ui/pull/440
* fix: toast panel attributes by @jrasm91 in https://github.com/immich-app/ui/pull/444
* fix: wrap long breadcrumbs by @jrasm91 in https://github.com/immich-app/ui/pull/452
* fix: broken action item data type by @jrasm91 in https://github.com/immich-app/ui/pull/453
* fix: hide trailing dividers by @jrasm91 in https://github.com/immich-app/ui/pull/454
* chore: expose more modal size options by @danieldietzler in https://github.com/immich-app/ui/pull/455
* fix: alert content width by @jrasm91 in https://github.com/immich-app/ui/pull/464
* fix: remove unnecessary cursor-pointer by @meesfrensel in https://github.com/immich-app/ui/pull/472
* fix: compare origin in external link check by @YarosMallorca in https://github.com/immich-app/ui/pull/462
* fix: focus outlines for buttons by @ben-basten in https://github.com/immich-app/ui/pull/477
* fix: autogrow textarea bugs during animation by @midzelis in https://github.com/immich-app/ui/pull/480
* fix: tooltip in toast by @alextran1502 in https://github.com/immich-app/ui/pull/485
* fix: ignore disabled shortcuts by @jrasm91 in https://github.com/immich-app/ui/pull/491
* fix: command palette by @jrasm91 in https://github.com/immich-app/ui/pull/493
* fix: command palette shortcuts by @jrasm91 in https://github.com/immich-app/ui/pull/494
* fix: optional icons by @jrasm91 in https://github.com/immich-app/ui/pull/496
* fix: better is-enabled checks by @jrasm91 in https://github.com/immich-app/ui/pull/498
* fix: on close by @jrasm91 in https://github.com/immich-app/ui/pull/509
* fix: field context by @jrasm91 in https://github.com/immich-app/ui/pull/514
* fix: title font size on different screen size by @alextran1502 in https://github.com/immich-app/ui/pull/519
* fix: select by @jrasm91 in https://github.com/immich-app/ui/pull/521
* fix: table html attributes by @jrasm91 in https://github.com/immich-app/ui/pull/522
* fix: navigate external links by @jrasm91 in https://github.com/immich-app/ui/pull/533
* fix: select bind value by @jrasm91 in https://github.com/immich-app/ui/pull/535
* fix: allow select empty strings by @jrasm91 in https://github.com/immich-app/ui/pull/537
* fix: borderless sidebar by @jrasm91 in https://github.com/immich-app/ui/pull/539
* fix: control bar color by @jrasm91 in https://github.com/immich-app/ui/pull/551
* chore: control bar tweaks by @jrasm91 in https://github.com/immich-app/ui/pull/553
* fix: app shell bar & types by @jrasm91 in https://github.com/immich-app/ui/pull/555
* fix: avatar by @jrasm91 in https://github.com/immich-app/ui/pull/557
## New Contributors
* @meesfrensel made their first contribution in https://github.com/immich-app/ui/pull/389
* @insertish made their first contribution in https://github.com/immich-app/ui/pull/425
* @YarosMallorca made their first contribution in https://github.com/immich-app/ui/pull/462
* @aviv926 made their first contribution in https://github.com/immich-app/ui/pull/486
**Full Changelog**: https://github.com/immich-app/ui/compare/svelte-markdown-preprocess-v0.1.0...svelte-markdown-preprocess-v0.2.0
## 0.1.0 (2025-10-30)
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### 🚀 Features
* feat: default layout by @jrasm91 in https://github.com/immich-app/ui/pull/365
**Full Changelog**: https://github.com/immich-app/ui/compare/svelte-markdown-preprocess-v0.0.2...svelte-markdown-preprocess-v0.1.0
## 0.0.2 (2025-10-29)
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### 🐛 Bug fixes
* fix: bad import by @jrasm91 in https://github.com/immich-app/ui/pull/355
* fix: markdown spacing by @jrasm91 in https://github.com/immich-app/ui/pull/359
* fix: curly braces in code by @jrasm91 in https://github.com/immich-app/ui/pull/363
**Full Changelog**: https://github.com/immich-app/ui/compare/svelte-markdown-preprocess-v0.0.1...svelte-markdown-preprocess-v0.0.2
## 0.0.1 (2025-10-28)
<!-- Release notes generated using configuration in .github/release.yml at main -->
## What's Changed
### 🐛 Bug fixes
* fix: markdown example by @jrasm91 in https://github.com/immich-app/ui/pull/350
**Full Changelog**: https://github.com/immich-app/ui/compare/svelte-markdown-preprocess-v0.0.0...svelte-markdown-preprocess-v0.0.1
## 0.0.0 (2025-10-27)
Initial commit
@@ -1,45 +0,0 @@
{
"name": "@immich/svelte-markdown-preprocess",
"version": "0.3.0",
"license": "GNU Affero General Public License version 3",
"repository": {
"type": "git",
"url": "git+https://github.com/immich-app/ui.git",
"directory": "packages/svelte-markdown-preprocess"
},
"scripts": {
"start": "npm run start:dev",
"build": "tsc --project ./tsconfig.json",
"test": "vitest",
"watch": "tsc --project ./tsconfig.json --watch"
},
"files": [
"dist",
"!dist/**/*.test.*",
"!dist/**/*.spec.*"
],
"types": "./dist/index.d.ts",
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
}
},
"peerDependencies": {
"svelte": "^5.0.0"
},
"dependencies": {
"front-matter": "^4.0.2",
"marked": "^17.0.0",
"node-emoji": "^2.2.0"
},
"devDependencies": {
"@types/node": "^24.12.0",
"vite": "^8.0.0",
"vitest": "^4.0.5"
},
"volta": {
"node": "24.14.1"
}
}
@@ -1,84 +0,0 @@
import fm from 'front-matter';
import { marked, MarkedExtension } from 'marked';
import { mkdirSync, writeFileSync } from 'node:fs';
import { dirname } from 'node:path';
import type { PreprocessorGroup } from 'svelte/compiler';
import { markedSvelte } from './marked-svelte.js';
import { SvelteFile } from './svelte-file.js';
type Layouts = Record<string, string>;
type Options = {
/** defaults to `@immich/ui` */
markdownPackageName?: string;
debugPath?: string;
layouts?: Layouts;
/** additional extensions to use with marked */
markedExtensions?: MarkedExtension[];
};
const resolveLayout = (layout?: string, layouts?: Layouts) => {
if (!layouts) {
return;
}
return layouts[layout || 'default'];
};
const SCRIPT_BODY_REGEX = /<script.*>(?<body>(.|\n)*?)<\/script>/;
const parse = (content: string) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
const { attributes, body: bodyParsed } = fm(content);
let scriptBody = '';
let body = bodyParsed;
const match = SCRIPT_BODY_REGEX.exec(body);
const bodyGroup = match?.groups?.body;
if (bodyGroup) {
scriptBody = bodyGroup.trim();
body = body.substring(match.index + match[0].length).trim();
}
return { attributes, body, scriptBody };
};
export const svelteMarkdownPreprocess = (options: Options) => {
const { layouts, debugPath, markdownPackageName = '@immich/ui', markedExtensions = [] } = options || {};
const md = marked.use(...markedExtensions, markedSvelte());
return {
name: '@immich/svelte-markdown-preprocess',
async markup({ content, filename }) {
if (!filename?.endsWith('.md')) {
return;
}
const { attributes, body, scriptBody } = parse(content);
const markup = await md.parse(body);
const file = new SvelteFile();
file.addScript(`import { Markdown } from '${markdownPackageName}';`);
const layout = resolveLayout(attributes.layout, layouts);
if (layout) {
file.addScript(`import Layout from '${layout}';`);
file.addTag(`<Layout attributes={${JSON.stringify(attributes)}}>`, '</Layout>');
}
file.addScript(scriptBody);
file.addTemplate(markup);
const code = file.export();
if (debugPath) {
const dir = dirname(debugPath);
mkdirSync(dir, { recursive: true });
writeFileSync(debugPath, code);
}
return { code };
},
} satisfies PreprocessorGroup;
};
@@ -1,127 +0,0 @@
import { MarkedExtension } from 'marked';
import { emojify } from 'node-emoji';
import { createAttributes, escapeSvelteCode, getIdFromText } from './utility.js';
export const markedSvelte = (): MarkedExtension => ({
tokenizer: {
code(src) {
if (src.startsWith(' ')) {
return false;
}
},
},
renderer: {
heading({ tokens, depth }) {
const text = this.parser.parseInline(tokens);
const id = getIdFromText(text);
switch (depth) {
case 1:
case 2:
case 3:
case 4:
case 5:
case 6: {
return `<Markdown.Heading id="${id}" level={${depth}}>${text}</Markdown.Heading>\n`;
}
}
return `<Markdown.Paragraph>${text}</Markdown.Paragraph>\n`;
},
list({ items, ordered, start }) {
const startAttribute = start && start !== 1 ? ` start={${start}}` : '';
let output = '';
output += `<Markdown.List ordered={${ordered}}${startAttribute}>\n`;
for (const item of items) {
const content = this.parser.parse(item.tokens);
const attributes = [item.task && 'task', item.checked && 'checked'].filter(Boolean);
output += `<Markdown.ListItem ${attributes.join(' ')}>${content}</Markdown.ListItem>\n`;
}
output += `</Markdown.List>\n`;
return output;
},
blockquote({ tokens }) {
const children = this.parser.parse(tokens);
return `<Markdown.BlockQuote>${children}</Markdown.BlockQuote>\n`;
},
paragraph({ tokens }) {
const children = this.parser.parseInline(tokens);
// pass through svelte syntax unchanged
if (
children.startsWith('{#') ||
children.startsWith('{/') ||
children.startsWith('{:') ||
children.startsWith('{@')
) {
return children;
}
return `<Markdown.Paragraph>${children}</Markdown.Paragraph>\n`;
},
text(token) {
if (token.type === 'text') {
return token.tokens ? this.parser.parseInline(token.tokens) : emojify(token.text);
}
return token.text;
},
image({ href, text: alt, title }) {
return `<Markdown.Image${createAttributes({ src: href, alt, title })}/>\n`;
},
space() {
return `<Markdown.Space />\n`;
},
table({ header, rows }) {
// table
let output = `<Markdown.Table>\n`;
// header
output += `<Markdown.TableHeader>\n`;
for (const cell of header) {
const content = this.parser.parseInline(cell.tokens);
output += `<Markdown.TableHeading>${content}</Markdown.TableHeading>\n`;
}
output += `</Markdown.TableHeader>\n`;
// body
output += `<Markdown.TableBody>\n`;
for (const row of rows) {
output += `<Markdown.TableRow>\n`;
for (const cell of row) {
const content = this.parser.parseInline(cell.tokens);
output += `<Markdown.TableCell>${content}</Markdown.TableCell>\n`;
}
output += `</Markdown.TableRow>\n`;
}
output += `</Markdown.TableBody>\n`;
output += `</Markdown.Table>\n`;
return output;
},
code({ text, lang }) {
const escaped = escapeSvelteCode(text);
return `<Markdown.Code lang="${lang}" code={\`${escaped}\`} multiline />\n`;
},
hr() {
return `<Markdown.LineBreak />\n`;
},
link({ href, title, text }) {
return `<Markdown.Link${createAttributes({ href, title })}>${text}</Markdown.Link>`;
},
codespan({ text }) {
return `<Markdown.Code code={\`${text}\`} />`;
},
},
});
@@ -1,42 +0,0 @@
export class SvelteFile {
private scripts: string[] = [];
private lines: string[] = [];
private closingTags: string[] = [];
addScript(line: string) {
if (line) {
this.scripts.push(line);
}
return this;
}
addTemplate(line: string) {
this.lines.push(line);
return this;
}
addTag(tag: string, closingTag: string) {
this.lines.push(tag);
this.closingTags.push(closingTag);
}
export() {
const lines: string[] = [];
lines.push(`<script lang="ts">`);
for (const line of this.scripts) {
lines.push(' ' + line);
}
lines.push('</script>');
for (const line of this.lines) {
lines.push(line);
}
for (const line of this.closingTags.toReversed()) {
lines.push(line);
}
return lines.join('\n');
}
}
@@ -1,27 +0,0 @@
import { describe, expect, it } from 'vitest';
import { escapeSvelteCode, getIdFromText } from './utility.js';
describe('utility', () => {
describe(getIdFromText.name, () => {
it('should generate a valid ID from text', () => {
const result = getIdFromText('Hello World!');
expect(result).toBe('hello-world');
});
});
describe(escapeSvelteCode.name, () => {
it('should escape curly braces', () => {
const code = "const test = { foo: 'bar' };";
const expected = `const test = \\{ foo: 'bar' \\};`;
expect(escapeSvelteCode(code)).toBe(expected);
});
it('should escape backtics', () => {
const code = 'console.log(`Hello World!`);';
const expected = 'console.log(\\`Hello World!\\`);';
expect(escapeSvelteCode(code)).toBe(expected);
});
});
});
@@ -1,34 +0,0 @@
export const getIdFromText = (text: string) => {
let id = text
.toLowerCase()
.replace(/<[^>]*>/g, '')
.replace(/[^a-z1-9 ]/g, '')
.replace(/\s+/g, '-');
if (id.endsWith('-')) {
id = id.slice(0, -1);
}
return id;
};
export const escapeSvelteCode = (text: string) => {
let escaped = text;
for (const char of ['{', '}', '`']) {
escaped = escaped.replaceAll(char, `\\${char}`);
}
return escaped;
};
export const createAttributes = (attributes: Record<string, string | null | undefined>) => {
const results = Object.entries(attributes)
.filter(([, value]) => !!value)
.map(([key, value]) => `${key}="${value}"`);
if (results.length === 0) {
return '';
}
return ' ' + results.join(' ');
};
@@ -1,169 +0,0 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`markup > should render 'code-block.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Code lang="ts" code={\`const foo = 'bar';\`} multiline />
",
}
`;
exports[`markup > should render 'code-block-curly-braces.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Code lang="ts" code={\`const name = 'world';
const message = \\\`Hello $\\{name\\}!\\\`;\`} multiline />
",
}
`;
exports[`markup > should render 'h1.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Heading id="heading-1" level={1}>Heading 1</Markdown.Heading>
",
}
`;
exports[`markup > should render 'h2.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Heading id="heading-2" level={2}>Heading 2</Markdown.Heading>
",
}
`;
exports[`markup > should render 'h3.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Heading id="heading-3" level={2}>Heading 3</Markdown.Heading>
",
}
`;
exports[`markup > should render 'h4.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Heading id="heading-4" level={2}>Heading 4</Markdown.Heading>
",
}
`;
exports[`markup > should render 'h5.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Heading id="heading-5" level={2}>Heading 5</Markdown.Heading>
",
}
`;
exports[`markup > should render 'h6.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Heading id="heading-6" level={2}>Heading 6</Markdown.Heading>
",
}
`;
exports[`markup > should render 'image.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is an image <Markdown.Image src="https://immich.app/"/>
This is an image with alt <Markdown.Image src="https://immich.app/" alt="alt text"/>
This is an image with alt and a title <Markdown.Image src="https://immich.app/," alt="alt text" title="title text"/>
</Markdown.Paragraph>
",
}
`;
exports[`markup > should render 'link.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is a <Markdown.Link href="https://immich.app/">link</Markdown.Link></Markdown.Paragraph>
",
}
`;
exports[`markup > should render 'link-shothand.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is a shorthand link: <Markdown.Link href="https://immich.app/">https://immich.app/</Markdown.Link></Markdown.Paragraph>
",
}
`;
exports[`markup > should render 'snippets.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
{#snippet postScript()}<Markdown.Space />
<Markdown.Paragraph>This should work</Markdown.Paragraph>
<Markdown.Space />
{/snippet}",
}
`;
exports[`markup > should render 'text-bold.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is <strong>bold</strong> text.</Markdown.Paragraph>
",
}
`;
exports[`markup > should render 'text-code.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is <Markdown.Code code={\`code\`} /> text.</Markdown.Paragraph>
",
}
`;
exports[`markup > should render 'text-italic.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is <em>italic</em> text.</Markdown.Paragraph>
",
}
`;
exports[`markup > should render 'text-strike-through.md' correctly 1`] = `
{
"code": "<script lang="ts">
import { Markdown } from '@immich/ui';
</script>
<Markdown.Paragraph>This is <del>strike-through</del> text.</Markdown.Paragraph>
",
}
`;
@@ -1,4 +0,0 @@
```ts
const name = 'world';
const message = `Hello ${name}!`;
```
@@ -1,3 +0,0 @@
```ts
const foo = 'bar';
```
@@ -1 +0,0 @@
# Heading 1
@@ -1 +0,0 @@
## Heading 2
@@ -1 +0,0 @@
## Heading 3
@@ -1 +0,0 @@
## Heading 4
@@ -1 +0,0 @@
## Heading 5
@@ -1 +0,0 @@
## Heading 6
@@ -1,3 +0,0 @@
This is an image ![](https://immich.app/)
This is an image with alt ![alt text](https://immich.app/)
This is an image with alt and a title ![alt text](https://immich.app/, 'title text')
@@ -1 +0,0 @@
This is a shorthand link: <https://immich.app/>
@@ -1 +0,0 @@
This is a [link](https://immich.app/)
@@ -1,5 +0,0 @@
{#snippet postScript()}
This should work
{/snippet}
@@ -1 +0,0 @@
This is **bold** text.
@@ -1 +0,0 @@
This is `code` text.
@@ -1 +0,0 @@
This is _italic_ text.
@@ -1 +0,0 @@
This is ~~strike-through~~ text.
@@ -1,21 +0,0 @@
import { basename } from 'node:path';
import { describe, expect, it } from 'vitest';
import { svelteMarkdownPreprocess } from '../src/index.js';
const fixtureMap: Record<string, { default: string }> = import.meta.glob('./fixtures/*.md', {
query: '?raw',
eager: true,
});
const fixtures = Object.entries(fixtureMap).map(([filepath, { default: content }]) => ({
filename: basename(filepath),
filepath,
content,
}));
describe('markup', () => {
it.each(fixtures)('should render $filename correctly', async ({ filename, content }) => {
const sut = svelteMarkdownPreprocess({});
const output = await sut.markup({ content, filename });
expect(output).toMatchSnapshot();
});
});
@@ -1,20 +0,0 @@
{
"compilerOptions": {
"declaration": true,
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": false,
"strict": true,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "./dist",
"types": ["vite/client", "node"],
"rootDir": "./src"
},
"include": ["src"],
"exclude": ["dist", "test", "**/*.spec.*", "vitest.config.js"]
}
@@ -1,7 +0,0 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
include: ['{src,test}/**/*.{test,spec}.{js,ts}'],
},
});
+1 -1
View File
@@ -60,7 +60,7 @@
"vitest": "^4.1.0"
},
"dependencies": {
"@immich/svelte-markdown-preprocess": "workspace:^",
"@immich/svelte-markdown-preprocess": "^0.3.0",
"@internationalized/date": "^3.10.0",
"@mdi/js": "^7.4.47",
"bits-ui": "^2.15.7",
+17 -28
View File
@@ -54,36 +54,11 @@ importers:
specifier: ^4.1.0
version: 4.1.1(@types/node@24.12.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@24.12.0)(esbuild@0.27.2)(jiti@2.6.1))
packages/svelte-markdown-preprocess:
dependencies:
front-matter:
specifier: ^4.0.2
version: 4.0.2
marked:
specifier: ^17.0.0
version: 17.0.5
node-emoji:
specifier: ^2.2.0
version: 2.2.0
svelte:
specifier: ^5.0.0
version: 5.55.0
devDependencies:
'@types/node':
specifier: ^24.12.0
version: 24.12.0
vite:
specifier: ^8.0.0
version: 8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@24.12.0)(esbuild@0.27.2)(jiti@2.6.1)
vitest:
specifier: ^4.0.5
version: 4.1.1(@types/node@24.12.0)(vite@8.0.3(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)(@types/node@24.12.0)(esbuild@0.27.2)(jiti@2.6.1))
packages/ui:
dependencies:
'@immich/svelte-markdown-preprocess':
specifier: workspace:^
version: link:../svelte-markdown-preprocess
specifier: ^0.3.0
version: 0.3.0(svelte@5.55.0)
'@internationalized/date':
specifier: ^3.10.0
version: 3.12.0
@@ -393,6 +368,11 @@ packages:
resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==}
engines: {node: '>=18.18'}
'@immich/svelte-markdown-preprocess@0.3.0':
resolution: {integrity: sha512-6xspWnOgaTi+TasteJgI6DjOGjBQQI30mOYiY/FnyEjczNbrV6r5SFWjNbR+JY+Umn7MsPcZf5yzomK+q5AThg==}
peerDependencies:
svelte: ^5.0.0
'@internationalized/date@3.12.0':
resolution: {integrity: sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==}
@@ -1965,6 +1945,13 @@ snapshots:
'@humanwhocodes/retry@0.4.3': {}
'@immich/svelte-markdown-preprocess@0.3.0(svelte@5.55.0)':
dependencies:
front-matter: 4.0.2
marked: 17.0.5
node-emoji: 2.2.0
svelte: 5.55.0
'@internationalized/date@3.12.0':
dependencies:
'@swc/helpers': 0.5.19
@@ -2235,6 +2222,7 @@ snapshots:
'@types/node@24.12.0':
dependencies:
undici-types: 7.16.0
optional: true
'@types/trusted-types@2.0.7': {}
@@ -3138,7 +3126,8 @@ snapshots:
typescript@6.0.2: {}
undici-types@7.16.0: {}
undici-types@7.16.0:
optional: true
unicode-emoji-modifier-base@1.0.0: {}
-3
View File
@@ -14,9 +14,6 @@
"packages": {
"packages/ui": {
"component": "ui"
},
"packages/svelte-markdown-preprocess": {
"component": "svelte-markdown-preprocess"
}
}
}