Wiki reader and editor parity contract #52
Notifications
Due Date
No due date set.
Blocks
#58 Wiki page frame, reader and editor
ShadowsOverWestgate/sow-nodebb-theme
Reference: ShadowsOverWestgate/sow-nodebb-theme#52
Reference in New Issue
Block a user
Part of #47
Question
What must hold true in both the wiki reader and the wiki editor, so a frame change cannot break one by fixing the other?
This is not hypothetical. A previous pass justified text in the reader and broke the editor. The wiki editor is a TipTap surface in
sow-nodebb-plugin-wiki(tiptap/,wiki-compose.tpl); the reader iswiki-page.tplstyled by the 1700-linescss/westgate/_wiki-prose.scssin this theme.Resolve:
Output is a short contract that later wiki tickets are held to.
Answer: parity is a DOM contract, not a rule anyone has to remember
Ownership first, because it decides everything else.
The wiki plugin owns its own chrome. Its endgame is publishable open source, not locked to our infra: it must look good standing alone on Harmony defaults, with no theme tweaks. Everything it renders is then customizable from outside with plain CSS, the way Harmony itself is. Our theme is just one consumer of that surface.
That rules out enforcing parity by forbidding the theme to write CSS — the customization we want and the prohibition cannot both hold. So parity comes from structure instead:
That is the whole contract. The rest is what it implies.
Shared hooks (prose — a rule here MUST hit both)
Already true today, and now load-bearing rather than incidental:
.westgate-wikion both. Readertemplates/wiki-page.tpl:1, composetemplates/wiki-compose.tpl:1(class="westgate-wiki westgate-wiki-compose"— the compose root carries both)..wiki-article-proseon both. Readerwiki-page.tpl:63, editablewiki-compose.tpl:47.public/wiki-article-body.css, served aswestgate-wiki/compose/article-body.css(readerwiki-page.tpl:268, composewiki-compose.tpl:87, mapped inlib/core/compose-assets.js).Must be identical in both, because a difference shows as content jumping when you hit edit: content column width and reading measure, font stack, font size, line height, paragraph and heading spacing, list indentation, heading scale, link colour, blockquote/code/table/callout/infobox rendering, text alignment and hyphenation.
Editor-only hooks (chrome — differing here is correct)
.westgate-wiki-composeand.wiki-editor__*, plus.ProseMirror-*state classes. Legitimately different: toolbar, source panel, gutters, sticky offsets, caret and selection styling, placeholder text, node-selected outlines, resize handles, slash-command menu.The boundary test: if turning the property off would change how the finished page reads, it is prose and belongs on the shared hooks. If it only exists while editing, it is chrome.
Where the styling physically lives
--wiki-*token values only. It does not restate plugin structure.Prose alignment
Justified reading prose is plugin-owned behaviour, not a theme selector. The plugin owns the implementation and the full opt-out set (table cells, blockquote,
pre, namespace/section listings). Site preference is expressed through an enumerated token the plugin honours —--wiki-prose-text-align: start | justify, defaultstart— so a consumer flips one value and gets justification applied identically to both surfaces, opt-outs travelling with it. What a consumer cannot do is re-scope what gets justified. Westgate setsjustify; it is our taste, not the plugin default.Known editor hazards
text-align: justify— confirmed, cost a pass. Now plugin-owned per above.hyphens: auto— travels with justification, same fix.scss/westgate/_wiki-prose.scss:228caps.wiki-content-layoutat58remfor the reader;:236repeats58remfor.westgate-wiki-compose .wiki-compose-editor.wiki-article-prose. One meaning, two constants, two selectors — drifts the moment one is edited. Collapses to--wiki-prose-measure(plugin default70ch,wiki-article-body.css:79)._wiki-prose.scss(roughly:341–:540) target.ck.ck-editor__editable_inline.ck-content— CKEditor classes the TipTap editor never emits. They are editor-only copies of heading rules: the exact shape that produced hazard 1, still sitting in the file, now also dead. Delete..wiki-page-content,.wiki-with-fab,.wiki-content-layout,.wiki-namespace-indexexist only on the reader. Any prose property reached through them is by construction missing in the editor..card. The reader wraps prose in acard, the editor does not; card padding and background rules therefore land on one surface only.How parity is verified
Cheap, mechanical, runs before any wiki frame change is called done:
../sow-nodebb(nix develop --command make dev), open the same wiki page as reader and as editor, and compare computed styles on the.wiki-article-proseelement and a paragraph inside it:font-family,font-size,line-height,max-width,text-align,hyphens,margin-*. Any difference is a bug in the change, not an editor quirk. Then read a paragraph on both, side by side — a computed-style match still misses a broken caret or a shifted first line.Reader-only verification does not count as verification. That law stands.
Follow-up
Cleanup implied by this contract (delete the dead CKEditor block, collapse the duplicated
58reminto--wiki-prose-measure, add the static parity test) is build work, not map work. Filed separately; this map only holds later wiki tickets to the contract above.