Skip to content

feat: button-link navigation — href on buttons, nav links, multi-page routing#2

Merged
teezeit merged 6 commits intomainfrom
feat/button-href
Apr 17, 2026
Merged

feat: button-link navigation — href on buttons, nav links, multi-page routing#2
teezeit merged 6 commits intomainfrom
feat/button-href

Conversation

@teezeit
Copy link
Copy Markdown
Owner

@teezeit teezeit commented Apr 17, 2026

Tracking PR to upstream: akonan#79

Summary

wiremd now supports interactive multi-page navigation in the dev server.

17.04.2026_18.46.53_REC_trimmed.mp4

Write a shared navbar with page links, run wiremd home.md --serve 3001, and clicking a button navigates to and renders the target .md file — no build step between pages.

wiremd examples/gallery/multi-page/home.md --serve 3001
# Click [About] → renders about.md live
# Click [Contact] → renders contact.md live
[[ :logo: MyApp | *Home* | [About](./about.md) | [Contact](./contact.md)* ]]

See examples/gallery/multi-page/ for a working three-page prototype.


What enables this

Dev server routes any .md on demand

GET / redirects to the entry file. GET /page.md renders that file on demand via the existing renderFile callback — no pre-build required.

Nav [[ ]] items now support real hrefs (bug fix)

[text](url) inside [[ ]] previously dropped the URL silently. Root cause: the inline-containers plugin used c.value || '' which returns empty string for MDAST link nodes. Fixed with a serializeChild function that reconstructs [text](url) from the link node before pipe-splitting.

*text* active state in nav (bug fix)

*Home* inside [[ ]] previously rendered as the literal string *Home*. Fixed: detected as the active/current-page item, asterisks stripped, .active class added (all 6 themes).

[text](url)* primary CTA in nav

Nav items with * suffix render with primary button styling, consistent with [Button]* elsewhere.

Multiple [[Btn](url)] on one line (bug fix)

[[Get Started](url)]* [[See Features](url)] previously broke after the first button — the second URL was dropped and brackets showed as literal text. Root cause: the 3-child button-link detection only handled a single button. For two buttons on one line, remark produces 5 children ([, link, ]* [, link, ]). Replaced the 3-child check with tryParseButtonLinkSequence which handles n ≥ 1.

Button href on standalone buttons

[[Go to Docs](./docs.md)]     → <a href="..." class="wmd-button">
[[Get Started](url)]*         → primary button-link
[Button]{href:./page.md}      → attribute form

Disambiguation

[Text](url)       → plain link
[Text]            → non-navigating button
[[Text](url)]     → button that navigates

Inside [[ ]] nav:

Text              → nav item (href="#")
*Text*            → active/current page
[Text](url)       → nav item with real href
[Text](url)*      → primary CTA

Test plan

  • Nav [text](url) → href preserved
  • *Home* in nav → no literal asterisks, active styling
  • [[Btn1](url)]* [[Btn2](url)] on one line → two buttons, no literal brackets
  • Dev server: GET / redirects to entry file
  • Dev server: GET /page.md renders on demand
  • 501 tests passing
  • examples/gallery/multi-page/ — navigable three-page prototype

🤖 Generated with Claude Code

teezeit and others added 6 commits April 17, 2026 14:34
[Button]{href:./page.md} now renders as a styled <a> anchor instead
of a non-navigating <button>. Checks both node.href and node.props.href
so the attribute form {href:url} works naturally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
[[Text](url)] renders as a button-styled <a> anchor. CommonMark parses
this as text:"[" + link + text:"]" — the transformer now detects that
3-child pattern and hoists the link url to button.href.

Supports variants: [[Label](url)]* for primary, [[Label](url)]{.cls}
for attributes. Also fixes {href:url} attribute form which was stored
in props.href but renderer only checked node.href.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
a.wmd-button gets text-decoration:none and color:inherit so button-links
look identical to regular buttons — no underline, no browser link color.
Applied once in getStyleCSS() so all 7 themes inherit it automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The dev server now renders any .md file on demand when its URL is
requested, enabling button-links like [[Docs](./docs.md)] to navigate
between wireframe files in the browser.

- startServer() accepts renderFile callback and rootDir
- GET /page.md → calls renderFile(path) and serves result
- GET /page.html → serves cached HTML or renders from .md
- GET / → serves main watched file (unchanged)
- GET unknown → 404
- startServer() now returns the server instance (testability)
- CLI passes renderFile and rootDir to startServer
- Add href? to button node type

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GET / now redirects to /{inputFile} (e.g. /agency-site.md) so there
is no special root — every file is addressed by its own path. Links
back to the entry file work the same as links to any other file.

Fallback: when no inputFile is set (programmatic use), / still serves
the pre-rendered outputPath as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Nav `[[ ]]` items now fully support links and active states:

- `[text](url)` inside `[[ ]]` creates a navigable nav item with real href.
  Previously the link URL was silently dropped (remark parses links as
  `link` nodes with no `.value`; the inline-containers plugin was using
  `c.value || ''` which discarded them).
  Fix: added `serializeChild` to reconstruct `[text](url)` from MDAST
  link nodes before splitting items on `|`.

- `*text*` inside `[[ ]]` is now treated as the active/current-page item
  (strips asterisks, adds `.active` class with theme-matched styling).
  Previously rendered as literal `*text*`.

- `[text](url)*` in nav renders as a primary-styled button link.

- Multiple `[[Btn](url)]` patterns on the same line now render correctly.
  Previously the second button's URL was dropped and brackets showed as
  literal text. Root cause: `transformParagraph`'s 3-child detection
  only handled a single button-link. For two buttons on one line remark
  produces 5 children (`[`, link, `]* [`, link, `]`).
  Fix: new `tryParseButtonLinkSequence` generalises detection to n ≥ 1
  (replaces the old 3-child check); multiple matches return a
  `button-group` container.

Also adds:
- Active nav-item CSS for all 6 themes (`.wmd-nav-item.wmd-active`)
- `docs/guide/syntax.md` — Button Links section
- `QUICK-REFERENCE.md` — nav link and active-state rows
- `examples/gallery/multi-page/` — three-page navigable prototype
  (home/about/contact sharing a nav with live button-link navigation)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant