Skip to content

Commit

Permalink
feat: add previous and next link to each doc page
Browse files Browse the repository at this point in the history
  • Loading branch information
quentinderoubaix committed Jan 23, 2024
1 parent c4e7eb1 commit 71cddee
Show file tree
Hide file tree
Showing 33 changed files with 286 additions and 64 deletions.
3 changes: 2 additions & 1 deletion demo/src/lib/markdown/Markdown.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import {marked} from 'marked';
import MdSection from '$lib/markdown/renderers/MdSection.svelte';
import MdImage from '$lib/markdown/renderers/MdImage.svelte';
import MdLink from '$lib/markdown/renderers/MdLink.svelte';
export let source: string;
Expand Down Expand Up @@ -40,7 +41,7 @@
}
$: tokens = getTokens(source);
const renderers: Partial<Renderers> = {image: MdImage, heading: Heading, code: MdCode, section: MdSection} as Partial<Renderers>;
const renderers: Partial<Renderers> = {image: MdImage, heading: Heading, code: MdCode, section: MdSection, link: MdLink} as Partial<Renderers>;
</script>

<SvelteMarkdown source={tokens} {renderers} />
25 changes: 25 additions & 0 deletions demo/src/lib/markdown/renderers/MdLink.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<script lang="ts">
import {page} from '$app/stores';
import type {Page} from '@sveltejs/kit';
export let href = '';
export let title: string;
const validMdRegex = /^\d{2}-([a-zA-Z-]*)\.md$/;
const categoryRegex = /\/\d{2}-([a-zA-Z-]*\/)/g;
const mdEndRegex = /\/\d{2}-([a-zA-Z-]*)\.md$/g;
function computedAppliedHref(inputHref: string, page: Page<Record<string, string>>) {
if (inputHref.startsWith('../')) {
return new URL(
inputHref.replace(categoryRegex, (_m, gr1) => '/' + gr1.toLowerCase()).replace(mdEndRegex, (_m, gr1) => '/' + gr1.toLowerCase()),
page.url.href,
).href;
} else {
return inputHref.match(validMdRegex)?.[1]?.toLowerCase() ?? href;
}
}
$: appliedHref = computedAppliedHref(href, $page);
</script>

<a href={appliedHref} {title}><slot /></a>
83 changes: 61 additions & 22 deletions demo/src/lib/server/index.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,70 @@
import {readFile, readdir} from 'node:fs/promises';

const validMdRegex = /^\d{2}-[a-z-]*\.md$/g;
const validMdRegex = /^\d{2}-[a-zA-Z-]*\.md$/g;

export async function listMarkdown() {
const categories = (await readdir(`../docs`)).filter((folder) => folder !== 'code');
const files: {slug: string; path: string}[] = [];
for (const category of categories) {
(await readdir(`../docs/${category}`))
.filter((file) => file.match(validMdRegex))
.forEach((file) => {
files.push({slug: `${category}/${file.slice(3, -3)}`, path: `../docs/${category}/${file}`});
});
}
return files;
}
const componentsSubMenu = [
{title: 'Accordion', slug: 'components/accordion/', subpath: 'examples'},
{title: 'Alert', slug: `components/alert/`, subpath: 'examples'},
{title: 'Modal', slug: `components/modal/`, subpath: 'examples'},
{title: 'Pagination', slug: `components/pagination/`, subpath: 'examples'},
{title: 'Progressbar', slug: `components/progressbar/`, subpath: 'examples'},
{title: 'Rating', slug: `components/rating/`, subpath: 'examples'},
{title: 'Select', slug: `components/select/`, subpath: 'examples'},
{title: 'Slider', slug: `components/slider/`, subpath: 'examples'},
];

