@liminis/editor 0.3.0 → 0.4.1
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/LICENSE +0 -13
- package/README.md +122 -75
- package/dist/app/editor/CorrectionPanelPlugin.js +10 -11
- package/dist/app/editor/DragHandlePlugin.js +1 -1
- package/dist/app/editor/SelectionContextMenuPlugin.js +4 -4
- package/dist/app/editor/nodes/C4Component.js +8 -10
- package/dist/app/editor/nodes/C4Node.d.ts +1 -1
- package/dist/app/editor/nodes/DiagramContextMenu.js +5 -5
- package/dist/headless.d.ts +3 -5
- package/dist/headless.js +2 -4
- package/dist/index.d.ts +1 -1
- package/dist/styles.css +425 -454
- package/docs/architecture.md +80 -0
- package/docs/decisions/adr-93-liminis-editor-defined-aliases.md +28 -1
- package/docs/decisions/adr-98-invert-token-direction.md +309 -0
- package/docs/diagrams/architecture-1-dark.svg +1 -0
- package/docs/diagrams/architecture-1.svg +1 -0
- package/docs/diagrams/architecture-2-dark.svg +1 -0
- package/docs/diagrams/architecture-2.svg +1 -0
- package/package.json +2 -2
- package/dist/app/editor/c4/C4InteractiveRenderer.d.ts +0 -35
- package/dist/app/editor/c4/C4InteractiveRenderer.js +0 -299
- package/dist/app/editor/c4/edge-clipping.d.ts +0 -24
- package/dist/app/editor/c4/edge-clipping.js +0 -139
- package/dist/app/editor/c4/hooks/useC4DiagramDrag.d.ts +0 -38
- package/dist/app/editor/c4/hooks/useC4DiagramDrag.js +0 -112
- package/dist/app/editor/c4/layout.d.ts +0 -25
- package/dist/app/editor/c4/layout.js +0 -839
- package/dist/app/editor/c4/parser.d.ts +0 -19
- package/dist/app/editor/c4/parser.js +0 -410
- package/dist/app/editor/c4/render-to-string.d.ts +0 -24
- package/dist/app/editor/c4/render-to-string.js +0 -34
- package/dist/app/editor/c4/renderer.d.ts +0 -64
- package/dist/app/editor/c4/renderer.js +0 -569
- package/dist/app/editor/c4/types.d.ts +0 -203
- package/dist/app/editor/c4/types.js +0 -43
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
Which entry point to import, what each one costs you, and where the boundary
|
|
4
|
+
between this package and its host actually falls.
|
|
5
|
+
|
|
6
|
+
## The package and the world around it
|
|
7
|
+
|
|
8
|
+
`@liminis/editor` is a component, not an application. It has no storage, no file
|
|
9
|
+
dialogs, no network, and no opinion about where a document came from. Everything
|
|
10
|
+
it needs from its environment arrives through the host seam as an injected
|
|
11
|
+
function with a working default, so `<Editor>` renders in a host that supplies
|
|
12
|
+
nothing at all — and a host that supplies everything gets an editor wired into
|
|
13
|
+
its own file system, its own clipboard, and its own annotation store.
|
|
14
|
+
|
|
15
|
+
```c4 static height=24rem
|
|
16
|
+
Person(author, "Author", "Writes and edits markdown documents")
|
|
17
|
+
|
|
18
|
+
System_Boundary(host, "Host application") {
|
|
19
|
+
Container(shell, "Host shell", "Electron or browser", "Owns documents, storage and windows. Supplies the seam.")
|
|
20
|
+
Container(editor, "@liminis/editor", "React + Lexical", "The editing surface, the markdown pipeline and annotations")
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
System_Ext(store, "Document store", "Files, a database, a sync service — the host's concern, never this package's")
|
|
24
|
+
|
|
25
|
+
Rel(author, shell, "Opens and edits documents")
|
|
26
|
+
Rel(shell, editor, "Mounts <Editor>, injects host services")
|
|
27
|
+
Rel(editor, shell, "Reports changes, requests services through the seam")
|
|
28
|
+
Rel(shell, store, "Reads and writes")
|
|
29
|
+
```
|
|
30
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="./diagrams/architecture-1-dark.svg" /><img src="./diagrams/architecture-1.svg" alt="Diagram 1 from architecture.md" /></picture>
|
|
31
|
+
|
|
32
|
+
The arrow that matters is the one from the editor back to the shell. It is not a
|
|
33
|
+
callback bolted on for one feature; it is how every capability the editor cannot
|
|
34
|
+
implement for itself is obtained. A host that ignores it still gets an editor,
|
|
35
|
+
because every one of those services has a default.
|
|
36
|
+
|
|
37
|
+
## Entry points
|
|
38
|
+
|
|
39
|
+
The package is split so that a consumer pays only for what it imports. The
|
|
40
|
+
divide that does the most work is `./headless`: it is DOM-free, which is what
|
|
41
|
+
lets the Electron **main** process import it at all.
|
|
42
|
+
|
|
43
|
+
```c4 static height=26rem
|
|
44
|
+
Container_Boundary(pkg, "@liminis/editor") {
|
|
45
|
+
Component(main, ".", "React", "<Editor>, the host seam, the annotation UI")
|
|
46
|
+
Component(md, "./markdown", "mdast", "parseMarkdown / stringifyMarkdown, no editor mounted")
|
|
47
|
+
Component(ann, "./annotations", "TypeScript", "Range anchoring that survives edits")
|
|
48
|
+
Component(headless, "./headless", "DOM-free", "Safe in an Electron main process")
|
|
49
|
+
Component(nodes, "./nodes", "Lexical", "The custom node set, for a host building its own editor")
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
System_Ext(lexical, "Lexical", "Peer dependency — the editing engine")
|
|
53
|
+
System_Ext(mdast, "mdast / micromark", "GFM, math, footnotes, definition lists, wiki-links")
|
|
54
|
+
System_Ext(diagrams, "@liminis/diagrams", "Renders the C4 diagrams on this page")
|
|
55
|
+
|
|
56
|
+
Rel(main, nodes, "Registers")
|
|
57
|
+
Rel(main, md, "Parses and serialises through")
|
|
58
|
+
Rel(main, ann, "Anchors annotations with")
|
|
59
|
+
Rel(nodes, lexical, "Extends")
|
|
60
|
+
Rel(md, mdast, "Built on")
|
|
61
|
+
Rel(headless, diagrams, "Re-exports renderC4DiagramToSVG")
|
|
62
|
+
Rel(headless, mdast, "Parses with")
|
|
63
|
+
```
|
|
64
|
+
<picture><source media="(prefers-color-scheme: dark)" srcset="./diagrams/architecture-2-dark.svg" /><img src="./diagrams/architecture-2.svg" alt="Diagram 2 from architecture.md" /></picture>
|
|
65
|
+
|
|
66
|
+
`./headless` re-exporting `renderC4DiagramToSVG` is the reason the two packages
|
|
67
|
+
appear together here: a C4 diagram in a document has to render in the main
|
|
68
|
+
process too, where there is no DOM, and `@liminis/diagrams/server` is DOM-free
|
|
69
|
+
for exactly that reason.
|
|
70
|
+
|
|
71
|
+
## What this means when you install it
|
|
72
|
+
|
|
73
|
+
- Importing `.` brings React and Lexical. That is the editor.
|
|
74
|
+
- Importing `./markdown` or `./annotations` brings neither. They are ordinary
|
|
75
|
+
TypeScript over mdast, usable in a script or a server.
|
|
76
|
+
- Importing `./headless` is a promise enforced by its own doc comment: nothing
|
|
77
|
+
reachable from it may touch `document`, `window`, or Lexical.
|
|
78
|
+
- Lexical is a **peer** dependency. The host owns the version, because a host
|
|
79
|
+
that mounts its own Lexical plugins beside this editor must not end up with
|
|
80
|
+
two copies of it.
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# ADR-93: `--liminis-editor-*` Names Are Defined as Aliases of Their Legacy Names
|
|
2
2
|
|
|
3
3
|
**Date:** 2026-08-20
|
|
4
|
-
**Status:** Accepted
|
|
4
|
+
**Status:** Accepted (amended by ADR-98 — see the note marked *Amended by ADR-98* below; the alias direction this ADR chose is reversed)
|
|
5
5
|
**Supersedes:** none
|
|
6
6
|
**Amends:** none
|
|
7
|
+
**Amended by:** ADR-98 (#98 inverts this ADR's alias direction — the legacy names stop carrying the real defaults, and become shims to `--liminis-editor-*` instead)
|
|
7
8
|
**Issue:** #93 (verveguy/liminis-editor)
|
|
8
9
|
|
|
9
10
|
## Context
|
|
@@ -61,6 +62,25 @@ anticipated by the plan:
|
|
|
61
62
|
|
|
62
63
|
## Decision
|
|
63
64
|
|
|
65
|
+
> **Amended 2026-08-22 by ADR-98 (#98) — this clause no longer holds.** The
|
|
66
|
+
> direction chosen here is reversed: `--liminis-editor-*` names now carry the
|
|
67
|
+
> real defaults, and the legacy names below become one-line shims
|
|
68
|
+
> (`<legacy>: var(--liminis-editor-x);`). This ADR's own reasoning for why
|
|
69
|
+
> the *opposite* direction was unsafe — "adding `--liminis-editor-foreground:
|
|
70
|
+
> <default>` unconditionally would resolve every consumption chain at the
|
|
71
|
+
> new name before ever reaching the old one" — no longer applies once every
|
|
72
|
+
> internal consumption site reads `--liminis-editor-*` only (ADR-98's FR-003),
|
|
73
|
+
> which removes the nested legacy fallback this ADR's Decision explicitly
|
|
74
|
+
> chose to leave in place. This also reverses this ADR's own non-breaking
|
|
75
|
+
> guarantee below for one direction: a host that only *reads* a legacy name
|
|
76
|
+
> still gets a real value (the shim resolves fine), but a host that only
|
|
77
|
+
> *sets* a legacy name no longer themes the editor, since nothing internal
|
|
78
|
+
> reads that name to pick the override up — verified empirically, not
|
|
79
|
+
> assumed, and accepted as an intentional breaking change. See ADR-98's
|
|
80
|
+
> "Verified, not assumed" section for the full rationale. The rest of this
|
|
81
|
+
> section is kept as the historical record of what was decided and why in
|
|
82
|
+
> 2026-08-20, not edited to match the new direction.
|
|
83
|
+
|
|
64
84
|
**Legacy names keep carrying the real defaults. Each `--liminis-editor-*`
|
|
65
85
|
name becomes a new declaration that reads its legacy name via `var()`** —
|
|
66
86
|
`--liminis-editor-foreground: var(--vscode-foreground);` — added in a new
|
|
@@ -125,6 +145,13 @@ comment noting they are superseded by the new canonical default. The
|
|
|
125
145
|
spec's Out of Scope section explicitly permits this as a side effect of
|
|
126
146
|
choosing FR-001's value, not as a design goal in its own right.
|
|
127
147
|
|
|
148
|
+
> **Amended 2026-08-22 by ADR-98 (#98) — this clause no longer holds.** Every
|
|
149
|
+
> consumption site's nested legacy fallback, called "provably dead code"
|
|
150
|
+
> below, is removed by ADR-98 — precisely because leaving it in place would
|
|
151
|
+
> mean this package still textually reads the legacy vocabulary ADR-98's
|
|
152
|
+
> FR-003 forbids. The "materially larger, coordinated change deferred out of
|
|
153
|
+
> this issue's scope" this paragraph anticipated is ADR-98 itself.
|
|
154
|
+
|
|
128
155
|
**Consumption sites are left untouched.** All 224 `styles.css` sites and 26
|
|
129
156
|
`.tsx` sites keep their existing `var(--liminis-editor-x, var(--old-name-x, ...))`
|
|
130
157
|
chains. Simplifying them to a single `var(--liminis-editor-x)` call was
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# ADR-98: Invert the Token Direction — `--liminis-editor-*` Carries the Values, Legacy Names Become Shims
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-08-22
|
|
4
|
+
**Status:** Accepted
|
|
5
|
+
**Supersedes:** none
|
|
6
|
+
**Amends:** none
|
|
7
|
+
**Issue:** #98 (verveguy/liminis-editor)
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
ADR-93 (#93) gave every `--liminis-editor-*` name a real `:root`/`.dark`
|
|
12
|
+
declaration, but as a forward to its legacy name —
|
|
13
|
+
`--liminis-editor-foreground: var(--vscode-foreground);`. The real values
|
|
14
|
+
kept living on the legacy side. That was a deliberate, narrow fix for a
|
|
15
|
+
narrow problem (a host reading `--liminis-editor-*` got nothing at all,
|
|
16
|
+
zusammen#129); it was never the end state, and ADR-092's own "Not decided
|
|
17
|
+
here" section named the inversion as an open item.
|
|
18
|
+
|
|
19
|
+
The narrowness became a concrete defect. verveguy/zusammen#134 migrated its
|
|
20
|
+
shadcn palette onto `--liminis-editor-*` and had to leave three tokens
|
|
21
|
+
behind, because their aliases lead to a literal, not a value:
|
|
22
|
+
`--liminis-editor-primary: var(--color-primary, #3b82f6)`,
|
|
23
|
+
`--liminis-editor-errorForeground: var(--vscode-errorForeground, #f14c4c)`,
|
|
24
|
+
`--liminis-editor-focus-border: var(--vscode-focus-border, #007acc)`. Wiring
|
|
25
|
+
Zusammen's `--primary` to the first would have replaced its purple brand
|
|
26
|
+
colour with an unrelated blue — a visible, app-wide regression, and not a
|
|
27
|
+
Zusammen problem to work around: `--color-primary` has zero definitions in
|
|
28
|
+
this package, so the alias never led anywhere real to begin with.
|
|
29
|
+
|
|
30
|
+
**Verified against the current codebase, not the issue's approximate
|
|
31
|
+
counts** (the spec's own Assumptions permit this — Implement diffs against
|
|
32
|
+
real source, not the issue's illustrative numbers):
|
|
33
|
+
|
|
34
|
+
- 59 `--liminis-editor-*` names are declared (the issue said 65).
|
|
35
|
+
- 26 legacy names need a shim: 24 distinct `--vscode-*` names,
|
|
36
|
+
`--checkbox-border`, and `--editor-brand`.
|
|
37
|
+
- The 61 `--slashmd-*` names need no shim — verified zero hits across both
|
|
38
|
+
`verveguy/zusammen` and `verveguy/liminis` (the one `slashmd` string that
|
|
39
|
+
does appear, `.slashmd-editor`, is an unrelated CSS class name). They are
|
|
40
|
+
upstream vocabulary no known consumer reads, so #98 deletes them outright.
|
|
41
|
+
- `--slashmd-heading-color` is declared three times (twice in the `:root`/
|
|
42
|
+
`.dark` blocks ADR-93 left in place, once in `@media print`) but consumed
|
|
43
|
+
nowhere and has no `--liminis-editor-*` counterpart — dropped entirely,
|
|
44
|
+
including from the print block, rather than inventing one.
|
|
45
|
+
- Exactly 10 `var(--color-*)` references exist in `src/`: 4 in the
|
|
46
|
+
`styles.css` alias block this ADR deletes, and 6 in `C4Component.tsx`
|
|
47
|
+
(the C4 diagram layout-toggle buttons) — the only place
|
|
48
|
+
`--color-primary`/`--color-muted-foreground`/their `-100` variants are
|
|
49
|
+
read anywhere in this package.
|
|
50
|
+
|
|
51
|
+
## Decision
|
|
52
|
+
|
|
53
|
+
**Invert the direction.** Each `--liminis-editor-*` name now carries its own
|
|
54
|
+
literal (or, for two names, a value built only from another
|
|
55
|
+
`--liminis-editor-*` name) at `:root`/`.dark`. Each of the 26 legacy names
|
|
56
|
+
above becomes a one-line shim, `<legacy>: var(--liminis-editor-x);`, in a
|
|
57
|
+
new `:root`-only block — no `.dark` duplicate is needed, since
|
|
58
|
+
`var(--liminis-editor-x)` re-resolves against whichever cascade value is
|
|
59
|
+
active at the point of use, the same reasoning ADR-93 already relied on in
|
|
60
|
+
the opposite direction. **The physical structure of `styles.css`'s two
|
|
61
|
+
blocks swaps roles, not position**, so the diff reads as "these two blocks
|
|
62
|
+
traded places" rather than a scrambled rewrite.
|
|
63
|
+
|
|
64
|
+
### Verified, not assumed: the shim preserves reads, not writes
|
|
65
|
+
|
|
66
|
+
The issue asked for this to be verified, not assumed, and it was — with a
|
|
67
|
+
real, corrected finding, not a confirmation of the original premise. The
|
|
68
|
+
issue's own proposed mechanism claimed a host *setting* only a legacy name
|
|
69
|
+
would still theme the editor, "because the package consumes
|
|
70
|
+
`--liminis-editor-foreground` and the host's declaration wins by cascade."
|
|
71
|
+
That is false, and checking it (a static HTML fixture opened in a real
|
|
72
|
+
Chromium via Playwright's cached binary, then the same check repeated
|
|
73
|
+
against `examples/electron/e2e/theming-aliases.spec.ts`'s running shell)
|
|
74
|
+
shows why: a `var()` reference resolves the cascade of the *exact* property
|
|
75
|
+
name written inside it. `--liminis-editor-foreground`'s own declaration is
|
|
76
|
+
a literal, containing no reference to `--vscode-foreground` at all — so a
|
|
77
|
+
host's override of `--vscode-foreground` changes what `--vscode-foreground`
|
|
78
|
+
itself computes to, and nothing else. Nothing inside this package reads
|
|
79
|
+
`--vscode-foreground`, so the override never reaches the editor. Two custom
|
|
80
|
+
properties do not auto-synchronize; only a `var()` reference that names one
|
|
81
|
+
inside the other's declaration creates any relationship between them, and
|
|
82
|
+
here the reference runs one way only (legacy → new, in the shim), not both
|
|
83
|
+
— a bidirectional shim (each side referencing the other via `var()`) is a
|
|
84
|
+
CSS cycle, which the spec defines as producing a guaranteed-invalid value on
|
|
85
|
+
*both* properties, so that was never an option either.
|
|
86
|
+
|
|
87
|
+
**The corrected, accepted guarantee: a shim preserves reads, not writes.** A
|
|
88
|
+
host that *reads* a legacy name (e.g. Zusammen's
|
|
89
|
+
`--vscode-errorForeground`/`--vscode-focus-border`) still gets the real,
|
|
90
|
+
current value, since the shim's `var(--liminis-editor-x)` reference resolves
|
|
91
|
+
normally. A host that *sets* only a legacy name no longer themes the editor
|
|
92
|
+
— this is accepted as an intentional breaking change (see CHANGELOG's
|
|
93
|
+
`## Unreleased` / Breaking changes), not a regression to silently work
|
|
94
|
+
around, because the only alternative (`--liminis-editor-x: var(--legacy-x,
|
|
95
|
+
<literal>)`, checking the legacy name first at the *definition* site) would
|
|
96
|
+
keep the legacy name in the resolution path for every one of the 26 shimmed
|
|
97
|
+
tokens — reintroducing, in a new shape, the exact dependence on the legacy
|
|
98
|
+
vocabulary this issue exists to remove. Measured directly: neither
|
|
99
|
+
`liminis-app` nor Zusammen sets a legacy name today (`liminis-app` sets
|
|
100
|
+
`--liminis-editor-primary`/`--liminis-editor-muted-foreground`; Zusammen
|
|
101
|
+
only reads), so this break has no currently-known victim, and it is also
|
|
102
|
+
`0.2.0`'s already-announced deprecation ("removed in a future major
|
|
103
|
+
release") completing on schedule rather than early.
|
|
104
|
+
`examples/electron/e2e/theming-aliases.spec.ts` pins both halves directly
|
|
105
|
+
with `getComputedStyle` in a running Electron shell: a legacy-name read
|
|
106
|
+
still resolves, and a legacy-name-only *write* no longer reaches the
|
|
107
|
+
editor's computed style — a deliberate assertion of the new, documented
|
|
108
|
+
behavior, not a gap left uncovered.
|
|
109
|
+
|
|
110
|
+
**FR-003 ("no internal code may read a `--vscode-*`/`--slashmd-*`/
|
|
111
|
+
`--checkbox-*` property") is taken literally.** All CSS and TSX consumption
|
|
112
|
+
sites under `src/` lose their now-redundant nested `var(--legacy-x, …)`
|
|
113
|
+
fallback, becoming a bare `var(--liminis-editor-x)`. Every name now has an
|
|
114
|
+
unconditional default, so the fallback was provably dead weight, not a
|
|
115
|
+
safety net — the same "provably dead code" ADR-93 left in place in the
|
|
116
|
+
other direction, except this time removed, because leaving it would mean
|
|
117
|
+
this package still textually reads the legacy vocabulary FR-003 forbids.
|
|
118
|
+
The `@media print` block — an *internal* consumer, not a host — is migrated
|
|
119
|
+
the same way, overriding `--liminis-editor-*` names directly.
|
|
120
|
+
|
|
121
|
+
**`--liminis-editor-primary`/`-100` are brand-derived, not host-borrowed.**
|
|
122
|
+
`--editor-brand` — this package's own, already-themed purple,
|
|
123
|
+
`oklch(0.55 0.20 303)` light / `oklch(0.70 0.20 303)` dark — becomes
|
|
124
|
+
`--liminis-editor-primary`'s value directly; no new public token name is
|
|
125
|
+
invented. `--editor-brand` itself becomes a one-line shim,
|
|
126
|
+
`--editor-brand: var(--liminis-editor-primary);`.
|
|
127
|
+
`--liminis-editor-primary-100` becomes the same brand colour at 10% alpha,
|
|
128
|
+
mirroring how the existing callout tokens already derive a tint from
|
|
129
|
+
`--editor-brand`. This replaces the previous forward to liminis-app's
|
|
130
|
+
`--color-primary`/`-100` (§the issue's point 3: "this looks like a defect
|
|
131
|
+
introduced by #93 rather than a deliberate default") — this package never
|
|
132
|
+
defined `--color-primary`, so that forward never had a real value behind
|
|
133
|
+
it; a package-owned brand colour is a deliberate default the package
|
|
134
|
+
actually owns.
|
|
135
|
+
|
|
136
|
+
**`--color-primary`/`--color-muted-foreground`/their `-100` variants are not
|
|
137
|
+
part of this package's legacy vocabulary and stay outside FR-003's
|
|
138
|
+
forbidden list** (only `--vscode-*`/`--slashmd-*`/`--checkbox-*` are
|
|
139
|
+
forbidden). liminis-app sets `--color-primary`/`--color-muted-foreground`
|
|
140
|
+
today, and that override must keep working unmodified. Once
|
|
141
|
+
`--liminis-editor-primary`'s *definition* no longer forwards to
|
|
142
|
+
`--color-primary`, the only place left to preserve that override is
|
|
143
|
+
`C4Component.tsx`'s own 6 consumption sites — so, uniquely, those sites are
|
|
144
|
+
**not** simplified to a bare `var(--liminis-editor-x)` like every other
|
|
145
|
+
site in this package. They are reordered to
|
|
146
|
+
`var(--color-x, var(--liminis-editor-x))`, checking liminis-app's token
|
|
147
|
+
first and falling back to this package's own default, dropping only the
|
|
148
|
+
now-redundant third-level literal. **This is the one deliberate exception
|
|
149
|
+
to "strip every legacy fallback," and it is the single highest-risk spot in
|
|
150
|
+
this change** — a future pass that "simplifies" it to match every other
|
|
151
|
+
call site would silently stop liminis-app's existing override from working.
|
|
152
|
+
An inline comment at the site says so explicitly, not only this ADR.
|
|
153
|
+
|
|
154
|
+
> **Amended 2026-08-22 (#101) — this exception is removed.** Measured
|
|
155
|
+
> against both known consumers' current `main`, the two arms resolved
|
|
156
|
+
> identically in liminis-app (`--color-primary` and `--liminis-editor-primary`
|
|
157
|
+
> both trace to `var(--primary)`) and the `--color-*` arm was dead in
|
|
158
|
+
> Zusammen (neither `--color-primary-100` nor `--color-muted-100` was ever
|
|
159
|
+
> defined there). The fallback changed no observable outcome anywhere it was
|
|
160
|
+
> deployed, while permanently coupling this package to a host's Tailwind
|
|
161
|
+
> `@theme` namespace it does not define or control. `C4Component.tsx`'s six
|
|
162
|
+
> sites now read `var(--liminis-editor-x)` only, the same as every other
|
|
163
|
+
> consumption site; a host that wants to override the C4 diagram colours
|
|
164
|
+
> sets `--liminis-editor-primary` and its siblings, exactly as it would for
|
|
165
|
+
> any other token. This confirms the risk this ADR itself flagged above —
|
|
166
|
+
> the "single highest-risk spot" and "permanent asymmetry" — rather than
|
|
167
|
+
> contradicting it.
|
|
168
|
+
|
|
169
|
+
**`PREVIOUS_NAME` in `scripts/lib/theming-tokens.mjs` drops its `-primary-100`/
|
|
170
|
+
`-muted-foreground`/`-muted-100` entries** (they pointed at `--color-*`,
|
|
171
|
+
which this package never defined — keeping them implied a migration
|
|
172
|
+
relationship that never existed) **and repoints `-primary` at
|
|
173
|
+
`--editor-brand`**, the name it now genuinely shims. The map's remaining
|
|
174
|
+
entries (`--slashmd-*`, most `--vscode-*`) are kept as a historical
|
|
175
|
+
migration record for the README's "Previous name" column, even though
|
|
176
|
+
`--slashmd-*` itself is deleted — the record of what a token used to be
|
|
177
|
+
called remains useful to a host migrating an old override, and nothing
|
|
178
|
+
about deleting the definition requires deleting the history of the rename.
|
|
179
|
+
|
|
180
|
+
**`resolvesToPreviousName()` is deleted, not just updated, and replaced with
|
|
181
|
+
`LEGACY_SHIM_TARGET` + `resolvesToShimTarget()`.** The old guard's premise —
|
|
182
|
+
a consumption-site fallback protects a host still supplying only the legacy
|
|
183
|
+
name — is exactly what this ADR inverts: that protection now lives in the
|
|
184
|
+
`:root` shim declaration, not at the consumption site. The new guard checks
|
|
185
|
+
the new invariant directly: every one of the 26 legacy names in
|
|
186
|
+
`LEGACY_SHIM_TARGET` is declared in `styles.css` as a one-line `var()`
|
|
187
|
+
forward to its `--liminis-editor-*` target (FR-002), and — a second,
|
|
188
|
+
independent check — nothing under `src/` contains `var(--vscode-`,
|
|
189
|
+
`var(--slashmd-`, or `var(--checkbox-` at all (FR-003). A plain-text scan
|
|
190
|
+
is sufficient for the second check and more robust than the old paren-depth
|
|
191
|
+
-aware fallback check, because after this change there is no longer any
|
|
192
|
+
legitimate reason for those substrings to appear inside a `var()` call
|
|
193
|
+
anywhere in this package.
|
|
194
|
+
|
|
195
|
+
**One side effect of the `C4Component.tsx` exception, not separately
|
|
196
|
+
designed:** `scripts/lib/theming-tokens.mjs`'s `consumedTokens()` treats the
|
|
197
|
+
outermost (depth-0) name in a `var()` fallback chain as the "primary"
|
|
198
|
+
consumed name — the same logic ADR-93 relied on to keep alias declarations
|
|
199
|
+
out of the consumed set. Since `var(--color-x, var(--liminis-editor-x))`'s
|
|
200
|
+
outer argument is `--color-x`, that is now the name the README's generated
|
|
201
|
+
table documents at those 4 token pairs, not `--liminis-editor-primary`/
|
|
202
|
+
`-100`/`-muted-foreground`/`-muted-100` — those four remain fully real,
|
|
203
|
+
declared defaults (verified by the baseline and by `defaultedTokens()`),
|
|
204
|
+
just no longer the *documented-as-consumed* name at this one file's sites.
|
|
205
|
+
`TOKEN_DESCRIPTIONS` gains four new entries for the `--color-*` names
|
|
206
|
+
instead, describing the override relationship in both directions.
|
|
207
|
+
|
|
208
|
+
## Consequences
|
|
209
|
+
|
|
210
|
+
**Good:**
|
|
211
|
+
|
|
212
|
+
- A host reading `--liminis-editor-*` now gets a real value in every case,
|
|
213
|
+
including the 23 aliases that previously baked a literal — the entire
|
|
214
|
+
point of this issue and the prerequisite for zusammen#134's read
|
|
215
|
+
migration (FR-001, SC-001).
|
|
216
|
+
- A host supplying only a legacy name keeps *reading* a real value, verified
|
|
217
|
+
by `getComputedStyle` in a running Electron shell, not assumed from
|
|
218
|
+
cascade theory alone (FR-002, FR-003) — see "Verified, not assumed" above
|
|
219
|
+
for the corrected scope of this guarantee (reads, not writes).
|
|
220
|
+
- `--liminis-editor-primary` now resolves to a value this package actually
|
|
221
|
+
owns, closing the defect the issue's point 3 named (FR-008).
|
|
222
|
+
- The ADR-092 baseline guard now protects the 26 shim declarations the same
|
|
223
|
+
way it already protected every other definition — an accidental deletion
|
|
224
|
+
of a shim fails `pnpm test`, naming the token.
|
|
225
|
+
- `--slashmd-*`'s 61 names are gone entirely — the largest single reduction
|
|
226
|
+
in this package's declared token surface since #51, with a verified
|
|
227
|
+
absence of consumers backing the removal, not a guess.
|
|
228
|
+
|
|
229
|
+
**Bad / accepted:**
|
|
230
|
+
|
|
231
|
+
- **A host that sets only a legacy name no longer themes the editor** — this
|
|
232
|
+
package's initial framing of this issue called the whole change
|
|
233
|
+
"non-breaking," and that framing was wrong for this one direction (see
|
|
234
|
+
"Verified, not assumed" above). Accepted because the only fix would keep
|
|
235
|
+
the legacy name in every shimmed token's resolution path, defeating the
|
|
236
|
+
purpose of the inversion, and because neither known consumer (`liminis-app`,
|
|
237
|
+
Zusammen) currently sets a legacy name — this is documented in the
|
|
238
|
+
CHANGELOG's `## Unreleased` / Breaking changes as of this decision.
|
|
239
|
+
- **`--liminis-editor-primary`/`-100`'s new computed value is a real,
|
|
240
|
+
visible change** for anything relying on the old `#3b82f6`-derived default
|
|
241
|
+
rather than overriding it. This is out of this repository's control —
|
|
242
|
+
`zusammen`/`liminis-app` are separate repositories — but is a deliberate,
|
|
243
|
+
known consequence of FR-008, not an oversight, and is called out
|
|
244
|
+
prominently in the PR description.
|
|
245
|
+
- **The `C4Component.tsx` `--color-*` exception is a permanent asymmetry** in
|
|
246
|
+
an otherwise uniform "every consumption site reads `--liminis-editor-*`
|
|
247
|
+
only" rule. It is the one place a future contributor could plausibly
|
|
248
|
+
"clean up" into a silent regression against liminis-app. The inline
|
|
249
|
+
comment at the site and this ADR are the two places that asymmetry is
|
|
250
|
+
recorded; there is no CI guard that would catch a well-intentioned but
|
|
251
|
+
wrong simplification here, because the wrong version is textually
|
|
252
|
+
indistinguishable from a normal consumption site.
|
|
253
|
+
> **Amended 2026-08-22 (#101) — removed.** The exception is gone; see the
|
|
254
|
+
> amendment in the Decision section above. `--color-*` is now forbidden
|
|
255
|
+
> under `src/` on the same footing as `--vscode-*`/`--slashmd-*`/
|
|
256
|
+
> `--checkbox-*`, with no per-file carve-out.
|
|
257
|
+
- **The README's generated token table no longer lists
|
|
258
|
+
`--liminis-editor-primary`/`-100`/`-muted-foreground`/`-muted-100` as
|
|
259
|
+
their own rows** — `--color-primary`/`-100`/`-muted-foreground`/`-muted-100`
|
|
260
|
+
appear instead, as a direct consequence of which name is "outermost" in
|
|
261
|
+
`C4Component.tsx`'s reordered fallback chain (see Decision). The four
|
|
262
|
+
`--liminis-editor-*` names remain fully real, declared, overridable
|
|
263
|
+
defaults; they are simply not the *documented-as-consumed* name at this
|
|
264
|
+
one file's sites. A future contributor auditing "does every
|
|
265
|
+
`--liminis-editor-*` name have a row in the README" needs to know this
|
|
266
|
+
before treating the absence as a bug.
|
|
267
|
+
- **`--editor-brand` was never itself part of `PREVIOUS_NAME`'s renamed-token
|
|
268
|
+
history before this change** (it had no consumption site to preserve a
|
|
269
|
+
fallback for), so its entry is new, not migrated — a minor asymmetry with
|
|
270
|
+
every other `PREVIOUS_NAME` entry, which all trace back to #51.
|
|
271
|
+
|
|
272
|
+
**Neutral:**
|
|
273
|
+
|
|
274
|
+
- `scripts/lib/theming-tokens.mjs`'s `consumptionSitesIn()`/
|
|
275
|
+
`isCustomPropertyDeclarationValue()` machinery (ADR-93) needed no change:
|
|
276
|
+
it is direction-agnostic, and correctly treats this ADR's new shim
|
|
277
|
+
declarations as declaration-side values, not consumption sites, the same
|
|
278
|
+
way it treated ADR-93's aliases.
|
|
279
|
+
- `resolvesWithoutHost()` needed no change either: once every
|
|
280
|
+
`--liminis-editor-*` name has a real `:root`/`.dark` declaration, a bare
|
|
281
|
+
`var(--liminis-editor-x)` with no fallback resolves without a host by
|
|
282
|
+
construction — the guard's existing logic already covers this.
|
|
283
|
+
|
|
284
|
+
## References
|
|
285
|
+
|
|
286
|
+
- Issue #98 (this decision); ADR-092's "Not decided here," Item 3 — this
|
|
287
|
+
decision's direct origin
|
|
288
|
+
- `docs/decisions/adr-93-liminis-editor-defined-aliases.md` — the decision
|
|
289
|
+
this one inverts; amended to note its alias direction is superseded here
|
|
290
|
+
- `docs/decisions/adr-092.md` — the checked-in baseline guard this
|
|
291
|
+
decision's shim declarations and dropped `--slashmd-*` names are
|
|
292
|
+
reconciled against (`pnpm docs:theming-baseline`)
|
|
293
|
+
- `docs/decisions/adr-087.md` — the consumption-side rename and
|
|
294
|
+
`PREVIOUS_NAME`/fallback design this decision's `resolvesToPreviousName()`
|
|
295
|
+
retirement supersedes for the definition side
|
|
296
|
+
- `src/styles.css` — the swapped shim/definition blocks; the migrated
|
|
297
|
+
`@media print` block; the inline comment at `C4Component.tsx`'s
|
|
298
|
+
`--color-*` sites
|
|
299
|
+
- `scripts/lib/theming-tokens.mjs` — `LEGACY_SHIM_TARGET`,
|
|
300
|
+
`resolvesToShimTarget()`, the adjusted `PREVIOUS_NAME`
|
|
301
|
+
- `scripts/lib/theming-defined-tokens-baseline.json` — regenerated via
|
|
302
|
+
`pnpm docs:theming-baseline` (61 `--slashmd-*` removed, 13
|
|
303
|
+
previously-undeclared `--vscode-*` shims added)
|
|
304
|
+
- `README.md`, "Theming: CSS custom properties" — regenerated table and
|
|
305
|
+
hand-rewritten prose describing the inverted mechanism
|
|
306
|
+
- [verveguy/zusammen#134](https://github.com/verveguy/zusammen/issues/134) —
|
|
307
|
+
the downstream migration this decision unblocks
|
|
308
|
+
- [verveguy/zusammen#129](https://github.com/verveguy/zusammen/issues/129) —
|
|
309
|
+
the earlier, narrower migration ADR-93 unblocked
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="1286" height="535" viewBox="-50 0 1286 535" xmlns="http://www.w3.org/2000/svg" data-diagram="c4" style="font-family:system-ui, -apple-system, sans-serif"><g class="boundaries-layer"><g><rect x="190" y="40" width="440" height="455" rx="8" ry="8" fill="#131619" stroke="#47657d" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="410" y="64" text-anchor="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Host application</text></g></g><g class="nodes-layer"><g><circle cx="50" cy="156" r="14" fill="#006b2d" stroke="#009848" stroke-width="1.5"></circle><rect x="30" y="174" width="40" height="30" rx="20" ry="8" fill="#006b2d" stroke="#009848" stroke-width="1.5"></rect><text x="50" y="232" text-anchor="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Author</text><text x="50" y="246" text-anchor="middle" fill="#d6d6d6" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7">Writes and edits ...</text></g><g><rect x="230" y="135" width="360" height="110" rx="8" ry="8" fill="#16191c" stroke="#0098e0" stroke-width="2.5" stroke-dasharray="none"></rect><text x="410" y="178" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Host shell</text><text x="410" y="194" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[Electron or browser]</text><text x="410" y="216" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="410" dy="0">Owns documents, storage and windows. Supplies the seam.</tspan></text></g><g><rect x="230" y="345" width="360" height="110" rx="8" ry="8" fill="#16191c" stroke="#0098e0" stroke-width="2.5" stroke-dasharray="none"></rect><text x="410" y="388" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">@liminis/editor</text><text x="410" y="404" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[React + Lexical]</text><text x="410" y="426" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="410" dy="0">The editing surface, the markdown pipeline and</tspan><tspan x="410" dy="14">annotations</tspan></text></g><g><rect x="820" y="143" width="360" height="94" rx="8" ry="8" fill="#2d2d2d" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1000" y="184" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Document store</text><text x="1000" y="204" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1000" dy="0">Files, a database, a sync service — the host's concern,</tspan><tspan x="1000" dy="14">never this package's</tspan></text></g></g><g class="edges-layer"><g><path d="M 110 190 L 222 190" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="230,190 222,194 222,186" fill="#a7a7a7"></polygon><text x="170" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 170, 190)"><tspan x="170" y="194">Opens and edits documents</tspan></text></g><g><path d="M 397.5 245 L 397.5 337" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="397.5,345 393.5,337 401.5,337" fill="#a7a7a7"></polygon><rect x="387.5" y="285" width="20" height="20" rx="3" fill="#16191c" stroke="#a7a7a7" stroke-width="1.5"></rect><text x="397.5" y="299" text-anchor="middle" fill="#a7a7a7" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">B</text></g><g><path d="M 422.5 345 L 422.5 253" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="422.5,245 426.5,253 418.5,253" fill="#a7a7a7"></polygon><rect x="412.5" y="285" width="20" height="20" rx="3" fill="#16191c" stroke="#a7a7a7" stroke-width="1.5"></rect><text x="422.5" y="299" text-anchor="middle" fill="#a7a7a7" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">A</text></g><g><path d="M 590 190 L 653.6 190" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 756.4 190 L 812 190" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="820,190 812,194 812,186" fill="#a7a7a7"></polygon><text x="705" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 705, 190)"><tspan x="705" y="194">Reads and writes</tspan></text></g></g><g class="legend-layer"><g><rect x="920" y="20" width="18" height="18" rx="3" fill="#16191c" stroke="#a7a7a7" stroke-width="1.5"></rect><text x="929" y="33" text-anchor="middle" fill="#a7a7a7" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">A</text><text x="946" y="33" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif">Reports changes, requests services through the seam</text></g><g><rect x="920" y="44" width="18" height="18" rx="3" fill="#16191c" stroke="#a7a7a7" stroke-width="1.5"></rect><text x="929" y="57" text-anchor="middle" fill="#a7a7a7" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">B</text><text x="946" y="57" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif">Mounts <Editor>, injects host services</text></g></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="1286" height="535" viewBox="-50 0 1286 535" xmlns="http://www.w3.org/2000/svg" data-diagram="c4" style="font-family:system-ui, -apple-system, sans-serif"><g class="boundaries-layer"><g><rect x="190" y="40" width="440" height="455" rx="8" ry="8" fill="#f4f7fb" stroke="#63869b" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="410" y="64" text-anchor="middle" fill="#3d3d3d" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Host application</text></g></g><g class="nodes-layer"><g><circle cx="50" cy="156" r="14" fill="#006b2d" stroke="#004b1e" stroke-width="1.5"></circle><rect x="30" y="174" width="40" height="30" rx="20" ry="8" fill="#006b2d" stroke="#004b1e" stroke-width="1.5"></rect><text x="50" y="232" text-anchor="middle" fill="#3d3d3d" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Author</text><text x="50" y="246" text-anchor="middle" fill="#3d3d3d" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7">Writes and edits ...</text></g><g><rect x="230" y="135" width="360" height="110" rx="8" ry="8" fill="#ffffff" stroke="#005998" stroke-width="2.5" stroke-dasharray="none"></rect><text x="410" y="178" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Host shell</text><text x="410" y="194" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[Electron or browser]</text><text x="410" y="216" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="410" dy="0">Owns documents, storage and windows. Supplies the seam.</tspan></text></g><g><rect x="230" y="345" width="360" height="110" rx="8" ry="8" fill="#ffffff" stroke="#005998" stroke-width="2.5" stroke-dasharray="none"></rect><text x="410" y="388" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">@liminis/editor</text><text x="410" y="404" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[React + Lexical]</text><text x="410" y="426" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="410" dy="0">The editing surface, the markdown pipeline and</tspan><tspan x="410" dy="14">annotations</tspan></text></g><g><rect x="820" y="143" width="360" height="94" rx="8" ry="8" fill="#f0f4f8" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1000" y="184" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Document store</text><text x="1000" y="204" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1000" dy="0">Files, a database, a sync service — the host's concern,</tspan><tspan x="1000" dy="14">never this package's</tspan></text></g></g><g class="edges-layer"><g><path d="M 110 190 L 222 190" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="230,190 222,194 222,186" fill="#565656"></polygon><text x="170" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 170, 190)"><tspan x="170" y="194">Opens and edits documents</tspan></text></g><g><path d="M 397.5 245 L 397.5 337" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="397.5,345 393.5,337 401.5,337" fill="#565656"></polygon><rect x="387.5" y="285" width="20" height="20" rx="3" fill="#ffffff" stroke="#565656" stroke-width="1.5"></rect><text x="397.5" y="299" text-anchor="middle" fill="#565656" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">B</text></g><g><path d="M 422.5 345 L 422.5 253" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="422.5,245 426.5,253 418.5,253" fill="#565656"></polygon><rect x="412.5" y="285" width="20" height="20" rx="3" fill="#ffffff" stroke="#565656" stroke-width="1.5"></rect><text x="422.5" y="299" text-anchor="middle" fill="#565656" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">A</text></g><g><path d="M 590 190 L 653.6 190" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 756.4 190 L 812 190" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="820,190 812,194 812,186" fill="#565656"></polygon><text x="705" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 705, 190)"><tspan x="705" y="194">Reads and writes</tspan></text></g></g><g class="legend-layer"><g><rect x="920" y="20" width="18" height="18" rx="3" fill="#ffffff" stroke="#565656" stroke-width="1.5"></rect><text x="929" y="33" text-anchor="middle" fill="#565656" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">A</text><text x="946" y="33" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif">Reports changes, requests services through the seam</text></g><g><rect x="920" y="44" width="18" height="18" rx="3" fill="#ffffff" stroke="#565656" stroke-width="1.5"></rect><text x="929" y="57" text-anchor="middle" fill="#565656" font-size="10" font-weight="600" font-family="system-ui, -apple-system, sans-serif">B</text><text x="946" y="57" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif">Mounts <Editor>, injects host services</text></g></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="1761" height="545" viewBox="0 0 1761 545" xmlns="http://www.w3.org/2000/svg" data-diagram="c4" style="font-family:system-ui, -apple-system, sans-serif"><g class="boundaries-layer"></g><g class="nodes-layer"><g><rect x="40" y="40" width="1105" height="455" rx="8" ry="8" fill="#131619" stroke="#47657d" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="592.5" y="64" text-anchor="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">@liminis/editor</text></g><g><rect x="388" y="135" width="294" height="110" rx="4" ry="4" fill="#16191c" stroke="#2b89bf" stroke-width="2.5"></rect><text x="535" y="186" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">.</text><text x="535" y="202" text-anchor="middle" fill="#b2b2b2" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[React]</text></g><g><rect x="355" y="345" width="360" height="110" rx="4" ry="4" fill="#16191c" stroke="#2b89bf" stroke-width="2.5"></rect><text x="535" y="396" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./markdown</text><text x="535" y="412" text-anchor="middle" fill="#b2b2b2" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[mdast]</text></g><g><rect x="80" y="345" width="245" height="110" rx="4" ry="4" fill="#16191c" stroke="#2b89bf" stroke-width="2.5"></rect><text x="202.5" y="396" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./annotations</text><text x="202.5" y="412" text-anchor="middle" fill="#b2b2b2" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[TypeScript]</text></g><g><rect x="712" y="135" width="240" height="110" rx="4" ry="4" fill="#16191c" stroke="#2b89bf" stroke-width="2.5"></rect><text x="832" y="186" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./headless</text><text x="832" y="202" text-anchor="middle" fill="#b2b2b2" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[DOM-free]</text></g><g><rect x="745" y="345" width="360" height="110" rx="4" ry="4" fill="#16191c" stroke="#2b89bf" stroke-width="2.5"></rect><text x="925" y="396" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./nodes</text><text x="925" y="412" text-anchor="middle" fill="#b2b2b2" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[Lexical]</text></g><g><rect x="1371" y="411" width="252" height="94" rx="8" ry="8" fill="#2d2d2d" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1497" y="452" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Lexical</text><text x="1497" y="472" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1497" dy="0">Peer dependency — the editing engine</tspan></text></g><g><rect x="1371" y="277" width="350" height="94" rx="8" ry="8" fill="#2d2d2d" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1546" y="318" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">mdast / micromark</text><text x="1546" y="338" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1546" dy="0">GFM, math, footnotes, definition lists, wiki-links</tspan></text></g><g><rect x="1371" y="143" width="252" height="94" rx="8" ry="8" fill="#2d2d2d" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1497" y="184" text-anchor="middle" dominant-baseline="middle" fill="#d6d6d6" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">@liminis/diagrams</text><text x="1497" y="204" text-anchor="middle" fill="#b2b2b2" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1497" dy="0">Renders the C4 diagrams on this page</tspan></text></g></g><g class="edges-layer"><g><path d="M 637.143 245 L 703.68 280.828" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 756.904 309.487 L 815.813 341.207" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="822.857,345 813.917,344.729 817.71,337.685" fill="#a7a7a7"></polygon><text x="730" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(28.301, 730, 295)"><tspan x="730" y="299">Registers</tspan></text></g><g><path d="M 535 245 L 535 287.2" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 535 304.2 L 535 337" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="535,345 531,337 539,337" fill="#a7a7a7"></polygon><text x="535" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 535, 295)"><tspan x="535" y="299">Parses and serialises through</tspan></text></g><g><path d="M 447.917 245 L 432.353 254.83" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 304.515 335.569 L 296.347 340.728" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="289.583,345 294.211,337.346 298.483,344.11" fill="#a7a7a7"></polygon><text x="368.75" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(-32.276, 368.75, 295)"><tspan x="368.75" y="299">Anchors annotations with</tspan></text></g><g><path d="M 1105 418.252 L 1214.019 429.306" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 1262.122 434.184 L 1363.041 444.417" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="1371,445.224 1362.637,448.397 1363.444,440.437" fill="#a7a7a7"></polygon><text x="1238" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(5.79, 1238, 431.738)"><tspan x="1238" y="435.738">Extends</tspan></text></g><g><path d="M 715 386.469 L 1015.824 363.855" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 1070.071 359.777 L 1363.023 337.755" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="1371,337.155 1363.322,341.743 1362.723,333.766" fill="#a7a7a7"></polygon><text x="1043" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(-4.299, 1043, 361.812)"><tspan x="1043" y="365.812">Built on</tspan></text></g><g><path d="M 952 190 L 1098 190" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 1225 190 L 1363 190" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="1371,190 1363,194 1363,186" fill="#a7a7a7"></polygon><text x="1161.5" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 1161.5, 190)"><tspan x="1161.5" y="183">Re-exports</tspan><tspan x="1161.5" y="197">renderC4DiagramToSVG</tspan></text></g><g><path d="M 952 212.521 L 1125.974 245.172" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><path d="M 1197.279 258.554 L 1363.137 289.681" fill="none" stroke="#a7a7a7" stroke-width="1.5"></path><polygon points="1371,291.157 1362.399,293.613 1363.875,285.75" fill="#a7a7a7"></polygon><text x="1161.5" text-anchor="middle" fill="#bebebe" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(10.629, 1161.5, 251.839)"><tspan x="1161.5" y="255.839">Parses with</tspan></text></g></g></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg width="1761" height="545" viewBox="0 0 1761 545" xmlns="http://www.w3.org/2000/svg" data-diagram="c4" style="font-family:system-ui, -apple-system, sans-serif"><g class="boundaries-layer"></g><g class="nodes-layer"><g><rect x="40" y="40" width="1105" height="455" rx="8" ry="8" fill="#f4f7fb" stroke="#63869b" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="592.5" y="64" text-anchor="middle" fill="#3d3d3d" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">@liminis/editor</text></g><g><rect x="388" y="135" width="294" height="110" rx="4" ry="4" fill="#f8f8f8" stroke="#0068a0" stroke-width="2.5"></rect><text x="535" y="186" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">.</text><text x="535" y="202" text-anchor="middle" fill="#626262" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[React]</text></g><g><rect x="355" y="345" width="360" height="110" rx="4" ry="4" fill="#f8f8f8" stroke="#0068a0" stroke-width="2.5"></rect><text x="535" y="396" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./markdown</text><text x="535" y="412" text-anchor="middle" fill="#626262" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[mdast]</text></g><g><rect x="80" y="345" width="245" height="110" rx="4" ry="4" fill="#f8f8f8" stroke="#0068a0" stroke-width="2.5"></rect><text x="202.5" y="396" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./annotations</text><text x="202.5" y="412" text-anchor="middle" fill="#626262" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[TypeScript]</text></g><g><rect x="712" y="135" width="240" height="110" rx="4" ry="4" fill="#f8f8f8" stroke="#0068a0" stroke-width="2.5"></rect><text x="832" y="186" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./headless</text><text x="832" y="202" text-anchor="middle" fill="#626262" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[DOM-free]</text></g><g><rect x="745" y="345" width="360" height="110" rx="4" ry="4" fill="#f8f8f8" stroke="#0068a0" stroke-width="2.5"></rect><text x="925" y="396" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="13" font-weight="500" font-family="system-ui, -apple-system, sans-serif">./nodes</text><text x="925" y="412" text-anchor="middle" fill="#626262" font-size="10" font-family="system-ui, -apple-system, sans-serif" opacity="0.8">[Lexical]</text></g><g><rect x="1371" y="411" width="252" height="94" rx="8" ry="8" fill="#f0f4f8" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1497" y="452" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">Lexical</text><text x="1497" y="472" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1497" dy="0">Peer dependency — the editing engine</tspan></text></g><g><rect x="1371" y="277" width="350" height="94" rx="8" ry="8" fill="#f0f4f8" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1546" y="318" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">mdast / micromark</text><text x="1546" y="338" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1546" dy="0">GFM, math, footnotes, definition lists, wiki-links</tspan></text></g><g><rect x="1371" y="143" width="252" height="94" rx="8" ry="8" fill="#f0f4f8" stroke="#667280" stroke-width="2.5" stroke-dasharray="8 4"></rect><text x="1497" y="184" text-anchor="middle" dominant-baseline="middle" fill="#303030" font-size="14" font-weight="600" font-family="system-ui, -apple-system, sans-serif">@liminis/diagrams</text><text x="1497" y="204" text-anchor="middle" fill="#626262" font-size="11" font-family="system-ui, -apple-system, sans-serif" opacity="0.7"><tspan x="1497" dy="0">Renders the C4 diagrams on this page</tspan></text></g></g><g class="edges-layer"><g><path d="M 637.143 245 L 703.68 280.828" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 756.904 309.487 L 815.813 341.207" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="822.857,345 813.917,344.729 817.71,337.685" fill="#565656"></polygon><text x="730" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(28.301, 730, 295)"><tspan x="730" y="299">Registers</tspan></text></g><g><path d="M 535 245 L 535 287.2" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 535 304.2 L 535 337" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="535,345 531,337 539,337" fill="#565656"></polygon><text x="535" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 535, 295)"><tspan x="535" y="299">Parses and serialises through</tspan></text></g><g><path d="M 447.917 245 L 432.353 254.83" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 304.515 335.569 L 296.347 340.728" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="289.583,345 294.211,337.346 298.483,344.11" fill="#565656"></polygon><text x="368.75" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(-32.276, 368.75, 295)"><tspan x="368.75" y="299">Anchors annotations with</tspan></text></g><g><path d="M 1105 418.252 L 1214.019 429.306" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 1262.122 434.184 L 1363.041 444.417" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="1371,445.224 1362.637,448.397 1363.444,440.437" fill="#565656"></polygon><text x="1238" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(5.79, 1238, 431.738)"><tspan x="1238" y="435.738">Extends</tspan></text></g><g><path d="M 715 386.469 L 1015.824 363.855" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 1070.071 359.777 L 1363.023 337.755" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="1371,337.155 1363.322,341.743 1362.723,333.766" fill="#565656"></polygon><text x="1043" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(-4.299, 1043, 361.812)"><tspan x="1043" y="365.812">Built on</tspan></text></g><g><path d="M 952 190 L 1098 190" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 1225 190 L 1363 190" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="1371,190 1363,194 1363,186" fill="#565656"></polygon><text x="1161.5" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(0, 1161.5, 190)"><tspan x="1161.5" y="183">Re-exports</tspan><tspan x="1161.5" y="197">renderC4DiagramToSVG</tspan></text></g><g><path d="M 952 212.521 L 1125.974 245.172" fill="none" stroke="#565656" stroke-width="1.5"></path><path d="M 1197.279 258.554 L 1363.137 289.681" fill="none" stroke="#565656" stroke-width="1.5"></path><polygon points="1371,291.157 1362.399,293.613 1363.875,285.75" fill="#565656"></polygon><text x="1161.5" text-anchor="middle" fill="#4a4a4a" font-size="11" font-family="system-ui, -apple-system, sans-serif" transform="rotate(10.629, 1161.5, 251.839)"><tspan x="1161.5" y="255.839">Parses with</tspan></text></g></g></svg>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liminis/editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"//publishing": "Publishing is deliberate, never incidental. `private: true` was this package's guard until verveguy/liminis-editor#39 took the publish decision; it is gone because that decision was taken, not because it was tidied away. The guard is now `prepublishOnly` -> scripts/guard-publish.mjs, which refuses unless LIMINIS_ALLOW_PUBLISH=1 is set explicitly. That variable is set at step scope in .github/workflows/publish.yml and nowhere else, so a release is the only path that publishes. Note that `npm publish --dry-run` does NOT report a private package as blocked (npm 10.8.2), which is why the guard is a script rather than a flag.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Lexical-based markdown WYSIWYG editor with mdast round-trip and a host-injection seam",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"react-dom": "^19.2.0"
|
|
100
100
|
},
|
|
101
101
|
"dependencies": {
|
|
102
|
-
"@
|
|
102
|
+
"@liminis/diagrams": "^0.1.5",
|
|
103
103
|
"@mathjax/src": "^4.1.1",
|
|
104
104
|
"lucide-react": "^1.11.0",
|
|
105
105
|
"mdast-util-definition-list": "^2.0.0",
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* C4InteractiveRenderer - Interactive SVG renderer with drag support
|
|
3
|
-
*
|
|
4
|
-
* Wraps the C4Renderer with drag-and-drop functionality for manual layout mode.
|
|
5
|
-
* Maintains local position state during drag and recalculates edges in real-time.
|
|
6
|
-
*/
|
|
7
|
-
import type { C4Diagram } from './types.js';
|
|
8
|
-
/** Synthetic ID used to store legend position in manual positions map */
|
|
9
|
-
export declare const LEGEND_POSITION_ID = "__legend__";
|
|
10
|
-
export interface C4InteractiveRendererProps {
|
|
11
|
-
/** Parsed C4 diagram */
|
|
12
|
-
diagram: C4Diagram;
|
|
13
|
-
/** Whether dark mode is enabled */
|
|
14
|
-
isDarkMode: boolean;
|
|
15
|
-
/** Whether edit mode (drag) is enabled */
|
|
16
|
-
isEditMode: boolean;
|
|
17
|
-
/** Current manual positions */
|
|
18
|
-
manualPositions: Record<string, {
|
|
19
|
-
x: number;
|
|
20
|
-
y: number;
|
|
21
|
-
}>;
|
|
22
|
-
/** Callback when positions change (during drag or on drag end) */
|
|
23
|
-
onPositionChange: (positions: Record<string, {
|
|
24
|
-
x: number;
|
|
25
|
-
y: number;
|
|
26
|
-
}>) => void;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Interactive C4 diagram renderer with drag support.
|
|
30
|
-
*
|
|
31
|
-
* When isEditMode is true, nodes can be dragged to new positions.
|
|
32
|
-
* Edges and boundaries are recalculated in real-time during drag.
|
|
33
|
-
*/
|
|
34
|
-
export declare function C4InteractiveRenderer({ diagram, isDarkMode, isEditMode, manualPositions, onPositionChange, }: C4InteractiveRendererProps): JSX.Element;
|
|
35
|
-
export default C4InteractiveRenderer;
|