@zvndev/darkmown 1.4.0 → 2.0.0
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/AGENTS.md +17 -3
- package/CHANGELOG.md +38 -0
- package/README.md +114 -17
- package/SECURITY.md +21 -18
- package/docs/cli.md +5 -1
- package/docs/spec-alignment.md +31 -4
- package/package.json +1 -1
- package/site/_/base.skin +239 -18
- package/site/_/base.wd +4 -0
- package/site/_/feature-card.wd +4 -0
- package/site/_/footer.wd +4 -0
- package/site/_/nav.wd +5 -1
- package/site/_/scoped-promo.wd +4 -0
- package/site/_/scoped-stat.wd +4 -0
- package/site/pages/404.wd +1 -0
- package/site/pages/app.skin +27 -5
- package/site/pages/app.wd +1 -0
- package/site/pages/blog/_schema.wd +15 -0
- package/site/pages/blog/collections-and-pagination.md +38 -0
- package/site/pages/blog/collections-and-pagination.skin +127 -0
- package/site/pages/blog/drafts-that-never-leak.md +2 -0
- package/site/pages/blog/drafts-that-never-leak.skin +127 -0
- package/site/pages/blog/index.skin +144 -0
- package/site/pages/blog/index.wd +74 -0
- package/site/pages/blog/shipping-feeds.md +1 -0
- package/site/pages/blog/shipping-feeds.skin +127 -0
- package/site/pages/blog/typed-frontmatter.md +45 -0
- package/site/pages/blog/typed-frontmatter.skin +127 -0
- package/site/pages/blog/unfinished-thoughts.skin +127 -0
- package/site/pages/blog/zero-js-by-default.md +31 -0
- package/site/pages/blog/zero-js-by-default.skin +127 -0
- package/site/pages/carousel/index.wd +1 -0
- package/site/pages/compass/index.wd +1 -0
- package/site/pages/data.skin +50 -9
- package/site/pages/data.wd +3 -0
- package/site/pages/docs/-relative-note.wd +4 -0
- package/site/pages/docs/index.skin +27 -0
- package/site/pages/docs/index.wd +115 -11
- package/site/pages/folio/-style.wd +4 -0
- package/site/pages/folio/cart.wd +1 -0
- package/site/pages/folio/index.wd +1 -0
- package/site/pages/forge/index.wd +1 -0
- package/site/pages/highlight/index.wd +1 -0
- package/site/pages/index.wd +1 -0
- package/site/pages/interactions/index.wd +1 -0
- package/site/pages/ledger/index.wd +1 -0
- package/site/pages/loops.skin +43 -6
- package/site/pages/loops.wd +1 -0
- package/site/pages/media/index.wd +1 -0
- package/site/pages/pulse/index.wd +1 -0
- package/site/pages/reactive.skin +38 -6
- package/site/pages/reactive.wd +1 -0
- package/site/pages/scoped/index.wd +1 -0
- package/site/pages/showcase/index.wd +1 -0
- package/site/pages/store.skin +43 -6
- package/site/pages/store.wd +1 -0
- package/site/pages/theme.wd +1 -0
- package/src/builder.js +535 -48
- package/src/cli.js +96 -18
- package/src/compiler/actions.js +303 -0
- package/src/compiler/body.js +36 -24
- package/src/compiler/collections.js +316 -0
- package/src/compiler/context.js +83 -6
- package/src/compiler/directives.js +31 -1470
- package/src/compiler/fetch.js +159 -0
- package/src/compiler/format.js +17 -4
- package/src/compiler/forms.js +456 -0
- package/src/compiler/frontmatter.js +10 -5
- package/src/compiler/includes.js +66 -1
- package/src/compiler/index.js +15 -3
- package/src/compiler/loops.js +181 -31
- package/src/compiler/markdown.js +65 -15
- package/src/compiler/media.js +133 -0
- package/src/compiler/page.js +78 -41
- package/src/compiler/state.js +168 -0
- package/src/compiler/structure.js +377 -0
- package/src/dev.js +76 -0
- package/src/headers.js +56 -17
- package/src/router.js +12 -1
- package/src/runtime.js +5 -3
- package/src/statics.js +63 -12
- package/src/templates/blog/README.md +13 -4
- package/src/templates/blog/site/_/nav.wd +4 -0
- package/src/templates/blog/site/pages/index.skin +87 -0
- package/src/templates/blog/site/pages/index.wd +10 -4
- package/src/templates/blog/site/pages/posts/_schema.wd +16 -0
- package/src/templates/blog/site/pages/posts/hello-darkmown.md +2 -0
- package/src/templates/blog/site/pages/posts/hello-darkmown.skin +59 -0
- package/src/templates/blog/site/pages/posts/markdown-native.md +9 -4
- package/src/templates/blog/site/pages/posts/markdown-native.skin +59 -0
- package/src/templates/dashboard/site/_/nav.wd +4 -0
- package/src/templates/dashboard/site/pages/index.skin +84 -0
- package/src/templates/dashboard/site/pages/index.wd +1 -0
- package/src/templates/landing/site/_/nav.wd +4 -0
- package/src/templates/landing/site/pages/index.skin +113 -6
- package/src/templates/landing/site/pages/index.wd +1 -0
- package/src/templates/starter/site/_/nav.wd +4 -0
- package/src/templates/starter/site/pages/about.md +18 -1
- package/src/templates/starter/site/pages/about.skin +69 -0
- package/src/templates/starter/site/pages/index.skin +81 -3
- package/src/templates/starter/site/pages/index.wd +1 -0
- package/src/templates/store/site/_/nav.wd +4 -0
- package/src/templates/store/site/pages/index.skin +93 -11
- package/src/templates/store/site/pages/index.wd +1 -0
- package/site/pages/blog/index.md +0 -13
- package/src/templates/blog/site/_/posts.json +0 -16
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* Colocated post styling — a .skin next to a .md attaches automatically, so
|
|
2
|
+
these prose pages stay static (zero JS) yet still read on-brand. A .md can't
|
|
3
|
+
@include /base.wd, so this reading skin carries the site's tokens itself.
|
|
4
|
+
Kept in sync with site/_/base.skin; copy it beside each new post. */
|
|
5
|
+
|
|
6
|
+
tokens
|
|
7
|
+
ink #1c1814
|
|
8
|
+
ink-soft #4b4239
|
|
9
|
+
muted #756a5d
|
|
10
|
+
paper #faf8f3
|
|
11
|
+
panel #ffffff
|
|
12
|
+
sunk #efe9dc
|
|
13
|
+
line #e7e1d4
|
|
14
|
+
accent #0f6b5e
|
|
15
|
+
accent-deep #0a4f45
|
|
16
|
+
accent-soft #e3f0ec
|
|
17
|
+
code-bg #1b2420
|
|
18
|
+
code-ink #e9efe7
|
|
19
|
+
code-line #2c3b34
|
|
20
|
+
radius 12px
|
|
21
|
+
|
|
22
|
+
tokens dark
|
|
23
|
+
ink #ece6db
|
|
24
|
+
ink-soft #c3bbab
|
|
25
|
+
muted #9a9081
|
|
26
|
+
paper #14110d
|
|
27
|
+
panel #1e1913
|
|
28
|
+
sunk #221d17
|
|
29
|
+
line #2f281f
|
|
30
|
+
accent #5ccab4
|
|
31
|
+
accent-deep #8fe0cf
|
|
32
|
+
accent-soft #16302a
|
|
33
|
+
code-bg #100d0a
|
|
34
|
+
code-ink #e4ebe2
|
|
35
|
+
code-line #2a231b
|
|
36
|
+
|
|
37
|
+
html
|
|
38
|
+
bg $paper
|
|
39
|
+
|
|
40
|
+
page
|
|
41
|
+
max-width 720px
|
|
42
|
+
margin 0 auto
|
|
43
|
+
padding 3rem 1.5rem 5rem
|
|
44
|
+
font-family ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, Cambria, serif
|
|
45
|
+
font-size 18px
|
|
46
|
+
line-height 1.7
|
|
47
|
+
color $ink
|
|
48
|
+
bg $paper
|
|
49
|
+
-webkit-font-smoothing antialiased
|
|
50
|
+
text-rendering optimizeLegibility
|
|
51
|
+
|
|
52
|
+
h1
|
|
53
|
+
font-size clamp(2rem, 5vw, 2.8rem)
|
|
54
|
+
line-height 1.12
|
|
55
|
+
letter-spacing -.022em
|
|
56
|
+
margin 1rem 0 1.25rem
|
|
57
|
+
color $ink
|
|
58
|
+
|
|
59
|
+
h2
|
|
60
|
+
font-size 1.5rem
|
|
61
|
+
line-height 1.2
|
|
62
|
+
letter-spacing -.012em
|
|
63
|
+
margin 2.4rem 0 .6rem
|
|
64
|
+
color $ink
|
|
65
|
+
|
|
66
|
+
h3
|
|
67
|
+
font-size 1.2rem
|
|
68
|
+
margin 1.8rem 0 .4rem
|
|
69
|
+
color $ink
|
|
70
|
+
|
|
71
|
+
p
|
|
72
|
+
margin 1.1rem 0
|
|
73
|
+
|
|
74
|
+
a
|
|
75
|
+
color $accent
|
|
76
|
+
text-underline-offset 2px
|
|
77
|
+
|
|
78
|
+
a:hover
|
|
79
|
+
color $accent-deep
|
|
80
|
+
|
|
81
|
+
strong
|
|
82
|
+
font-weight 650
|
|
83
|
+
color $ink
|
|
84
|
+
|
|
85
|
+
hr
|
|
86
|
+
border 0
|
|
87
|
+
border-top 1px solid $line
|
|
88
|
+
margin 2.5rem 0
|
|
89
|
+
|
|
90
|
+
ul, ol
|
|
91
|
+
margin 1.1rem 0
|
|
92
|
+
padding-left 1.4rem
|
|
93
|
+
|
|
94
|
+
li
|
|
95
|
+
margin .35rem 0
|
|
96
|
+
|
|
97
|
+
code
|
|
98
|
+
font-family ui-monospace, "SF Mono", Menlo, Consolas, monospace
|
|
99
|
+
font-size .88em
|
|
100
|
+
bg $sunk
|
|
101
|
+
color $accent-deep
|
|
102
|
+
padding .12rem .36rem
|
|
103
|
+
radius 6px
|
|
104
|
+
|
|
105
|
+
pre
|
|
106
|
+
bg $code-bg
|
|
107
|
+
color $code-ink
|
|
108
|
+
padding 1.2rem 1.35rem
|
|
109
|
+
margin 1.5rem 0
|
|
110
|
+
radius $radius
|
|
111
|
+
overflow-x auto
|
|
112
|
+
line-height 1.62
|
|
113
|
+
font-size .87rem
|
|
114
|
+
box-shadow inset 0 0 0 1px $code-line
|
|
115
|
+
|
|
116
|
+
pre code
|
|
117
|
+
bg transparent
|
|
118
|
+
color inherit
|
|
119
|
+
padding 0
|
|
120
|
+
font-size 1em
|
|
121
|
+
|
|
122
|
+
blockquote
|
|
123
|
+
margin 1.6rem 0
|
|
124
|
+
padding .6rem 1.3rem
|
|
125
|
+
border-left 3px solid $accent
|
|
126
|
+
color $ink-soft
|
|
127
|
+
font-style italic
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Zero JavaScript, by default
|
|
3
|
+
description: A Darkmown page ships no framework JavaScript unless it declares reactive behavior. The blog you are reading proves it.
|
|
4
|
+
date: 2026-06-25
|
|
5
|
+
excerpt: View source on this page. There is no runtime script tag, because nothing on it is reactive — and the framework knows the difference.
|
|
6
|
+
tags: [performance, philosophy]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Zero JavaScript, by default
|
|
10
|
+
|
|
11
|
+
Open your browser's view-source on this post. Look for a `<script>` that loads a
|
|
12
|
+
framework runtime. There isn't one — and there isn't one on the blog index, or
|
|
13
|
+
on any of its paginated pages either. None of them declare reactive behavior, so
|
|
14
|
+
none of them pay for it.
|
|
15
|
+
|
|
16
|
+
That is the whole bargain. A `.md` file is plain CommonMark. Rename it to `.wd`
|
|
17
|
+
and you unlock directives — state, loops, conditionals — but you only ship the
|
|
18
|
+
~7.4 KB runtime on the pages that actually use them. A listing built from a
|
|
19
|
+
collection loop resolves entirely at build time, so it stays static HTML.
|
|
20
|
+
|
|
21
|
+
## The extension is the feature gate
|
|
22
|
+
|
|
23
|
+
There is no flag to toggle, no "static export" mode to remember. The compiler
|
|
24
|
+
tracks whether a page declared anything reactive and emits `runtime: false` into
|
|
25
|
+
`routes.json` when it didn't. A collection listing, a paginated archive, a page
|
|
26
|
+
of prose with a code block — all static, all cacheable on a CDN forever, all
|
|
27
|
+
fast on the first byte because there is nothing to hydrate.
|
|
28
|
+
|
|
29
|
+
When you do want an island of interactivity — a search box, a cart, a sortable
|
|
30
|
+
table — you declare it, and only that page loads the runtime. The rest of the
|
|
31
|
+
site stays weightless.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* Colocated post styling — a .skin next to a .md attaches automatically, so
|
|
2
|
+
these prose pages stay static (zero JS) yet still read on-brand. A .md can't
|
|
3
|
+
@include /base.wd, so this reading skin carries the site's tokens itself.
|
|
4
|
+
Kept in sync with site/_/base.skin; copy it beside each new post. */
|
|
5
|
+
|
|
6
|
+
tokens
|
|
7
|
+
ink #1c1814
|
|
8
|
+
ink-soft #4b4239
|
|
9
|
+
muted #756a5d
|
|
10
|
+
paper #faf8f3
|
|
11
|
+
panel #ffffff
|
|
12
|
+
sunk #efe9dc
|
|
13
|
+
line #e7e1d4
|
|
14
|
+
accent #0f6b5e
|
|
15
|
+
accent-deep #0a4f45
|
|
16
|
+
accent-soft #e3f0ec
|
|
17
|
+
code-bg #1b2420
|
|
18
|
+
code-ink #e9efe7
|
|
19
|
+
code-line #2c3b34
|
|
20
|
+
radius 12px
|
|
21
|
+
|
|
22
|
+
tokens dark
|
|
23
|
+
ink #ece6db
|
|
24
|
+
ink-soft #c3bbab
|
|
25
|
+
muted #9a9081
|
|
26
|
+
paper #14110d
|
|
27
|
+
panel #1e1913
|
|
28
|
+
sunk #221d17
|
|
29
|
+
line #2f281f
|
|
30
|
+
accent #5ccab4
|
|
31
|
+
accent-deep #8fe0cf
|
|
32
|
+
accent-soft #16302a
|
|
33
|
+
code-bg #100d0a
|
|
34
|
+
code-ink #e4ebe2
|
|
35
|
+
code-line #2a231b
|
|
36
|
+
|
|
37
|
+
html
|
|
38
|
+
bg $paper
|
|
39
|
+
|
|
40
|
+
page
|
|
41
|
+
max-width 720px
|
|
42
|
+
margin 0 auto
|
|
43
|
+
padding 3rem 1.5rem 5rem
|
|
44
|
+
font-family ui-serif, "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, Cambria, serif
|
|
45
|
+
font-size 18px
|
|
46
|
+
line-height 1.7
|
|
47
|
+
color $ink
|
|
48
|
+
bg $paper
|
|
49
|
+
-webkit-font-smoothing antialiased
|
|
50
|
+
text-rendering optimizeLegibility
|
|
51
|
+
|
|
52
|
+
h1
|
|
53
|
+
font-size clamp(2rem, 5vw, 2.8rem)
|
|
54
|
+
line-height 1.12
|
|
55
|
+
letter-spacing -.022em
|
|
56
|
+
margin 1rem 0 1.25rem
|
|
57
|
+
color $ink
|
|
58
|
+
|
|
59
|
+
h2
|
|
60
|
+
font-size 1.5rem
|
|
61
|
+
line-height 1.2
|
|
62
|
+
letter-spacing -.012em
|
|
63
|
+
margin 2.4rem 0 .6rem
|
|
64
|
+
color $ink
|
|
65
|
+
|
|
66
|
+
h3
|
|
67
|
+
font-size 1.2rem
|
|
68
|
+
margin 1.8rem 0 .4rem
|
|
69
|
+
color $ink
|
|
70
|
+
|
|
71
|
+
p
|
|
72
|
+
margin 1.1rem 0
|
|
73
|
+
|
|
74
|
+
a
|
|
75
|
+
color $accent
|
|
76
|
+
text-underline-offset 2px
|
|
77
|
+
|
|
78
|
+
a:hover
|
|
79
|
+
color $accent-deep
|
|
80
|
+
|
|
81
|
+
strong
|
|
82
|
+
font-weight 650
|
|
83
|
+
color $ink
|
|
84
|
+
|
|
85
|
+
hr
|
|
86
|
+
border 0
|
|
87
|
+
border-top 1px solid $line
|
|
88
|
+
margin 2.5rem 0
|
|
89
|
+
|
|
90
|
+
ul, ol
|
|
91
|
+
margin 1.1rem 0
|
|
92
|
+
padding-left 1.4rem
|
|
93
|
+
|
|
94
|
+
li
|
|
95
|
+
margin .35rem 0
|
|
96
|
+
|
|
97
|
+
code
|
|
98
|
+
font-family ui-monospace, "SF Mono", Menlo, Consolas, monospace
|
|
99
|
+
font-size .88em
|
|
100
|
+
bg $sunk
|
|
101
|
+
color $accent-deep
|
|
102
|
+
padding .12rem .36rem
|
|
103
|
+
radius 6px
|
|
104
|
+
|
|
105
|
+
pre
|
|
106
|
+
bg $code-bg
|
|
107
|
+
color $code-ink
|
|
108
|
+
padding 1.2rem 1.35rem
|
|
109
|
+
margin 1.5rem 0
|
|
110
|
+
radius $radius
|
|
111
|
+
overflow-x auto
|
|
112
|
+
line-height 1.62
|
|
113
|
+
font-size .87rem
|
|
114
|
+
box-shadow inset 0 0 0 1px $code-line
|
|
115
|
+
|
|
116
|
+
pre code
|
|
117
|
+
bg transparent
|
|
118
|
+
color inherit
|
|
119
|
+
padding 0
|
|
120
|
+
font-size 1em
|
|
121
|
+
|
|
122
|
+
blockquote
|
|
123
|
+
margin 1.6rem 0
|
|
124
|
+
padding .6rem 1.3rem
|
|
125
|
+
border-left 3px solid $accent
|
|
126
|
+
color $ink-soft
|
|
127
|
+
font-style italic
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
html: true
|
|
2
3
|
title: Swiper — a draggable carousel wired to wd.subscribe
|
|
3
4
|
description: An image carousel with arrow-key nav, pointer drag / swipe, and a sliding transition — the things a deliberately tiny framework leaves to you. Darkmown owns the reactive slide state, the dots, and the readout declaratively; a colocated index.js adds the gestures through window.wd.subscribe and window.wd.set.
|
|
4
5
|
image: https://darkmown.com/__wd/media/og-showcase.png
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
html: true
|
|
2
3
|
title: Compass — find your match
|
|
3
4
|
description: A guided product-finder quiz built in one Markdown file. Four questions advance a state machine with :if branching, accumulate scores with :button actions, and a :computed recommendation lands the perfect pick. Zero hand-written JavaScript.
|
|
4
5
|
image: https://darkmown.com/__wd/media/og-compass.png
|
package/site/pages/data.skin
CHANGED
|
@@ -29,18 +29,44 @@ h2
|
|
|
29
29
|
padding-top 1.2rem
|
|
30
30
|
|
|
31
31
|
button
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
display inline-flex
|
|
33
|
+
align-items center
|
|
34
|
+
justify-content center
|
|
35
|
+
gap .5rem
|
|
36
|
+
border 1px solid $accent
|
|
37
|
+
bg $accent
|
|
34
38
|
color white
|
|
35
|
-
padding .
|
|
39
|
+
padding .6rem 1.1rem
|
|
36
40
|
margin .3rem .5rem .3rem 0
|
|
37
|
-
radius
|
|
38
|
-
font
|
|
41
|
+
radius 999px
|
|
42
|
+
font system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
|
|
43
|
+
font-size .92rem
|
|
44
|
+
font-weight 560
|
|
45
|
+
line-height 1.15
|
|
39
46
|
cursor pointer
|
|
47
|
+
appearance none
|
|
48
|
+
box-shadow 0 1px 2px rgba(23,23,23,.08)
|
|
49
|
+
transition transform .14s cubic-bezier(.2,.7,.3,1), box-shadow .14s ease, background .14s ease, border-color .14s ease
|
|
40
50
|
|
|
41
51
|
button:hover
|
|
42
52
|
bg $accent
|
|
43
53
|
border-color $accent
|
|
54
|
+
transform translateY(-1px)
|
|
55
|
+
box-shadow 0 8px 18px -8px rgba(22,100,90,.5)
|
|
56
|
+
|
|
57
|
+
button:active
|
|
58
|
+
transform translateY(0)
|
|
59
|
+
box-shadow 0 1px 2px rgba(23,23,23,.08)
|
|
60
|
+
|
|
61
|
+
button:focus-visible
|
|
62
|
+
outline 2px solid $accent
|
|
63
|
+
outline-offset 2px
|
|
64
|
+
|
|
65
|
+
button:disabled
|
|
66
|
+
opacity .5
|
|
67
|
+
cursor not-allowed
|
|
68
|
+
box-shadow none
|
|
69
|
+
transform none
|
|
44
70
|
|
|
45
71
|
a
|
|
46
72
|
color $accent
|
|
@@ -75,21 +101,36 @@ form
|
|
|
75
101
|
margin 1rem 0
|
|
76
102
|
|
|
77
103
|
input
|
|
78
|
-
padding .
|
|
104
|
+
padding .62rem .85rem
|
|
79
105
|
border 1px solid $line
|
|
80
106
|
radius $radius
|
|
81
107
|
font inherit
|
|
108
|
+
font-size .95rem
|
|
82
109
|
bg $panel
|
|
110
|
+
appearance none
|
|
111
|
+
transition border-color .14s ease, box-shadow .14s ease
|
|
112
|
+
|
|
113
|
+
input:hover
|
|
114
|
+
border-color $accent
|
|
115
|
+
|
|
116
|
+
input:focus-visible
|
|
117
|
+
outline none
|
|
118
|
+
border-color $accent
|
|
119
|
+
box-shadow 0 0 0 3px rgba(22,100,90,.18)
|
|
83
120
|
|
|
84
121
|
.pulse-button
|
|
85
|
-
border
|
|
122
|
+
border 1px solid $warm
|
|
86
123
|
bg $warm
|
|
87
124
|
color white
|
|
88
|
-
padding .
|
|
89
|
-
radius
|
|
125
|
+
padding .6rem 1.1rem
|
|
126
|
+
radius 999px
|
|
90
127
|
font inherit
|
|
91
128
|
cursor pointer
|
|
92
129
|
|
|
130
|
+
.pulse-button:hover
|
|
131
|
+
transform translateY(-1px)
|
|
132
|
+
box-shadow 0 8px 18px -8px rgba(168,63,42,.5)
|
|
133
|
+
|
|
93
134
|
.tally-card
|
|
94
135
|
border 1px solid $line
|
|
95
136
|
bg $panel
|
package/site/pages/data.wd
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
+
html: true
|
|
2
3
|
title: Data, forms, and persistence
|
|
3
4
|
transitions: true
|
|
4
5
|
---
|
|
@@ -38,6 +39,8 @@ That loop also proves `:if` over loop items: the lead badge is decided per row.
|
|
|
38
39
|
|
|
39
40
|
Every `:fetch` tracks the whole lifecycle — `loading`, `error`, `empty`, and data — so a page can answer each one. Here the same primitive shows an **error** (a missing URL 404s) and an **empty** result (a file that is just `[]`):
|
|
40
41
|
|
|
42
|
+
*(Heads up: the browser console will log a `404` for `intentionally-missing.json` on this page — that failure is deliberate, so the error branch below has something real to show.)*
|
|
43
|
+
|
|
41
44
|
:fetch broken from "/__wd/data/intentionally-missing.json"
|
|
42
45
|
|
|
43
46
|
:if broken_error
|
|
@@ -17,6 +17,33 @@ main.docs
|
|
|
17
17
|
color $ink-soft
|
|
18
18
|
max-width 60ch
|
|
19
19
|
|
|
20
|
+
/* On-page TOC — a compact multi-column block of plain # anchors. */
|
|
21
|
+
.docs-toc
|
|
22
|
+
border 1px solid $line
|
|
23
|
+
bg $panel
|
|
24
|
+
radius $radius
|
|
25
|
+
padding 1.1rem 1.35rem
|
|
26
|
+
margin 1.25rem 0 .5rem
|
|
27
|
+
|
|
28
|
+
.docs-toc ul
|
|
29
|
+
columns 2
|
|
30
|
+
column-gap 2.5rem
|
|
31
|
+
margin .55rem 0 0
|
|
32
|
+
padding 0
|
|
33
|
+
list-style none
|
|
34
|
+
|
|
35
|
+
.docs-toc li
|
|
36
|
+
margin .18rem 0
|
|
37
|
+
break-inside avoid
|
|
38
|
+
font-size .95rem
|
|
39
|
+
|
|
40
|
+
.docs-toc a
|
|
41
|
+
font-weight 500
|
|
42
|
+
|
|
43
|
+
@media (max-width: 600px)
|
|
44
|
+
.docs-toc ul
|
|
45
|
+
columns 1
|
|
46
|
+
|
|
20
47
|
/* Section headings get a quiet rule above them so the long page scans. */
|
|
21
48
|
main.docs h2
|
|
22
49
|
margin-top 3rem
|