@zvndev/darkmown 0.9.0 → 0.11.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.
@@ -0,0 +1,80 @@
1
+ tokens
2
+ ink #171717
3
+ paper #faf8f3
4
+ panel #ffffff
5
+ line #dedbd3
6
+ accent #16645a
7
+ warm #a83f2a
8
+ radius 8px
9
+
10
+ page
11
+ margin 0
12
+ font ui-serif, Georgia, Cambria, serif
13
+ color $ink
14
+ bg $paper
15
+ line-height 1.7
16
+
17
+ main
18
+ max-width 820px
19
+ margin 0 auto
20
+ padding 3rem 2rem 5rem
21
+
22
+ h1
23
+ font-size 3rem
24
+ line-height 1
25
+
26
+ h2
27
+ margin-top 2.4rem
28
+ border-top 1px solid $line
29
+ padding-top 1.2rem
30
+
31
+ a
32
+ color $accent
33
+
34
+ button
35
+ border 1px solid $ink
36
+ bg $ink
37
+ color white
38
+ padding .72rem 1rem
39
+ margin .3rem .5rem .3rem 0
40
+ radius $radius
41
+ font inherit
42
+ cursor pointer
43
+
44
+ button:hover
45
+ bg $accent
46
+ border-color $accent
47
+
48
+ input
49
+ padding .7rem .9rem
50
+ border 1px solid $line
51
+ radius $radius
52
+ font inherit
53
+ bg $panel
54
+ width 100%
55
+ max-width 360px
56
+ margin 1rem 0
57
+
58
+ ul
59
+ border 1px solid $line
60
+ bg $panel
61
+ padding 1rem 1rem 1rem 2rem
62
+ radius $radius
63
+
64
+ .person-row
65
+ border 1px solid $line
66
+ bg $panel
67
+ padding .65rem 1.1rem
68
+ margin .5rem 0
69
+ radius $radius
70
+ display flex
71
+ gap .6rem
72
+ align-items baseline
73
+ flex-wrap wrap
74
+
75
+ #paged
76
+ border 1px dashed $line
77
+ bg $panel
78
+ padding .4rem 1.2rem 1.2rem
79
+ margin 1rem 0
80
+ radius $radius
@@ -0,0 +1,86 @@
1
+ ---
2
+ title: Loop ergonomics
3
+ ---
4
+
5
+ @include /nav.wd
6
+
7
+ <main>
8
+
9
+ # Loop ergonomics
10
+
11
+ One loop, fully equipped. `@loop` gains `sort by`, `offset`, `limit`, `reverse`,
12
+ an `@empty` branch, and per-row meta variables (`{ $number }`, `{ $first }`,
13
+ `{ $last }`, `{ $count }`) — all in plain Markdown, all reactive when the source
14
+ or a clause argument is `:state`.
15
+
16
+ :state people = [{"id": 1, "name": "Ada", "age": 36}, {"id": 2, "name": "Cyrus", "age": 71}, {"id": 3, "name": "Bao", "age": 29}, {"id": 4, "name": "Dax", "age": 52}, {"id": 5, "name": "Esme", "age": 44}]
17
+ :state sortOffset = 0
18
+ :state pageSize = 2
19
+ :state query = ""
20
+ :state recent = [{"id": 1, "label": "Item 1"}, {"id": 2, "label": "Item 2"}, {"id": 3, "label": "Item 3"}, {"id": 4, "label": "Item 4"}, {"id": 5, "label": "Item 5"}]
21
+
22
+ ## Sorted, numbered, with first / last markers
23
+
24
+ `sort by p.age desc` orders the eldest first. Each row reads its position from
25
+ the loop meta vars: `{ $number }` is the 1-based index, and `:if $first` /
26
+ `:if $last` light up only on the boundary rows.
27
+
28
+ @loop people into p sort by p.age desc offset sortOffset
29
+ ::: card .person-row
30
+ **{ $number }. { p.name }** — age { p.age }
31
+ :if $first
32
+ (first)
33
+ :endif
34
+ :if $last
35
+ (last)
36
+ :endif
37
+ :::
38
+ @endloop
39
+
40
+ The list above is sorted oldest-first. `offset` is wired to a `:state`, so a
41
+ button can slide the window without a reload:
42
+
43
+ :button "Sort: skip the eldest" -> sortOffset = 1
44
+ :button "Reset order" -> sortOffset = 0
45
+
46
+ ## Reactive paging with `limit`
47
+
48
+ `limit pageSize` reads a `:state` value, so paging is just a button that bumps
49
+ the number. The runtime re-slices the same loop in place — no extra request, no
50
+ reload.
51
+
52
+ ::: section #paged
53
+ @loop people into p limit pageSize
54
+ ::: card .person-row
55
+ { p.name } — age { p.age }
56
+ :::
57
+ @endloop
58
+
59
+ :button "Show more" -> pageSize += 2
60
+ :button "Collapse" -> pageSize = 2
61
+ :::
62
+
63
+ ## `where` + `@empty`
64
+
65
+ `where` filters live as you type, and `@empty` renders the moment the filtered
66
+ set hits zero rows — the one place a loop gets to say "nothing here":
67
+
68
+ :bind query placeholder="Search people…"
69
+
70
+ @loop people into p where p.name contains query
71
+ ::: card .person-row
72
+ { p.name }
73
+ :::
74
+ @empty
75
+ No matches.
76
+ @endloop
77
+
78
+ ## `reverse` flips the source order
79
+
80
+ No sort key needed — `reverse` walks the list back to front:
81
+
82
+ @loop recent into r reverse
83
+ - { r.label }
84
+ @endloop
85
+
86
+ </main>
@@ -0,0 +1,70 @@
1
+ tokens
2
+ ink #171717
3
+ paper #faf8f3
4
+ panel #ffffff
5
+ line #dedbd3
6
+ accent #16645a
7
+ warm #a83f2a
8
+ radius 8px
9
+
10
+ page
11
+ margin 0
12
+ font ui-serif, Georgia, Cambria, serif
13
+ color $ink
14
+ bg $paper
15
+ line-height 1.7
16
+
17
+ main
18
+ max-width 820px
19
+ margin 0 auto
20
+ padding 3rem 2rem 5rem
21
+
22
+ h1
23
+ font-size 3rem
24
+ line-height 1
25
+
26
+ h2
27
+ margin-top 2.4rem
28
+ border-top 1px solid $line
29
+ padding-top 1.2rem
30
+
31
+ a
32
+ color $accent
33
+
34
+ button
35
+ border 1px solid $ink
36
+ bg $ink
37
+ color white
38
+ padding .72rem 1rem
39
+ margin .3rem .5rem .3rem 0
40
+ radius $radius
41
+ font inherit
42
+ cursor pointer
43
+
44
+ button:hover
45
+ bg $accent
46
+ border-color $accent
47
+
48
+ input
49
+ padding .7rem .9rem
50
+ border 1px solid $line
51
+ radius $radius
52
+ font inherit
53
+ bg $panel
54
+ width 100%
55
+ max-width 360px
56
+ margin 1rem 0
57
+
58
+ #shop
59
+ border 1px solid $line
60
+ bg $panel
61
+ padding .4rem 1.4rem 1.4rem
62
+ margin 1.5rem 0
63
+ radius $radius
64
+
65
+ .line
66
+ border 1px solid $line
67
+ bg $paper
68
+ padding .55rem 1.1rem
69
+ margin .45rem 0
70
+ radius $radius
@@ -0,0 +1,53 @@
1
+ ---
2
+ title: Global store
3
+ ---
4
+
5
+ @include /nav.wd
6
+
7
+ <main>
8
+
9
+ # Global store
10
+
11
+ `:store` is durable, page-global state. It persists to `localStorage` under the
12
+ `wd:store:` prefix, rehydrates on load, and syncs across tabs through the
13
+ `storage` event — no backend, no wiring. Add `ephemeral` to opt a store out of
14
+ persistence entirely.
15
+
16
+ ::: section #shop
17
+ :store cart = []
18
+
19
+ ## A durable cart
20
+
21
+ This cart is a `:store`, so it survives a full reload and mirrors into every open
22
+ tab. Add a couple of items, refresh the page, and the count holds.
23
+
24
+ Cart: { cart.length }
25
+
26
+ :button "Add to cart" -> cart append {"id": "sticker", "name": "Sticker", "price": 4}
27
+ :button "Reset cart" -> cart reset
28
+
29
+ @loop cart into line
30
+ ::: card .line
31
+ { line.name } — ${ line.price }
32
+ :::
33
+ @empty
34
+ The cart is empty. Add something, then reload — it stays.
35
+ @endloop
36
+
37
+ `Reset cart` runs `-> cart reset`, which restores the **declared** seed (`[]`),
38
+ not the last persisted value — and writes that seed back to storage.
39
+ :::
40
+
41
+ ## An ephemeral draft
42
+
43
+ `:store draft = "" ephemeral` is in-memory only. It is bound two-way to the
44
+ input and echoed below, but nothing reaches `localStorage`, so a reload wipes it
45
+ clean.
46
+
47
+ :store draft = "" ephemeral
48
+
49
+ :bind draft placeholder="Type a draft note…"
50
+
51
+ Draft says: **{ draft }**
52
+
53
+ </main>
package/src/builder.js CHANGED
@@ -66,21 +66,26 @@ export function buildSite(cwd = process.cwd()) {
66
66
  }
