@zvndev/darkmown 1.1.0 → 1.2.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 (54) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +54 -3
  3. package/docs/cli.md +46 -16
  4. package/docs/spec-alignment.md +9 -3
  5. package/package.json +1 -1
  6. package/site/_/roadmap.json +3 -1
  7. package/site/pages/app.wd +1 -1
  8. package/site/pages/data.wd +2 -2
  9. package/site/pages/docs/index.wd +21 -0
  10. package/site/pages/folio/cart.wd +2 -2
  11. package/site/pages/forge/index.wd +1 -1
  12. package/site/pages/interactions/index.skin +113 -0
  13. package/site/pages/interactions/index.wd +86 -0
  14. package/src/api-runner.js +219 -0
  15. package/src/behaviors/carousel.js +153 -0
  16. package/src/behaviors/sortable.js +175 -0
  17. package/src/builder.js +199 -4
  18. package/src/cli.js +79 -54
  19. package/src/compiler/body.js +14 -0
  20. package/src/compiler/context.js +12 -1
  21. package/src/compiler/directives.js +123 -0
  22. package/src/compiler/loops.js +57 -8
  23. package/src/compiler/page.js +9 -3
  24. package/src/deploy.js +174 -0
  25. package/src/headers.js +4 -0
  26. package/src/runtime.js +3 -1
  27. package/src/scaffold.js +79 -147
  28. package/src/templates/blog/README.md +25 -0
  29. package/src/templates/blog/site/_/nav.wd +6 -0
  30. package/src/templates/blog/site/_/posts.json +16 -0
  31. package/src/templates/blog/site/pages/index.skin +51 -0
  32. package/src/templates/blog/site/pages/index.wd +24 -0
  33. package/src/templates/blog/site/pages/posts/hello-darkmown.md +16 -0
  34. package/src/templates/blog/site/pages/posts/markdown-native.md +20 -0
  35. package/src/templates/dashboard/README.md +25 -0
  36. package/src/templates/dashboard/api/metrics.js +15 -0
  37. package/src/templates/dashboard/site/_/nav.wd +6 -0
  38. package/src/templates/dashboard/site/pages/index.skin +74 -0
  39. package/src/templates/dashboard/site/pages/index.wd +75 -0
  40. package/src/templates/landing/README.md +25 -0
  41. package/src/templates/landing/site/_/nav.wd +6 -0
  42. package/src/templates/landing/site/pages/index.skin +140 -0
  43. package/src/templates/landing/site/pages/index.wd +54 -0
  44. package/src/templates/starter/README.md +32 -0
  45. package/src/templates/starter/site/_/nav.wd +7 -0
  46. package/src/templates/starter/site/pages/about.md +10 -0
  47. package/src/templates/starter/site/pages/index.skin +47 -0
  48. package/src/templates/starter/site/pages/index.wd +27 -0
  49. package/src/templates/store/README.md +28 -0
  50. package/src/templates/store/api/checkout.js +18 -0
  51. package/src/templates/store/site/_/nav.wd +6 -0
  52. package/src/templates/store/site/_/products.json +8 -0
  53. package/src/templates/store/site/pages/index.skin +100 -0
  54. package/src/templates/store/site/pages/index.wd +83 -0
