diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 0b022929..ece94c32 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -17,6 +17,7 @@ updates: groups: build: patterns: + - mdsvex - sass - "svelte" - "svelte-*" diff --git a/docs/package.json b/docs/package.json index dcabd470..5da58926 100644 --- a/docs/package.json +++ b/docs/package.json @@ -19,6 +19,7 @@ "@sveltejs/adapter-static": "^3.0.8", "@sveltejs/kit": "^2.16.1", "@sveltejs/vite-plugin-svelte": "^5.0.3", + "mdsvex": "^0.12.3", "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.3", "sass": "^1.83.4", diff --git a/docs/src/lib/breadcrumbs.ts b/docs/src/lib/breadcrumbs.ts index fbf09e29..a63edd03 100644 --- a/docs/src/lib/breadcrumbs.ts +++ b/docs/src/lib/breadcrumbs.ts @@ -1,5 +1,8 @@ import type { Breadcrumb, BreadcrumbNames } from "./types"; +/** + * Get the breadcrumbs for the given route. + */ export function getBreadcrumbs( routeId: string | null, breadcrumbNames: BreadcrumbNames, @@ -17,15 +20,22 @@ export function getBreadcrumbs( return breadcrumbs; } +/** + * Import breadcrumb names from page modules. + * + * Supports both `export const breadcrumb` from +page.svelte files and the + * `title` and `breadcrumb` frontmatter properties from +page.md files. + * + * Resolves to an object mapping routes to breadcrumb names. + */ export async function loadBreadcrumbNames(): Promise { - const modules = import.meta.glob("../routes/**/+page.svelte"); + const modules = import.meta.glob("../routes/**/+page.*"); const names: BreadcrumbNames = {}; await Promise.all( Object.entries(modules).map(async ([key, value]) => { key = routeFromModulePath(key); if (!key) return; - const name = (await nameFromModule(value)) || nameFromKey(key); - names[key] = name; + names[key] = nameFromModule(await value()) || nameFromKey(key); }), ); return names; @@ -34,7 +44,7 @@ export async function loadBreadcrumbNames(): Promise { const routeSegmentPattern = /\/[^+.(\/]+/g; /** - * Strip the "../routes/" prefix, "/+page.svelte" suffix, and any route + * Strip the "../routes/" prefix, "/+page.*" suffix, and any route * "(group)/"s from the module path. */ function routeFromModulePath(path: string): string { @@ -48,9 +58,26 @@ function routeFromModulePath(path: string): string { return route; } -async function nameFromModule(mod: () => Promise): Promise { - const name = (await mod()).breadcrumb; - return typeof name === "string" ? name : ""; +function nameFromModule(mod: unknown): string | undefined { + if (typeof mod !== "object") { + return undefined; + } + + // Try getting `breadcrumb` export from svelte page component + if (typeof (mod as any).breadcrumb === "string") { + return (mod as any).breadcrumb; + } + + // Try getting frontmatter `breadcrumb` or `title` from markdown page + if (typeof (mod as any).metadata !== "object") { + return undefined; + } + if (typeof ((mod as any).metadata as any).breadcrumb === "string") { + return ((mod as any).metadata as any).breadcrumb; + } + if (typeof ((mod as any).metadata as any).title === "string") { + return ((mod as any).metadata as any).title; + } } function nameFromKey(key: string): string { diff --git a/docs/src/lib/markdown-nav.ts b/docs/src/lib/markdown-nav.ts new file mode 100644 index 00000000..7abaa60b --- /dev/null +++ b/docs/src/lib/markdown-nav.ts @@ -0,0 +1,29 @@ +import { base } from "$app/paths"; + +export type MarkdownNav = Array; +export type MarkdownNavItem = Record; +export type ParsedNav = Array; +export type ParsedNavItem = { link: Link; children?: ParsedNav }; +export type Link = { name: string; href: string }; + +export function parseNav(list?: MarkdownNav): ParsedNav | undefined { + if (!list || !list.length) return; + const result: ParsedNav = []; + for (const item of list) { + let link, children; + for (let [key, value] of Object.entries(item)) { + if (typeof value === "string") { + const href = value.charAt(0) === "#" ? value : `${base}${value}`; + link = { name: key, href }; + } else if (Array.isArray(value)) { + children = parseNav(value); + } + } + if (link) { + result.push({ link, children }); + } else { + console.error(`Invalid nav list: ${JSON.stringify(item)}`); + } + } + if (result.length) return result; +} diff --git a/docs/src/markdown/components/A.svelte b/docs/src/markdown/components/A.svelte new file mode 100644 index 00000000..e5e12202 --- /dev/null +++ b/docs/src/markdown/components/A.svelte @@ -0,0 +1,11 @@ + + + + {@render children?.()} + diff --git a/docs/src/markdown/layouts/default.svelte b/docs/src/markdown/layouts/default.svelte new file mode 100644 index 00000000..fa2a0f1f --- /dev/null +++ b/docs/src/markdown/layouts/default.svelte @@ -0,0 +1,41 @@ + + + + + + {title || "Manon"} + + +{#snippet navlist(items: ParsedNav)} +
    + {#each items as { link, children }} +
  • {link.name}
  • + {#if children}{@render navlist(children)}{/if} + {/each} +
+{/snippet} + +
+ {#if parsedNav} + {@render navlist(parsedNav)} + {/if} +
+ {@render children?.()} +
+
diff --git a/docs/src/md.d.ts b/docs/src/md.d.ts new file mode 100644 index 00000000..d0ec5270 --- /dev/null +++ b/docs/src/md.d.ts @@ -0,0 +1,7 @@ +declare module '*.md' { + import type { SvelteComponent } from 'svelte' + + export default class Comp extends SvelteComponent{} + + export const metadata: Record +} diff --git a/docs/src/routes/components/button-base/+page.svelte b/docs/src/routes/components/button-base/+page.svelte deleted file mode 100644 index de047593..00000000 --- a/docs/src/routes/components/button-base/+page.svelte +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - Knoppen (basisweergave) - - -
- - - - -
-
-

Knoppen (basisweergave)

-
-

button

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- Lorem ipsum -`} - /> -
- - - -
-

button uitgeschakeld

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- button primary -`} - /> -
- -
-

input type="button"

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- -`} - /> - -

input type="button" uitgeschakeld

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- -`} - /> -
- -
-

Bijbehorende bestanden

-

- Voor meer informatie over importeren en instellen van componenten. Zie: - Componenten gebruiken en styling toevoegen -

-

Import scss-file

- - -

Import via npm-package

- -
- - -
-
-
diff --git a/docs/src/routes/components/button-call-to-action/+page.svelte b/docs/src/routes/components/button-call-to-action/+page.svelte deleted file mode 100644 index 4e0de8a3..00000000 --- a/docs/src/routes/components/button-call-to-action/+page.svelte +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - Call to action button - - -
- - - - -
-
-

Call to action button

-
-

button

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- Lorem ipsum -`} - /> - -

button uitgeschakeld

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- button primary -`} - /> -
- -
-

input type="button"

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- -`} - /> - -

input type="button" uitgeschakeld

-

Visuele weergave:

- - - -

HTML-voorbeeld:

- -`} - /> -
- -
-

Bijbehorende bestanden

-

- Voor meer informatie over het importeren en instellen van componenten. Zie: - Componenten gebruiken en styling toevoegen -

-

Importeer component via npm

-

CSS-voorbeeld:

- -
- - -
-
-
diff --git a/docs/src/routes/components/button-container/+page.svelte b/docs/src/routes/components/button-container/+page.svelte deleted file mode 100644 index ec62c06f..00000000 --- a/docs/src/routes/components/button-container/+page.svelte +++ /dev/null @@ -1,197 +0,0 @@ - - - - - - Knoppen groeperen - - -
- - - -
-
-
-

Knoppen groeperen

- -

Benodigde stappen:

-
    -
  1. - Voeg de benodigde bestanden toe aan het project. Voor een overzicht van de benodigde en - optionele bestanden zie: Bijbehorende bestanden. -
  2. -
  3. - Vul de variabelen met de gewenste stijlkeuzes. Voor meer informatie zie het overzicht - met instelbare variabelen. -
  4. -
  5. - Groepeer de knoppen binnen een <div> met de class - button-container. -
  6. -
-
- -
-

Voorbeelden:

- -

Paragraaf

-

Visueel voorbeeld:

-
- - -
- -

HTML-voorbeeld:

- - - -
-`} - /> - - -
-

Bijbehorende bestanden

-

- Voor meer informatie over importeren en instellen van componenten. Zie: - Componenten gebruiken en styling toevoegen -

- -

Importeer component via npm

- -

CSS-voorbeeld:

- -

- Let op: de volgode waarin de componenten geïmporteerd worden is belangrijk. Dit - component moet na de overige button-componenten geïmporteerd worden. -

-
- -
-

Instelbare variabelen

-

- Let op: De uitlijning van horizontaal uitgelijnde tags werken alleen in - combinatie met de class horizotal-view. -

-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Beschikbare instelbare variabelen:
VariabeleCSS-attribuutManon ingestelde waardeBreekpuntClass
--button-container-flex-directionflex-directionrow-button-container
--button-container-align-itemsalign-itemscenter-
--button-container-flex-wrapflex-wrapwrap-
--button-container-gapgapvar(--application-base-gap-medium)-
--button-container-padding-toppadding-top0-
--button-container-padding-rightpadding-right0-
--button-container-padding-bottompadding-bottom0-
--button-container-padding-leftpadding-left0-
-
- -

CSS

-

- Overzicht van de beschikbare variabelen om te kunnen gebruiken binnen de CSS van jouw - project. Kies en gebruik de benodigde variabelen. -

- -
- - - -
-
diff --git a/docs/src/routes/components/button/+page.md b/docs/src/routes/components/button/+page.md new file mode 100644 index 00000000..10b5d636 --- /dev/null +++ b/docs/src/routes/components/button/+page.md @@ -0,0 +1,87 @@ +--- +title: Knoppen +nav: + - Snelstart: "#quickstart" + - HTML-element kiezen: "#button-html" + - Soorten knoppen: "#button-types" +--- + +# Knoppen + +

Snelstart

+ +1. Bepaal welk HTML-element geschikt is. Zie [HTML-element kiezen](#button-html) + voor meer informatie. +2. Bepaal welke stijl geschikt is voor de knop. Kies een van de [soorten + knoppen](#button-types). +3. Kopiëer de voorbeeldcode van het gekozen component. + +

HTML-element kiezen

+ +Knoppen kunnen op verschillende manieren opgebouwd worden. Iets wat er visueel +als een knop uit ziet kan in de HTML een link zijn. Welk HTML-element geschikt +is hangt af van de situatie. In deze documentatie zetten we de verschillen met +situatieschetsen uiteen. + +Kies altijd voor het semantisch correcte HTML-element. Bijvoorbeeld een +`` voor een link en een ` + +#### HTML-voorbeeld: + +```html + +``` + +### Link als button: `a` + +#### Visuele weergave: + +Lorem ipsum + +#### HTML-voorbeeld: + +```html +Lorem ipsum +``` + +### `button` uitgeschakeld + +#### Visuele weergave: + + + +#### HTML-voorbeeld: + +```html + +``` + +### `input type="button"` + +#### Visuele weergave: + + + +#### HTML-voorbeeld: + +```html + +``` + +### `input type="button"` uitgeschakeld + +#### Visuele weergave: + + + +#### HTML-voorbeeld: + +```html + +``` + +

Bijbehorende bestanden

+ +Zie voor meer informatie over importeren en instellen van componenten [Componenten gebruiken en styling toevoegen](/documentation/import-styling). + +### Import via npm-package + +```scss +@use "@minvws/manon/button-base"; +``` + + + +- [Test- en voorbeelden-pagina](/components/button-test) diff --git a/docs/src/routes/components/button/button-container/+page.md b/docs/src/routes/components/button/button-container/+page.md new file mode 100644 index 00000000..7f315cde --- /dev/null +++ b/docs/src/routes/components/button/button-container/+page.md @@ -0,0 +1,86 @@ +--- +title: Knoppen groeperen +nav: + - Introductie: "#introduction" + - Voorbeelden: "#examples" + - Bijbehorende bestanden: "#requirements" + - Gerelateerde pagina's: "#related" +--- + +

Knoppen groeperen

+ +## Benodigde stappen + +1. Voeg de benodigde bestanden toe aan het project. Voor een overzicht van de benodigde en optionele bestanden zie: [Bijbehorende bestanden](#requirements). +2. Vul de variabelen met de gewenste stijlkeuzes. Voor meer informatie zie het overzicht met [instelbare variabelen](#variables). +3. Groepeer de knoppen binnen een `
` met de class `button-container`. + +

Voorbeelden

+ +### Paragraaf + +#### Visueel voorbeeld + +
+ + +
+ +#### HTML-voorbeeld + +```html +
+ + +
+``` + +

Bijbehorende bestanden

+ +Zie voor meer informatie over importeren en instellen van componenten: [Componenten gebruiken en styling toevoegen](/documentation/import-styling). + +### Importeer component via npm + +#### SCSS-voorbeeld + +```scss +@use "@minvws/manon/button-container"; +``` + +**Let op:** de volgorde waarin de componenten geïmporteerd worden is belangrijk. Dit component moet **na** de overige `button-`componenten geïmporteerd worden. + +

Instelbare variabelen

+ +**Let op:** De uitlijning van horizontaal uitgelijnde tags werken alleen in combinatie met de class `horizotal-view`. + +| Variabele | CSS-attribuut | Manon ingestelde waarde | Breekpunt | Class | +| ---------------------------------- | --------------------------------------------------------- | ---------------------------------- | --------- | ---------------- | +| \--button-container-flex-direction | [flex-direction](/documentation/variables#flex-direction) | row | \- | button-container | +| \--button-container-align-items | [align-items](/documentation/variables#align-items) | center | \- | +| \--button-container-flex-wrap | [flex-wrap](/documentation/variables#flex-wrap) | wrap | \- | +| \--button-container-gap | [gap](/documentation/variables#gap) | var(--application-base-gap-medium) | \- | +| \--button-container-padding-top | [padding-top](/documentation/variables#padding-top) | 0 | \- | +| \--button-container-padding-right | [padding-right](/documentation/variables#padding-right) | 0 | \- | +| \--button-container-padding-bottom | [padding-bottom](/documentation/variables#padding-bottom) | 0 | \- | +| \--button-container-padding-left | [padding-left](/documentation/variables#padding-left) | 0 | \- | + +### CSS + +Overzicht van de beschikbare variabelen om te kunnen gebruiken binnen de CSS van jouw project. Kies en gebruik de benodigde variabelen. + +```css +:root { + --button-container-flex-direction: ; + --button-container-align-items: ; + --button-container-flex-wrap: ; + --button-container-gap: ; + --button-container-padding-top: ; + --button-container-padding-right: ; + --button-container-padding-bottom: ; + --button-container-padding-left: ; +} +``` + + + +[Test- en voorbeelden-pagina](/components/button-container-test) diff --git a/docs/src/routes/components/button/call-to-action/+page.md b/docs/src/routes/components/button/call-to-action/+page.md new file mode 100644 index 00000000..65dc4197 --- /dev/null +++ b/docs/src/routes/components/button/call-to-action/+page.md @@ -0,0 +1,75 @@ +--- +title: Call to action button +nav: + - Voorbeelden: "#examples" + - Bijbehorende bestanden: "#requirements" + - Gerelateerde pagina's: "#related" +--- + +# Call to action button + +

Voorbeelden

+ +### ` + +#### HTML-voorbeeld + +```html + +``` + +### ` + +#### HTML-voorbeeld + +```html + +``` + +### `` + +#### Visuele weergave + + + +#### HTML-voorbeeld + +```html + +``` + +### `` + +#### Visuele weergave + + + +#### HTML-voorbeeld + +```html + +``` + +

Bijbehorende bestanden

+ +Zie voor meer informatie over het importeren en instellen van componenten: [Componenten gebruiken en styling toevoegen](/documentation/import-styling). + +### Importeer component via npm + +#### SCSS-voorbeeld + +```scss +@use "@minvws/manon/button-cta"; +``` + + + +[Test- en voorbeelden-pagina](/components/button-call-to-action-test) diff --git a/docs/svelte.config.js b/docs/svelte.config.js index 4b03915c..0628cf03 100644 --- a/docs/svelte.config.js +++ b/docs/svelte.config.js @@ -1,10 +1,13 @@ +import { fileURLToPath } from "node:url"; import adapter from "@sveltejs/adapter-static"; import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"; import { importAssets } from "svelte-preprocess-import-assets"; +import { mdsvex } from "mdsvex"; import { redirects } from "./src/redirects.js"; /** @type {import('@sveltejs/kit').Config} */ const config = { + extensions: [".svelte", ".md"], kit: { adapter: adapter(), prerender: { @@ -19,7 +22,19 @@ const config = { relative: true, }, }, - preprocess: [vitePreprocess(), importAssets()], + preprocess: [ + vitePreprocess(), + mdsvex({ + extensions: [".md"], + layout: { + _: fileURLToPath(import.meta.resolve("./src/markdown/layouts/default.svelte")), + }, + highlight: { + highlighter: (code, lang) => ``, + }, + }), + importAssets(), + ], }; export default config; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab5deec1..fed1c129 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: '@sveltejs/vite-plugin-svelte': specifier: ^5.0.3 version: 5.0.3(svelte@5.19.3)(vite@6.0.11(@types/node@20.11.30)(sass@1.83.4)(terser@5.29.2)) + mdsvex: + specifier: ^0.12.3 + version: 0.12.3(svelte@5.19.3) prettier: specifier: ^3.4.2 version: 3.4.2 @@ -548,6 +551,9 @@ packages: '@types/node@20.11.30': resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==} + '@types/unist@2.0.11': + resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} + acorn-typescript@1.4.13: resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} peerDependencies: @@ -890,6 +896,11 @@ packages: mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + mdsvex@0.12.3: + resolution: {integrity: sha512-C/uIJamjNo5PHHnR3JHqsBPoLcfUBpzRmAEB6FLMXI/s7XHOceswjDMKqSPEW2WHmYpKm0taZ3U20GSyhMridA==} + peerDependencies: + svelte: ^3.56.0 || ^4.0.0 || ^5.0.0-next.120 + meow@13.2.0: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} @@ -984,6 +995,13 @@ packages: engines: {node: '>=14'} hasBin: true + prism-svelte@0.4.7: + resolution: {integrity: sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ==} + + prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -1163,9 +1181,15 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + unist-util-stringify-position@2.0.3: + resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + vfile-message@2.0.4: + resolution: {integrity: sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==} + vite@6.0.11: resolution: {integrity: sha512-4VL9mQPKoHy4+FE0NnRE/kbY51TOfaknxAjt3fJbGJxhIpBZiqVzlZDEesWWsuREXHwNdAoOFZ9MkPEVXczHwg==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} @@ -1543,6 +1567,8 @@ snapshots: undici-types: 5.26.5 optional: true + '@types/unist@2.0.11': {} + acorn-typescript@1.4.13(acorn@8.14.0): dependencies: acorn: 8.14.0 @@ -1842,6 +1868,14 @@ snapshots: mdn-data@2.12.2: {} + mdsvex@0.12.3(svelte@5.19.3): + dependencies: + '@types/unist': 2.0.11 + prism-svelte: 0.4.7 + prismjs: 1.29.0 + svelte: 5.19.3 + vfile-message: 2.0.4 + meow@13.2.0: {} merge2@1.4.1: {} @@ -1913,6 +1947,10 @@ snapshots: prettier@3.4.2: {} + prism-svelte@0.4.7: {} + + prismjs@1.29.0: {} + queue-microtask@1.2.3: {} readdirp@4.1.1: {} @@ -2165,8 +2203,17 @@ snapshots: undici-types@5.26.5: optional: true + unist-util-stringify-position@2.0.3: + dependencies: + '@types/unist': 2.0.11 + util-deprecate@1.0.2: {} + vfile-message@2.0.4: + dependencies: + '@types/unist': 2.0.11 + unist-util-stringify-position: 2.0.3 + vite@6.0.11(@types/node@20.11.30)(sass@1.83.4)(terser@5.29.2): dependencies: esbuild: 0.24.2