1
1
Fork
You've already forked wiki-plugin-topicmap
0
No description
  • JavaScript 63.7%
  • Nix 21.5%
  • CSS 8.9%
  • HTML 5.9%
2026年01月03日 15:20:15 +01:00
client fix(topicmap): defer reload until viewport exists to avoid transient boot failures 2026年01月03日 15:20:15 +01:00
.envrc chore(devshell,docs): add initial SPEC/PLAN/RESEARCH/WORKLOG and refine .envrc flake usage 2025年10月26日 12:51:15 +01:00
.gitignore feat: add input controller and repomix config 2026年01月02日 16:44:14 +01:00
.stylelintignore build(stylelint): integrate Stylelint via Nix; add config & auto-fix CSS 2025年10月11日 15:37:36 +02:00
factory.json feat(topicmap): add inline Elm mode, theme tokens, and origin-pinned messaging 2025年10月09日 15:18:23 +02:00
flake.lock feat(devshell): add Nix flake (pack_install/wiki_run/watch) and document local workflow 2025年10月04日 09:21:39 +02:00
flake.nix build(nix): add .envrc for direnv flake shell; fix WIKI_CONFIG path 2025年10月24日 18:22:58 +02:00
IMPLEMENTATION_PLAN.md docs: align topicmap docs with dm6-elm AppEmbed contract 2026年01月02日 17:37:43 +01:00
package-lock.json build(stylelint): integrate Stylelint via Nix; add config & auto-fix CSS 2025年10月11日 15:37:36 +02:00
package.json feat: add input controller and repomix config 2026年01月02日 16:44:14 +01:00
README.md fix(topicmap): resolve viewport via live button and observe async DOM rebuilds 2026年01月03日 14:51:56 +01:00
repomix.config.json docs: align topicmap docs with dm6-elm AppEmbed contract 2026年01月02日 17:37:43 +01:00
RESEARCH.md fix(topicmap): load input controller via relative URL and harden inline boot lifecycle 2026年01月02日 19:41:19 +01:00
SPEC.md fix(topicmap): load input controller via relative URL and harden inline boot lifecycle 2026年01月02日 19:41:19 +01:00
stylelint.config.mjs build(stylelint): integrate Stylelint via Nix; add config & auto-fix CSS 2025年10月11日 15:37:36 +02:00
WORKLOG.md docs: align topicmap docs with dm6-elm AppEmbed contract 2026年01月02日 17:37:43 +01:00

Federated Wiki - Topicmap Plugin (dm6-elm AppEmbed)

This plugin renders a Federated Wiki topicmap inline and reuses dm6-elm's AppEmbed. It loads an Elm bundle into the page and mounts window.Elm.AppEmbed inside the plugin viewport. dm6-elm's public/cold-boot.html remains the reference harness in dm6-elm, and is not used directly by this plugin.

Quick Start (integration-first)

  1. Build and install the plugin into a local wiki:
cd ~/workspace/wiki-plugin-topicmap
npm pack -s
cd ~/workspace/wiki/node_modules/wiki
npm i $(npm pack ../../../wiki-plugin-topicmap | tail -1)
  1. Add a topicmap item to a page, and configure the Elm bundle in the item text:
ELM_BUNDLE /assets/dm6-elm/app.js
# Optional:
# ELM_BUNDLE_DEBUG /assets/dm6-elm/app.debug.js
# DEBUG true
# HEIGHT 480
# THEME auto
  1. Ensure the bundle exports window.Elm.AppEmbed.

Runtime Contract (authoritative)

The plugin always boots window.Elm.AppEmbed and passes flags shaped like:

{ slug: String, stored: String }

stored is a JSON string. If the page data is unavailable, the plugin sends "{}" by default.