67
67
 
68
68
  /**
69
- * Strip JSDoc `/** ... *\/` blocks from the runtime before it ships.
70
- * The source keeps full type annotations (for `checkJs` + `.d.ts`), but the
71
- * browser never needs to download them — this keeps the shipped runtime lean
72
- * and the gzip budget honest (measured against what users actually receive).
73
- * Only `/** ... *\/` blocks are removed; code and string literals are untouched.
69
+ * Strip developer comments from the runtime before it ships. The source keeps
70
+ * full JSDoc type annotations (for `checkJs` + `.d.ts`) and explanatory comments
71
+ * so it stays readable; the browser downloads neither. This keeps the shipped
72
+ * runtime lean and the gzip budget honest (measured against what users receive),
73
+ * WITHOUT minifying — identifiers, structure, and whitespace are all preserved.
74
+ *
75
+ * Two passes, each conservative: `/** ... *\/` JSDoc blocks, then whole-line
76
+ * `//` comments (a line that is nothing but a comment). Trailing `//` after code
77
+ * and `//` inside strings/URLs are deliberately left untouched, so no string
78
+ * literal is ever harmed.
74
79
  * @param {string} source
75
80
  * @returns {string}
76
81
  */
77
82
  export function stripRuntimeComments(source) {
78
83
  return source
79
- // Remove the JSDoc block text only — never the surrounding newlines, so an
80
- // inline `/** @type {x} */ code` keeps its line and never glues onto a
81
- // preceding `//` comment.
84
+ // JSDoc blocks — type annotations the browser never needs.
82
85
  .replace(/\/\*\*[\s\S]*?\*\//g, "")
83
- // Drop the now blank/whitespace-only lines the removed blocks leave behind.
86
+ // Whole-line `//` comments — developer notes that don't belong in the download.
87
+ .replace(/^[ \t]*\/\/.*$/gm, "")
88
+ // Drop the now blank/whitespace-only lines the removals leave behind.
84
89
  .replace(/^[ \t]*\n/gm, "");
85
90
  }
86
91
 
package/src/cli.js CHANGED
@@ -20,8 +20,9 @@ if (command === "help" || command === "--help" || command === "-h") {
20
20
  } else if (command === "init") {
21
21
  const target = process.argv[3] || ".";
22
22
  const result = initProject(path.resolve(process.cwd(), target));
23
- console.log(`Created Darkmown project at ${path.relative(process.cwd(), result.root) || "."}`);
24
- console.log(`Next: cd ${path.relative(process.cwd(), result.root) || "."} && npm install && npm run dev`);
23
+ const relativeRoot = path.relative(process.cwd(), result.root) || ".";
24
+ console.log(`Created Darkmown project at ${relativeRoot}`);
25
+ console.log(`Next: ${nextStep(relativeRoot)}`);
25
26
  } else if (command === "build") {
26
27
  const result = buildSite();
27
28
  console.log(`Built ${result.routes.length} routes into ${path.relative(process.cwd(), result.distRoot)}`);
@@ -157,6 +158,7 @@ Usage:
157
158
  darkmown dev Start the live compiler dev server
158
159
  darkmown build Compile site/pages into dist
159
160
  darkmown serve Preview the built dist locally
161
+ darkmown version Print the installed Darkmown version
160
162
  darkmown help Show this help
161
163
 
162
164
  Authoring:
@@ -167,3 +169,13 @@ Authoring:
167
169
  *.js Colocated page behavior
168
170
  `);
169
171
  }
172
+
173
+
174
+ /**
175
+ * @param {string} relativeRoot
176
+ * @returns {string}
177
+ */
178
+ function nextStep(relativeRoot) {
179
+ if (relativeRoot === ".") return "npm install && npm run dev";
180
+ return `cd ${relativeRoot} && npm install && npm run dev`;
181
+ }