vowel 0.1.2 → 0.1.4
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/.cache.json +1 -0
- package/bin.js +48 -3
- package/content/home.md +13 -11
- package/content/roadmap.md +5 -2
- package/package.json +5 -1
- package/server.js +6 -5
- package/src/lib/components/ConditionalWrapper.svelte +10 -0
- package/src/lib/components/DefaultStyles.svelte +428 -107
- package/src/lib/components/Frontmatter.svelte +0 -2
- package/src/lib/components/FrontmatterProperty.svelte +0 -2
- package/src/lib/components/Markdown/Image.svelte +2 -2
- package/src/lib/components/Markdown/Link.svelte +10 -1
- package/src/lib/components/Nav.svelte +1 -1
- package/src/lib/components/Page.svelte +0 -2
- package/src/lib/utilities/mutateMarkdownAST.js +1 -1
- package/src/lib/utilities/mutateMarkdownFrontmatter.js +1 -1
- package/src/lib/utilities/processMarkdownFiles.js +7 -2
- package/src/routes/[...path]/+layout.server.js +5 -5
- package/src/routes/[...path]/+page.svelte +4 -3
- package/svelte.config.js +8 -3
- package/vite.config.js +4 -2
package/.cache.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/bin.js
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
3
3
|
import { execSync, spawn } from 'child_process';
|
|
4
4
|
import path from 'node:path';
|
|
5
5
|
import url from 'node:url';
|
|
6
|
+
import pc from 'picocolors';
|
|
7
|
+
import mri from 'mri';
|
|
8
|
+
import filterConsole from 'filter-console';
|
|
9
|
+
import process from 'process';
|
|
10
|
+
import readline from 'readline';
|
|
11
|
+
import logUpdate from 'log-update';
|
|
12
|
+
|
|
13
|
+
const args = mri(process.argv);
|
|
6
14
|
|
|
7
15
|
// Directory where the module is
|
|
8
16
|
const binURL = import.meta.url;
|
|
@@ -12,17 +20,54 @@ const binDirName = path.dirname(binFilePath);
|
|
|
12
20
|
// Directory where the command was called
|
|
13
21
|
const homeDir = process.cwd();
|
|
14
22
|
|
|
23
|
+
const spawnArgs = ['./server.js', '--directory', homeDir];
|
|
24
|
+
if (args.build) spawnArgs.push('--build');
|
|
25
|
+
|
|
26
|
+
if (!args.verbose) {
|
|
27
|
+
filterConsole(['jsconfig', 'vite', 'Vite', 'tsconfig', `--host`]);
|
|
28
|
+
console.log(`\n\n`);
|
|
29
|
+
}
|
|
30
|
+
|
|
15
31
|
// Args: File to run, home directory,
|
|
16
|
-
const child = spawn('node',
|
|
32
|
+
const child = spawn('node', spawnArgs, {
|
|
17
33
|
cwd: binDirName
|
|
18
34
|
});
|
|
19
35
|
|
|
36
|
+
let processedFiles = 0;
|
|
37
|
+
let foundFiles = 0;
|
|
38
|
+
const std = process.stdout;
|
|
39
|
+
|
|
20
40
|
child.stdout.on('data', (data) => {
|
|
21
|
-
|
|
41
|
+
const message = data.toString();
|
|
42
|
+
if (message.match('fileread')) {
|
|
43
|
+
processedFiles++;
|
|
44
|
+
logUpdate(pc.green(` Files read: ${processedFiles}/${foundFiles}`));
|
|
45
|
+
} else if (message.startsWith('filesfound')) {
|
|
46
|
+
const count = Number(message.split(':').at(-1).slice(0, -1));
|
|
47
|
+
foundFiles += count;
|
|
48
|
+
} else if (message.startsWith('loaded')) {
|
|
49
|
+
logUpdate(pc.green(` Files read: ${foundFiles}/${foundFiles}`));
|
|
50
|
+
console.log(`\n\n`);
|
|
51
|
+
processedFiles = 0;
|
|
52
|
+
foundFiles = 0;
|
|
53
|
+
} else if (message.match('http://localhost:')) {
|
|
54
|
+
const url = message.match(/http:\/\/localhost:\S+/);
|
|
55
|
+
console.log(
|
|
56
|
+
pc.bgCyan(
|
|
57
|
+
pc.bold(`
|
|
58
|
+
|
|
59
|
+
Website: ${url}
|
|
60
|
+
`)
|
|
61
|
+
)
|
|
62
|
+
);
|
|
63
|
+
console.log(`\n`);
|
|
64
|
+
} else {
|
|
65
|
+
console.log(pc.blue(data));
|
|
66
|
+
}
|
|
22
67
|
});
|
|
23
68
|
|
|
24
69
|
child.stderr.on('data', (data) => {
|
|
25
|
-
console.error(
|
|
70
|
+
console.error(pc.red(data));
|
|
26
71
|
});
|
|
27
72
|
|
|
28
73
|
child.on('close', (code) => {
|
package/content/home.md
CHANGED
|
@@ -14,6 +14,8 @@ npx -p svelte@next -p vowel@latest npx vowel
|
|
|
14
14
|
|
|
15
15
|
Vowel is a minimal website framework for developers who love to write CSS and read RSS.
|
|
16
16
|
|
|
17
|
+
> Here's a lovely block quote.
|
|
18
|
+
|
|
17
19
|
Vowel will generate a feature-rich HTML website from a directory of markdown files. The output is plain HTML. You can style it however you want with your own CSS.
|
|
18
20
|
|
|
19
21
|
See a [demo on StackBlitz](https://stackblitz.com/edit/stackblitz-starters-nh7m7v?file=home.md). (**Error:** This demo might not work due conflicts in Svelte 5's peer dependencies.)
|
|
@@ -24,47 +26,47 @@ Vowel is created by Sam Littlefair. If you have questions or comments, [reach ou
|
|
|
24
26
|
|
|
25
27
|
# Features
|
|
26
28
|
|
|
27
|
-
## 🗺️
|
|
29
|
+
## Sitemap 🗺️
|
|
28
30
|
|
|
29
31
|
Submit your website to search engines with a sitemap that lists all of your pages.
|
|
30
32
|
|
|
31
|
-
## 📡
|
|
33
|
+
## RSS 📡
|
|
32
34
|
|
|
33
35
|
Deliver your content to RSS readers with an Atom feed that lists your full posts in reverse-chronology.
|
|
34
36
|
|
|
35
|
-
## ⚡️
|
|
37
|
+
## Speed ⚡️
|
|
36
38
|
|
|
37
39
|
Get a blazing-fast, Svelte-rendered website.
|
|
38
40
|
|
|
39
|
-
##
|
|
41
|
+
## Static generation 🗿
|
|
40
42
|
|
|
41
43
|
Load pages quickly with plain HTML.
|
|
42
44
|
|
|
43
|
-
## 🔒
|
|
45
|
+
## Copyright 🔒
|
|
44
46
|
|
|
45
47
|
Display an up-to-date copyright in the footer of your website.
|
|
46
48
|
|
|
47
|
-
##
|
|
49
|
+
## Rich link previews 🔗
|
|
48
50
|
|
|
49
51
|
Create rich links with titles and images, both internally and externally.
|
|
50
52
|
|
|
51
|
-
## 🚏
|
|
53
|
+
## Navigation 🚏
|
|
52
54
|
|
|
53
55
|
Structure your content with a header, nav, sitemap, and breadcrumbs.
|
|
54
56
|
|
|
55
|
-
##
|
|
57
|
+
## Emoji favicon 🙃
|
|
56
58
|
|
|
57
59
|
Use any emoji you want for your website's icon.
|
|
58
60
|
|
|
59
|
-
##
|
|
61
|
+
## Custom taxonomies 🖇️
|
|
60
62
|
|
|
61
63
|
Go beyond tags to create authors and categories.
|
|
62
64
|
|
|
63
|
-
##
|
|
65
|
+
## Advanced frontmatter 🧮
|
|
64
66
|
|
|
65
67
|
Display dates, lists, nested properties, links, and images in your frontmatter.
|
|
66
68
|
|
|
67
|
-
##
|
|
69
|
+
## Live editing 👩🎤
|
|
68
70
|
|
|
69
71
|
See updates live as you save.
|
|
70
72
|
|
package/content/roadmap.md
CHANGED
|
@@ -24,10 +24,13 @@ description: What's planned.
|
|
|
24
24
|
|
|
25
25
|
## V2
|
|
26
26
|
|
|
27
|
-
- [
|
|
28
|
-
- [ ] Create post list element (`#tags/blue`, `@tags/blue`, `~tags/blue`)
|
|
27
|
+
- [ ] Tables of contents
|
|
29
28
|
- [/] CSS defaults (work in progress)
|
|
29
|
+
- [ ] Fallback homepages
|
|
30
|
+
- [ ] Init CLI
|
|
31
|
+
- [ ] Better default styles
|
|
30
32
|
- [ ] CSS layout [presets](https://github.com/swyxio/spark-joy?tab=readme-ov-file#drop-in-css-frameworks)
|
|
33
|
+
- [ ] Post list element (`#tags/blue`, `@tags/blue`, `~tags/blue`)
|
|
31
34
|
- [x] Images as <figure>s
|
|
32
35
|
- [x] Frontmatter interpolation (title and description)
|
|
33
36
|
- [ ] Frontmatter interpolation (image)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vowel",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"bin": "./bin.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"dev": "vite dev",
|
|
@@ -20,10 +20,14 @@
|
|
|
20
20
|
"@sveltejs/vite-plugin-svelte": "^4.0.0-next.3",
|
|
21
21
|
"any-date-parser": "^1.5.4",
|
|
22
22
|
"change-case": "^5.4.1",
|
|
23
|
+
"filter-console": "^1.0.0",
|
|
23
24
|
"js-yaml": "^4.1.0",
|
|
25
|
+
"loading-cli": "^1.1.2",
|
|
26
|
+
"log-update": "^6.0.0",
|
|
24
27
|
"milligram": "^1.4.1",
|
|
25
28
|
"object-path": "^0.11.8",
|
|
26
29
|
"open-props": "^1.6.13",
|
|
30
|
+
"picocolors": "^1.0.1",
|
|
27
31
|
"prettier": "^3.0.0",
|
|
28
32
|
"prettier-plugin-svelte": "^3.0.0",
|
|
29
33
|
"remark": "^15.0.1",
|
package/server.js
CHANGED
|
@@ -3,17 +3,18 @@ import { createServer, build } from 'vite';
|
|
|
3
3
|
import { writeFile, mkdir, readFile } from 'fs/promises';
|
|
4
4
|
import { existsSync } from 'fs';
|
|
5
5
|
import { dirname, join } from 'path';
|
|
6
|
+
import mri from 'mri';
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const args = mri(process.argv);
|
|
9
|
+
const { build: isBuild, directory } = args;
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
const isBuild = process.argv[2] === 'build';
|
|
11
|
+
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
11
12
|
|
|
12
13
|
// If this is not a build, read the process argument
|
|
13
14
|
const arg = !isBuild ? process.argv[2] : false;
|
|
14
15
|
|
|
15
16
|
// Check if this is a user (process argument) or package dev (cwd)
|
|
16
|
-
const $home =
|
|
17
|
+
const $home = isBuild ? join(process.cwd(), 'content') : directory;
|
|
17
18
|
|
|
18
19
|
const define = {
|
|
19
20
|
$home
|
|
@@ -73,7 +74,7 @@ async function runServer() {
|
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
// If build mode
|
|
76
|
-
if (isBuild
|
|
77
|
+
if (isBuild) {
|
|
77
78
|
buildProject();
|
|
78
79
|
} else {
|
|
79
80
|
runServer();
|
|
@@ -1,138 +1,459 @@
|
|
|
1
1
|
<style>
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
|
7
|
-
--font-mono: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
|
8
|
-
}
|
|
2
|
+
/*
|
|
3
|
+
Inspiration for this stylesheet comes from Normalize.css, Josh Comeau,
|
|
4
|
+
Barebones, Basic.css, Pico, Typeplate, Simple.css, and more
|
|
5
|
+
*/
|
|
9
6
|
|
|
10
|
-
:global
|
|
11
|
-
|
|
12
|
-
padding: 0;
|
|
13
|
-
box-sizing: border-box;
|
|
14
|
-
}
|
|
7
|
+
:global {
|
|
8
|
+
/* Variables */
|
|
15
9
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
:root {
|
|
11
|
+
--font-sans: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue,
|
|
12
|
+
helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
|
|
13
|
+
--font-serif: Iowan Old Style, Apple Garamond, Baskerville, Times New Roman, Droid Serif,
|
|
14
|
+
Times, Source Serif Pro, serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
|
|
15
|
+
--font-mono: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
|
|
16
|
+
--text-color: hsl(0, 0%, 13%);
|
|
17
|
+
--accent-color: hsl(215, 100%, 35%);
|
|
18
|
+
--accent-color-hover: hsl(215, 76%, 49%);
|
|
19
|
+
--border-color: hsl(0, 0%, 73%);
|
|
20
|
+
--main-background: hsl(0, 0%, 100%);
|
|
21
|
+
--code-background: hsl(0, 0%, 95%);
|
|
22
|
+
--soft-background: hsl(0, 0%, 95%);
|
|
23
|
+
}
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
@media (prefers-color-scheme: dark) {
|
|
26
|
+
:root {
|
|
27
|
+
--text-color: hsl(0, 0%, 80%);
|
|
28
|
+
--accent-color: hsl(194, 76%, 49%);
|
|
29
|
+
--accent-color-hover: hsl(194, 86%, 57%);
|
|
30
|
+
--border-color: hsl(0, 0%, 27%);
|
|
31
|
+
--main-background: hsl(0, 0%, 12%);
|
|
32
|
+
--code-background: hsl(0, 0%, 5%);
|
|
33
|
+
--soft-background: hsl(0, 0%, 14%);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
31
36
|
|
|
32
|
-
|
|
37
|
+
/*
|
|
38
|
+
Reset
|
|
39
|
+
*/
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
*,
|
|
42
|
+
*::before,
|
|
43
|
+
*::after {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
}
|
|
39
46
|
|
|
40
|
-
|
|
47
|
+
* {
|
|
48
|
+
margin: 0;
|
|
49
|
+
}
|
|
41
50
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
justify-content: flex-start;
|
|
48
|
-
}
|
|
51
|
+
html {
|
|
52
|
+
line-height: 1.15;
|
|
53
|
+
-webkit-text-size-adjust: 100%;
|
|
54
|
+
font-size: 62.5%;
|
|
55
|
+
}
|
|
49
56
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
body {
|
|
58
|
+
font-size: 1.6rem;
|
|
59
|
+
line-height: 1.5;
|
|
60
|
+
-webkit-font-smoothing: antialiased;
|
|
61
|
+
font-weight: 400;
|
|
62
|
+
}
|
|
53
63
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
64
|
+
main,
|
|
65
|
+
img,
|
|
66
|
+
details,
|
|
67
|
+
picture,
|
|
68
|
+
video,
|
|
69
|
+
canvas,
|
|
70
|
+
svg {
|
|
71
|
+
display: block;
|
|
72
|
+
max-width: 100%;
|
|
73
|
+
}
|
|
57
74
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
font-weight: bold;
|
|
62
|
-
font-size: 2em;
|
|
63
|
-
}
|
|
75
|
+
summary {
|
|
76
|
+
display: list-item;
|
|
77
|
+
}
|
|
64
78
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
79
|
+
hr {
|
|
80
|
+
box-sizing: content-box;
|
|
81
|
+
height: 0;
|
|
82
|
+
overflow: visible;
|
|
83
|
+
}
|
|
68
84
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
85
|
+
pre {
|
|
86
|
+
font-family: monospace, monospace;
|
|
87
|
+
font-size: 1em;
|
|
88
|
+
}
|
|
74
89
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
90
|
+
a {
|
|
91
|
+
background-color: transparent;
|
|
92
|
+
}
|
|
78
93
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
abbr[title] {
|
|
95
|
+
border-bottom: none;
|
|
96
|
+
text-decoration: underline;
|
|
97
|
+
text-decoration: underline dotted;
|
|
98
|
+
}
|
|
84
99
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
b,
|
|
101
|
+
strong {
|
|
102
|
+
font-weight: bolder;
|
|
103
|
+
}
|
|
88
104
|
|
|
89
|
-
|
|
105
|
+
code,
|
|
106
|
+
kbd,
|
|
107
|
+
samp {
|
|
108
|
+
font-family: monospace, monospace;
|
|
109
|
+
font-size: 1em;
|
|
110
|
+
}
|
|
90
111
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
overflow-x: auto;
|
|
95
|
-
}
|
|
112
|
+
small {
|
|
113
|
+
font-size: 80%;
|
|
114
|
+
}
|
|
96
115
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
116
|
+
sub,
|
|
117
|
+
sup {
|
|
118
|
+
font-size: 75%;
|
|
119
|
+
line-height: 0;
|
|
120
|
+
position: relative;
|
|
121
|
+
vertical-align: baseline;
|
|
122
|
+
}
|
|
101
123
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
124
|
+
sub {
|
|
125
|
+
bottom: -0.25em;
|
|
126
|
+
}
|
|
105
127
|
|
|
106
|
-
|
|
128
|
+
sup {
|
|
129
|
+
top: -0.5em;
|
|
130
|
+
}
|
|
107
131
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
border-radius: 5px;
|
|
113
|
-
}
|
|
132
|
+
img {
|
|
133
|
+
border-style: none;
|
|
134
|
+
height: auto;
|
|
135
|
+
}
|
|
114
136
|
|
|
115
|
-
|
|
137
|
+
/* Layout */
|
|
116
138
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
.container {
|
|
140
|
+
height: 100vh;
|
|
141
|
+
overflow-y: scroll;
|
|
142
|
+
font-family: var(--font-sans);
|
|
143
|
+
}
|
|
120
144
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
145
|
+
.page {
|
|
146
|
+
max-width: 60ch;
|
|
147
|
+
margin: auto;
|
|
148
|
+
min-height: 100vh;
|
|
149
|
+
display: flex;
|
|
150
|
+
flex-direction: column;
|
|
151
|
+
padding: 1rem;
|
|
152
|
+
overflow-x: hidden;
|
|
153
|
+
}
|
|
126
154
|
|
|
127
|
-
|
|
155
|
+
main {
|
|
156
|
+
margin-bottom: auto;
|
|
157
|
+
padding-bottom: 4rem;
|
|
158
|
+
}
|
|
128
159
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
160
|
+
/* Colors */
|
|
161
|
+
|
|
162
|
+
body {
|
|
163
|
+
color: var(--text-color);
|
|
164
|
+
background: var(--main-background);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
a {
|
|
168
|
+
color: var(--accent-color);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
a:hover {
|
|
172
|
+
color: var(--accent-color-hover);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Typography */
|
|
176
|
+
|
|
177
|
+
p,
|
|
178
|
+
h1,
|
|
179
|
+
h2,
|
|
180
|
+
h3,
|
|
181
|
+
h4,
|
|
182
|
+
h5,
|
|
183
|
+
h6 {
|
|
184
|
+
overflow-wrap: break-word;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
h1,
|
|
188
|
+
h2,
|
|
189
|
+
h3,
|
|
190
|
+
h4,
|
|
191
|
+
h5,
|
|
192
|
+
h6 {
|
|
193
|
+
margin-top: 0.5rem;
|
|
194
|
+
margin-bottom: 1rem;
|
|
195
|
+
text-rendering: optimizeLegibility;
|
|
196
|
+
font-weight: 600;
|
|
197
|
+
line-height: 1.1;
|
|
198
|
+
}
|
|
199
|
+
h1 {
|
|
200
|
+
font-size: 3rem;
|
|
201
|
+
line-height: 1.2;
|
|
202
|
+
font-weight: 800;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
h2 {
|
|
206
|
+
font-size: 2.6rem;
|
|
207
|
+
margin-top: 3rem;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
h3 {
|
|
211
|
+
font-size: 2rem;
|
|
212
|
+
margin-top: 3rem;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
h4 {
|
|
216
|
+
font-size: 1.44rem;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
h5 {
|
|
220
|
+
font-size: 1.15rem;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
h6 {
|
|
224
|
+
font-size: 0.96rem;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
article h1 {
|
|
228
|
+
font-weight: 600;
|
|
229
|
+
font-size: 2rem;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@media only screen and (max-width: 720px) {
|
|
233
|
+
h1 {
|
|
234
|
+
font-size: 2.5rem;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
h2 {
|
|
238
|
+
font-size: 2.1rem;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
h3 {
|
|
242
|
+
font-size: 1.75rem;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
h4 {
|
|
246
|
+
font-size: 1.25rem;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
p {
|
|
251
|
+
margin-top: 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
ol,
|
|
255
|
+
ul {
|
|
256
|
+
/* padding-left: 0; */
|
|
257
|
+
margin-top: 0;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
ul ul,
|
|
261
|
+
ul ol,
|
|
262
|
+
ol ol,
|
|
263
|
+
ol ul {
|
|
264
|
+
font-size: 100%;
|
|
265
|
+
/* margin: 1rem 0 1rem 3rem; */
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
li {
|
|
269
|
+
margin-bottom: 0.5rem;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* Extra selector for specificity, see below */
|
|
273
|
+
li > p:not(:last-child) {
|
|
274
|
+
margin: 0;
|
|
275
|
+
padding: 0;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
code {
|
|
279
|
+
background: var(--code-background);
|
|
280
|
+
font-size: 0.9em;
|
|
281
|
+
white-space: nowrap;
|
|
282
|
+
margin-inline: 0px;
|
|
283
|
+
padding: 3px 4px;
|
|
284
|
+
border-radius: 5px;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
code,
|
|
288
|
+
mark {
|
|
289
|
+
-webkit-box-decoration-break: clone;
|
|
290
|
+
box-decoration-break: clone;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
pre {
|
|
294
|
+
background: var(--code-background);
|
|
295
|
+
padding: 1rem 1.5rem;
|
|
296
|
+
border-radius: 5px;
|
|
297
|
+
overflow-x: auto;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
dt {
|
|
301
|
+
float: left;
|
|
302
|
+
margin: 0 20px 0 0;
|
|
303
|
+
width: 120px;
|
|
304
|
+
color: #daf2fd;
|
|
305
|
+
font-weight: 500;
|
|
306
|
+
text-align: right;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
dd {
|
|
310
|
+
margin: 0 0 5px 0;
|
|
311
|
+
text-align: left;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
blockquote {
|
|
315
|
+
margin: 1.5em 0;
|
|
316
|
+
padding: 0 1.6em 0 1.6em;
|
|
317
|
+
border-left: 5px solid var(--border-color);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
a {
|
|
321
|
+
text-decoration: none;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
figcaption {
|
|
325
|
+
margin-top: 0.5rem;
|
|
326
|
+
font-style: italic;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
article {
|
|
330
|
+
border: 1px solid var(--border-color);
|
|
331
|
+
background: var(--soft-background);
|
|
332
|
+
padding: 1rem 2rem 1.5rem;
|
|
333
|
+
border-radius: 0.5rem;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
article + article {
|
|
337
|
+
margin-top: 1rem;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
th,
|
|
341
|
+
td {
|
|
342
|
+
padding: 12px 15px;
|
|
343
|
+
text-align: left;
|
|
344
|
+
border-bottom: 1px solid var(--border-color-softer);
|
|
345
|
+
}
|
|
346
|
+
th:first-child,
|
|
347
|
+
td:first-child {
|
|
348
|
+
padding-left: 0;
|
|
349
|
+
}
|
|
350
|
+
th:last-child,
|
|
351
|
+
td:last-child {
|
|
352
|
+
padding-right: 0;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
:where(pre, blockquote, dl, figure, table, p, ul, ol, form, article):not(:last-child) {
|
|
356
|
+
margin-bottom: 2.5rem;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
hr {
|
|
360
|
+
margin-top: 3rem;
|
|
361
|
+
margin-bottom: 3.5rem;
|
|
362
|
+
border-width: 0px;
|
|
363
|
+
border-top: 1px solid var(--text-color);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/* Header */
|
|
367
|
+
|
|
368
|
+
nav.top-bar {
|
|
369
|
+
border: 1px solid var(--border-color);
|
|
370
|
+
padding: 6px 10px;
|
|
371
|
+
margin-inline: -10px;
|
|
372
|
+
border-radius: 5px;
|
|
373
|
+
display: flex;
|
|
374
|
+
column-gap: 2rem;
|
|
375
|
+
row-gap: 0.5rem;
|
|
376
|
+
flex-wrap: wrap;
|
|
377
|
+
justify-content: flex-start;
|
|
378
|
+
background: var(--soft-background);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
nav.top-bar:has(+ nav.top-bar) {
|
|
382
|
+
border-bottom: none;
|
|
383
|
+
border-bottom-left-radius: 0;
|
|
384
|
+
border-bottom-right-radius: 0;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
nav.top-bar:has(+ nav.top-bar):after {
|
|
388
|
+
display: block;
|
|
389
|
+
content: '';
|
|
390
|
+
border-bottom: 1px solid var(--border-color);
|
|
391
|
+
flex-basis: 100%;
|
|
392
|
+
margin-top: 0.7rem;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
nav.top-bar + nav.top-bar {
|
|
396
|
+
border-top-left-radius: 0;
|
|
397
|
+
border-top-right-radius: 0;
|
|
398
|
+
border-top: none;
|
|
399
|
+
margin-top: 0;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
nav > a {
|
|
403
|
+
text-wrap: nowrap;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
header a.site-title {
|
|
407
|
+
color: unset;
|
|
408
|
+
text-decoration: none;
|
|
409
|
+
font-weight: 900;
|
|
410
|
+
font-size: 2.8em;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
header .slogan {
|
|
414
|
+
/* font-family: var(--font-serif); */
|
|
415
|
+
font-weight: 500;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
nav :where([aria-current='page'], [aria-current='true']),
|
|
419
|
+
nav :where([aria-current='page'], [aria-current='true']):hover {
|
|
420
|
+
text-decoration: none;
|
|
421
|
+
color: unset;
|
|
422
|
+
cursor: default;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
header .breadcrumbs {
|
|
426
|
+
margin-block: 4rem 1rem;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
header .breadcrumbs a {
|
|
430
|
+
font-size: 0.9em;
|
|
431
|
+
text-decoration: none;
|
|
432
|
+
color: unset;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
header .breadcrumbs .separator:after {
|
|
436
|
+
margin-inline: 0.5rem;
|
|
437
|
+
content: '|';
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/* Sidebar */
|
|
441
|
+
|
|
442
|
+
.sidebar {
|
|
443
|
+
margin: auto;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/* Footer */
|
|
447
|
+
|
|
448
|
+
footer {
|
|
449
|
+
text-align: center;
|
|
450
|
+
margin-block: 6rem 8rem;
|
|
451
|
+
}
|
|
132
452
|
|
|
133
|
-
|
|
453
|
+
/* Pages */
|
|
134
454
|
|
|
135
|
-
|
|
136
|
-
|
|
455
|
+
.page.home > main > h1 {
|
|
456
|
+
display: none;
|
|
457
|
+
}
|
|
137
458
|
}
|
|
138
459
|
</style>
|
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
let { node, level, website } = $props();
|
|
5
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
|
+
}
|
|
6
15
|
</script>
|
|
7
16
|
|
|
8
|
-
<a href={url}>
|
|
17
|
+
<a href={url} target={isAbsoluteURL(url) ? '_blank' : null}>
|
|
9
18
|
<Markdown props={{ ast: children, level, website }} />
|
|
10
19
|
</a>
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
{#if Object.keys(evergreen).some((key) => key !== '$' && key !== '_')}
|
|
21
|
-
<nav>
|
|
21
|
+
<nav class="top-bar">
|
|
22
22
|
{#if !child && evergreen['$']?.url !== '/'}
|
|
23
23
|
<a aria-current={isActiveLink(segments)} href={evergreen['$']?.url}
|
|
24
24
|
>{getFolderLabel(evergreen)}</a
|
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
let { page, content = true, link, level = 0, website = {}, format = 'html' } = $props();
|
|
6
6
|
let { ast, title, date, image, imputedProperties } = $derived(page || {});
|
|
7
7
|
|
|
8
|
-
console.log(`Page format: ${format}`);
|
|
9
|
-
|
|
10
8
|
const dateObject = date?.type === 'date' && new Date(date.output);
|
|
11
9
|
// TODO: Add conditional logic for format = 'xml'
|
|
12
10
|
</script>
|
|
@@ -37,7 +37,7 @@ export default async function mutateMarkdownAST(ast, cache) {
|
|
|
37
37
|
delete node.children;
|
|
38
38
|
} catch (error) {
|
|
39
39
|
node.value = url;
|
|
40
|
-
console.log(`Error on URL in content: ${url}`);
|
|
40
|
+
// console.log(`Error on URL in content: ${url}`);
|
|
41
41
|
}
|
|
42
42
|
} else {
|
|
43
43
|
node.metadata = cache[node.value];
|
|
@@ -89,7 +89,7 @@ export default async function mutateMarkdownFrontmatter(frontmatter, cache) {
|
|
|
89
89
|
input
|
|
90
90
|
};
|
|
91
91
|
} catch (e) {
|
|
92
|
-
console.error(`Error on URL in frontmatter: ${frontmatter[key]}`);
|
|
92
|
+
// console.error(`Error on URL in frontmatter: ${frontmatter[key]}`);
|
|
93
93
|
frontmatter[key] = {
|
|
94
94
|
type: 'string',
|
|
95
95
|
output: input,
|
|
@@ -103,6 +103,8 @@ async function readFolder(folderPath, parents, cache) {
|
|
|
103
103
|
|
|
104
104
|
let files = (await fs.readdir(folderPath, { withFileTypes: true })).filter(filterFiles);
|
|
105
105
|
|
|
106
|
+
console.log(`filesfound:${files.length}`);
|
|
107
|
+
|
|
106
108
|
const promises = files.map(async (file) => await readFile(file, parents, cache, folderPath));
|
|
107
109
|
|
|
108
110
|
const folder = (await Promise.all(promises)).reduce((acc, obj) => ({ ...acc, ...obj }), {});
|
|
@@ -134,7 +136,8 @@ async function readFile(file, parents, cache, folderPath) {
|
|
|
134
136
|
|
|
135
137
|
const { ast, frontmatter, imputedProperties } = await readMarkdownFile(filePath, cache);
|
|
136
138
|
const loadTime = (performance.now() - startLoad).toFixed(2);
|
|
137
|
-
console.log(`📄 ${shortPath} (${loadTime}ms)`);
|
|
139
|
+
// console.log(`📄 ${shortPath} (${loadTime}ms)`);
|
|
140
|
+
console.log('fileread');
|
|
138
141
|
if (frontmatter.published == false) return;
|
|
139
142
|
if (file.name === 'home.md' || file.name === 'settings.md') {
|
|
140
143
|
const key = file.name === 'home.md' ? '$' : '_';
|
|
@@ -173,7 +176,7 @@ async function readFile(file, parents, cache, folderPath) {
|
|
|
173
176
|
const folder = await readFolder(path.join(folderPath, file.name), url, cache);
|
|
174
177
|
|
|
175
178
|
const loadTime = (performance.now() - startLoad).toFixed(2);
|
|
176
|
-
console.log(`📁 ${shortPath} (${loadTime}ms)`);
|
|
179
|
+
// console.log(`📁 ${shortPath} (${loadTime}ms)`);
|
|
177
180
|
|
|
178
181
|
if (!folder.hasOwnProperty('$')) {
|
|
179
182
|
const $ = DefaultFile(url);
|
|
@@ -208,5 +211,7 @@ export default async function processMarkdownFiles(cache) {
|
|
|
208
211
|
const [homeDir] = $home;
|
|
209
212
|
const folder = await readFolder(homeDir, '', cache);
|
|
210
213
|
|
|
214
|
+
console.log('loaded');
|
|
215
|
+
|
|
211
216
|
return { folder, finalCache: cache };
|
|
212
217
|
}
|
|
@@ -22,15 +22,15 @@ async function checkFileExists(filePath, homeDir) {
|
|
|
22
22
|
|
|
23
23
|
/** @type {import('./$types').PageLoad} */
|
|
24
24
|
export async function load() {
|
|
25
|
-
const startLoad = performance.now();
|
|
25
|
+
// const startLoad = performance.now();
|
|
26
26
|
const now = Date.now();
|
|
27
27
|
const contentCacheDuration = 60000; // Cache for 1 minute
|
|
28
28
|
const initialURLCache = await loadCache($home[0]);
|
|
29
29
|
|
|
30
30
|
const cssExists = await checkFileExists(normalize('/assets/styles.css'), $home[0]);
|
|
31
31
|
|
|
32
|
-
if (cssExists) console.log('Found CSS file at /assets/styles.css');
|
|
33
|
-
else console.log('No CSS file found as /assets/styles.css');
|
|
32
|
+
// if (cssExists) console.log('Found CSS file at /assets/styles.css');
|
|
33
|
+
// else console.log('No CSS file found as /assets/styles.css');
|
|
34
34
|
|
|
35
35
|
const faviconExists = await checkFileExists(normalize('/assets/favicon.png'), $home[0]);
|
|
36
36
|
|
|
@@ -51,7 +51,7 @@ export async function load() {
|
|
|
51
51
|
console.log('Using content cache');
|
|
52
52
|
data = contentCache;
|
|
53
53
|
} else {
|
|
54
|
-
console.log('Not using content cache');
|
|
54
|
+
// console.log('Not using content cache');
|
|
55
55
|
data = await processMarkdownFiles(initialURLCache);
|
|
56
56
|
contentCache = data;
|
|
57
57
|
contentCacheTime = now;
|
|
@@ -64,7 +64,7 @@ export async function load() {
|
|
|
64
64
|
writeCache(finalCache, $home[0]);
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
console.log(`Load time: ${(performance.now() - startLoad).toFixed(2)} ms`);
|
|
67
|
+
// console.log(`Load time: ${(performance.now() - startLoad).toFixed(2)} ms`);
|
|
68
68
|
|
|
69
69
|
const folderName = basename($home[0]);
|
|
70
70
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { error } from '@sveltejs/kit';
|
|
7
7
|
import { getFolder, getFolderLabel } from '../../lib/utilities';
|
|
8
8
|
import { page as pageStore } from '$app/stores';
|
|
9
|
+
import ConditionalWrapper from '../../lib/components/ConditionalWrapper.svelte';
|
|
9
10
|
|
|
10
11
|
let { data } = $props();
|
|
11
12
|
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
const breadcrumbs = getBreadcrumbs().slice(1, -1).reverse();
|
|
45
|
-
const breadcrumbSegment = breadcrumbs.length ? ` - ${breadcrumbs.join(' - ')} - ` : '';
|
|
46
|
+
const breadcrumbSegment = breadcrumbs.length ? ` - ${breadcrumbs.join(' - ')} - ` : ' - ';
|
|
46
47
|
return `${pageMetaTitle}${breadcrumbSegment}${siteTitle}`;
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -113,9 +114,9 @@
|
|
|
113
114
|
<main>
|
|
114
115
|
<Page level={0} {page} {website} path={data.path} />
|
|
115
116
|
</main>
|
|
116
|
-
<
|
|
117
|
+
<nav class="sidebar">
|
|
117
118
|
<Sitemap section={data.website} segments={data.path.split('/')} root />
|
|
118
|
-
</
|
|
119
|
+
</nav>
|
|
119
120
|
<footer>
|
|
120
121
|
© {website._.author ? website._.author + ' ' : ''}
|
|
121
122
|
{new Date().getFullYear()}
|
package/svelte.config.js
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import adapter from '@sveltejs/adapter-static';
|
|
2
2
|
import path, { join } from 'path';
|
|
3
|
+
import mri from 'mri';
|
|
4
|
+
|
|
5
|
+
const args = mri(process.argv);
|
|
6
|
+
|
|
7
|
+
const isDev = args._.includes('dev');
|
|
3
8
|
|
|
4
9
|
const demoDir = process.cwd() + '/content';
|
|
5
|
-
const NPMRunDev = process.argv[2] === 'dev';
|
|
6
|
-
const isBuild = process.argv[2] === 'build';
|
|
7
|
-
const receivedHomePath =
|
|
10
|
+
// const NPMRunDev = process.argv[2] === 'dev';
|
|
11
|
+
// const isBuild = process.argv[2] === 'build';
|
|
12
|
+
const receivedHomePath = isDev || args.build ? false : args.directory;
|
|
8
13
|
const homeDir = receivedHomePath || demoDir;
|
|
9
14
|
const relativePathToHome = path.relative(process.cwd(), homeDir);
|
|
10
15
|
|
package/vite.config.js
CHANGED
|
@@ -2,11 +2,14 @@ import { sveltekit } from '@sveltejs/kit/vite';
|
|
|
2
2
|
import { defineConfig } from 'vite';
|
|
3
3
|
import path from 'path';
|
|
4
4
|
import { readMarkdownFile, loadCache } from './src/lib/utilities/index';
|
|
5
|
+
import mri from 'mri';
|
|
6
|
+
|
|
7
|
+
const args = mri(process.argv);
|
|
5
8
|
|
|
6
9
|
const demoDir = process.cwd() + '/content';
|
|
7
10
|
const NPMRunDev = process.argv[2] === 'dev';
|
|
8
11
|
const isBuild = process.argv[2] === 'build';
|
|
9
|
-
const receivedHomePath = NPMRunDev || isBuild ? false :
|
|
12
|
+
const receivedHomePath = NPMRunDev || isBuild ? false : args.directory;
|
|
10
13
|
|
|
11
14
|
const homeDir = receivedHomePath || demoDir;
|
|
12
15
|
|
|
@@ -19,7 +22,6 @@ export default defineConfig({
|
|
|
19
22
|
// Hot reload markdown
|
|
20
23
|
name: 'markdown:watch',
|
|
21
24
|
configureServer(server) {
|
|
22
|
-
console.log(`Root directory: ${homeDir}`);
|
|
23
25
|
server.watcher.add(homeDir);
|
|
24
26
|
server.watcher.on('change', async (homePath, stats) => {
|
|
25
27
|
if (homePath.endsWith('.md')) {
|