@@ -0,0 +1,18 @@
1
+ // Demo checkout endpoint. A plain Web-standard `(request) => Response` handler:
2
+ // it runs in `darkmown dev` and on Vercel Edge / Cloudflare Pages with no extra
3
+ // config. Echoes the order back with an id — swap in your real payment and
4
+ // fulfilment logic here (validate input, charge, write to a DB, send email).
5
+ export const config = { runtime: "edge" };
6
+
7
+ export default async function (request) {
8
+ if (request.method !== "POST") {
9
+ return Response.json({ ok: false, error: "POST only" }, { status: 405 });
10
+ }
11
+ const order = Object.fromEntries(await request.formData());
12
+ return Response.json({
13
+ ok: true,
14
+ received: order,
15
+ orderId: `ORD-${Date.now().toString(36).toUpperCase()}`,
16
+ at: new Date().toISOString()
17
+ });
18
+ }
@@ -0,0 +1,6 @@
1
+ <nav>
2
+ <strong>Shop</strong>
3
+ <span class="links">
4
+ <a href="/">Catalog</a>
5
+ </span>
6
+ </nav>
@@ -0,0 +1,8 @@
1
+ [
2
+ { "name": "Ceramic Mug", "emoji": "☕️", "price": 18 },
3
+ { "name": "Linen Tote", "emoji": "👜", "price": 32 },
4
+ { "name": "Pocket Notebook", "emoji": "📓", "price": 12 },
5
+ { "name": "Desk Lamp", "emoji": "💡", "price": 64 },
6
+ { "name": "Plant Pot", "emoji": "🪴", "price": 24 },
7
+ { "name": "Wall Clock", "emoji": "🕰️", "price": 48 }
8
+ ]
@@ -0,0 +1,100 @@
1
+ tokens
2
+ ink #1a1f2b
3
+ paper #fbfbf9
4
+ line #e6e4dd
5
+ accent #146b54
6
+
7
+ page
8
+ margin 0
9
+ font ui-sans-serif, system-ui, sans-serif
10
+ color $ink
11
+ bg $paper
12
+ line-height 1.55
13
+
14
+ main
15
+ max-width 860px
16
+ margin 0 auto
17
+ padding 2rem 1.5rem
18
+
19
+ nav
20
+ display flex
21
+ align-items center
22
+ justify-content space-between
23
+ max-width 860px
24
+ margin 0 auto
25
+ padding 1.25rem 1.5rem
26
+
27
+ nav strong
28
+ font-size 1.1rem
29
+
30
+ nav a
31
+ color $accent
32
+ text-decoration none
33
+
34
+ input
35
+ font inherit
36
+ padding .6rem .75rem
37
+ border 1px solid $line
38
+ radius 8px
39
+ width 100%
40
+ max-width 320px
41
+
42
+ .catalog
43
+ display grid
44
+ grid-template-columns repeat(auto-fill, minmax(160px, 1fr))
45
+ gap 1rem
46
+ margin 1.5rem 0
47
+
48
+ .product
49
+ border 1px solid $line
50
+ radius 12px
51
+ padding 1rem
52
+ text-align center
53
+ background white
54
+
55
+ .emoji
56
+ font-size 2.25rem
57
+
58
+ .pname
59
+ font-weight 600
60
+ margin .35rem 0 .15rem
61
+
62
+ .price
63
+ color $accent
64
+ font-weight 600
65
+ margin-bottom .6rem
66
+
67
+ button
68
+ font inherit
69
+ bg $accent
70
+ color white
71
+ border 0
72
+ padding .55rem .9rem
73
+ radius 8px
74
+ cursor pointer
75
+
76
+ .line
77
+ display flex
78
+ align-items center
79
+ justify-content space-between
80
+ gap 1rem
81
+ border 1px solid $line
82
+ radius 10px
83
+ padding .6rem .9rem
84
+ margin .4rem 0
85
+ background white
86
+
87
+ .line button
88
+ bg transparent
89
+ color $ink
90
+ border 1px solid $line
91
+
92
+ .cart-foot
93
+ font-size 1.1rem
94
+ margin .75rem 0
95
+
96
+ .receipt
97
+ border 1px solid $accent
98
+ radius 10px
99
+ padding 1rem
100
+ background #ecf6f1
@@ -0,0 +1,83 @@
1
+ ---
2
+ title: Shop — built with Darkmown
3
+ description: A storefront in Markdown — live search, a shared cart, and a checkout that posts to a serverless function.
4
+ transitions: true
5
+ ---
6
+
7
+ @include /nav.wd
8
+
9
+ <main>
10
+
11
+ ::: section #shop
12
+
13
+ :store cart = []
14
+ :state q = ""
15
+ :computed itemCount = count(cart)
16
+ :computed subtotal = sum(cart, price)
17
+
18
+ # Shop
19
+
20
+ ::: shop-search
21
+ :bind q placeholder="Search products…"
22
+ :::
23
+
24
+ ::: catalog
25
+ @loop /products.json into p where p.name contains q
26
+ ::: card .product
27
+ ::: emoji
28
+ { p.emoji }
29
+ :::
30
+ ::: pname
31
+ { p.name }
32
+ :::
33
+ ::: price
34
+ { p.price | money }
35
+ :::
36
+ :button "Add to cart" -> cart += p
37
+ :::
38
+ @empty
39
+ ::: card .empty
40
+ Nothing matches "**{ q }**".
41
+ :::
42
+ @endloop
43
+ :::
44
+
45
+ ## Your cart ({ itemCount })
46
+
47
+ @loop cart into item
48
+ ::: card .line
49
+ { item.emoji } **{ item.name }** — { item.price | money }
50
+ :button "Remove" -> cart remove item
51
+ :::
52
+ @empty
53
+ Your cart is empty — add something above.
54
+ @endloop
55
+
56
+ :if itemCount
57
+ ::: cart-foot
58
+ **Subtotal: { subtotal | money }**
59
+ :::
60
+
61
+ ### Checkout
62
+
63
+ This form posts to `api/checkout.js` — a plain serverless function that runs in
64
+ `darkmown dev` and on Vercel/Cloudflare alike. With JavaScript off it degrades to
65
+ a native POST.
66
+
67
+ :form action="/api/checkout" into receipt
68
+ :input name placeholder="Full name" required
69
+ :input email type=email placeholder="you@example.com" required
70
+ :submit "Place order"
71
+ :endform
72
+
73
+ :if receipt
74
+ ::: card .receipt
75
+ **Order placed ✓** — thanks { receipt.received.name }. A confirmation is on its way
76
+ to { receipt.received.email }. Order { receipt.orderId }.
77
+ :::
78
+ :endif
79
+ :endif
80
+
81
+ :::
82
+
83
+ </main>