Exact boot behavior from client/topicmap.js:

  • slug comes from the closest .page element, in order:
    1. data-slug
    2. id with a page_ prefix removed
    3. the last segment of location.pathname
    4. the literal fallback "empty"
  • stored is built from wiki.getData() when available; otherwise it uses "{}":
    • if wiki.getData() returns null/undefined or throws, the plugin sends "{}"
    • otherwise it sends JSON.stringify(pageData)

Elm Bundle Loading

The plugin loads an Elm bundle by inserting a script tag and then calling:

window.Elm.AppEmbed.init({ node: viewport, flags })

Item text options control the bundle path (these are parsed by client/topicmap.js):

  • ELM_BUNDLE (default: /assets/dm6-elm/app.js)
  • ELM_BUNDLE_DEBUG (optional; used when DEBUG true)
  • DEBUG (true/false) selects which bundle to load
  • INLINE is accepted for forward compatibility but ignored today (inline-only build)
  • AMBIENT (true/false) enables Ambient input mode (default: false)
  • AMBIENT_EXCLUDES (comma-separated selectors) to exclude in Ambient mode

Your bundle must export Elm.AppEmbed on window. If it does not, the plugin fails with: Elm module not found: Elm.AppEmbed.

Conceptual Alignment: Topics vs Boxes (dm6-elm)

In dm6-elm terms:

  • Topics store content.
  • Boxes store topics or other boxes.
  • boxId is the active container.
  • Only boxes can be fullscreen or act as drop targets.

The plugin aligns with these ideas by treating the current page as a container context and sending the page's data (stored) to AppEmbed for reconciliation.

Input Modes (Scoped and Ambient)

The client/topicmap-input-modes.js module defines explicit input modes for routing pointer, wheel, and key events to Elm:

  • Scoped (default): only events that originate inside the topicmap viewport are forwarded.
  • Ambient (opt-in): page-level listeners are enabled, but with guard rails.
    • Enable with AMBIENT true in the item text (default is false).
    • Add selector exclusions with AMBIENT_EXCLUDES .selector1,.selector2.

Ambient mode behavior:

  • Shows a badge in the viewport: "Ambient ON — press Esc to return to Scoped".
  • Pressing Esc exits Ambient and returns to Scoped.
  • A click on the badge also returns to Scoped.
  • Events are ignored when the target matches excluded selectors.

Exclusions include built-ins plus your own selectors:

  • Built-ins: input, textarea, select, [contenteditable=""], [contenteditable="true"], .page, .editor
  • Custom: pass excludes: [] when creating the controller

Input events are currently logged via console.debug until Elm-side ports are defined.

Troubleshooting

  • Missing module error:
    • Verify the bundle is loaded and that window.Elm.AppEmbed exists.
    • Run in the console: window.Elm && window.Elm.AppEmbed && typeof window.Elm.AppEmbed.init === 'function'
  • Flags decode failures:
    • Ensure flags.slug and flags.stored are strings and that Elm decoders accept them.
  • Stored JSON not parseable:
    • The plugin always sends a string. Confirm stored contains valid JSON and that your decoder treats it as a JSON string (default is "{}").
  • Bundle path not loading:
    • Confirm ELM_BUNDLE is correct and the file is accessible at that URL.

Note: Debug mode requires a stable DOM; the plugin may auto-fallback to the non-debug bundle during refresh/rebind if the viewport is not connected.

Smoke Test (real wiki page)

This is a minimal end-to-end check in a real wiki page with the current plugin.

  1. Install the plugin and load a wiki page that includes a topicmap item.
  2. Set item text to ensure debug mode and the bundle path:
ELM_BUNDLE /assets/dm6-elm/app.js
DEBUG true
  1. Open DevTools console and verify boot logs show flags:
    • Look for [topicmap] Elm inline booted and confirm slug/stored.
  2. Click inside the viewport and observe input logs:
    • Look for [topicmap] input entries (scoped by default).

TODO: add a minimal demo page under docs/ or public/ once one of those directories exists in this repo.

License

MIT