export async function listPages() {
const docFolders = (await readdir(`../docs`)).filter((folder) => folder !== 'code');
const categories: {name: string; files: {slug: string; mdpath?: string; title: string; subpath: string}[]}[] = [];

export async function listSections(base: string) {
return (await readdir(`../docs/${base}`))
.filter((file) => file.match(validMdRegex))
.map((file) => {
const name = file.slice(3, -3);
return {name, title: name.substring(0, 1).toUpperCase() + name.substring(1).replace('-', ' ')};
for (const docFolder of docFolders) {
const name = docFolder.substring(3);
categories.push({
name,
files:
name === 'Components'
? componentsSubMenu
: (await readdir(`../docs/${docFolder}`))
.filter((file) => file.match(validMdRegex))
.map((file) => {
const normalizedFileName = file.slice(3, -3);
return {
slug: `${name.toLowerCase()}/${normalizedFileName.toLowerCase()}`,
mdpath: `../docs/${docFolder}/${file}`,
title: normalizedFileName.replace('-', ' '),
name: normalizedFileName,
subpath: '',
};
}),
});
}
return categories;
}

export async function retrieveMarkdown(slug: string) {
const files = await listMarkdown();
const file = files.find((file) => file.slug === slug);
return file ? await readFile(file.path, 'utf-8') : undefined;
const categories = await listPages();
let prev;
let next;
let file;
for (let i = 0; i < categories.length; i++) {
const category = categories[i];
for (let j = 0; j < category.files.length; j++) {
if (category.files[j].slug === slug) {
file = category.files[j];
if (j > 0) {
prev = category.files[j - 1];
} else if (i > 0) {
prev = categories[i - 1].files[categories[i - 1].files.length - 1];
prev = {...prev, title: `${categories[i - 1].name.replace('-', ' ')}: ${prev.title}`};
}
if (j < category.files.length - 1) {
next = category.files[j + 1];
} else if (i < categories.length - 1) {
next = categories[i + 1].files[0];
next = {...next, title: `${categories[i + 1].name.replace('-', ' ')}: ${next.title}`};
}
}
}
}
return file ? {prev, next, content: await readFile(file.mdpath!, 'utf-8')} : undefined;
}
12 changes: 7 additions & 5 deletions demo/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,15 @@
{:else}
<div class="container-xxl">
<div class="row flex-wrap flex-sm-nowrap align-content-between">
<aside class="demo-sidebar d-none d-md-flex align-items-center align-items-sm-start col-auto side-menu">
<aside class="demo-sidebar d-none d-md-flex align-items-center align-items-sm-start col-auto side-menu me-3">
<SideMenu />
</aside>
<div class="pb-4 col">
<MainSection>
<slot />
</MainSection>
</div>
<div class="demo-toc d-none d-md-flex col-auto side-menu">
<div class="demo-toc d-none d-md-flex col-auto side-menu me-auto">
<TOC />
</div>
</div>
Expand Down Expand Up @@ -150,14 +150,16 @@
.demo-sidebar {
position: sticky;
top: 0;
height: calc(100vh - 6rem);
height: calc(100vh - 60px);
overflow-y: auto;
min-width: 220px;
}
.demo-toc {
position: sticky;
top: 0;
min-width: 250px;
height: calc(100vh - 6rem);
min-width: 220px;
height: calc(100vh - 60px);
overflow-y: auto;
}
</style>
41 changes: 9 additions & 32 deletions demo/src/routes/docs/[framework]/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,15 @@
import {listSections} from '$lib/server';
import {listPages} from '$lib/server';

export const load = async ({params}) => {
return {
includesFwk: true,
menu: [
{
title: 'Getting started',
submenu: (await listSections('getting-started')).map((file) => ({
label: file.title,
path: `docs/${params.framework}/getting-started/${file.name}`,
subpath: '',
})),
},
{
title: 'Components',
submenu: [
{label: 'Accordion', path: `docs/${params.framework}/components/accordion/`, subpath: 'examples'},
{label: 'Alert', path: `docs/${params.framework}/components/alert/`, subpath: 'examples'},
{label: 'Modal', path: `docs/${params.framework}/components/modal/`, subpath: 'examples'},
{label: 'Pagination', path: `docs/${params.framework}/components/pagination/`, subpath: 'examples'},
{label: 'Progressbar', path: `docs/${params.framework}/components/progressbar/`, subpath: 'examples'},
{label: 'Rating', path: `docs/${params.framework}/components/rating/`, subpath: 'examples'},
{label: 'Select', path: `docs/${params.framework}/components/select/`, subpath: 'examples'},
{label: 'Slider', path: `docs/${params.framework}/components/slider/`, subpath: 'examples'},
],
},
{
title: 'Services',
submenu: (await listSections('services')).map((file) => ({
label: file.title,
path: `docs/${params.framework}/services/${file.name}`,
subpath: '',
})),
},
],
menu: (await listPages()).map((category) => ({
title: category.name.replace('-', ' '),
submenu: category.files.map((file) => ({
label: file.title,
path: `docs/${params.framework}/${file.slug}`,
subpath: file.subpath,
})),
})),
};
};
24 changes: 24 additions & 0 deletions demo/src/routes/docs/[framework]/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script>
import {page} from '$app/stores';
import {pathToRoot$, selectedFramework$} from '$lib/stores';
</script>

<slot />

<hr />

<div class="w-100 d-flex justify-content-between">
<div>
{#if $page.data.prev}
<div class="fw-bolder text-start">PREVIOUS</div>
<a class="text-start" href="{$pathToRoot$}docs/{$selectedFramework$}/{$page.data.prev.slug}{$page.data.prev.subpath}">{$page.data.prev.title}</a
>
{/if}
</div>
<div>
{#if $page.data.next}
<div class="fw-bolder text-end">NEXT</div>
<a class="text-end" href="{$pathToRoot$}docs/{$selectedFramework$}/{$page.data.next.slug}{$page.data.next.subpath}">{$page.data.next.title}</a>
{/if}
</div>
</div>
8 changes: 5 additions & 3 deletions demo/src/routes/docs/[framework]/[...slug]/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import {retrieveMarkdown} from '$lib/server';
import {error} from '@sveltejs/kit';

export const load = async ({params}) => {
const source = await retrieveMarkdown(params.slug);
if (!source) error(404);
const file = await retrieveMarkdown(params.slug);
if (!file) error(404);
else {
return {
source,
content: file.content,
prev: file.prev,
next: file.next,
slug: params.slug,
};
}
Expand Down
2 changes: 1 addition & 1 deletion demo/src/routes/docs/[framework]/[...slug]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@
<meta name="description" content={`Documentation for ${data.slug.replace('/', ' ').replace('-', ' ')}`} />
</svelte:head>

<Markdown source={data.source} />
<Markdown source={data.content} />
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/accordion/api'},
{title: 'Playground', key: 'playground', path: '/components/accordion/playground#'},
],
prev: {
title: 'Bootstrap flavor: Extending',
slug: 'bootstrap-flavor/extending',
subpath: '',
},
next: {
title: 'Alert',
slug: 'components/alert/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/alert/api'},
{title: 'Playground', key: 'playground', path: '/components/alert/playground#{"props":{"slotDefault":"This is an alert"}}'},
],
prev: {
title: 'Accordion',
slug: 'components/accordion/',
subpath: 'examples',
},
next: {
title: 'Modal',
slug: 'components/modal/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,15 @@ export const load = async () => {
path: '/components/modal/playground#{"props":{"visible":true,"slotDefault":"Dialog content","slotTitle":"Dialog"}}',
},
],
prev: {
title: 'Alert',
slug: 'components/alert/',
subpath: 'examples',
},
next: {
title: 'Pagination',
slug: 'components/pagination/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/pagination/api'},
{title: 'Playground', key: 'playground', path: '/components/pagination/playground'},
],
prev: {
title: 'Modal',
slug: 'components/modal/',
subpath: 'examples',
},
next: {
title: 'Progressbar',
slug: 'components/progressbar/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/progressbar/api'},
{title: 'Playground', key: 'playground', path: '/components/progressbar/playground'},
],
prev: {
title: 'Pagination',
slug: 'components/pagination/',
subpath: 'examples',
},
next: {
title: 'Rating',
slug: 'components/rating/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/rating/api'},
{title: 'Playground', key: 'playground', path: '/components/rating/playground'},
],
prev: {
title: 'Progressbar',
slug: 'components/progressbar/',
subpath: 'examples',
},
next: {
title: 'Select',
slug: 'components/select/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/select/api'},
{title: 'Playground', key: 'playground', path: '/components/select/playground'},
],
prev: {
title: 'Rating',
slug: 'components/rating/',
subpath: 'examples',
},
next: {
title: 'Slider',
slug: 'components/slider/',
subpath: 'examples',
},
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,15 @@ export const load = async () => {
{title: 'Api', key: 'api', path: '/components/slider/api'},
{title: 'Playground', key: 'playground', path: '/components/slider/playground'},
],
prev: {
title: 'Select',
slug: 'components/select/',
subpath: 'examples',
},
next: {
title: 'Services: Introduction',
slug: 'services/introduction',
subpath: '',
},
};
};
Loading

0 comments on commit 71cddee

Please sign in to comment.