@zvndev/darkmown 2.12.0 → 2.12.2

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 CHANGED
@@ -73,7 +73,7 @@ rss_limit: 20
73
73
  ```
74
74
 
75
75
  - `title`, `description`, `image` drive `<title>`, the meta description, and the Open Graph / Twitter card. `lang` sets `<html lang>` (default `en`).
76
- - `html: true` allows raw HTML in that file's body. `transitions: true` opts into an opacity-only cross-fade view transition plus link prerendering.
76
+ - `html: true` allows raw HTML in that file's body. `transitions: true` opts into a view transition (instant swap, no root animation) plus link prerendering.
77
77
  - `draft: true` keeps the page out of `dist`, `routes.json`, the sitemap, and the feed. `darkmown dev` still serves it; `darkmown build --drafts` includes it.
78
78
  - `noindex: true` builds the page but removes it from discovery: a robots `noindex,nofollow` meta, and exclusion from `sitemap.xml`, `rss.xml`, and the generated `llms.txt`/`llms-full.txt`. On a collection entry with a `_schema.wd`, declare it as `noindex: boolean?`.
79
79
  - `icon: /path` sets the favicon verbatim (a `type` is added for `.svg`/`.png`/`.ico`). With no `icon:` key, the first of `site/pages/icon.svg`, `icon.png`, `favicon.ico` wins; with neither, the built-in mark is the fallback.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to Darkmown are documented here. Versions follow [semver](https://semver.org); pre-1.0 minor versions may contain breaking changes.
4
4
 
5
+ ## 2.12.1 (2026-10-16)
6
+
7
+ A one-item patch revising the navigation animation again, this time from frame-level measurement instead of reading the stylesheet.
8
+
9
+ - **BEHAVIOR CHANGE: the default view transition is now no animation at all.** Three animated defaults were field-tested on the real demo and each failed somewhere: the directional slide read as a bounce, the 2.12.0 simultaneous cross-fade double-exposed on camera (the incoming snapshot stacks over the outgoing one), and the sequenced out-then-in shipped hours earlier was ignored by a shipping browser (Arc) in favor of its own cross-fade. View-transition animation compositing varies too much across engines to ship as a default, so both roots now get `animation: none`: the swap is an instant cut with no possible artifact, and the speculation-rules prerender (unchanged) is what makes navigation feel smooth. Authors who want a fade can add `::view-transition-old`/`::view-transition-new` rules in their own skin. The `@view-transition` opt-in is unchanged, and a `transitions: true` page still ships zero JS.
10
+
5
11
  ## 2.12.0 (2026-10-16)
6
12
 
7
13
  A perceived-performance release from client-demo feedback (fonts visibly swapped on every reload, and the navigation transition read as a flicker): fonts now preload, the preview server revalidates instead of re-downloading, the default view transition is a plain cross-fade, and Markdown images can carry an author-set `sizes`. No breaking change; the transition animation change is called out below.
package/README.md CHANGED
@@ -288,7 +288,7 @@ A few reserved keys drive **drafts and feeds** (see [SEO & feeds](#seo--feeds-si
288
288
 
289
289
  **Markdown sources: `md_source: true`** on the home page opts the whole site in to publishing every page's byte-exact source beside its HTML: `/docs/` also answers `/docs.md` (the exact `.md`/`.wd` file the author wrote, frontmatter and CRLF endings included) with a `text/markdown` content type, and each published page carries `<link rel="alternate" type="text/markdown" href="/docs.md" title="Markdown source">`, emitted exactly when the file is, so the link never 404s. A page opts back out with `md_source: false`; a page-level `true` without the home flag does nothing, drafts never emit a source, and sitemap/rss/robots never list the `.md` files (they are alternates, not routes). Off by default, and a site that never sets it builds byte-identical output.
290
290
 
291
- `transitions: true` opts a page into **instant, flash-free navigation**: zero JavaScript, all declarative. It emits an opacity-only **cross-fade view transition** for the page swap (old and new animate simultaneously at 160ms with one shared easing, since 2.12; the earlier directional slide read as a flicker mid-navigation), plus a **`<script type="speculationrules">` prerender** hint that renders the next same-origin page on hover/pointerdown so the click activates an already-painted page (no white render-gap flash). It honors `prefers-reduced-motion`. Only same-origin pages that both opt in transition; browsers without support, or with page-preloading disabled, navigate normally. Off by default; opt out with `transitions: false`. Mark a link `{.no-prefetch}` to exclude it from prerendering. (Chrome disables prerendering while DevTools is open, so test the built site with DevTools closed.)
291
+ `transitions: true` opts a page into **instant, flash-free navigation**: zero JavaScript, all declarative. It emits a **view transition** with no root animation, so the page swap is an instant cut with no possible compositing artifact (animated defaults were measured to double-expose or be replaced by the browser's own cross-fade; an instant swap is the only artifact-free choice), plus a **`<script type="speculationrules">` prerender** hint that renders the next same-origin page on hover/pointerdown so the click activates an already-painted page (no white render-gap flash, and this prerender is what makes navigation feel smooth). Authors who want a fade can add `::view-transition-old`/`::view-transition-new` rules in their own skin. It honors `prefers-reduced-motion` trivially, since nothing animates. Only same-origin pages that both opt in transition; browsers without support, or with page-preloading disabled, navigate normally. Off by default; opt out with `transitions: false`. Mark a link `{.no-prefetch}` to exclude it from prerendering. (Chrome disables prerendering while DevTools is open, so test the built site with DevTools closed.)
292
292
 
293
293
  ## Static assets
294
294
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  This audit compares the current Darkmown implementation with the original MARROW/WhateverDown vision and the follow-up decisions made on 2026-06-11.
4
4
 
5
+ ## 2.12.1 additions: the transition, measured frame by frame (2026-10-16)
6
+
7
+ - **The navigation animation is gone, because animated defaults kept failing in the field.** The directional slide read as a bounce; the 2.12.0 simultaneous cross-fade double-exposed on camera (incoming snapshot stacks over outgoing); the sequenced out-then-in was ignored by a shipping browser (Arc), which substituted its own cross-fade. VT animation compositing varies too much across engines for a default, so both roots get `animation: none` (an instant, artifact-free cut) and the prerender hint carries the perceived speed. Authors can still animate in their own skins.
8
+
5
9
  ## 2.12.0 additions: perceived performance from demo feedback (2026-10-16)
6
10
 
7
11
  - **First paint stops swapping fonts.** The font post-pass now injects per-page `<link rel="preload" as="font" crossorigin>` tags for exactly the project fonts a page's own stylesheets declare, leading with the subset woff2 when subsetting ran (the original otherwise, still a win), idempotently so dev rebuilds never duplicate a link. `darkmown serve` learned conditional requests: strong ETags and Last-Modified on every static response, RFC 7232-correct 304s, HTML at `no-cache`, fingerprinted-by-build assets at `public, max-age=3600`, dev deliberately unchanged. Together these close the demo's "fonts swap on every reload" complaint from both ends: first load preloads, reloads revalidate.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zvndev/darkmown",
3
- "version": "2.12.0",
3
+ "version": "2.12.2",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -475,7 +475,7 @@ Mark a page `draft: true` and it stays out of production: `darkmown build` leave
475
475
 
476
476
  ## Instant navigation
477
477
 
478
- Add `transitions: true` to a page's frontmatter for **instant, flash-free navigation**: zero JavaScript. It emits an opacity-only cross-fade view transition for the page swap (old and new animate simultaneously at 160ms with one shared easing; the earlier directional slide read as a flicker) and a `<script type="speculationrules">` prerender hint, so the browser renders the next same-origin page on hover/pointerdown and the click activates an already-painted page (no white render-gap). It honors `prefers-reduced-motion`, and only same-origin pages that both opt in transition. Off by default; opt out with `transitions: false`, or exclude a single link from prerendering with `{.no-prefetch}`. (Chrome turns prerendering off while DevTools is open, so test the built site with DevTools closed.)
478
+ Add `transitions: true` to a page's frontmatter for **instant, flash-free navigation**: zero JavaScript. It emits a view transition with no root animation, so the page swap is an instant cut with no possible compositing artifact (animated defaults were measured to double-expose or be replaced by the browser's own cross-fade), and a `<script type="speculationrules">` prerender hint, so the browser renders the next same-origin page on hover/pointerdown and the click activates an already-painted page (no white render-gap; the prerender is what makes navigation feel smooth). Authors who want a fade can add `::view-transition-old`/`::view-transition-new` rules in their own skin. and only same-origin pages that both opt in transition. Off by default; opt out with `transitions: false`, or exclude a single link from prerendering with `{.no-prefetch}`. (Chrome turns prerendering off while DevTools is open, so test the built site with DevTools closed.)
479
479
 
480
480
  ## Images
481
481
 
@@ -57,13 +57,7 @@ ${u}
57
57
  `),N=o.meta.transitions===!0||o.meta.transitions==="true",R=N?`
58
58
  <style>
59
59
  @view-transition { navigation: auto; }
60
- ::view-transition-old(root) { animation: wd-nav-out 160ms cubic-bezier(0.4, 0, 0.2, 1) both; }
61
- ::view-transition-new(root) { animation: wd-nav-in 160ms cubic-bezier(0.4, 0, 0.2, 1) both; }
62
- @keyframes wd-nav-out { to { opacity: 0; } }
63
- @keyframes wd-nav-in { from { opacity: 0; } }
64
- @media (prefers-reduced-motion: reduce) {
65
- ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 1ms; }
66
- }
60
+ ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
67
61
  </style>`:"",B=N?`
68
62
  <script type="speculationrules">{"prerender":[{"where":{"and":[{"href_matches":"/*"},{"not":{"selector_matches":".no-prefetch"}},{"not":{"selector_matches":"[rel~=nofollow]"}}]},"eagerness":"moderate"}]}<\/script>`:"",H=fn(e,t,r),J=H&&H.scoped?null:Mr(o.meta,e,t,r).map(C=>It(C,t.cwd,r)).find(C=>C.scoped),ne=H&&H.scoped?H.scopeId:J?.scopeId,re=ne?pn(o.html,ne):o.html,K=rb(re,t,r),{content:q,target:k}=nb(K);return{meta:o.meta,deps:o.deps,collectionsUsed:o.collectionsUsed,symbols:o.symbols,html:`<!doctype html>
69
63
  <html lang="${w(u)}">
@@ -183,25 +183,22 @@ export function compilePage(file, context, options = {}) {
183
183
  // (graceful, transition-free fallback) and only applies to same-origin
184
184
  // navigations where both the outgoing and incoming page opt in.
185
185
  //
186
- // The default is one simultaneous cross-fade: outgoing opacity 1→0 while
187
- // incoming 0→1, same duration and easing both ways. An earlier default paired
188
- // a fade-out with a fade-in of opposite translates and easings; measured on a
189
- // real site that read as a flicker (the outgoing page appeared to come back
190
- // mid-navigation). Opacity-only, no transform: the two snapshots overlap in
191
- // place, so nothing ever moves backwards. Under prefers-reduced-motion the
192
- // same fade runs at 1ms — a cut, keeping the block structure intact.
186
+ // The default is no animation at all: both snapshots drop and swap at
187
+ // commit. Three animated defaults were field-tested on a real site and each
188
+ // failed somewhere: the directional slide read as a bounce, the simultaneous
189
+ // cross-fade double-exposed (the incoming snapshot stacks over the outgoing
190
+ // one), and the sequenced out-then-in was ignored by a shipping browser in
191
+ // favor of its own cross-fade. View-transition animation compositing varies
192
+ // too much across engines to ship as a default. Zero animation is the only
193
+ // choice with no possible artifact, and the speculation-rules prerender
194
+ // below is what makes navigation feel instant anyway. Authors who want a
195
+ // fade can add ::view-transition-old/new rules in their own skin.
193
196
  const wantTransitions =
194
197
  compiled.meta.transitions === true || compiled.meta.transitions === "true";
195
198
  const transitions = wantTransitions
196
199
  ? `\n <style>
197
200
  @view-transition { navigation: auto; }
198
- ::view-transition-old(root) { animation: wd-nav-out 160ms cubic-bezier(0.4, 0, 0.2, 1) both; }
199
- ::view-transition-new(root) { animation: wd-nav-in 160ms cubic-bezier(0.4, 0, 0.2, 1) both; }
200
- @keyframes wd-nav-out { to { opacity: 0; } }
201
- @keyframes wd-nav-in { from { opacity: 0; } }
202
- @media (prefers-reduced-motion: reduce) {
203
- ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 1ms; }
204
- }
201
+ ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
205
202
  </style>`
206
203
  : "";
207
204