wiki-formant 0.76.0 → 0.77.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/README.md CHANGED
@@ -761,6 +761,8 @@ const safe = mapBlockTree(blocks, b => sanitizeCoreLeaf(b, clean), BLOCK_SHAPE);
761
761
 
762
762
  The default list is derived from what the editor nodes in `wiki-formant/tiptap` store — the embed wrappers' data attributes, the tab markup `activateTabGroups` reads back, the table classes — plus the presentational SVG subset the infographics pipeline embeds. Extend it with `tags`, `attributes`, `classes` and `schemesByTag` derived from your stored HTML, never from memory: a list written from memory erases content on the first render.
763
763
 
764
+ A YouTube iframe comes out as the `YouTube` node's markup, `<div data-youtube-video><iframe …></iframe></div>`, whoever wrote it: an agent, an import, a pasted embed code. The editor then opens it as that node, and `base.css` draws it as the same full-width 16:9 player as one the editor wrote, as it does a map embed. Two wikis had drawn that player in their own stylesheets and a third drew any iframe its own way; spacing, corners, borders and the editor's selection ring stay the site's.
765
+
764
766
  Classes pass by name only. Limiting `style` to layout and paint is worth nothing while `class` is free, because every site's own stylesheet ships `fixed inset-0 z-50`, and those draw a fake prompt over the chrome as well as `position` does.
765
767
 
766
768
  ## Image uploads
package/dist/base.css CHANGED
@@ -430,3 +430,15 @@ pre:hover > .code-copy-btn,
430
430
  .stats-filters a { display: inline-block; padding: 0.25em 0.75em; border: 1px solid; border-radius: 9999px; text-decoration: none; }
431
431
  .stats-filters p { margin: 0; opacity: 0.7; }
432
432
  .stats-count { font-variant-numeric: tabular-nums; }
433
+
434
+ /* ---- embeds ------------------------------------------------------------------
435
+ The players the `wiki-formant/tiptap` nodes store, filling their column at a
436
+ screen's proportions. The node writes a width and height onto the iframe,
437
+ which `aspect-ratio` with `height: auto` overrides. Spacing, corners,
438
+ borders and the editor's selection ring are the site's. */
439
+ :is(div[data-youtube-video], .map-embed) iframe {
440
+ display: block;
441
+ width: 100%;
442
+ height: auto;
443
+ aspect-ratio: 16 / 9;
444
+ }
package/dist/sanitize.js CHANGED
@@ -143,8 +143,16 @@ export function createHtmlSanitizer(options = {}) {
143
143
  // Drop the contents of a disallowed <script> or <style>, not just the tags.
144
144
  nonTextTags: ['script', 'style', 'textarea', 'option', 'noscript'],
145
145
  };
146
- return (html) => (!html || !html.includes('<') ? html : sanitizeHtml(html, config));
146
+ return (html) => (!html || !html.includes('<') ? html : asYouTubeNodes(sanitizeHtml(html, config)));
147
147
  }
148
+ // A YouTube player the editor did not write: an agent's, an import's, a pasted
149
+ // embed code. Run over the sanitiser's own output, whose markup is regular.
150
+ const BARE_YOUTUBE = /(<div data-youtube-video>)?(<iframe\b[^>]*\bsrc="https:\/\/www\.youtube(?:-nocookie)?\.com\/embed\/[^"]*"[^>]*><\/iframe>)/g;
151
+ /**
152
+ * Every YouTube iframe in the markup the `YouTube` node stores, so the editor
153
+ * opens it as that node and base.css draws it as one player, whoever wrote it.
154
+ */
155
+ const asYouTubeNodes = (html) => html.includes('youtube') ? html.replace(BARE_YOUTUBE, (all, wrapped, frame) => (wrapped ? all : `<div data-youtube-video>${frame}</div>`)) : html;
148
156
  const each = (v, map) => Array.isArray(v) ? v.map(item => (item && typeof item === 'object' ? map(item) : item)) : v;
149
157
  const str = (v) => typeof v === 'string';
150
158
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wiki-formant",
3
- "version": "0.76.0",
3
+ "version": "0.77.1",
4
4
  "description": "The portable half of a wiki: derived taxonomy and facet controls, a version-negotiating MCP transport, markdown twins, block rendering, a rich-text editor engine, conditional-GET plumbing, and the headers and CSP every origin sends.",
5
5
  "type": "module",
6
6
  "license": "MIT",