@zvndev/darkmown 0.20.0 → 1.1.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.
Files changed (57) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +29 -0
  3. package/README.md +125 -5
  4. package/docs/spec-alignment.md +23 -3
  5. package/package.json +3 -3
  6. package/site/_/base.skin +372 -0
  7. package/site/_/base.wd +4 -0
  8. package/site/_/footer.wd +14 -0
  9. package/site/_/metrics.json +13 -0
  10. package/site/_/nav.skin +35 -12
  11. package/site/_/nav.wd +8 -10
  12. package/site/_/products.json +10 -0
  13. package/site/pages/app.wd +1 -1
  14. package/site/pages/carousel/index.js +82 -0
  15. package/site/pages/carousel/index.skin +185 -0
  16. package/site/pages/carousel/index.wd +109 -0
  17. package/site/pages/carousel/slide-1.jpg +0 -0
  18. package/site/pages/carousel/slide-2.jpg +0 -0
  19. package/site/pages/carousel/slide-3.jpg +0 -0
  20. package/site/pages/carousel/slide-4.jpg +0 -0
  21. package/site/pages/carousel/slide-5.jpg +0 -0
  22. package/site/pages/compass/index.skin +247 -0
  23. package/site/pages/compass/index.wd +194 -0
  24. package/site/pages/docs/index.skin +48 -28
  25. package/site/pages/docs/index.wd +72 -5
  26. package/site/pages/folio/-style.skin +375 -0
  27. package/site/pages/folio/-style.wd +6 -0
  28. package/site/pages/folio/cart.skin +309 -0
  29. package/site/pages/folio/cart.wd +201 -0
  30. package/site/pages/folio/index.skin +24 -0
  31. package/site/pages/folio/index.wd +167 -0
  32. package/site/pages/forge/index.skin +676 -0
  33. package/site/pages/forge/index.wd +330 -0
  34. package/site/pages/index.skin +135 -144
  35. package/site/pages/index.wd +17 -5
  36. package/site/pages/ledger/index.skin +257 -0
  37. package/site/pages/ledger/index.wd +183 -0
  38. package/site/pages/media/clip-poster.jpg +0 -0
  39. package/site/pages/media/clip.mp4 +0 -0
  40. package/site/pages/media/index.skin +82 -0
  41. package/site/pages/media/index.wd +84 -0
  42. package/site/pages/media/tone.mp3 +0 -0
  43. package/site/pages/pulse/index.skin +434 -0
  44. package/site/pages/pulse/index.wd +178 -0
  45. package/site/pages/showcase/index.skin +130 -0
  46. package/site/pages/showcase/index.wd +168 -0
  47. package/src/compiler/body.js +89 -3
  48. package/src/compiler/context.js +1 -1
  49. package/src/compiler/directives.js +199 -3
  50. package/src/compiler/format.js +244 -0
  51. package/src/compiler/interpolation.js +36 -1
  52. package/src/compiler/loops.js +95 -24
  53. package/src/compiler/markdown.js +16 -7
  54. package/src/compiler/predicates.js +35 -2
  55. package/src/headers.js +5 -0
  56. package/src/runtime.js +168 -14
  57. package/src/skin.js +9 -1
