vowel 0.1.46 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -20
- package/bin.js +2 -78
- package/docs-source/$features/cards.md +7 -0
- package/docs-source/$features/editing.md +7 -0
- package/docs-source/$features/emoji.md +7 -0
- package/docs-source/$features/frontmatter.md +7 -0
- package/docs-source/$features/lists.md +7 -0
- package/docs-source/$features/navigation.md +7 -0
- package/docs-source/$features/rich-previews.md +7 -0
- package/docs-source/$features/robots.md +7 -0
- package/docs-source/$features/rss.md +7 -0
- package/docs-source/$features/sitemap.md +7 -0
- package/docs-source/$features/speed.md +7 -0
- package/docs-source/$features/static.md +7 -0
- package/docs-source/$features/taxonomies.md +7 -0
- package/docs-source/.cache.json +9 -0
- package/docs-source/.obsidian/app.json +3 -0
- package/docs-source/.obsidian/appearance.json +3 -0
- package/docs-source/.obsidian/core-plugins-migration.json +30 -0
- package/docs-source/.obsidian/core-plugins.json +20 -0
- package/docs-source/.obsidian/workspace.json +168 -0
- package/docs-source/.stackblitzrc +3 -0
- package/docs-source/.vercel/README.txt +11 -0
- package/docs-source/.vercel/project.json +1 -0
- package/docs-source/about.md +3 -0
- package/docs-source/assets/styles.css +51 -0
- package/docs-source/blog/home.md +5 -0
- package/docs-source/blog/url-ui.md +21 -0
- package/docs-source/docs/.votive.db +0 -0
- package/docs-source/docs/deploy.md +67 -0
- package/docs-source/docs/file-structure.md +31 -0
- package/docs-source/docs/folder-settings.md +23 -0
- package/docs-source/docs/home.md +55 -0
- package/docs-source/docs/images.md +10 -0
- package/docs-source/docs/items.md +13 -0
- package/docs-source/docs/pages.md +141 -0
- package/docs-source/docs/settings.md +4 -0
- package/docs-source/docs/styling.md +34 -0
- package/docs-source/docs/taxonomies.md +37 -0
- package/docs-source/home.md +42 -0
- package/docs-source/roadmap.md +98 -0
- package/docs-source/settings.md +12 -0
- package/extractDate.js +83 -0
- package/getMetadata.js +41 -0
- package/index.js +669 -0
- package/jsconfig.json +9 -17
- package/package.json +61 -63
- package/regex.js +36 -0
- package/{src/lib/components → stylesheets}/DefaultStyles.css +5 -5
- package/utils.js +10 -0
- package/.cache.json +0 -1
- package/.prettierrc +0 -8
- package/.vscode/settings.json +0 -3
- package/CHANGELOG.md +0 -79
- package/server.js +0 -87
- package/src/app.d.ts +0 -12
- package/src/app.html +0 -13
- package/src/lib/components/Breadcrumbs.svelte +0 -19
- package/src/lib/components/ConditionalWrapper.svelte +0 -10
- package/src/lib/components/DefaultStyles.svelte +0 -11
- package/src/lib/components/FrontMatterTaxonomy.svelte +0 -48
- package/src/lib/components/Frontmatter.svelte +0 -56
- package/src/lib/components/FrontmatterProperty.svelte +0 -78
- package/src/lib/components/Markdown/Image.svelte +0 -50
- package/src/lib/components/Markdown/Link.svelte +0 -19
- package/src/lib/components/Markdown/LinkPreview.svelte +0 -45
- package/src/lib/components/Markdown/Text.svelte +0 -6
- package/src/lib/components/Markdown/index.svelte +0 -147
- package/src/lib/components/Markdown/validators.js +0 -29
- package/src/lib/components/Nav.svelte +0 -40
- package/src/lib/components/NoStyles.svelte +0 -5
- package/src/lib/components/Page.svelte +0 -90
- package/src/lib/components/ResetStyles.svelte +0 -7
- package/src/lib/components/Sitemap.svelte +0 -38
- package/src/lib/components/TypographyStyles.svelte +0 -10
- package/src/lib/components/index.js +0 -12
- package/src/lib/index.js +0 -1
- package/src/lib/utilities/buildURL.js +0 -18
- package/src/lib/utilities/checkFileExists.js +0 -16
- package/src/lib/utilities/createFolderClass.js +0 -4
- package/src/lib/utilities/createPageClass.js +0 -6
- package/src/lib/utilities/getFileLabel.js +0 -35
- package/src/lib/utilities/getFolder.js +0 -16
- package/src/lib/utilities/getFolderLabel.js +0 -12
- package/src/lib/utilities/getMetadata.js +0 -46
- package/src/lib/utilities/getPage.js +0 -25
- package/src/lib/utilities/getPagesByFolder.js +0 -95
- package/src/lib/utilities/index.js +0 -22
- package/src/lib/utilities/isActiveLink.js +0 -12
- package/src/lib/utilities/isObject.js +0 -8
- package/src/lib/utilities/loadCache.js +0 -28
- package/src/lib/utilities/mutateMarkdownAST.js +0 -68
- package/src/lib/utilities/mutateMarkdownFrontmatter.js +0 -113
- package/src/lib/utilities/parseDate.js +0 -43
- package/src/lib/utilities/processMarkdownFiles.js +0 -243
- package/src/lib/utilities/readMarkdownFile.js +0 -188
- package/src/lib/utilities/regexPatterns.js +0 -12
- package/src/lib/utilities/resolveHomeDirPath.js +0 -5
- package/src/lib/utilities/sendWebmention.js +0 -34
- package/src/lib/utilities/writeCache.js +0 -14
- package/src/routes/$vowel/published.json/+server.js +0 -54
- package/src/routes/+error.svelte +0 -110
- package/src/routes/[...path]/+layout.server.js +0 -78
- package/src/routes/[...path]/+page.server.js +0 -42
- package/src/routes/[...path]/+page.svelte +0 -186
- package/src/routes/feed.xml/+server.js +0 -120
- package/src/routes/robots.txt/+server.js +0 -54
- package/src/routes/sitemap.xml/+server.js +0 -68
- package/static/favicon.png +0 -0
- package/static/styles.css +0 -0
- package/svelte.config.js +0 -30
- package/vercel.json +0 -5
- package/vite.config.js +0 -84
- /package/{src/lib/components → stylesheets}/ResetStyles.css +0 -0
- /package/{src/lib/components → stylesheets}/TypographyStyles.css +0 -0
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { sentenceCase } from 'change-case';
|
|
3
|
-
import Frontmatter from './Frontmatter.svelte';
|
|
4
|
-
import Image from './Markdown/Image.svelte';
|
|
5
|
-
|
|
6
|
-
/** @type {{ property: any, key: string }}*/
|
|
7
|
-
let { property, key, format } = $props();
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
{#if property}
|
|
11
|
-
<dl class={key}>
|
|
12
|
-
<dt>{sentenceCase(key)}</dt>
|
|
13
|
-
<dd>
|
|
14
|
-
{@render propertySwitch(property)}
|
|
15
|
-
</dd>
|
|
16
|
-
</dl>
|
|
17
|
-
{/if}
|
|
18
|
-
|
|
19
|
-
{#snippet array(items)}
|
|
20
|
-
<ul>
|
|
21
|
-
{#each items as item}
|
|
22
|
-
<li>
|
|
23
|
-
{@render propertySwitch(item)}
|
|
24
|
-
</li>
|
|
25
|
-
{/each}
|
|
26
|
-
</ul>
|
|
27
|
-
{/snippet}
|
|
28
|
-
|
|
29
|
-
{#snippet propertySwitch(value)}
|
|
30
|
-
{#if value.type === 'array'}
|
|
31
|
-
{@render array(value.output)}
|
|
32
|
-
{:else if value.type === 'object'}
|
|
33
|
-
<Frontmatter props={{ properties: value.output, format }} />
|
|
34
|
-
{:else if value.type === 'image'}
|
|
35
|
-
{@render image(value.output)}
|
|
36
|
-
{:else if value.type === 'date'}
|
|
37
|
-
{@render date(value.output)}
|
|
38
|
-
{:else if value.type === 'url'}
|
|
39
|
-
{@render url(value.output)}
|
|
40
|
-
{:else}
|
|
41
|
-
{value.output || value}
|
|
42
|
-
{/if}
|
|
43
|
-
{/snippet}
|
|
44
|
-
|
|
45
|
-
{#snippet image(value)}
|
|
46
|
-
<Image node={{ url: value, alt: '' }} />
|
|
47
|
-
{/snippet}
|
|
48
|
-
|
|
49
|
-
{#snippet date(value)}
|
|
50
|
-
{@const date = new Date(value)}
|
|
51
|
-
<time datetime={date.toISOString()}>{date.toLocaleDateString('en-US')}</time>
|
|
52
|
-
{/snippet}
|
|
53
|
-
|
|
54
|
-
{#snippet url(value)}
|
|
55
|
-
{#if format === 'rss'}
|
|
56
|
-
<a href={value.url}>
|
|
57
|
-
{value.title || value['og:title']}
|
|
58
|
-
</a>
|
|
59
|
-
{:else}
|
|
60
|
-
<article class="link-preview">
|
|
61
|
-
<a href={value.url}>
|
|
62
|
-
{#if value['og:image']}
|
|
63
|
-
<img src={value['og:image']} alt="" />
|
|
64
|
-
{/if}
|
|
65
|
-
<h2>
|
|
66
|
-
{value.title || value['og:title']}
|
|
67
|
-
</h2>
|
|
68
|
-
<p>
|
|
69
|
-
{value['og:description'] || value.og_description || value.description}
|
|
70
|
-
</p>
|
|
71
|
-
</a>
|
|
72
|
-
</article>
|
|
73
|
-
{/if}
|
|
74
|
-
{/snippet}
|
|
75
|
-
|
|
76
|
-
{#snippet pdf(value)}
|
|
77
|
-
<a href={value.url}>{value.url}</a>
|
|
78
|
-
{/snippet}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
let { node } = $props();
|
|
3
|
-
let { url, alt } = node;
|
|
4
|
-
|
|
5
|
-
let defaultWidth = 800;
|
|
6
|
-
const srcsetWidths = [640, 828, 1080, 1200, 1920, 2048, 3840];
|
|
7
|
-
|
|
8
|
-
let urlObject = createURLObject();
|
|
9
|
-
|
|
10
|
-
function createURLObject() {
|
|
11
|
-
try {
|
|
12
|
-
return new URL(url);
|
|
13
|
-
} catch (e) {
|
|
14
|
-
// console.error(`Error on image ${url}:`);
|
|
15
|
-
// console.error(e);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
let srcset = createSrcset();
|
|
20
|
-
|
|
21
|
-
function createSrcset() {
|
|
22
|
-
if (urlObject?.host.includes('imgix.net')) {
|
|
23
|
-
urlObject?.searchParams.set('width', String(defaultWidth));
|
|
24
|
-
urlObject?.searchParams.append('auto', 'format,compress');
|
|
25
|
-
|
|
26
|
-
return srcsetWidths.reduce((srcset, width) => {
|
|
27
|
-
urlObject?.searchParams.set('width', width);
|
|
28
|
-
return `${srcset}, ${urlObject?.href} ${width}w`;
|
|
29
|
-
}, '');
|
|
30
|
-
|
|
31
|
-
urlObject?.searchParams.set('width', String(defaultWidth));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
{#if urlObject?.pathname?.endsWith('.svg')}
|
|
37
|
-
<object type="image/svg+xml" data={urlObject.href} title={alt}></object>
|
|
38
|
-
{:else if urlObject}
|
|
39
|
-
<img src={urlObject.href} {alt} {srcset} />
|
|
40
|
-
{/if}
|
|
41
|
-
|
|
42
|
-
<style>
|
|
43
|
-
img {
|
|
44
|
-
transition: max-width 1s linear;
|
|
45
|
-
max-width: 100%;
|
|
46
|
-
height: auto;
|
|
47
|
-
width: auto;
|
|
48
|
-
margin-inline: auto;
|
|
49
|
-
}
|
|
50
|
-
</style>
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import Markdown from './index.svelte';
|
|
3
|
-
|
|
4
|
-
let { node, level, website } = $props();
|
|
5
|
-
let { url, children } = $derived(node);
|
|
6
|
-
|
|
7
|
-
function isAbsoluteURL(url) {
|
|
8
|
-
try {
|
|
9
|
-
new URL(url);
|
|
10
|
-
return true;
|
|
11
|
-
} catch (e) {
|
|
12
|
-
return false;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
</script>
|
|
16
|
-
|
|
17
|
-
<a href={url} target={isAbsoluteURL(url) ? '_blank' : null}>
|
|
18
|
-
<Markdown props={{ ast: children, level, website }} />
|
|
19
|
-
</a>
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
let { metadata, url, format } = $props();
|
|
3
|
-
let { image, description, og_description, author } = $derived(metadata || {});
|
|
4
|
-
|
|
5
|
-
const href = $derived(metadata?.og_url || metadata?.canonical || url || '');
|
|
6
|
-
|
|
7
|
-
const title = $derived(metadata?.og_title || metadata?.title || '');
|
|
8
|
-
|
|
9
|
-
const urlObject = new URL(url);
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
{#if metadata}
|
|
13
|
-
{#if format === 'rss'}
|
|
14
|
-
<p><a {href}>{title ? title + ' - ' : ''}{urlObject.host}</a></p>
|
|
15
|
-
{:else}
|
|
16
|
-
<article class="link-preview">
|
|
17
|
-
<a {href}>
|
|
18
|
-
{#if image}
|
|
19
|
-
<img src={image} alt="" />
|
|
20
|
-
{/if}
|
|
21
|
-
<h2>{title ? title + ' - ' : ''}<span class="host">{urlObject.host}</span></h2>
|
|
22
|
-
{#if author}
|
|
23
|
-
<p>
|
|
24
|
-
By {author}
|
|
25
|
-
</p>
|
|
26
|
-
{/if}
|
|
27
|
-
{#if description || og_description}
|
|
28
|
-
<p>
|
|
29
|
-
{description || og_description}
|
|
30
|
-
</p>
|
|
31
|
-
{/if}
|
|
32
|
-
</a>
|
|
33
|
-
</article>
|
|
34
|
-
{/if}
|
|
35
|
-
{:else if format === 'rss'}
|
|
36
|
-
<p><a {href}>{urlObject.host}</a></p>
|
|
37
|
-
{:else}
|
|
38
|
-
<article class="link-preview">
|
|
39
|
-
<a {href}>
|
|
40
|
-
<h2>
|
|
41
|
-
<span class="host">{urlObject.host}</span>
|
|
42
|
-
</h2>
|
|
43
|
-
</a>
|
|
44
|
-
</article>
|
|
45
|
-
{/if}
|
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { Page } from '$lib/components';
|
|
3
|
-
import { getPage, getPagesByFolder, createPageClass, createFolderClass } from '$lib/utilities';
|
|
4
|
-
import { getFolderAndCount, isFileLink } from './validators';
|
|
5
|
-
import Image from './Image.svelte';
|
|
6
|
-
import Link from './Link.svelte';
|
|
7
|
-
import Text from './Text.svelte';
|
|
8
|
-
import LinkPreview from './LinkPreview.svelte';
|
|
9
|
-
import { toString } from 'mdast-util-to-string';
|
|
10
|
-
import { kebabCase } from 'change-case';
|
|
11
|
-
|
|
12
|
-
let { props } = $props();
|
|
13
|
-
|
|
14
|
-
let { ast, level, website, format, identifier } = $derived(props);
|
|
15
|
-
|
|
16
|
-
function getElement(node) {
|
|
17
|
-
if (node.type === 'heading') {
|
|
18
|
-
return ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'div'][node.depth - 1];
|
|
19
|
-
}
|
|
20
|
-
const elements = {
|
|
21
|
-
emphasis: 'em',
|
|
22
|
-
text: 'span',
|
|
23
|
-
paragraph: 'p',
|
|
24
|
-
strong: 'strong',
|
|
25
|
-
list: node.ordered ? 'ol' : 'ul',
|
|
26
|
-
// listItem: 'li',
|
|
27
|
-
blockquote: 'blockquote',
|
|
28
|
-
inlineCode: 'code',
|
|
29
|
-
code: 'pre',
|
|
30
|
-
figure: 'figure',
|
|
31
|
-
figcaption: 'figcaption',
|
|
32
|
-
delete: 's',
|
|
33
|
-
table: 'table',
|
|
34
|
-
tableRow: 'tr',
|
|
35
|
-
tableCell: 'td'
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
// Handle list item separately
|
|
39
|
-
// Handle `pre` properly
|
|
40
|
-
// Handle `footnoteDefinition` and `footnoteReference`
|
|
41
|
-
|
|
42
|
-
if (elements[node.type]) return elements[node.type];
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const noteTypes = {
|
|
46
|
-
tip: 'Tip',
|
|
47
|
-
note: 'Note',
|
|
48
|
-
important: 'Important',
|
|
49
|
-
warning: 'Warning',
|
|
50
|
-
caution: 'Caution'
|
|
51
|
-
};
|
|
52
|
-
</script>
|
|
53
|
-
|
|
54
|
-
{#if ast}
|
|
55
|
-
{#each ast as node}
|
|
56
|
-
{@const { count, path, property, content } = getFolderAndCount(node)}
|
|
57
|
-
{#if count}
|
|
58
|
-
{@const pages = getPagesByFolder(website, path, true, count, property)}
|
|
59
|
-
<section class={createFolderClass(path)}>
|
|
60
|
-
{#each pages as page}
|
|
61
|
-
<article class={createPageClass(page.url, 'thumbnail')}>
|
|
62
|
-
<Page link={true} {content} {page} level={level + 1} {website} {format} />
|
|
63
|
-
</article>
|
|
64
|
-
{/each}
|
|
65
|
-
</section>
|
|
66
|
-
{:else if isFileLink(node)}
|
|
67
|
-
<article class={createPageClass(node.children[0].value, 'thumbnail')}>
|
|
68
|
-
<Page
|
|
69
|
-
link={true}
|
|
70
|
-
page={getPage(website, node.children[0].value)}
|
|
71
|
-
level={level + 1}
|
|
72
|
-
{website}
|
|
73
|
-
content={false}
|
|
74
|
-
{format}
|
|
75
|
-
/>
|
|
76
|
-
</article>
|
|
77
|
-
{:else if node.type === 'heading'}
|
|
78
|
-
<svelte:element this={getElement(node)} id={kebabCase(toString(node))}>
|
|
79
|
-
<svelte:self props={{ ast: node.children, level }} />
|
|
80
|
-
</svelte:element>
|
|
81
|
-
{:else if node.type === 'link' && node.children}
|
|
82
|
-
<Link {node} {level} {website} {format} />
|
|
83
|
-
{:else if node.type === 'thematicBreak'}
|
|
84
|
-
<hr />
|
|
85
|
-
{:else if node.type === 'image'}
|
|
86
|
-
<Image {node} />
|
|
87
|
-
{:else if node.type === 'url'}
|
|
88
|
-
<!-- {@const dummy = console.log(node)} -->
|
|
89
|
-
<LinkPreview url={node.url} metadata={node.metadata} {format} />
|
|
90
|
-
{:else if node.type === 'listItem'}
|
|
91
|
-
{@const isChecklistItem = node.checked !== null}
|
|
92
|
-
{#if isChecklistItem}
|
|
93
|
-
<li
|
|
94
|
-
class={`checklist-item ${node.checked ? 'checked' : 'unchecked'}`}
|
|
95
|
-
style:list-style-type={`"${node.checked ? '☑' : '☐'}"`}
|
|
96
|
-
>
|
|
97
|
-
<svelte:self props={{ ast: node.children, level, format }} />
|
|
98
|
-
</li>
|
|
99
|
-
{:else}
|
|
100
|
-
<li>
|
|
101
|
-
<svelte:self props={{ ast: node.children, level, format }} />
|
|
102
|
-
</li>
|
|
103
|
-
{/if}
|
|
104
|
-
{:else if node.type === 'footnoteReference'}
|
|
105
|
-
<sup
|
|
106
|
-
><a
|
|
107
|
-
href={`#footnote-definition-${node.identifier}`}
|
|
108
|
-
id={`footnote-${node.identifier}`}
|
|
109
|
-
aria-describedby="footnotes">{node.label}</a
|
|
110
|
-
></sup
|
|
111
|
-
>
|
|
112
|
-
{:else if node.type === 'footnotes'}
|
|
113
|
-
<section id="footnotes">
|
|
114
|
-
<h2>Footnotes</h2>
|
|
115
|
-
<ol>
|
|
116
|
-
{#each node.children as footnote}
|
|
117
|
-
<li id={`footnote-definition-${footnote.identifier}`}>
|
|
118
|
-
<svelte:self
|
|
119
|
-
props={{ ast: footnote.children, level, format, identifier: footnote.identifier }}
|
|
120
|
-
/>
|
|
121
|
-
</li>
|
|
122
|
-
{/each}
|
|
123
|
-
</ol>
|
|
124
|
-
</section>
|
|
125
|
-
{:else if node.type === 'containerDirective' && noteTypes[node.name]}
|
|
126
|
-
<aside class={`alert ${node.name}`}>
|
|
127
|
-
<h2>
|
|
128
|
-
{noteTypes[node.name]}
|
|
129
|
-
</h2>
|
|
130
|
-
<svelte:self props={{ ast: node.children, level, format }}></svelte:self>
|
|
131
|
-
</aside>
|
|
132
|
-
{:else if node.children}
|
|
133
|
-
<svelte:element this={getElement(node)}>
|
|
134
|
-
<svelte:self props={{ ast: node.children, level, format }} />{#if identifier}<a
|
|
135
|
-
href={`#footnote-${identifier}`}
|
|
136
|
-
aria-label="Back to content">↩</a
|
|
137
|
-
>{/if}
|
|
138
|
-
</svelte:element>
|
|
139
|
-
{:else if node.type === 'text'}
|
|
140
|
-
<Text {node} />
|
|
141
|
-
{:else}
|
|
142
|
-
<svelte:element this={getElement(node)}>
|
|
143
|
-
<Text {node} />
|
|
144
|
-
</svelte:element>
|
|
145
|
-
{/if}
|
|
146
|
-
{/each}
|
|
147
|
-
{/if}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
const pathRegex = /^\/[\/\$\w\d=-_\.\?&-]*$/;
|
|
2
|
-
|
|
3
|
-
export function getFolderAndCount(node) {
|
|
4
|
-
if (
|
|
5
|
-
node.type === 'paragraph' &&
|
|
6
|
-
node.children.length === 1 &&
|
|
7
|
-
node.children[0].type === 'text' &&
|
|
8
|
-
(node.children[0].value.match(pathRegex) || node.children[0].value.match(/^\/$/))
|
|
9
|
-
) {
|
|
10
|
-
const urlObject = new URL(node.children[0].value, 'https://placeholder.getvowel.com');
|
|
11
|
-
const isFolder = urlObject.searchParams.get('count');
|
|
12
|
-
const property = urlObject.searchParams.get('property');
|
|
13
|
-
const content = urlObject.searchParams.get('content') === 'true';
|
|
14
|
-
if (isFolder) return { count: isFolder, path: urlObject.pathname, property, content };
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function isFileLink(node) {
|
|
20
|
-
if (
|
|
21
|
-
node.type === 'paragraph' &&
|
|
22
|
-
node.children.length === 1 &&
|
|
23
|
-
node.children[0].type === 'text' &&
|
|
24
|
-
node.children[0].value.match(pathRegex)
|
|
25
|
-
) {
|
|
26
|
-
return true;
|
|
27
|
-
}
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { getFileLabel, getFolderLabel, isActiveLink } from '$lib/utilities';
|
|
3
|
-
|
|
4
|
-
let { folder, segments, child } = $props();
|
|
5
|
-
|
|
6
|
-
// There's definitely a better way to filter this
|
|
7
|
-
function filterFolder(folder) {
|
|
8
|
-
const filteredFolder = {};
|
|
9
|
-
for (let key in folder) {
|
|
10
|
-
if ((!folder[key]['$']?.date && !key.startsWith('$')) || key.length === 1) {
|
|
11
|
-
filteredFolder[key] = folder[key];
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
return filteredFolder;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const evergreen = $derived(filterFolder(folder));
|
|
18
|
-
</script>
|
|
19
|
-
|
|
20
|
-
{#if Object.keys(evergreen).some((key) => key !== '$' && key !== '_')}
|
|
21
|
-
<nav class="top-bar">
|
|
22
|
-
{#if !child}
|
|
23
|
-
<a aria-current={isActiveLink(segments)} href={evergreen?.url || evergreen['$']?.url}
|
|
24
|
-
>{getFolderLabel(evergreen, true)}</a
|
|
25
|
-
>
|
|
26
|
-
{/if}
|
|
27
|
-
{#each Object.keys(evergreen) as key}
|
|
28
|
-
{#if !key.match(/^[$_]$/) && key !== '.obsidian'}
|
|
29
|
-
<a
|
|
30
|
-
href={evergreen?.url || evergreen[key]['_']?.url || evergreen[key]['$']?.url}
|
|
31
|
-
aria-current={isActiveLink(segments, key)}
|
|
32
|
-
>{getFolderLabel(evergreen[key], true) || key}</a
|
|
33
|
-
>
|
|
34
|
-
{/if}
|
|
35
|
-
{/each}
|
|
36
|
-
</nav>
|
|
37
|
-
{#if segments[0]}
|
|
38
|
-
<svelte:self folder={evergreen[segments[0]]} segments={segments.slice(1)} child={true} />
|
|
39
|
-
{/if}
|
|
40
|
-
{/if}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { Markdown, Frontmatter } from '$lib/components';
|
|
3
|
-
import { toString } from 'mdast-util-to-string';
|
|
4
|
-
import { kebabCase } from 'change-case';
|
|
5
|
-
import Image from './Markdown/Image.svelte';
|
|
6
|
-
|
|
7
|
-
let { page, content = true, link, level = 0, website = {}, format = 'html', webmentions } = $props();
|
|
8
|
-
let { ast, title, date, image, imputedProperties } = $derived(page || {});
|
|
9
|
-
|
|
10
|
-
let headerImage = $derived(image?.output || !content && imputedProperties.image)
|
|
11
|
-
|
|
12
|
-
const dateObject = date?.type === 'date' && new Date(date.output);
|
|
13
|
-
// TODO: Add conditional logic for format = 'xml'
|
|
14
|
-
|
|
15
|
-
const headings = ast.filter((child) => child.type === 'heading');
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
<!-- Image -->
|
|
19
|
-
{#if headerImage}
|
|
20
|
-
{#if link}
|
|
21
|
-
<a href={page.url} class="image">
|
|
22
|
-
<Image node={{ url: headerImage, alt: '' }} />
|
|
23
|
-
</a>
|
|
24
|
-
{:else}
|
|
25
|
-
<Image node={{ url: headerImage, alt: '' }} />
|
|
26
|
-
{/if}
|
|
27
|
-
{/if}
|
|
28
|
-
|
|
29
|
-
<!-- Title -->
|
|
30
|
-
{#if title}
|
|
31
|
-
{#if link && page.url}
|
|
32
|
-
<h1>
|
|
33
|
-
<a href={page.url}>
|
|
34
|
-
{page.imputedProperties.title || title || page.imputedProperties?.fileName}
|
|
35
|
-
</a>
|
|
36
|
-
</h1>
|
|
37
|
-
{:else}
|
|
38
|
-
<h1 class="p-name">{page.imputedProperties.title || title || page.imputedProperties?.fileName}</h1>
|
|
39
|
-
{/if}
|
|
40
|
-
{/if}
|
|
41
|
-
|
|
42
|
-
<!-- Date -->
|
|
43
|
-
{#if link}
|
|
44
|
-
{#if dateObject}
|
|
45
|
-
<time class="dt-published" datetime={dateObject.toISOString()}>
|
|
46
|
-
<a href={page.url}>
|
|
47
|
-
{dateObject.toLocaleDateString()}
|
|
48
|
-
</a>
|
|
49
|
-
</time>
|
|
50
|
-
{/if}
|
|
51
|
-
{:else if dateObject}
|
|
52
|
-
<time datetime={dateObject.toISOString()}>{dateObject.toLocaleDateString()}</time>
|
|
53
|
-
{/if}
|
|
54
|
-
|
|
55
|
-
<Frontmatter props={{ properties: page, website, format }} />
|
|
56
|
-
|
|
57
|
-
{#if page?.description || (!content && page?.imputedProperties?.description)}
|
|
58
|
-
<p class="description p-summary">{page?.description || page?.imputedProperties.description}</p>
|
|
59
|
-
{/if}
|
|
60
|
-
|
|
61
|
-
{#if format === 'html' && page.toc && headings.length > 1}
|
|
62
|
-
<dl class="contents">
|
|
63
|
-
<dt>Contents</dt>
|
|
64
|
-
<dd>
|
|
65
|
-
<ul>
|
|
66
|
-
{#each headings as heading, index}
|
|
67
|
-
{@const headingString = toString(heading.children)}
|
|
68
|
-
<li class={`heading depth-${heading.depth}`}>
|
|
69
|
-
<a href={`#${kebabCase(headingString)}`}>{headingString}</a>
|
|
70
|
-
</li>
|
|
71
|
-
{/each}
|
|
72
|
-
</ul>
|
|
73
|
-
</dd>
|
|
74
|
-
</dl>
|
|
75
|
-
{/if}
|
|
76
|
-
|
|
77
|
-
{#if level < 2 && content}
|
|
78
|
-
<section class="content e-content">
|
|
79
|
-
<Markdown props={{ ast, level, website, format }} />
|
|
80
|
-
</section>
|
|
81
|
-
{/if}
|
|
82
|
-
|
|
83
|
-
{#if level < 2 && content && website._?.webmentions && webmentions?.children?.length}
|
|
84
|
-
<section class="webmentions">
|
|
85
|
-
<h2>Webmentions</h2>
|
|
86
|
-
{#each webmentions.children as webmention}
|
|
87
|
-
<a href={webmention.url} target="_blank">{webmention.url}</a>
|
|
88
|
-
{/each}
|
|
89
|
-
</section>
|
|
90
|
-
{/if}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { getFileLabel } from '$lib/utilities';
|
|
3
|
-
import { getFolderLabel, isActiveLink } from '../utilities';
|
|
4
|
-
|
|
5
|
-
let { section, key, root, segments } = $props();
|
|
6
|
-
|
|
7
|
-
const element = section['_'] ? 'ul' : 'div';
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<!-- TODO: Add a sort -->
|
|
11
|
-
|
|
12
|
-
{#if typeof section === 'object'}
|
|
13
|
-
<ul>
|
|
14
|
-
{#if root}
|
|
15
|
-
<li class="home">
|
|
16
|
-
<a aria-current={isActiveLink(segments)} href={section['$'].url}>
|
|
17
|
-
{getFileLabel(section['$']) || getFolderLabel(section)}
|
|
18
|
-
</a>
|
|
19
|
-
</li>
|
|
20
|
-
{/if}
|
|
21
|
-
{#each Object.keys(section) as key}
|
|
22
|
-
{#if Object.keys(section[key]).length === 1 && section[key].$ && !section[key].$.date && !key.startsWith('$')}
|
|
23
|
-
<li class={key}>
|
|
24
|
-
<a aria-current={isActiveLink(segments, key)} href={section[key].$.url}>
|
|
25
|
-
{getFileLabel(section[key]['$'], true) || getFolderLabel(section[key], true)}
|
|
26
|
-
</a>
|
|
27
|
-
</li>
|
|
28
|
-
{:else if section[key].$ && !section[key].$.date && !key.startsWith('$')}
|
|
29
|
-
<li class={key}>
|
|
30
|
-
<a aria-current={isActiveLink(segments, key)} href={section[key].$.url}>
|
|
31
|
-
{getFileLabel(section[key]['$']) || getFolderLabel(section[key])}
|
|
32
|
-
</a>
|
|
33
|
-
<svelte:self section={section[key]} segments={segments.slice(1)} {key} />
|
|
34
|
-
</li>
|
|
35
|
-
{/if}
|
|
36
|
-
{/each}
|
|
37
|
-
</ul>
|
|
38
|
-
{/if}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export { default as Breadcrumbs } from './Breadcrumbs.svelte';
|
|
2
|
-
export { default as Markdown } from './Markdown/index.svelte';
|
|
3
|
-
export { default as Nav } from './Nav.svelte';
|
|
4
|
-
export { default as Frontmatter } from './Frontmatter.svelte';
|
|
5
|
-
export { default as Page } from './Page.svelte';
|
|
6
|
-
export { default as Sitemap } from './Sitemap.svelte';
|
|
7
|
-
export { default as FrontmatterProperty } from './FrontmatterProperty.svelte';
|
|
8
|
-
export { default as FrontmatterTaxonomy } from './FrontMatterTaxonomy.svelte';
|
|
9
|
-
export { default as ResetStyles } from './ResetStyles.svelte';
|
|
10
|
-
export { default as TypographyStyles } from './TypographyStyles.svelte';
|
|
11
|
-
export { default as DefaultStyles } from './DefaultStyles.svelte';
|
|
12
|
-
export { default as NoStyles } from './NoStyles.svelte';
|
package/src/lib/index.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
// place files you want to import through the `$lib` alias in this folder.
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Build a URL for a file.
|
|
3
|
-
* @param {string} parents - Parent URL.
|
|
4
|
-
* @param {string} route - Filename.
|
|
5
|
-
* @returns {string} - URL for the file.
|
|
6
|
-
*/
|
|
7
|
-
export default function buildURL(parents, route) {
|
|
8
|
-
if (!parents) {
|
|
9
|
-
if (route === 'home' || route === 'settings') {
|
|
10
|
-
return '/';
|
|
11
|
-
}
|
|
12
|
-
return '/' + route;
|
|
13
|
-
}
|
|
14
|
-
if (route === 'home' || route === 'settings') {
|
|
15
|
-
return parents;
|
|
16
|
-
}
|
|
17
|
-
return parents + '/' + route;
|
|
18
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import fs from 'fs/promises';
|
|
2
|
-
// import { constants as fsConstants } from 'fs';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Description
|
|
6
|
-
* @param {string} folderPath - File page for a document.
|
|
7
|
-
* @returns {Promise<boolean>}
|
|
8
|
-
*/
|
|
9
|
-
export default async function checkFileExists(folderPath) {
|
|
10
|
-
try {
|
|
11
|
-
await fs.access(folderPath);
|
|
12
|
-
return true; // Folder exists
|
|
13
|
-
} catch (error) {
|
|
14
|
-
return false; // Folder does not exist
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { capitalCase } from 'change-case';
|
|
2
|
-
|
|
3
|
-
function createTitleFromDescription(description) {
|
|
4
|
-
if (description?.length > 30) {
|
|
5
|
-
return description.slice(0, 30) + '...';
|
|
6
|
-
}
|
|
7
|
-
return description;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export default function getFileLabel(page, shorter = false, date = true) {
|
|
11
|
-
const description = createTitleFromDescription(
|
|
12
|
-
page?.description || page?.imputedProperties?.description
|
|
13
|
-
);
|
|
14
|
-
|
|
15
|
-
const fileName = page?.imputedProperties?.fileName
|
|
16
|
-
? capitalCase(page?.imputedProperties?.fileName)
|
|
17
|
-
: false;
|
|
18
|
-
|
|
19
|
-
const formattedDate =
|
|
20
|
-
page?.date && date
|
|
21
|
-
? new Intl.DateTimeFormat('en-US').format(new Date(page?.date?.output))
|
|
22
|
-
: false;
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
(shorter && page?.breadcrumb) ||
|
|
26
|
-
page?.title ||
|
|
27
|
-
page?.imputedProperties?.title ||
|
|
28
|
-
page?.breadcrumb ||
|
|
29
|
-
formattedDate ||
|
|
30
|
-
(shorter && fileName) ||
|
|
31
|
-
description ||
|
|
32
|
-
fileName ||
|
|
33
|
-
null
|
|
34
|
-
);
|
|
35
|
-
}
|