tosijs-styled-editor 0.5.2 → 0.6.0

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.
@@ -36,7 +36,23 @@
36
36
  * comma in `hello,` takes the comma and stopping inside `hello` does not —
37
37
  * "as necessary" falls out rather than needing a rule.
38
38
  */
39
- export declare function stickySelectionBounds(text: string, anchor: number, head: number): {
39
+ export declare function stickySelectionBounds(text: string, anchor: number, head: number,
40
+ /**
41
+ * Has the drag left the word it began in? Defaults to asking in LOGICAL
42
+ * offsets, which is right whenever visual and logical order agree.
43
+ *
44
+ * They do not agree inside a bidi run, and that made short runs unselectable
45
+ * by drag. `עברית` inside an English list item is ~43px wide and renders
46
+ * right-to-left, so moving the pointer a few pixels RIGHT walks logically
47
+ * BACKWARDS out of the word — the offset test says "left the word", both ends
48
+ * snap, and the whole run highlights as one block on the first small
49
+ * movement. The same gesture in English stays inside a word long enough to
50
+ * show character precision, which is why only RTL looked broken.
51
+ *
52
+ * The caller measures it against the word's rendered box instead. Same rule,
53
+ * asked in the space the user is actually moving through.
54
+ */
55
+ leftTheAnchorWord?: boolean): {
40
56
  start: number;
41
57
  end: number;
42
58
  };
@@ -54,6 +70,35 @@ export declare class Selectable {
54
70
  root: HTMLElement;
55
71
  selecting: number | false;
56
72
  touchMode: boolean;
73
+ /**
74
+ * When word stickiness applies.
75
+ *
76
+ * `'touch'` by default, because the two pointers want different things. A
77
+ * mouse user expects the platform's own behaviour — character precision, and
78
+ * a double-click when they want a word — and silently rounding their drag out
79
+ * to word boundaries is the editor overriding a gesture they aimed. A
80
+ * fingertip has no such precision to override: snapping is the only way a
81
+ * drag across a word ends up selecting that word.
82
+ *
83
+ * `'always'` restores stickiness for the mouse too, `'never'` turns it off
84
+ * entirely. Read through `stickyApplies`, which also knows which pointer is
85
+ * mid-gesture.
86
+ *
87
+ * HYBRID DEVICES (a Surface Pro, a touchscreen laptop) are the reason this is
88
+ * decided per gesture rather than once per device. Two things make that hold:
89
+ * `touchMode` flips on every `mousedown`/`touchstart`, and the touch
90
+ * listeners are registered `passive: false` so `handleTouchStart` can
91
+ * `preventDefault()` — which is what stops Chrome firing its COMPATIBILITY
92
+ * mouse events after a touch. Without that, a finger would raise
93
+ * `touchstart` (sticky) and then a synthetic `mousedown` (not sticky) and
94
+ * lose stickiness mid-drag. Do not make those listeners passive.
95
+ *
96
+ * A stylus is a MOUSE here: pen input arrives as pointer + compatibility
97
+ * mouse events, not touch events, so a Surface Pen gets character precision.
98
+ * That is the right answer for a precise instrument, but it is a consequence
99
+ * of how the events arrive rather than a decision taken anywhere.
100
+ */
101
+ stickySelection: 'touch' | 'always' | 'never';
57
102
  constructor(root: HTMLElement);
58
103
  private lastHovered;
59
104
  /** A click inside a selection, resolved on mouseup if no drag started */
@@ -85,6 +130,44 @@ export declare class Selectable {
85
130
  } | null;
86
131
  indexOf: (node: Text, offset: number) => number | null;
87
132
  };
133
+ /**
134
+ * Remember where a character-granularity drag began, so the move handler can
135
+ * tell whether the pointer has left the anchor word yet.
136
+ *
137
+ * The mouse and the touch path BOTH call this. They used not to: the anchor
138
+ * was assigned inline in `handleMouseDown`, `handleTouchStart` was written
139
+ * separately, and so word stickiness existed for the mouse and not for the
140
+ * finger — exactly backwards, since a fingertip is the imprecise pointer.
141
+ */
142
+ private setDragAnchor;
143
+ /**
144
+ * Extend a live drag to a point: word-sticky where that applies, otherwise
145
+ * the end bound alone.
146
+ *
147
+ * Shared by the mouse and touch move handlers. Keeping two copies of this is
148
+ * how touch ended up without stickiness, under a comment claiming it was the
149
+ * "same measurement as a mouse drag" — true of `characterAtPoint`, false of
150
+ * the sticky rule, and the comment is what made it look finished.
151
+ */
152
+ extendTo(x: number, y: number, which?: 'start' | 'end'): void;
153
+ /**
154
+ * Begin dragging ONE existing bound, with the OTHER bound as the anchor —
155
+ * what a touch affordance handle does.
156
+ *
157
+ * This exists so a handle drag is the SAME gesture as a drag across text, and
158
+ * therefore gets the same stickiness. The component used to re-implement
159
+ * "move a bound to the character under the pointer" itself, which made it a
160
+ * third copy of the rule: once `Selectable`'s mouse and touch paths were
161
+ * sharing, the handles were the remaining path still doing it the old way, so
162
+ * a phone — where handles ARE how you adjust a selection — saw no snapping no
163
+ * matter what the two paths in here did.
164
+ *
165
+ * `touchMode` is set because a handle only exists as a result of touch, and
166
+ * `stickySelection: 'touch'` has to answer true for it.
167
+ */
168
+ beginBoundDrag(which: 'start' | 'end'): void;
169
+ /** End a handle drag, clearing the anchor as mouseup and touchend do. */
170
+ endBoundDrag(): void;
88
171
  /**
89
172
  * Move BOTH bounds, snapped to word boundaries once the drag has left the
90
173
  * word it started in. Returns false when stickiness does not apply and the
@@ -95,6 +178,26 @@ export declare class Selectable {
95
178
  * falls back — the text index is per-block, and a selection spanning blocks
96
179
  * has bigger units than words anyway.
97
180
  */
181
+ /**
182
+ * Is the pointer still inside the rendered box of the word the drag began in?
183
+ *
184
+ * Measured per LINE BOX (`getClientRects()`), not as one union rect: a word
185
+ * that wraps has two boxes with a huge gap between them, and the union would
186
+ * call the whole intervening area "inside the word".
187
+ *
188
+ * This is the visual half of the sticky rule. Asking it in logical offsets
189
+ * instead is what made a short right-to-left run snap as a single block on
190
+ * the first few pixels of movement — see `stickySelectionBounds`.
191
+ */
192
+ private pointerInAnchorWord;
193
+ /**
194
+ * Does word stickiness apply to the gesture in progress?
195
+ *
196
+ * `touchMode` is per-gesture — false on mousedown, true on touchstart — so
197
+ * one editor answers differently for a finger and for a mouse, which is the
198
+ * point: a hybrid laptop is one document with two pointers.
199
+ */
200
+ private get stickyApplies();
98
201
  private extendSticky;
99
202
  /** Put the bounds around the word containing an offset in a text node. */
100
203
  selectWordAt(node: Text, offset: number): void;
@@ -11,6 +11,27 @@ interface EditableParts extends PartsMap {
11
11
  edgeStart: HTMLElement;
12
12
  edgeEnd: HTMLElement;
13
13
  }
14
+ /**
15
+ * Edge length of a touch affordance, in px. Referenced by the CSS that sizes
16
+ * them AND by the maths that places them — they were two independent 44s, and
17
+ * the placement maths is where that drifts silently.
18
+ */
19
+ export declare const AFFORDANCE_SIZE = 44;
20
+ /**
21
+ * Where the context-menu affordance goes, horizontally, in doc coordinates.
22
+ *
23
+ * The start handle occupies `[startX - size, startX]` on the SAME row as the
24
+ * menu (both sit a handle's height above the first line), so a menu centred on
25
+ * the selection overlaps it whenever the selection is narrower than one
26
+ * handle — which is most selections, since 44px is only a few characters at any
27
+ * normal size. Reported from an iPhone.
28
+ *
29
+ * So: centred when there is room, otherwise forced right of the start handle,
30
+ * otherwise left of it. The collapsed-caret case already placed the menu at
31
+ * exactly `startX`, which is this rule's floor — so both cases go through here
32
+ * now rather than one of them being right by hand.
33
+ */
34
+ export declare function menuAffordanceX(startX: number, endX: number, size: number, maxX: number): number;
14
35
  export declare class TosijsStyledEditor extends WebComponent<EditableParts> {
15
36
  static formAssociated: boolean;
16
37
  static preferredTagName: string;
@@ -110,6 +131,69 @@ export declare class TosijsStyledEditor extends WebComponent<EditableParts> {
110
131
  * new line, a new session.
111
132
  */
112
133
  trackChanges: boolean;
134
+ /**
135
+ * Record a cross-block merge as *blocks out, blocks in* instead of refusing
136
+ * it. **OFF in 0.6.0, and that is a release decision rather than a default.**
137
+ *
138
+ * The representation is sound and the primitive is tested, but RESOLUTION has
139
+ * a confirmed defect: `trackStructuralEdit` asks `trackDeletion` to strike
140
+ * each outgoing block, `trackDeletion` silently declines any block with
141
+ * nothing to mark (empty, inline-wrapper-only, or already fully struck), and
142
+ * nothing reconciles the decline — so accepting such a merge leaves that
143
+ * block standing and anchors the replacement after it:
144
+ *
145
+ * <p>First</p><p></p><p>Third</p> + Delete in the empty block
146
+ * tracking off → <p>First|</p><p>Third</p>
147
+ * tracking on, accepted → <p></p><p>First|</p><p>Third</p>
148
+ *
149
+ * A flag about REVIEW deciding document structure is the one class this
150
+ * release spent five correctness rounds eliminating, so the feature waits for
151
+ * 0.7.0 rather than shipping reachable (board #3107). `rejectChanges()` is
152
+ * correct; accept is the broken half.
153
+ *
154
+ * With it off, a cross-block merge is REFUSED while tracking — `0.5.x`'s
155
+ * behaviour — through `merge-blocks-backward`, `merge-blocks-forward` and
156
+ * `merge-blocks-selection`. Unlike 0.5.x those refusals are not overridable,
157
+ * for the same reason `merge-blocks-not-mergeable` is not: an override that
158
+ * half-applies a gesture is what three earlier rounds kept producing.
159
+ *
160
+ * Turning it on is supported for working ON the feature. It is not a
161
+ * supported configuration for a document you care about.
162
+ */
163
+ trackStructuralEdits: boolean;
164
+ /**
165
+ * When a drag selection snaps to word boundaries: `'touch'` (the default),
166
+ * `'always'` or `'never'`.
167
+ *
168
+ * The default is per-pointer on purpose. A mouse user gets the platform's own
169
+ * behaviour — character precision, double-click for a word — because rounding
170
+ * a drag they aimed out to the nearest words is the editor overriding them. A
171
+ * fingertip has no precision to override, so snapping is what makes a drag
172
+ * across a word select that word. One editor answers differently for the two,
173
+ * which is what a hybrid laptop needs.
174
+ *
175
+ * A getter/setter over the `Selectable`'s own field, so it can be changed at
176
+ * any time and takes effect on the next drag — including before connection,
177
+ * which the creator form (`tosijsStyledEditor({ stickySelection: 'never' })`)
178
+ * relies on.
179
+ *
180
+ * It was a plain field assigned once in `connectedCallback`, which made every
181
+ * post-connection write silently inert while this comment promised otherwise
182
+ * — a host's "snap to words" preference toggle would have been a dead
183
+ * control. Nothing caught it because every test set
184
+ * `Selectable.stickySelection` directly, so deleting the one forwarding line
185
+ * left the suite green (`reviews/0.6.0-pre-release.md`, M-2).
186
+ */
187
+ get stickySelection(): 'touch' | 'always' | 'never';
188
+ set stickySelection(mode: 'touch' | 'always' | 'never');
189
+ /**
190
+ * Holds `stickySelection` until there is a `Selectable` to hold it.
191
+ *
192
+ * No default of its own: `Selectable` declares it, and two copies of one
193
+ * default is how they drift. Before connection the getter reads this, which
194
+ * starts as the same literal only because it is assigned from nowhere else.
195
+ */
196
+ private pendingStickySelection;
113
197
  /**
114
198
  * Identifies this editing session.
115
199
  *
@@ -204,25 +288,127 @@ export declare class TosijsStyledEditor extends WebComponent<EditableParts> {
204
288
  * `detail.reason` names which edit was refused.
205
289
  */
206
290
  /**
207
- * Run a gesture with tracking suspended.
291
+ * Move the bounds markers out of a block that is about to be removed.
292
+ *
293
+ * A block proposed by a structural edit is pure proposal, so rejecting it
294
+ * MUST take the block — but the caret is sitting in it, and an editor with no
295
+ * insertion point silently swallows everything typed into it. So the caret
296
+ * moves to the end of the preceding block, which for a rejected merge is
297
+ * where the restored text now ends.
298
+ */
299
+ private rescueCaretFrom;
300
+ /**
301
+ * Is everything in this block already inside a `<tosi-del>`?
302
+ *
303
+ * Asked before striking a block, so a second pass does not nest a mark
304
+ * inside a mark. It has to look at CONTENT, not element children: the first
305
+ * version tested `firstElementChild.matches(DEL_TAG) && children.length === 1`
306
+ * and so answered "already deleted" for `<p>keep <tosi-del>cut</tosi-del></p>`
307
+ * — the text node is not an element child. The block was then skipped, its
308
+ * surviving text stayed put, and accepting the merge left that text in the
309
+ * document TWICE, once in the original and once in the replacement.
310
+ */
311
+ private isFullyStruck;
312
+ /**
313
+ * A block's content as it would read if MY pending changes were accepted.
314
+ *
315
+ * Cloned, so the original is untouched. Insertions become plain text and
316
+ * deletions really go, so the proposal reads as the document reads NOW —
317
+ * which is what a reviewer is being asked to compare against. Marks are not
318
+ * copied: a copy cannot carry a mark's identity, and the originals keep
319
+ * theirs and stay independently resolvable. Selection chrome is dropped: the
320
+ * caret is placed deliberately at the join afterwards, and a cloned marker
321
+ * would be a second caret.
322
+ */
323
+ private resolvedClone;
324
+ /**
325
+ * A block like `model`, without the selection state stuck to it.
326
+ *
327
+ * `.selected-block` / `.first-block` / `.last-block` describe a selection in
328
+ * flight, not the document, and copying them onto a newly proposed block
329
+ * makes it look selected to every subsequent query.
330
+ */
331
+ private blockLike;
332
+ /**
333
+ * Can this pair of blocks be merged into one block at all?
334
+ *
335
+ * A list is not a paragraph: merging `<ul>` with `<p>` produces loose text as
336
+ * a direct child of the list, and on a grid table the mark becomes a grid
337
+ * item and shifts every `cellIndex`. Reproduced before this guard existed:
338
+ * a Backspace joining a table and a paragraph accepted to a document with
339
+ * the paragraph's text *gone entirely*.
340
+ *
341
+ * v0.5.0 refused every cross-block merge, so replacing that blanket refusal
342
+ * with a tracked merge silently widened what the editor would attempt. The
343
+ * guard has to live on ALL THREE paths — both keystrokes and the selection —
344
+ * which is exactly the kind of "applied at one site, missed at five" shape
345
+ * this subsystem keeps producing.
346
+ */
347
+ private canMergeBlocks;
348
+ /**
349
+ * Record a structural edit the brute-force way: BLOCKS OUT, BLOCKS IN.
350
+ *
351
+ * `blocksOut` are struck whole (`data-block-delete`, so accepting removes
352
+ * them rather than leaving them empty) and one new block is proposed
353
+ * (`data-block-insert`). The gesture shares one `data-change`, so
354
+ * `acceptChanges(id)` / `rejectChanges(id)` resolve it together — one
355
+ * keystroke is one change, the same rule paste follows. That is NOT a claim
356
+ * that a merge is atomic with everything around it: marks already in these
357
+ * blocks keep their own ids.
358
+ *
359
+ * CALLERS must have asked `canMergeBlocks` FIRST — this records, it does not
360
+ * decide, and it does not veto. A merge is an ordinary edit: marks already in
361
+ * these blocks keep their own ids and stay independently resolvable, because
362
+ * privileging a structural edit over a textual one is not this feature's
363
+ * job. What the reviewer sees is the old text and the new text; what ends up
364
+ * in the document is their call.
365
+ *
366
+ * Returns the new mark and its caret; it always records something.
367
+ */
368
+ private trackStructuralEdit;
369
+ /**
370
+ * Announce a structural refusal, and report whether the host overrode it.
208
371
  *
209
- * For the one case where a host has OVERRIDDEN a structural refusal. The
210
- * edit then happens as a plain structural change with no marks — which is
211
- * the only honest reading, since if tracking could have represented it there
212
- * would have been nothing to refuse.
372
+ * `false` means a host called `preventDefault()`. Honoured for the POLICY
373
+ * refusals — `remove-list-item`, `merge-list-items` — where proceeding with
374
+ * the raw edit is a coherent thing to want.
213
375
  *
214
- * Without this the override half-applied: the block merge itself went
215
- * through a raw `caretBlock.remove()` with nothing in `changes`, while the
216
- * character that rides along on the same keystroke was MARKED — leaving the
217
- * document simultaneously mid-merge and mid-proposal, where neither
218
- * accepting nor rejecting reproduces a document either party proposed.
376
+ * Not honoured for `merge-blocks-not-mergeable`, which goes through
377
+ * `refuseMerge`; there is no coherent override for a guard about valid DOM
378
+ * that fires with tracking off. There used to be an `asUntracked` helper for
379
+ * exactly that case, and it is gone with the contract it served: every one of
380
+ * its three call sites was either unreachable or performed a destructive
381
+ * no-op.
219
382
  */
220
- private asUntracked;
221
383
  private refuseStructural;
384
+ /**
385
+ * Stamp a change mark as this editor, this session. One address, so the five
386
+ * that used to write these attributes by hand cannot drift again — and one of
387
+ * them already had (`reviews/0.6.0-dx-review.md`, M-3). The rule lives in
388
+ * `changes.ts`'s `stampMark`, beside the sanitizer it has to apply.
389
+ */
390
+ private stamp;
222
391
  /** Every tracked change, in document order. */
223
392
  get changes(): TrackedChange[];
224
393
  /** Accept one change by id, or every change when given none. */
225
394
  acceptChanges(id?: string): void;
395
+ /**
396
+ * The top-level blocks owned by the block-scoped marks among `targets`.
397
+ *
398
+ * ONE address for what was the same predicate at two — the accept sweep and
399
+ * the reject sweep — and both got it wrong the same way. They took
400
+ * `c.element.parentElement` and kept it only if its parent was the doc. For
401
+ * a NESTED mark that is the wrong element: a struck intermediate proposal is
402
+ * `<p><tosi-del data-block-delete><tosi-ins data-block-insert>…</tosi-ins></tosi-del></p>`,
403
+ * so the insert mark's parent is the `<tosi-del>`, the `<p>` was excluded
404
+ * from the sweep, and rejecting a chain of merges left one stray empty
405
+ * paragraph per intermediate step — in the document and in `value`
406
+ * (`reviews/0.6.0-remediation-rereview.md`, M-2).
407
+ *
408
+ * `block()` already walks to the top-level block, which is both the right
409
+ * answer and the condition the hand-written filter was approximating.
410
+ */
411
+ private blocksOwnedByMarks;
226
412
  /** Reject one change by id, or every change when given none. */
227
413
  rejectChanges(id?: string): void;
228
414
  /**
@@ -469,6 +655,96 @@ export declare class TosijsStyledEditor extends WebComponent<EditableParts> {
469
655
  * Returns the isolate in force, or null when none is needed.
470
656
  */
471
657
  private isolateForTyping;
658
+ /**
659
+ * Refuse a cross-block gesture whose blocks cannot become one block.
660
+ *
661
+ * ONE address, called from both keystroke paths. The previous version was a
662
+ * 17-line block meant to be pasted into each — and it went into `backspace()`
663
+ * TWICE and `forwardDelete()` not at all, so three Delete presses still
664
+ * destroyed a grid table in the untracked default while the commit message
665
+ * said both paths were covered. `grep -c` returned 2 and I read it as one per
666
+ * path; counting occurrences is not verifying placement.
667
+ *
668
+ * It gates the WHOLE gesture, not just the merge: with the check on the merge
669
+ * alone the character deletion ran first, so a refused merge still ate a
670
+ * character of the neighbouring block, unbounded, with no event to observe.
671
+ */
672
+ private refuseIfUnmergeable;
673
+ /**
674
+ * Announce an unmergeable-blocks refusal. **Not overridable**, and the
675
+ * dispatch result is deliberately discarded.
676
+ *
677
+ * `merge-blocks-not-mergeable` is the one refusal about VALID DOM rather than
678
+ * review policy — merging a list or a grid table puts loose text directly
679
+ * inside a `<ul>`, or turns a mark into a grid item and shifts every
680
+ * `cellIndex`. It fires with `trackChanges` OFF as well, where "perform it
681
+ * untracked" means nothing, which is what settles the question: there is no
682
+ * coherent thing for an override to do. The other refusals
683
+ * (`remove-list-item`, `merge-list-items`) are policy and stay overridable
684
+ * through `refuseStructural` directly.
685
+ *
686
+ * It was ACCIDENTALLY non-overridable before, which is worse than either
687
+ * answer: `refuseIfUnmergeable` discarded `refuseStructural`'s return and the
688
+ * only code that read it — an inner `canMergeBlocks` branch — had become
689
+ * unreachable, because by the time it ran the guard had already proved the
690
+ * pair mergeable. So a reader checking "is the override honoured?" found code
691
+ * that honoured it and never learned it could not run, while README promised
692
+ * `preventDefault()` performed the edit untracked
693
+ * (`reviews/0.6.0-pre-release.md`, M-1).
694
+ */
695
+ private refuseMerge;
696
+ /**
697
+ * Record a cross-block merge: both blocks out, one merged block in.
698
+ *
699
+ * `earlier` and `later` are in DOCUMENT order, which the callers have to fix
700
+ * because Backspace looks back and Delete looks forward. One address for the
701
+ * two keystroke paths: they each carried a copy of this, identical down to
702
+ * the comments and differing only in the order of that pair — and the
703
+ * previous generation of that same paste is what put a guard into
704
+ * `backspace()` twice and `forwardDelete()` not at all.
705
+ */
706
+ /**
707
+ * The UNTRACKED cross-block gesture: delete the paragraph break, and nothing
708
+ * else.
709
+ *
710
+ * "And nothing else" is the fix. Both keystroke paths used to delete a
711
+ * CHARACTER first and then merge, so `<p>one</p><p>two</p>` + Backspace at
712
+ * the start of `two` produced **"ontwo"** and Delete at the end of `one`
713
+ * produced **"onewo"** — silent content loss on the shipped default path with
714
+ * the commonest keystroke in a text editor. The tracked path was correct on
715
+ * the identical DOM, because it returns before the character deletion.
716
+ *
717
+ * The rule was already written down one comment above the bug: a deletion
718
+ * that crosses a block boundary deletes a paragraph BREAK, not a character.
719
+ * It had been applied to the REFUSED case (by hoisting `refuseIfUnmergeable`)
720
+ * and never to the allowed one. (`reviews/0.6.0-remediation-rereview.md`,
721
+ * B-1 — pre-existing, found in triage, covered by no test.)
722
+ *
723
+ * Element content follows the same rule: Backspace at the start of a
724
+ * paragraph whose predecessor ends in an `<img>` merges the paragraphs, it
725
+ * does not eat the image.
726
+ */
727
+ private mergeBlocksRaw;
728
+ /**
729
+ * Should this gesture be RECORDED structurally, or refused?
730
+ *
731
+ * One address, so the four dispatch sites cannot disagree — which is the
732
+ * failure this release spent five rounds on. `reason` is the 0.5.x refusal
733
+ * string for the gesture, so a host's existing handler keeps working.
734
+ */
735
+ private mayTrackStructurally;
736
+ private mergeBlocksTracked;
737
+ /**
738
+ * The nearest sibling block in `direction`, skipping this editor's own chrome.
739
+ *
740
+ * The affordance div is a sibling of every block, not a descendant of one, so
741
+ * a naive `previousElementSibling`/`nextElementSibling` finds UI furniture —
742
+ * and did: it parked the caret inside `.touch-affordances`, where
743
+ * `insertionPoint()` still answers non-null and the next keystroke builds
744
+ * text into chrome. Extracted from `rescueCaretFrom`, which had the only
745
+ * copy, before adding a second caller.
746
+ */
747
+ private siblingBlock;
472
748
  /** Delete the character before the caret */
473
749
  private backspace;
474
750
  /** Forward delete */
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const version = "0.5.2";
1
+ export declare const version = "0.6.0";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tosijs-styled-editor",
3
- "version": "0.5.2",
4
- "description": "Rich text editor web component \u2014 no contentEditable, no browser selection APIs",
3
+ "version": "0.6.0",
4
+ "description": "Rich text editor web component — no contentEditable, no browser selection APIs",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/tonioloewald/tosijs-editor.git"
@@ -41,7 +41,16 @@
41
41
  "format": "bun prettier --write .",
42
42
  "haltija": "haltija --name tosijs-editor --port 8702 --server",
43
43
  "tls": "bunx tosijs-dev-certs",
44
- "typecheck": "bun tsc --noEmit --noUnusedLocals --noUnusedParameters"
44
+ "typecheck": "bun tsc --noEmit --noUnusedLocals --noUnusedParameters",
45
+ "test:browser": "bun bin/test-browser.ts",
46
+ "dev:stop": "bun bin/dev-stop.ts",
47
+ "release:ready": "bun ../tosijs-coding-practices/tools/attest.ts",
48
+ "falsify": "bun bin/falsify.ts"
49
+ },
50
+ "releaseDoctor": {
51
+ "attestedLanes": [
52
+ "test:browser"
53
+ ]
45
54
  },
46
55
  "author": "Tonio Loewald",
47
56
  "license": "Apache-2.0",
@@ -52,8 +61,9 @@
52
61
  "devDependencies": {
53
62
  "bun-types": "^1.3.0",
54
63
  "chokidar": "^4.0.3",
55
- "haltija": "1.12.9",
64
+ "haltija": "^1.13.0-beta.1",
56
65
  "happy-dom": "^20.14.0",
66
+ "playwright": "^1.63.0",
57
67
  "prettier": "^2",
58
68
  "tjs-lang": "^0.13.1",
59
69
  "tosijs": "^1.10.1",