Skip to content

Commit

Permalink
feat: markdown doc (#365)
Browse files Browse the repository at this point in the history
  • Loading branch information
quentinderoubaix authored Jan 17, 2024
1 parent 12c6df6 commit 88f02c7
Show file tree
Hide file tree
Showing 92 changed files with 702 additions and 407 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {Component} from '@angular/core';
<input class="form-check-input" type="checkbox" id="containerHasFocus" [checked]="hasFocusApi.hasFocus$ | async" disabled />
<label class="form-check-label" for="containerHasFocus">Focus in container</label>
</div>
<label for="activeElement" class="form-label">Active element history:</label>
<label for="activeElementHistory" class="form-label">Active element history:</label>
<textarea class="form-control mb-2" id="activeElementHistory" readonly>{{ activeElementsJson }}</textarea>
<button class="btn btn-primary" (click)="clear()">Clear</button>
</div>
Expand Down
1 change: 1 addition & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.2.8",
"svelte-check": "^3.6.3",
"svelte-markdown": "^0.4.1",
"ts-node": "^10.9.2"
}
}
4 changes: 0 additions & 4 deletions demo/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ export function getTitle(title: string, frameworkName = '') {
return `AgnosUI - ${title}` + (frameworkName ? ` for ${frameworkName}` : '');
}

export function getWidgetDescription(name: string, frameworkName = '') {
return `${name} widget of AgnosUI` + (frameworkName ? ` for ${frameworkName}` : '');
}

/**
* Split all the lines of a text, so that it can be easily used in a loop
* @param text text to split
Expand Down
21 changes: 0 additions & 21 deletions demo/src/lib/layout/ComponentPage.svelte

This file was deleted.

17 changes: 12 additions & 5 deletions demo/src/lib/layout/Header.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,27 @@
<script lang="ts">
import {pathToRoot$, selectedFramework$} from '../stores';
import {pathToRoot$, selectedFramework$, selectedTabName$} from '../stores';
import {page} from '$app/stores';
import {getTitle} from '../../app';
export let title: string;
export let tabs: {title: string; key: string; path: string}[];
export let tab = '';
$: tabs = $page.data.tabs ?? [];
</script>

<svelte:head>
<title>{getTitle(title, $selectedFramework$)}</title>
</svelte:head>

<header class="bg-light pt-4 pb-5 px-4 px-lg-5 d-flex mb-4 align-items-center title">
<div class="row mb-4 align-items-center w-100">
<h1 class="col-auto me-auto me-md-none mb-0 p-3">{title}</h1>
</div>
<ul class="nav-tabs px-4 px-lg-5 content-tabset justify-content-start nav" role="tablist">
{#each tabs as { title, key, path }}
{@const isActive = tab === key}
{@const isActive = $selectedTabName$ === key}
<li class="nav-item" role="presentation">
<a
href={`${$pathToRoot$}${$selectedFramework$}${path}`}
href={`${$pathToRoot$}docs/${$selectedFramework$}${path}`}
role="tab"
class="nav-link link-body-emphasis"
aria-selected={isActive}
Expand Down
34 changes: 34 additions & 0 deletions demo/src/lib/layout/Heading.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<script lang="ts">
import Header from '$lib/layout/Header.svelte';
import Svg from './Svg.svelte';
import link from 'bootstrap-icons/icons/link-45deg.svg?raw';
export let depth: 1 | 2 | 3 | 4 | 5 | 6;
export let text: string;
export let id: string = text.toLowerCase().replace(/\s/g, '-').trim();
export let headerClassName: string | undefined = undefined;
</script>

{#if depth > 1}
<svelte:element this={'h' + depth} {id} class={headerClassName}>
{text}
<a class="anchor-link" href="#{id}" aria-label="link to {text}"><Svg className="icon-24 align-middle" svg={link} /></a>
</svelte:element>
{:else}
<Header title={text} />
{/if}

<style lang="scss">
.anchor-link {
text-decoration: none;
opacity: 0;
transition: opacity 0.15s ease-in-out;
&:focus,
&:hover,
:hover > &,
:target > & {
opacity: 1;
}
}
</style>
2 changes: 1 addition & 1 deletion demo/src/lib/layout/Sample.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import {tooltip} from '$lib/tooltip/tooltip';
import openLink from 'bootstrap-icons/icons/box-arrow-up-right.svg?raw';
import codeSvg from 'bootstrap-icons/icons/code.svg?raw';
import stackblitz from '../../resources/icons/stackblitz.svg?raw';
import stackblitz from '$resources/icons/stackblitz.svg?raw';
import type {Frameworks} from '../stores';
import {pathToRoot$, selectedFramework$} from '../stores';
import Lazy from './Lazy.svelte';
Expand Down
25 changes: 3 additions & 22 deletions demo/src/lib/layout/Section.svelte
Original file line number Diff line number Diff line change
@@ -1,32 +1,13 @@
<script lang="ts">
import Svg from './Svg.svelte';
import link from 'bootstrap-icons/icons/link-45deg.svg?raw';
import Heading from '$lib/layout/Heading.svelte';
export let level: 1 | 2 | 3;
export let label: string;
export let id: string;
export let id: string = label.toLowerCase().replace(/\s/g, '-').trim();
export let headerClassName: string | undefined = undefined;
</script>

<section>
<svelte:element this={'h' + level} {id} class={headerClassName}>
{label}
<a class="anchor-link" href="#{id}" aria-label="link to {label}"><Svg className="icon-24 align-middle" svg={link} /></a>
</svelte:element>
<Heading depth={level} text={label} {id} {headerClassName} />
<slot />
</section>

<style lang="scss">
.anchor-link {
text-decoration: none;
opacity: 0;
transition: opacity 0.15s ease-in-out;
&:focus,
&:hover,
:hover > &,
:target > & {
opacity: 1;
}
}
</style>
46 changes: 46 additions & 0 deletions demo/src/lib/markdown/Markdown.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<script lang="ts">
import SvelteMarkdown, {type Renderers} from 'svelte-markdown';
import Heading from '$lib/layout/Heading.svelte';
import MdCode from '$lib/markdown/renderers/MdCode.svelte';
import {marked} from 'marked';
import MdSection from '$lib/markdown/renderers/MdSection.svelte';
import MdImage from '$lib/markdown/renderers/MdImage.svelte';
export let source: string;
function getTokens(src: string) {
const tokens = marked.lexer(src);
const walkTokens = (tokens: marked.TokensList | marked.Token[]) => {
let indexLastHeading = -1;
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i];
if ((token as marked.Tokens.Generic).tokens?.length) {
walkTokens((token as marked.Tokens.Generic).tokens!);
}
if (token.type === 'heading' && token.depth === 2) {
if (indexLastHeading >= 0) {
tokens.splice(indexLastHeading, i - indexLastHeading, {
type: 'section',
tokens: tokens.slice(indexLastHeading, i),
} as unknown as marked.Token);
i = indexLastHeading + 1;
}
indexLastHeading = i;
}
}
if (indexLastHeading >= 0) {
tokens.splice(indexLastHeading, tokens.length - indexLastHeading, {
type: 'section',
tokens: tokens.slice(indexLastHeading, tokens.length),
} as unknown as marked.Token);
}
};
walkTokens(tokens);
return tokens;
}
$: tokens = getTokens(source);
const renderers: Partial<Renderers> = {image: MdImage, heading: Heading, code: MdCode, section: MdSection} as Partial<Renderers>;
</script>

<SvelteMarkdown source={tokens} {renderers} />
54 changes: 54 additions & 0 deletions demo/src/lib/markdown/renderers/MdCode.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<script lang="ts">
import Code from '$lib/layout/Code.svelte';
import Sample from '$lib/layout/Sample.svelte';
import type {SampleInfo} from '$lib/layout/sample';
import {selectedFramework$} from '$lib/stores';
import samples from '../samples';
export let lang: string;
export let text: string;
let code = '';
let title: string;
let sample: SampleInfo;
let height = 500;
const extensions: Map<string, string> = new Map();
extensions.set('typescript', 'ts');
extensions.set('bash', 'sh');
async function getCode(text: string, selectedFramework: string, lang: string) {
if (lang !== 'sample' && text.trim().match(/^\{[a-z-]+\}$/) && extensions.has(lang)) {
const codeKey = text.trim().slice(1, -1);
code = (await import(`../../../../../docs/code/${codeKey}/${codeKey}-${selectedFramework}.${extensions.get(lang)}?raw`)).default;
} else {
code = text.trim();
}
}
async function getSample(text: string, lang: string) {
if (lang === 'sample') {
const match = text.trim().match(/^\{([^:]+):([a-zA-Z-/]+):(\d+)\}$/);
if (match) {
title = match[1];
const sampleKey = match[2];
height = Number.parseInt(match[3], 10);
if (samples.has(sampleKey)) {
sample = samples.get(sampleKey)!;
}
}
}
}
$: void getCode(text, $selectedFramework$, lang);
$: void getSample(text, lang);
</script>

{#if lang === 'sample'}
{#if sample}
<Sample {title} {sample} {height} />
{:else}
Sample not found, make sure to fill the samples.ts file.
{/if}
{:else}
<Code language={lang} {code} />
{/if}
13 changes: 13 additions & 0 deletions demo/src/lib/markdown/renderers/MdImage.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<script lang="ts">
export let href = '';
export let title: string;
export let text = '';
let src: string;
async function getSrc(href: string) {
src = (await import(`../../../resources/images/${href.slice(href.indexOf('resources/images/') + 17, -5)}.webp`)).default;
}
$: void getSrc(href);
</script>

<img {src} {title} alt={text} />
1 change: 1 addition & 0 deletions demo/src/lib/markdown/renderers/MdSection.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<section><slot /></section>
10 changes: 10 additions & 0 deletions demo/src/lib/markdown/samples.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type {SampleInfo} from '$lib/layout/sample';

import focustrack from '@agnos-ui/samples/focustrack/focustrack';
import floatingUI from '@agnos-ui/samples/floatingUI/floatingUI';

const samples: Map<string, SampleInfo> = new Map();
samples.set('focustrack/focustrack', focustrack);
samples.set('floatingUI/floatingUI', floatingUI);

export default samples;
31 changes: 31 additions & 0 deletions demo/src/lib/server/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {readFile, readdir} from 'node:fs/promises';

const validMdRegex = /^\d{2}-[a-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;
}

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('-', ' ')};
});
}

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;
}
20 changes: 9 additions & 11 deletions demo/src/lib/stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import {computed, get} from '@amadeus-it-group/tansu';
import {browser} from '$app/environment';
import {page} from '$app/stores';
import {createIntersection} from '@agnos-ui/core/services/intersection';
import {resolveRoute} from '$app/paths';

// Return how deep the current route is compared to base
export const routeLevel$ = computed(() => {
export const resolvedRoute$ = computed(() => {
const $page = get(page);
if (!$page.route.id) {
throw new Error('Page error');
}
return $page.route.id.split('/').length - 2;
return $page.route.id ? resolveRoute($page.route.id, $page.params) : './';
});

// Return how deep the current route is compared to base
export const routeLevel$ = computed(() => resolvedRoute$().split('/').length - 2);

// Return the url relative path to root, ex './', '../' or '../..'
export const relativePathToRoot$ = computed(() => {
const routeLevel = routeLevel$();
Expand All @@ -37,7 +37,7 @@ export const selectedFramework$ = computed(() => {
return <Frameworks>(get(page).params.framework ?? 'angular');
});

const tabRegExp = /^\/\[framework\]\/components\/[^/]*\/([^/]*)/;
const tabRegExp = /^\/docs\/\[framework\]\/components\/[^/]*\/([^/]*)/;
/**
* Current selected tab
*/
Expand All @@ -46,9 +46,7 @@ export const selectedTabName$ = computed(() => {
return match?.[1] || 'examples';
});

const frameworkKeyRegExp = /^\/\[framework\]\//;
export const frameworkLessUrl$ = computed(() => {
return (get(page).route.id || '').replace(frameworkKeyRegExp, '');
});
const frameworkKeyRegExp = /^\/docs\/[a-z]*\//;
export const frameworkLessUrl$ = computed(() => resolvedRoute$().replace(frameworkKeyRegExp, ''));

export const intersectionApi = createIntersection();
Binary file added demo/src/resources/images/reactivity.webp
Binary file not shown.
Loading

0 comments on commit 88f02c7

Please sign in to comment.