Skip to content

feat(index): index .mdx files as markdown-twin content nodes#716

Merged
germanamz merged 1 commit into
mainfrom
feat/mdx-support
Jul 14, 2026
Merged

feat(index): index .mdx files as markdown-twin content nodes#716
germanamz merged 1 commit into
mainfrom
feat/mdx-support

Conversation

@germanamz

Copy link
Copy Markdown
Owner

What

Adds .mdx file support to Tusk. An .mdx file is a full markdown twin: indexed, queryable, renderable, sub-unit-split, editable via the node/edge write tools, and a valid edge source/target — parsed as markdown (frontmatter + prose + wikilinks), exactly like .md.

Why

MDX is markdown-with-JSX; vaults that mix .md and .mdx notes were silently dropping every .mdx file (the reindex walk only picked up .md/.html/.htm).

How

  • .mdx is indexable — added to index.indexableExts.
  • Id retains its extension (foo.mdx) so foo.md and foo.mdx never collide on the nodes.id primary key (Decision feat: add circular parent detection (Phase 1) #12). .md stays the only bare-stem kind.
  • One id rule + its inverse. The three previously-divergent id-derivation sites (reindex.nodeIDForPath, node.nodeIDForPath, parse.go) now delegate to a single index.NodeIDForPath (strip only .md, retain every other indexable kind). Its inverse index.FilePathForID replaces every hardcoded sourceID + ".md" reconstruction (edgewrite.go ×5, doctor.go). FilePathForID treats a .md-suffixed id as a bare stem (a *.md.md file) since .md is the only stripped kind, so it's a true inverse.
  • Content routing needs no new branch.mdx falls through the markdown default in ParseContentFile / NodeText / the sub-unit split. JSX tags and import lines parse as markdown (raw HTML / paragraph text). No MDX compiler — documented limitation.

Verification

Automated: full suite (go test ./...) + -race on index/node/reindex green; gofmt/vet/golangci-lint clean. New tests: NodeIDForPath/FilePathForID round-trip incl. the .md.md case; md+mdx coexistence through the real reindex.Run pipeline; Create-accepts-.mdx; rename referrer-retarget to a moved .mdx node (the #687 analogue).

Live e2e (built binary, scratch vault):

  • .mdx indexed as a first-class note; foo.md + foo.mdx coexist as distinct nodes
  • body [[wikilink]] materialized as an edge; full sub-unit split
  • node get / query / node modify / edge add / node move all work on the .mdx id; frontmatter rewrites preserve the MDX body (imports + <Callout> JSX)
  • referrer edge retargeted on move; doctor clean; double-reindex converges to 0 indexed / 0 skipped
  • regression fix confirmed live: edge add on a changelog.md.md node writes to the correct file

Review

An adversarial multi-agent review of the diff surfaced one real (minor) regression — FilePathForID mis-reconstructing a *.md.md file — which is fixed here, plus the durability tests above.

Out of scope

MDX/JSX compilation; .markdown extension; per-component semantic extraction.

Add .mdx to the indexable-extension set and treat it as a full markdown
twin: parsed as markdown (frontmatter + prose + wikilinks), sub-unit
split, editable via the node/edge write tools, and a valid edge
source/target.

A .mdx node's id RETAINS its extension (foo.mdx) so foo.md and foo.mdx
never collide on the nodes.id primary key. Unify the three previously
divergent id-derivation sites onto one rule in index.NodeIDForPath
(strip only ".md", retain every other indexable kind) and add its
inverse index.FilePathForID, replacing every hardcoded `sourceID + ".md"`
reconstruction (edgewrite x5, doctor). FilePathForID treats a ".md"-
suffixed id as a bare stem (a "*.md.md" file), since ".md" is the only
stripped kind — so it is a true inverse and does not regress that file.

Content routing needs no new branch: .mdx falls through the markdown
default in ParseContentFile / NodeText / the sub-unit split. JSX tags
and import lines are parsed as markdown (raw HTML / paragraph text); no
MDX compiler.

Tests: id round-trip incl. .md.md; md+mdx coexistence through the real
reindex.Run pipeline; Create-accepts-.mdx; rename referrer-retarget to a
moved .mdx node (the #687 analogue).
@germanamz
germanamz merged commit d112ce2 into main Jul 14, 2026
9 checks passed
@germanamz
germanamz deleted the feat/mdx-support branch July 14, 2026 17:38
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