@nerd-bible/wordgard 0.6.2-beta4 → 0.6.2-beta6

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/dist/editor.d.ts CHANGED
@@ -375,10 +375,11 @@ declare const enum TileFlag {
375
375
  Composition = 128,
376
376
  Synced = 256,// Node has been synced. DOM content matches child list / text content, child array becomes read-only
377
377
  Atom = 512,// Composite tile whose length isn't determined by child length
378
- HasContent = 1024,// EltTile whose elt has a content hole
379
- AfterContent = 2048,// Tiles that sit after their parent's content position
380
- ContentNotLast = 4096,// EltTile that has children with AfterContent flag
381
- Dirty = 8192
378
+ Uneditable = 1024,// Tile's DOM is uneditable
379
+ HasContent = 2048,// EltTile whose elt has a content hole
380
+ AfterContent = 4096,// Tiles that sit after their parent's content position
381
+ ContentNotLast = 8192,// EltTile that has children with AfterContent flag
382
+ Dirty = 16384
382
383
  }
383
384
  declare const enum Orientation {
384
385
  Row = 0,
@@ -420,14 +421,15 @@ declare abstract class Tile {
420
421
  get boundary(): 0 | 1;
421
422
  get firstChild(): Tile | null;
422
423
  get lastChild(): Tile | null;
423
- get nodeParent(): Tile;
424
424
  ignoreEvent(event: Event): boolean;
425
425
  get ignoreMutations(): boolean;
426
426
  toString(): string;
427
427
  abstract sync(): void;
428
428
  connect(): void;
429
429
  disconnect(reused?: Map<Tile, Reused>): void;
430
- nearestNode(): Tile;
430
+ nearestNode(): Tile & {
431
+ tag: Node$1.Tag;
432
+ };
431
433
  markDirty(): void;
432
434
  posAtCoords(state: GardState, x: number, y: number): CoordPos;
433
435
  abstract posAtCoordsInner(start: number, state: GardState, x: number, y: number, textblock: TextblockMap | null, orientation: Orientation): CoordPos;
@@ -437,6 +439,7 @@ declare class CompositeTile extends Tile {
437
439
  children: Tile[];
438
440
  dom: Element;
439
441
  addChild(child: Tile): void;
442
+ putChild(child: Tile, index: number): void;
440
443
  sync(): void;
441
444
  syncChildren(): void;
442
445
  posAtCoordsInner(start: number, state: GardState, x: number, y: number, textblock: TextblockMap | null, orientation: Orientation): CoordPos;
package/dist/editor.js CHANGED
@@ -202,6 +202,14 @@ class Widget {
202
202
  },
203
203
  editable: true
204
204
  });
205
+ Widget.blockImg = Widget.create({
206
+ render() {
207
+ let img = document.createElement("img");
208
+ img.className = "wg-blockBuffer";
209
+ return img;
210
+ },
211
+ editable: true
212
+ });
205
213
  Widget.br = Widget.create({
206
214
  render() { return document.createElement("br"); },
207
215
  editable: true
@@ -1284,12 +1292,6 @@ class Tile {
1284
1292
  let last = this.children.length - 1;
1285
1293
  return last < 0 ? null : this.children[last];
1286
1294
  }
1287
- get nodeParent() {
1288
- let tile = this;
1289
- while (!tile.tag)
1290
- tile = tile.parent;
1291
- return tile;
1292
- }
1293
1295
  ignoreEvent(event) { return false; }
1294
1296
  get ignoreMutations() { return false; }
1295
1297
  toString() { return this.dom.nodeName + (this.children.length ? `(${this.children})` : ""); }
@@ -1309,8 +1311,8 @@ class Tile {
1309
1311
  return tile;
1310
1312
  }
1311
1313
  markDirty() {
1312
- if (!(this.flags & 8192)) {
1313
- this.flags |= 8192;
1314
+ if (!(this.flags & 16384)) {
1315
+ this.flags |= 16384;
1314
1316
  this.parent?.markDirty();
1315
1317
  }
1316
1318
  }
@@ -1321,10 +1323,10 @@ class Tile {
1321
1323
  static get(node) { return node.wgTile; }
1322
1324
  }
1323
1325
  function checkSync(tile) {
1324
- if ((tile.flags & 256) && !(tile.flags & 8192))
1326
+ if ((tile.flags & 256) && !(tile.flags & 16384))
1325
1327
  return false;
1326
1328
  tile.flags |= 256;
1327
- tile.flags &= -8193;
1329
+ tile.flags &= -16385;
1328
1330
  return true;
1329
1331
  }
1330
1332
  class CompositeTile extends Tile {
@@ -1332,9 +1334,9 @@ class CompositeTile extends Tile {
1332
1334
  addChild(child) {
1333
1335
  if (this.flags & 256)
1334
1336
  throw new Error("Cannot add to a synced tile");
1335
- if ((this.flags & 4096) && !(child.flags & 2048)) {
1337
+ if ((this.flags & 8192) && !(child.flags & 4096)) {
1336
1338
  let i = this.children.length;
1337
- while (i > 0 && (this.children[i - 1].flags & 2048))
1339
+ while (i > 0 && (this.children[i - 1].flags & 4096))
1338
1340
  i--;
1339
1341
  this.children.splice(i, 0, child);
1340
1342
  }
@@ -1343,6 +1345,10 @@ class CompositeTile extends Tile {
1343
1345
  }
1344
1346
  child.parent = this;
1345
1347
  }
1348
+ putChild(child, index) {
1349
+ this.children.splice(index, 0, child);
1350
+ child.parent = this;
1351
+ }
1346
1352
  sync() {
1347
1353
  if (!checkSync(this))
1348
1354
  return;
@@ -1633,7 +1639,7 @@ class DocTile extends CompositeTile {
1633
1639
  parentBefore = before;
1634
1640
  before = before.children[beforeI = before.children.length - 1];
1635
1641
  }
1636
- if (before.isNodeInner && (before.flags & 2048) || (before.flags & 64)) {
1642
+ if (before.isNodeInner && (before.flags & 4096) || (before.flags & 64)) {
1637
1643
  parent = parentBefore;
1638
1644
  i = beforeI;
1639
1645
  continue adjust;
@@ -1645,7 +1651,7 @@ class DocTile extends CompositeTile {
1645
1651
  parentAfter = after;
1646
1652
  after = after.children[afterI = 0];
1647
1653
  }
1648
- if (after.isNodeInner && !(after.flags & 2048) || (after.flags & 32)) {
1654
+ if (after.isNodeInner && !(after.flags & 4096) || (after.flags & 32)) {
1649
1655
  parent = parentAfter;
1650
1656
  i = afterI + 1;
1651
1657
  continue adjust;
@@ -1764,20 +1770,20 @@ class EltTile extends CompositeTile {
1764
1770
  get boundary() { return this._tag && !(this.flags & 512) ? 1 : 0; }
1765
1771
  get tag() { return this._tag; }
1766
1772
  get contentTile() {
1767
- if (!(this.flags & 1024))
1773
+ if (!(this.flags & 2048))
1768
1774
  return null;
1769
1775
  for (let ch of this.children)
1770
- if (ch.isNodeInner && (ch.flags & 1024))
1776
+ if (ch.isNodeInner && (ch.flags & 2048))
1771
1777
  return ch.contentTile;
1772
1778
  return this;
1773
1779
  }
1774
1780
  static of(elt, tag, flags, length, dom) {
1775
1781
  if (elt.hasContent) {
1776
- flags |= 1024;
1782
+ flags |= 2048;
1777
1783
  if (elt.children.length > 1) {
1778
1784
  let zero = elt.children.indexOf(0);
1779
1785
  if (zero > -1 && zero < elt.children.length - 1)
1780
- flags |= 4096;
1786
+ flags |= 8192;
1781
1787
  }
1782
1788
  }
1783
1789
  return new EltTile(elt, tag, flags, length, dom || elt.outerDOM());
@@ -1789,8 +1795,13 @@ function setUneditable(dom) {
1789
1795
  span.appendChild(dom);
1790
1796
  dom = span;
1791
1797
  }
1792
- if (dom.contentEditable == "inherit" && !/^(br|hr|img|input|wbr)$/i.test(dom.nodeName))
1793
- dom.contentEditable = "false";
1798
+ let cur = dom.contentEditable;
1799
+ if (cur == "false")
1800
+ return true;
1801
+ if (cur != "inherit" || !/^(br|hr|img|input|wbr)$/i.test(dom.nodeName))
1802
+ return false;
1803
+ dom.contentEditable = "false";
1804
+ return true;
1794
1805
  }
1795
1806
  class WidgetTile extends Tile {
1796
1807
  widget;
@@ -1949,7 +1960,12 @@ class TilePointer {
1949
1960
  let { tile, index } = this;
1950
1961
  if (tile.isAtom)
1951
1962
  return tile;
1952
- return index < tile.children.length ? tile.children[index] : null;
1963
+ for (; index < tile.children.length; index++) {
1964
+ let next = tile.children[index];
1965
+ if (!(next instanceof WidgetTile && (next.widget == Widget.blockImg || next.widget == Widget.br)))
1966
+ return next;
1967
+ }
1968
+ return null;
1953
1969
  }
1954
1970
  matchingWrapper(elt, spanning, reused) {
1955
1971
  let best, bestScore = 0;
@@ -1987,7 +2003,7 @@ class TilePointer {
1987
2003
  if (!before.isPoint)
1988
2004
  break;
1989
2005
  if (!reused.has(before) && before instanceof WidgetTile && before.widget.eq(widget) &&
1990
- (before.flags & 96) == sideFlag && !(before.flags & 8192)) {
2006
+ (before.flags & 96) == sideFlag && !(before.flags & 16384)) {
1991
2007
  reused.set(before, 1);
1992
2008
  return before;
1993
2009
  }
@@ -2073,7 +2089,7 @@ class ContentUpdate {
2073
2089
  else if (this.new.lastChild instanceof TextTile && !this.new.lastChild.isComposition) {
2074
2090
  this.addText(tile.text.slice(from, to));
2075
2091
  }
2076
- else if (!from && to == tile.text.length && !(tile.flags & 8192) && !this.reused.has(tile)) {
2092
+ else if (!from && to == tile.text.length && !(tile.flags & 16384) && !this.reused.has(tile)) {
2077
2093
  this.reused.set(tile, 1);
2078
2094
  this.new.addChild(tile);
2079
2095
  }
@@ -2242,7 +2258,7 @@ class ContentUpdate {
2242
2258
  if (!(next instanceof TextTile) || this.reused.has(next)) {
2243
2259
  this.addText(node.param);
2244
2260
  }
2245
- else if (next.text == node.param && !(next.flags & 8192)) {
2261
+ else if (next.text == node.param && !(next.flags & 16384)) {
2246
2262
  this.reused.set(next, 1);
2247
2263
  this.new.addChild(next);
2248
2264
  }
@@ -2290,9 +2306,10 @@ class ContentUpdate {
2290
2306
  : null;
2291
2307
  if (!tile) {
2292
2308
  let dom = widget.render(this.wg);
2293
- if (!widget.type.editable)
2294
- setUneditable(dom);
2295
- tile = new WidgetTile(widget, null, 16 | sideFlag, dom);
2309
+ let flags = 16 | sideFlag;
2310
+ if (!widget.type.editable && setUneditable(dom))
2311
+ flags |= 1024;
2312
+ tile = new WidgetTile(widget, null, flags, dom);
2296
2313
  if (widget.type.connect)
2297
2314
  this.toConnect.push(tile);
2298
2315
  }
@@ -2329,27 +2346,33 @@ class ContentUpdate {
2329
2346
  }
2330
2347
  buildNodeShape(tag, length, shape, reuse, inEditable = true, afterContent = 0) {
2331
2348
  if (shape instanceof Elt) {
2349
+ let flags = (tag ? (shape.hasContent ? 0 : 512)
2350
+ : 1 | (shape.hasContent ? 0 : 16)) | afterContent;
2332
2351
  if (inEditable && !shape.hasContent) {
2333
- if (Attributes.get(shape.attrs, "contenteditable") == null && !/^(br|hr|img|input|wbr)$/i.test(shape.tagName))
2352
+ let contentEd = Attributes.get(shape.attrs, "contenteditable");
2353
+ if (contentEd == null && !/^(br|hr|img|input|wbr)$/i.test(shape.tagName)) {
2334
2354
  shape = Elt.create(shape.tagName, Attributes.merge(shape.attrs, ["contenteditable", "false"]), shape.children);
2355
+ flags |= 1024;
2356
+ }
2357
+ else if (contentEd == "false") {
2358
+ flags |= 1024;
2359
+ }
2335
2360
  inEditable = false;
2336
2361
  }
2337
2362
  let reusable, dom, strict = true;
2338
2363
  if (reusable = this.findReusableTile(shape, reuse, strict) || this.findReusableTile(shape, reuse, strict = false)) {
2339
2364
  this.reused.set(reusable, 2);
2340
2365
  dom = reusable.dom;
2341
- if (reusable.flags & 8192)
2366
+ if (reusable.flags & 16384)
2342
2367
  updateAttributes(dom, takeAttributes(reusable.dom), shape.attrs);
2343
2368
  else if (!strict)
2344
2369
  updateAttributes(dom, reusable.elt.attrs, shape.attrs);
2345
2370
  }
2346
- let flags = (tag ? (shape.hasContent ? 0 : 512)
2347
- : 1 | (shape.hasContent ? 0 : 16)) | afterContent;
2348
2371
  let tile = EltTile.of(shape, tag, flags, tag ? length : 0, dom);
2349
2372
  let afterContentInner = 0;
2350
2373
  for (let ch of shape.children) {
2351
2374
  if (ch === 0) {
2352
- afterContentInner = 2048;
2375
+ afterContentInner = 4096;
2353
2376
  tile.flags |= 2;
2354
2377
  }
2355
2378
  else {
@@ -2358,8 +2381,7 @@ class ContentUpdate {
2358
2381
  }
2359
2382
  return tile;
2360
2383
  }
2361
- else {
2362
- let reusable, dom;
2384
+ else { let reusable, dom;
2363
2385
  if (reusable = this.findReusableTile(shape, reuse, false)) {
2364
2386
  this.reused.set(reusable, 2);
2365
2387
  dom = reusable.dom;
@@ -2367,9 +2389,9 @@ class ContentUpdate {
2367
2389
  else {
2368
2390
  dom = shape.render(this.wg);
2369
2391
  }
2370
- if (inEditable && !shape.type.editable)
2371
- setUneditable(dom);
2372
2392
  let flags = (tag ? 512 : 16 | 1) | afterContent;
2393
+ if (inEditable && !shape.type.editable && setUneditable(dom))
2394
+ flags |= 1024;
2373
2395
  let tile = new WidgetTile(shape, tag, flags, dom, tag ? length : 0);
2374
2396
  if (shape.type.connect)
2375
2397
  this.toConnect.push(tile);
@@ -2382,25 +2404,26 @@ class ContentUpdate {
2382
2404
  if (tile.isNodeOuter)
2383
2405
  for (let child of tile.children)
2384
2406
  if (child.isNodeInner) {
2385
- copy.addChild((child.flags & 1024) ? this.copyEltStructure(child) : child);
2407
+ copy.addChild((child.flags & 2048) ? this.copyEltStructure(child) : child);
2386
2408
  }
2387
2409
  return copy;
2388
2410
  }
2389
- ensureHackNode() {
2390
- let tile = this.new;
2391
- if (!tile.isPlotContent)
2392
- return;
2393
- while (tile.isNodeInner)
2394
- tile = tile.parent;
2395
- let tag = tile.tag;
2396
- if (!tag || !tag.isPlot || !(tag.isTextblock || tag.type.isInline))
2397
- return;
2411
+ ensureHackNodes() {
2412
+ if (this.new.isPlotContent || this.new.isWrapper) {
2413
+ let { tag } = this.new.nearestNode();
2414
+ if (this.new.isPlotContent && tag.isPlot && (tag.isTextblock || tag.type.isInline))
2415
+ this.ensureTrailingHackNode(this.new);
2416
+ if (tag.isPlot && !tag.inlineContent)
2417
+ this.ensureBlockSeparators(this.new);
2418
+ }
2419
+ }
2420
+ ensureTrailingHackNode(target) {
2398
2421
  let hasHack = -1, needsHack = true;
2399
- for (let parent = this.new, i = parent.children.length;;) {
2422
+ for (let parent = target, i = parent.children.length;;) {
2400
2423
  if (i > 0) {
2401
2424
  let next = parent.children[--i];
2402
2425
  if (next.isNodeInner || next instanceof WidgetTile && !next.widget.type.inFlow) ;
2403
- else if (next instanceof WidgetTile && next.widget == Widget.br && parent == this.new) {
2426
+ else if (next instanceof WidgetTile && next.widget == Widget.br && parent == target) {
2404
2427
  hasHack = i;
2405
2428
  }
2406
2429
  else if (next.dom.nodeName == "BR") {
@@ -2415,7 +2438,7 @@ class ContentUpdate {
2415
2438
  break;
2416
2439
  }
2417
2440
  }
2418
- else if (parent == this.new) {
2441
+ else if (parent == target) {
2419
2442
  break;
2420
2443
  }
2421
2444
  else {
@@ -2425,14 +2448,32 @@ class ContentUpdate {
2425
2448
  }
2426
2449
  if (hasHack > -1) {
2427
2450
  if (!needsHack)
2428
- this.new.children.splice(hasHack, 1);
2451
+ target.children.splice(hasHack, 1);
2429
2452
  }
2430
2453
  else if (needsHack) {
2431
- this.new.addChild(new WidgetTile(Widget.br, null, 16 | 64, Widget.br.render(this.wg)));
2454
+ target.addChild(new WidgetTile(Widget.br, null, 16 | 64, Widget.br.render(this.wg)));
2455
+ }
2456
+ }
2457
+ ensureBlockSeparators(target) {
2458
+ for (let i = 0, prev = null;; i++) {
2459
+ let next = i == target.children.length ? null : target.children[i];
2460
+ if (next && next.isNodeInner)
2461
+ continue;
2462
+ if (!next && !prev)
2463
+ break;
2464
+ if ((next || prev) &&
2465
+ (!next || ((next.flags & 1024) && !(next.flags & 32))) &&
2466
+ (!prev || ((prev.flags & 1024) && !(prev.flags & 64)))) {
2467
+ let widget = new WidgetTile(Widget.blockImg, null, 16 | 64, Widget.blockImg.render(this.wg));
2468
+ target.putChild(widget, i++);
2469
+ }
2470
+ if (!next)
2471
+ break;
2472
+ prev = next;
2432
2473
  }
2433
2474
  }
2434
2475
  up() {
2435
- this.ensureHackNode();
2476
+ this.ensureHackNodes();
2436
2477
  this.new = this.new.parent;
2437
2478
  }
2438
2479
  leaveNode() {
@@ -2515,7 +2556,7 @@ class ContentUpdate {
2515
2556
  finish() {
2516
2557
  while (!(this.new instanceof DocTile))
2517
2558
  this.up();
2518
- this.ensureHackNode();
2559
+ this.ensureHackNodes();
2519
2560
  return this.new;
2520
2561
  }
2521
2562
  }
@@ -2917,6 +2958,9 @@ const baseStyles = /*@__PURE__*/buildTheme("." + styleID, {
2917
2958
  verticalAlign: "bottom",
2918
2959
  height: "1em",
2919
2960
  },
2961
+ ".wg-blockBuffer": {
2962
+ position: "absolute"
2963
+ },
2920
2964
  "wg-placeholder": {
2921
2965
  opacity: "0.6",
2922
2966
  display: "inline-block",
@@ -5209,7 +5253,7 @@ class Wordgard {
5209
5253
  }));
5210
5254
  }
5211
5255
  static label(label) {
5212
- return Wordgard.editorAttributes.of(typeof label == "string" ? { "aria-label": label }
5256
+ return Wordgard.contentAttributes.of(typeof label == "string" ? { "aria-label": label }
5213
5257
  : (wg => ({ "aria-label": label(wg.state) })));
5214
5258
  }
5215
5259
  static clipboardOutputFilter = clipboardOutputFilter;
package/dist/state.d.ts CHANGED
@@ -492,7 +492,7 @@ declare namespace Transaction {
492
492
  scrollIntoView?: boolean;
493
493
  /**
494
494
  Only meaningful for specs that are combined with another
495
- transaction spec (via {@link Transaction.merge or by being
495
+ transaction spec (via {@link Transaction.merge} or by being
496
496
  returned from an {@link Transaction.extender extender}.
497
497
  Normally, when specs are combined, the positions in `changes`
498
498
  are taken to refer to the document positions in the initial
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nerd-bible/wordgard",
3
- "version": "0.6.2-beta4",
3
+ "version": "0.6.2-beta6",
4
4
  "description": "Semantic rich text editor system",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",