@@ -0,0 +1,201 @@
1
+ ---
2
+ title: Folio — your basket
3
+ description: The Folio checkout. The same :store cart shared with the catalog, a per-row remove, and a form that round-trips to a server — all written in Markdown.
4
+ image: https://darkmown.com/__wd/media/og-folio.png
5
+ transitions: true
6
+ ---
7
+
8
+ @include /nav.wd
9
+ @include /base.wd
10
+ @include ./-style.wd
11
+
12
+ <main class="wide app-folio">
13
+
14
+ ::: section #checkout
15
+
16
+ :store cart = []
17
+ :computed count = cart.length
18
+ :computed subtotal = sum(cart, price)
19
+ :computed tax = subtotal * 0.08
20
+ :computed total = subtotal * 1.08
21
+
22
+ ::: shop-head
23
+ ::: shop-mark
24
+ ::: shop-eyebrow
25
+ Checkout
26
+ :::
27
+
28
+ # Your *basket*
29
+
30
+ ::: shop-tagline
31
+ The same basket you filled on the shelf — it carried over on its own. Review it, then place a test order through a live server round-trip.
32
+ :::
33
+ :::
34
+
35
+ ::: cart-peek
36
+ { count } items
37
+ :::
38
+ :::
39
+
40
+ ::: cart-grid
41
+
42
+ ::: cart-lines
43
+
44
+ ## Items
45
+
46
+ @loop cart into item
47
+ ::: card .line
48
+ ::: line-emoji
49
+ { item.emoji }
50
+ :::
51
+ ::: line-body
52
+ ::: line-name
53
+ { item.name }
54
+ :::
55
+ ::: line-cat
56
+ { item.category }
57
+ :::
58
+ :::
59
+ ::: line-price
60
+ { item.price | money }
61
+ :::
62
+ :button "Remove" -> cart remove item
63
+ :::
64
+ @empty
65
+ ::: card .cart-blank
66
+ **Your basket is empty.**
67
+
68
+ Nothing here yet — the shelf is just a click away.
69
+
70
+ [← Back to the shop](/folio/)
71
+ :::
72
+ @endloop
73
+
74
+ :if count > 0
75
+ ::: card .order-summary
76
+ ### Order summary
77
+
78
+ ::: sum-row
79
+ Subtotal ({ count | pluralize:"item" })
80
+ ::: sum-val
81
+ { subtotal | money }
82
+ :::
83
+ :::
84
+ ::: sum-row
85
+ Tax (8%)
86
+ ::: sum-val
87
+ { tax | money }
88
+ :::
89
+ :::
90
+ ::: sum-row .sum-total
91
+ **Total**
92
+ ::: sum-val
93
+ **{ total | money }**
94
+ :::
95
+ :::
96
+
97
+ :button "Clear basket" -> cart clear
98
+ :::
99
+ :endif
100
+
101
+ :::
102
+
103
+ ::: checkout-panel
104
+
105
+ ## Place your order
106
+
107
+ This is a real form. With the runtime it posts over `fetch` and shows the reply inline; with JavaScript off, the identical markup degrades to a native POST. The demo endpoint simply echoes your order back.
108
+
109
+ :form action="/__wd/echo" into receipt
110
+ :input name placeholder="Full name" required
111
+ :input email type=email placeholder="you@studio.com" required
112
+ :select shipping
113
+ - Standard — 3-5 days
114
+ - Express — overnight
115
+ - Local pickup
116
+ :submit "Place order"
117
+ :endform
118
+
119
+ :if receipt
120
+ ::: card .receipt
121
+ **Order received ✓**
122
+
123
+ Thank you, **{ receipt.received.name }** — a confirmation is on its way to { receipt.received.email }. Shipping: { receipt.received.shipping }.
124
+
125
+ ::: receipt-stamp
126
+ Logged by the server at { receipt.at }
127
+ :::
128
+ :::
129
+ :else
130
+ ::: checkout-hint
131
+ Fill in your details and place the order to see the server's reply appear right here.
132
+ :::
133
+ :endif
134
+
135
+ :if receipt_error
136
+ ::: card .receipt-error
137
+ Something went wrong: { receipt_error }
138
+ :::
139
+ :endif
140
+
141
+ :::
142
+
143
+ :::
144
+
145
+ ::: persist-note
146
+ ::: dot
147
+ ✷
148
+ :::
149
+ This basket is the **same `:store`** declared on the catalog — one name, one shared storage. Remove a line here and it's gone on the shelf too, in every open tab, even after a reload.
150
+ :::
151
+
152
+ <details class="source-reveal">
153
+ <summary>View source — it's Markdown</summary>
154
+
155
+ ```wd
156
+ :store cart = []
157
+ :computed count = cart.length
158
+ :computed subtotal = sum(cart, price)
159
+ :computed total = subtotal * 1.08
160
+
161
+ @loop cart into item
162
+ ::: card .line
163
+ { item.emoji } **{ item.name }** — { item.price | money }
164
+ :button "Remove" -> cart remove item
165
+ :::
166
+ @empty
167
+ Your basket is empty.
168
+ @endloop
169
+
170
+ Subtotal ({ count | pluralize:"item" }) — **{ subtotal | money }**
171
+ Total with tax — **{ total | money }**
172
+
173
+ :button "Clear basket" -> cart clear
174
+
175
+ :form action="/__wd/echo" into receipt
176
+ :input name placeholder="Full name" required
177
+ :input email type=email placeholder="you@studio.com" required
178
+ :select shipping
179
+ - Standard — 3-5 days
180
+ - Express — overnight
181
+ - Local pickup
182
+ :submit "Place order"
183
+ :endform
184
+
185
+ :if receipt
186
+ Thank you, { receipt.received.name }!
187
+ :endif
188
+ ```
189
+
190
+ </details>
191
+
192
+ ::: folio-foot
193
+ Keep browsing —
194
+ [← Back to the shop](/folio/)
195
+ :::
196
+
197
+ :::
198
+
199
+ </main>
200
+
201
+ @include /footer.wd
@@ -0,0 +1,24 @@
1
+ /* Folio catalog page — thin layer over style.skin (the shared boutique look)
2
+ and /base.wd. Only the catalog-specific header chip lives here. */
3
+
4
+ /* The live basket count, sitting in the storefront header. */
5
+ .app-folio .cart-peek
6
+ display inline-flex
7
+ align-items center
8
+ gap .45rem
9
+ font-family system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
10
+ font-size .82rem
11
+ font-weight 600
12
+ text-transform uppercase
13
+ letter-spacing .08em
14
+ color var(--brand-deep)
15
+ background var(--brand-soft)
16
+ border 1px solid var(--brand)
17
+ padding .5rem .9rem
18
+ radius 999px
19
+ white-space nowrap
20
+
21
+ .app-folio .cart-peek::before
22
+ content "✦"
23
+ font-size .9rem
24
+ color var(--brand)
@@ -0,0 +1,167 @@
1
+ ---
2
+ title: Folio — a boutique storefront
3
+ description: A multi-page store written in pure Markdown. The cart persists across pages, reloads, and browser tabs; navigation is instant. No framework JavaScript written by hand.
4
+ image: https://darkmown.com/__wd/media/og-folio.png
5
+ transitions: true
6
+ ---
7
+
8
+ @include /nav.wd
9
+ @include /base.wd
10
+ @include ./-style.wd
11
+
12
+ <main class="wide app-folio">
13
+
14
+ ::: section #store
15
+
16
+ :store cart = []
17
+ :computed count = cart.length
18
+ :state q = ""
19
+
20
+ ::: shop-head
21
+ ::: shop-mark
22
+ ::: shop-eyebrow
23
+ Objects for everyday rituals
24
+ :::
25
+
26
+ # Fol*i*o
27
+
28
+ ::: shop-tagline
29
+ A small, considered shop — eight things, chosen well. Your basket follows you from page to page, through a reload, even into a second tab.
30
+ :::
31
+ :::
32
+
33
+ ::: cart-peek
34
+ { count } in your basket
35
+ :::
36
+ :::
37
+
38
+ ::: shop-layout
39
+
40
+ ::: shop-main
41
+
42
+ ::: shop-search
43
+ :bind q placeholder="Search the shop…"
44
+
45
+ ::: shop-hint
46
+ Type to filter the shelf — it narrows as you go, no page reload.
47
+ :::
48
+ :::
49
+
50
+ ::: catalog
51
+ @loop /products.json into p where p.name contains q
52
+ ::: card .product
53
+ ::: chip
54
+ { p.emoji }
55
+ :::
56
+ ::: body
57
+ ::: pname
58
+ { p.name }
59
+ :::
60
+
61
+ ::: tag
62
+ { p.category }
63
+ :::
64
+
65
+ ::: blurb
66
+ { p.blurb }
67
+ :::
68
+
69
+ ::: foot
70
+ ::: price
71
+ { p.price | money }
72
+ :::
73
+ :button "Add" -> cart += p
74
+ :::
75
+ :::
76
+ :::
77
+ @empty
78
+ ::: card .catalog-empty
79
+ **Nothing on the shelf matches "{ q }".**
80
+
81
+ Try a shorter word, or clear the search to see all eight pieces.
82
+ :::
83
+ @endloop
84
+ :::
85
+
86
+ :::
87
+
88
+ ::: cart-rail
89
+ ::: rail-eyebrow
90
+ Your basket
91
+ { count } items
92
+ :::
93
+
94
+ ::: rail-count
95
+ { count }
96
+ :::
97
+
98
+ ::: rail-sub
99
+ Saved to this browser. Add a few pieces, then head to checkout when you're ready.
100
+ :::
101
+
102
+ [View basket →](/folio/cart/){.rail-link}
103
+
104
+ ::: rail-note
105
+ Persisted with a single `:store cart = []`. The very same line on the cart page shares this basket — no backend, no wiring.
106
+ :::
107
+ :::
108
+
109
+ :::
110
+
111
+ ::: persist-note
112
+ ::: dot
113
+ ✷
114
+ :::
115
+ **Your basket persists across pages, reloads, and tabs.** Open this page in two tabs, add something in one, and watch the count rise in the other — that's a `:store`, synced over the browser's storage event.
116
+ :::
117
+
118
+ ## Built from Markdown
119
+
120
+ Every product card, the live search, and the running count are written as plain Markdown with a handful of Darkmown directives. The catalog unrolls from a JSON file; the basket is one shared `:store`. No components, no JSX, no hand-written event handlers.
121
+
122
+ <details class="source-reveal">
123
+ <summary>View source — it's Markdown</summary>
124
+
125
+ ```wd
126
+ :store cart = []
127
+ :computed count = cart.length
128
+ :state q = ""
129
+
130
+ :bind q placeholder="Search the shop…"
131
+
132
+ ::: catalog
133
+ @loop /products.json into p where p.name contains q
134
+ ::: card .product
135
+ ::: chip
136
+ { p.emoji }
137
+ :::
138
+ ::: body
139
+ ::: pname
140
+ { p.name }
141
+ :::
142
+ ::: foot
143
+ ::: price
144
+ { p.price | money }
145
+ :::
146
+ :button "Add" -> cart += p
147
+ :::
148
+ :::
149
+ :::
150
+ @empty
151
+ Nothing matches "{ q }".
152
+ @endloop
153
+ :::
154
+ ```
155
+
156
+ </details>
157
+
158
+ ::: folio-foot
159
+ A storefront in two `.wd` files.
160
+ [Open the basket →](/folio/cart/)
161
+ :::
162
+
163
+ :::
164
+
165
+ </main>
166
+
167
+ @include /footer.wd