u2ui 1.5.3 → 1.5.4
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/el/ico/ico.js +5 -5
- package/el/rte/README.md +53 -13
- package/el/rte/manifest.json +19 -4
- package/el/rte/rte.css +31 -6
- package/el/rte/rte.js +174 -44
- package/el/rte0/README.md +37 -0
- package/el/rte0/manifest.json +33 -0
- package/el/rte0/rte0.css +9 -0
- package/el/rte0/rte0.js +56 -0
- package/el/system/styler.js +2 -0
- package/el/tooltip/tooltip.css +2 -2
- package/js/Placer/Placer.js +2 -1
- package/js/rte/AGENTS.md +142 -0
- package/js/rte/PLAN.md +488 -0
- package/js/rte/README.md +319 -25
- package/js/rte/blocks.js +7 -0
- package/js/rte/breaks.js +6 -0
- package/js/rte/classes.js +7 -0
- package/js/rte/docs/usage.md +845 -0
- package/js/rte/images.js +7 -0
- package/js/rte/link.js +8 -0
- package/js/rte/playground/README.md +95 -0
- package/js/rte/playground/hosts.html +518 -0
- package/js/rte/playground/index.html +824 -0
- package/js/rte/rte.js +56 -5
- package/js/rte/source.js +12 -0
- package/js/rte/src/browser/README.md +40 -0
- package/js/rte/src/browser/range-rect.js +82 -0
- package/js/rte/src/client/README.md +378 -0
- package/js/rte/src/client/blocks.js +38 -0
- package/js/rte/src/client/breaks.js +212 -0
- package/js/rte/src/client/classes.js +48 -0
- package/js/rte/src/client/editor.js +461 -0
- package/js/rte/src/client/external-input.js +47 -0
- package/js/rte/src/client/history.js +13 -0
- package/js/rte/src/client/images.js +275 -0
- package/js/rte/src/client/link.js +572 -0
- package/js/rte/src/client/marks.js +25 -0
- package/js/rte/src/client/source.js +182 -0
- package/js/rte/src/client/structure.js +27 -0
- package/js/rte/src/client/tables.js +162 -0
- package/js/rte/src/client/unstyle.js +32 -0
- package/js/rte/src/command/README.md +517 -0
- package/js/rte/src/command/block-boundary.js +43 -0
- package/js/rte/src/command/block-style.js +120 -0
- package/js/rte/src/command/commands.js +158 -0
- package/js/rte/src/command/delete.js +112 -0
- package/js/rte/src/command/edit.js +72 -0
- package/js/rte/src/command/element.js +45 -0
- package/js/rte/src/command/enter.js +175 -0
- package/js/rte/src/command/fragment.js +76 -0
- package/js/rte/src/command/insert.js +52 -0
- package/js/rte/src/command/list.js +284 -0
- package/js/rte/src/command/mark.js +583 -0
- package/js/rte/src/command/pending-marks.js +216 -0
- package/js/rte/src/command/table.js +207 -0
- package/js/rte/src/command/unstyle.js +248 -0
- package/js/rte/src/config/README.md +96 -0
- package/js/rte/src/config/config.js +127 -0
- package/js/rte/src/core/README.md +41 -0
- package/js/rte/src/core/core.js +156 -0
- package/js/rte/src/history/README.md +83 -0
- package/js/rte/src/history/history.js +283 -0
- package/js/rte/src/input/README.md +155 -0
- package/js/rte/src/input/external-input.js +130 -0
- package/js/rte/src/input/input-pipeline.js +414 -0
- package/js/rte/src/mark/README.md +219 -0
- package/js/rte/src/mark/dom-adapter.js +100 -0
- package/js/rte/src/mark/mark.js +133 -0
- package/js/rte/src/mark/standard.js +76 -0
- package/js/rte/src/model/README.md +71 -0
- package/js/rte/src/model/content-model.js +213 -0
- package/js/rte/src/model/html/README.md +51 -0
- package/js/rte/src/model/html/html-model.js +90 -0
- package/js/rte/src/normalize/execute/README.md +33 -0
- package/js/rte/src/normalize/execute/repair-executor.js +129 -0
- package/js/rte/src/normalize/normalizer/README.md +48 -0
- package/js/rte/src/normalize/normalizer/normalizer.js +141 -0
- package/js/rte/src/normalize/repair/README.md +70 -0
- package/js/rte/src/normalize/repair/repair-planner.js +208 -0
- package/js/rte/src/sanitize/README.md +105 -0
- package/js/rte/src/sanitize/native.js +43 -0
- package/js/rte/src/sanitize/policy.js +202 -0
- package/js/rte/src/selection/README.md +39 -0
- package/js/rte/src/selection/map/README.md +53 -0
- package/js/rte/src/selection/map/point-map.js +307 -0
- package/js/rte/src/selection/ownership/README.md +32 -0
- package/js/rte/src/selection/ownership/ownership.js +42 -0
- package/js/rte/src/selection/point/README.md +34 -0
- package/js/rte/src/selection/point/point.js +83 -0
- package/js/rte/src/selection/range/README.md +38 -0
- package/js/rte/src/selection/range/edit-range.js +223 -0
- package/js/rte/src/selection/snapshot.js +64 -0
- package/js/rte/src/source/README.md +64 -0
- package/js/rte/src/source/source.js +193 -0
- package/js/rte/src/surface/README.md +36 -0
- package/js/rte/src/surface/content.js +16 -0
- package/js/rte/src/surface/surface.js +87 -0
- package/js/rte/src/transaction/README.md +35 -0
- package/js/rte/src/transaction/transaction.js +56 -0
- package/js/rte/src/ui/README.md +255 -0
- package/js/rte/src/ui/chrome.js +214 -0
- package/js/rte/src/ui/handles.js +179 -0
- package/js/rte/src/ui/place.js +25 -0
- package/js/rte/src/ui/toolbar.js +283 -0
- package/js/rte/src/unstyle/README.md +103 -0
- package/js/rte/src/unstyle/unstyle.js +140 -0
- package/js/rte/tables.js +7 -0
- package/js/rte/unstyle.js +8 -0
- package/js/rte0/README.md +37 -0
- package/js/rte0/rte.js +7 -0
- package/js/{rte → rte0}/src/behavior.js +0 -1
- package/js/{rte → rte0}/src/events.js +0 -1
- package/js/{rte → rte0}/src/range.js +0 -2
- package/js/{rte → rte0}/src/ui.items.js +0 -2
- package/js/{rte → rte0}/src/ui.js +0 -1
- package/package.json +1 -1
- package/u2/Element.js +2 -2
- package/u2/plan-scoped-refactoring.md +133 -303
- package/u2/projects.json +18 -2
- package/u2/tools/update.repos.json.js +1 -1
- package/el/qrcode/package.json +0 -22
- /package/js/{rte → rte0}/old/NodeCleaner.js +0 -0
- /package/js/{rte → rte0}/old/Rte/Rte.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/Rte.ui.items.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/Rte.ui.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/crossbrowser.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/font/tinymce.svg +0 -0
- /package/js/{rte → rte0}/old/Rte/font/tinymce.woff +0 -0
- /package/js/{rte → rte0}/old/Rte/helpers.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/htmlparser.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/index.mjs +0 -0
- /package/js/{rte → rte0}/old/Rte/main.css +0 -0
- /package/js/{rte → rte0}/old/old.rte.js +0 -0
- /package/js/{rte → rte0}/old/range-selection.old.js +0 -0
- /package/js/{rte → rte0}/src/fixes.js +0 -0
- /package/js/{rte → rte0}/src/rte.js +0 -0
- /package/js/{rte → rte0}/src/ui/items/ai.js +0 -0
- /package/js/{rte → rte0}/src/ui/items/code.js +0 -0
- /package/js/{rte → rte0}/src/ui/items/undo.js +0 -0
- /package/js/{rte → rte0}/src/util/htmlparser.js +0 -0
- /package/js/{rte → rte0}/src/util/indentHtml.js +0 -0
package/js/rte/images.js
ADDED
package/js/rte/link.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# RTE playground
|
|
2
|
+
|
|
3
|
+
`index.html` is a dependency-free visual client of the real `RepairPlanner`,
|
|
4
|
+
`Normalizer`, `PointMap`, range classes, command registry, and mark commands. It
|
|
5
|
+
contains no alternative editor or normalization implementation.
|
|
6
|
+
|
|
7
|
+
`hosts.html` is a focused live matrix for comparing the convention client
|
|
8
|
+
across block, text, interactive, list, table, and custom editing hosts. It also
|
|
9
|
+
covers links in both nesting directions, non-modal and declarative `show-modal`
|
|
10
|
+
dialogs, `showPopover()` and fullscreen hosts, plain-text editing, empty hosts,
|
|
11
|
+
and non-editable islands. The shared editor chrome follows an active native
|
|
12
|
+
top-layer boundary and returns to the document when that boundary closes.
|
|
13
|
+
It reports registration, resolved host defaults, selection, serialized content,
|
|
14
|
+
and recent native events without turning the observations into cross-browser
|
|
15
|
+
assertions.
|
|
16
|
+
|
|
17
|
+
Open `/u2/js/rte/playground/` through the local HTTP server. Included scenarios
|
|
18
|
+
cover inline runs, generic blocks, redundant wrappers, lists, lift-and-split,
|
|
19
|
+
nested editable isolation, CSS-class marks, and the original invalid `p/div`
|
|
20
|
+
example.
|
|
21
|
+
|
|
22
|
+
## Capabilities
|
|
23
|
+
|
|
24
|
+
- Analyze planned actions without changing DOM.
|
|
25
|
+
- Execute exactly one normalizer operation or run to a fixed point.
|
|
26
|
+
- Change cleanup level and default block through the production CSS custom
|
|
27
|
+
properties; `auto` demonstrates semantic host defaults such as `li` for a
|
|
28
|
+
`ul` editor.
|
|
29
|
+
- Dispatch selected Input Events through the production `InputPipeline` and
|
|
30
|
+
control its `input paste drop command` triggers with `--u2-rte-clean-on`.
|
|
31
|
+
- Observe the prevented-input path: `insertParagraph` and `insertLineBreak` run
|
|
32
|
+
the registered `enter` and `lineBreak` commands instead of native editing;
|
|
33
|
+
structural Backspace uses the same production command as the convention
|
|
34
|
+
client.
|
|
35
|
+
- Apply, remove, or toggle the `.x` mark over a live selection. The toggle
|
|
36
|
+
exposes active, mixed, and caret state; the dedicated scenario makes wrapper
|
|
37
|
+
creation, reuse of an existing inline element, and cleanup of a neutral
|
|
38
|
+
`span` visible in the DOM tree and serialized HTML. At a caret, toggling also
|
|
39
|
+
formats the next ordinary text input through `PendingMarks`.
|
|
40
|
+
- Exercise the convention prototype's full ready toolbar: undo and redo, the
|
|
41
|
+
standard inline marks, bulleted and numbered lists with their nesting levels,
|
|
42
|
+
and a separator. The readout under that surface reports how many history
|
|
43
|
+
entries exist and where it stands, which makes grouping visible — continuous
|
|
44
|
+
typing coalesces into one entry, while each command is its own step.
|
|
45
|
+
- Configure the prototype surface live from the panel beside it: tick the
|
|
46
|
+
controls `--u2-rte-toolbar` lists, and switch the other host properties. A
|
|
47
|
+
change and its effect stay in view at once, and the control names come from
|
|
48
|
+
the registered modules, so the panel cannot drift from what the editor offers.
|
|
49
|
+
- Give a selection one of the host's declared content classes and watch the same
|
|
50
|
+
declaration drive the sanitizer and remove-format.
|
|
51
|
+
- Click the image and drag a corner to resize it, or reset it to its own size.
|
|
52
|
+
- Put the caret in a table cell and use the handles on the table to add or drop
|
|
53
|
+
its rows and columns.
|
|
54
|
+
- Create a link from a selection or edit an existing one from a caret through
|
|
55
|
+
the contextual form, and remove one by emptying its address.
|
|
56
|
+
- Open the surface's HTML in the modal source dialog, syntax highlighted through
|
|
57
|
+
`<u2-code>`, edit it, and apply it as one undo step.
|
|
58
|
+
- Toggle the ready-made bold mark by button or Ctrl/Command+B. The scenario
|
|
59
|
+
exposes `<b>` alias recognition, canonical `<strong>` output, semantic
|
|
60
|
+
removal, and pending bold input at a caret.
|
|
61
|
+
- Exercise the production roaming `Toolbar` with application-owned markup: it
|
|
62
|
+
follows the active surface, reflects command availability and mark state,
|
|
63
|
+
preserves the selection during pointer or keyboard interaction, and uses the
|
|
64
|
+
production collapsed-range geometry in its replaceable placement callback.
|
|
65
|
+
- Exercise the one-import `rte.js` convention client on a visible surface.
|
|
66
|
+
It is opted in only through CSS and exposes its lazy default Bold toolbar,
|
|
67
|
+
optional `blocks.js` value control, context-aware Enter behavior, and the
|
|
68
|
+
optional staged `unstyle.js` action and non-mutating `breaks.js` line-break
|
|
69
|
+
marker without playground-side wiring.
|
|
70
|
+
- Edit content directly or parse serialized HTML through the browser.
|
|
71
|
+
- Compare the live DOM tree with `innerHTML` serialization.
|
|
72
|
+
- Display executed actions, unresolved repairs, and selection endpoints. Green
|
|
73
|
+
anchor and blue focus `┃` markers also show the exact boundary directly in
|
|
74
|
+
the rendered DOM tree; element-boundary carets get their own marker line
|
|
75
|
+
between the affected children.
|
|
76
|
+
- Map and restore a live selection through each normalization run.
|
|
77
|
+
|
|
78
|
+
Scenarios that browsers repair during HTML parsing are constructed with DOM
|
|
79
|
+
methods. The raw HTML button remains available specifically to expose that
|
|
80
|
+
difference.
|
|
81
|
+
|
|
82
|
+
`tests/playground.test.js` loads the complete page in a same-origin frame. It
|
|
83
|
+
checks bootstrapping, pure analysis, one-step selection restoration, complete
|
|
84
|
+
normalization, action reporting, host-specific list defaults, synthetic input
|
|
85
|
+
routing including structural Backspace, and the roaming toolbar. It also drives
|
|
86
|
+
the class-mark controls and checks their exact DOM result in every target
|
|
87
|
+
browser.
|
|
88
|
+
|
|
89
|
+
## TODO
|
|
90
|
+
|
|
91
|
+
- Highlight the nodes affected by the current plan in the editable view.
|
|
92
|
+
- Add scope selection and transaction dirty-scope visualization.
|
|
93
|
+
- Show before/after range boundaries for every individual operation.
|
|
94
|
+
- Export and import minimized custom scenarios as JSON.
|
|
95
|
+
- Add clipboard/drop payload and history panels when those modules exist.
|
|
@@ -0,0 +1,518 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang=en>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset=utf-8>
|
|
5
|
+
<meta name=viewport content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>RTE host matrix</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
color-scheme: light dark;
|
|
10
|
+
font: 14px/1.4 system-ui, sans-serif;
|
|
11
|
+
--border: color-mix(in srgb, CanvasText 25%, transparent);
|
|
12
|
+
--panel: color-mix(in srgb, CanvasText 5%, Canvas);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
* { box-sizing: border-box; }
|
|
16
|
+
body { margin: 0 auto; max-inline-size: 90rem; padding: 1rem; }
|
|
17
|
+
h1 { font-size: 1.35rem; margin-block: 0 .25rem; }
|
|
18
|
+
h2 { font-size: 1.1rem; margin-block: .35rem 0; }
|
|
19
|
+
h3 { font-size: 1rem; margin-block: 0 .65rem; }
|
|
20
|
+
p { margin-block: .35rem .8rem; }
|
|
21
|
+
code, pre { font: .85rem/1.4 ui-monospace, monospace; }
|
|
22
|
+
|
|
23
|
+
.matrix {
|
|
24
|
+
display: grid;
|
|
25
|
+
gap: .8rem;
|
|
26
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
|
|
27
|
+
}
|
|
28
|
+
.group { grid-column: 1 / -1; }
|
|
29
|
+
.case, .inspector {
|
|
30
|
+
background: var(--panel);
|
|
31
|
+
border: 1px solid var(--border);
|
|
32
|
+
border-radius: .4rem;
|
|
33
|
+
min-inline-size: 0;
|
|
34
|
+
padding: .8rem;
|
|
35
|
+
}
|
|
36
|
+
.case[data-active=true] { border-color: Highlight; }
|
|
37
|
+
.case > output {
|
|
38
|
+
display: block;
|
|
39
|
+
margin-block-start: .65rem;
|
|
40
|
+
overflow-wrap: anywhere;
|
|
41
|
+
}
|
|
42
|
+
.shell { margin: 0; padding-inline-start: 1.5rem; }
|
|
43
|
+
.shell-table { border-collapse: collapse; inline-size: 100%; }
|
|
44
|
+
.shell-table :is(th, td) { border: 1px solid var(--border); padding: .35rem; }
|
|
45
|
+
|
|
46
|
+
.rte-host {
|
|
47
|
+
--u2-rte: true;
|
|
48
|
+
--u2-rte-toolbar: undo redo block style bold italic underline strike code link bullets numbers outdent indent rule insertTable imageOriginal unstyle breaks source;
|
|
49
|
+
border: 2px solid color-mix(in srgb, Highlight 48%, var(--border));
|
|
50
|
+
min-block-size: 2.8rem;
|
|
51
|
+
outline: 0;
|
|
52
|
+
padding: .45rem;
|
|
53
|
+
|
|
54
|
+
&:focus { border-color: Highlight; }
|
|
55
|
+
}
|
|
56
|
+
ul.rte-host { padding-inline-start: 2rem; }
|
|
57
|
+
li.rte-host { display: list-item; }
|
|
58
|
+
x-editor.rte-host { display: block; }
|
|
59
|
+
table.rte-host { border-collapse: collapse; inline-size: 100%; }
|
|
60
|
+
table.rte-host :is(th, td) { border: 1px solid var(--border); padding: .35rem; }
|
|
61
|
+
dialog.rte-host[open]:not([data-modal]) { inline-size: 100%; margin: 0; position: static; }
|
|
62
|
+
dialog.rte-host[data-modal] { inline-size: min(30rem, calc(100% - 2rem)); }
|
|
63
|
+
dialog.rte-host::backdrop { background: #0008; }
|
|
64
|
+
.rte-host:popover-open { inline-size: min(30rem, calc(100% - 2rem)); }
|
|
65
|
+
.rte-host:fullscreen { background: Canvas; box-sizing: border-box; padding: 2rem; }
|
|
66
|
+
button.rte-host { color: inherit; font: inherit; inline-size: 100%; text-align: start; }
|
|
67
|
+
a.rte-host, a > .rte-host { display: inline-block; min-inline-size: 10rem; }
|
|
68
|
+
[contenteditable=false] { border: 1px dashed var(--border); padding: .2rem; }
|
|
69
|
+
|
|
70
|
+
.inspector { margin-block-start: .8rem; }
|
|
71
|
+
.inspector header { align-items: center; display: flex; gap: .8rem; justify-content: space-between; }
|
|
72
|
+
.inspector h2 { font-size: 1rem; margin: 0; }
|
|
73
|
+
.inspector h3 { font-size: .9rem; font-weight: 500; margin: 0; }
|
|
74
|
+
.inspector button { font: inherit; }
|
|
75
|
+
.readout {
|
|
76
|
+
display: grid;
|
|
77
|
+
gap: .8rem;
|
|
78
|
+
grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr));
|
|
79
|
+
margin-block-start: .7rem;
|
|
80
|
+
}
|
|
81
|
+
pre {
|
|
82
|
+
background: Canvas;
|
|
83
|
+
border: 1px solid var(--border);
|
|
84
|
+
margin: .25rem 0 0;
|
|
85
|
+
min-block-size: 5rem;
|
|
86
|
+
overflow: auto;
|
|
87
|
+
padding: .5rem;
|
|
88
|
+
white-space: pre-wrap;
|
|
89
|
+
}
|
|
90
|
+
</style>
|
|
91
|
+
</head>
|
|
92
|
+
<body>
|
|
93
|
+
<nav><a href=index.html>Normalization playground</a></nav>
|
|
94
|
+
<h1>RTE host matrix</h1>
|
|
95
|
+
<p>
|
|
96
|
+
Focus and edit every surface, especially with Enter and Backspace. These
|
|
97
|
+
are representative content models rather than a whitelist of supported
|
|
98
|
+
tags. Link activation and element-specific browser behavior remain native.
|
|
99
|
+
</p>
|
|
100
|
+
|
|
101
|
+
<main class=matrix>
|
|
102
|
+
<h2 class=group>Block containers</h2>
|
|
103
|
+
|
|
104
|
+
<section class=case>
|
|
105
|
+
<h3><code><div contenteditable></code></h3>
|
|
106
|
+
<div class=rte-host contenteditable data-name=div>Editable generic block</div>
|
|
107
|
+
<output></output>
|
|
108
|
+
</section>
|
|
109
|
+
|
|
110
|
+
<section class=case>
|
|
111
|
+
<h3><code><article contenteditable></code></h3>
|
|
112
|
+
<article class=rte-host contenteditable data-name=article>Editable article</article>
|
|
113
|
+
<output></output>
|
|
114
|
+
</section>
|
|
115
|
+
|
|
116
|
+
<section class=case>
|
|
117
|
+
<h3><code><blockquote contenteditable></code></h3>
|
|
118
|
+
<blockquote class=rte-host contenteditable data-name=blockquote>Editable quotation</blockquote>
|
|
119
|
+
<output></output>
|
|
120
|
+
</section>
|
|
121
|
+
|
|
122
|
+
<section class=case>
|
|
123
|
+
<h3><code><figure contenteditable></code></h3>
|
|
124
|
+
<figure class=rte-host contenteditable data-name=figure>Editable figure content</figure>
|
|
125
|
+
<output></output>
|
|
126
|
+
</section>
|
|
127
|
+
|
|
128
|
+
<section class=case>
|
|
129
|
+
<h3><code><figcaption contenteditable></code></h3>
|
|
130
|
+
<figure>
|
|
131
|
+
<figcaption class=rte-host contenteditable data-name=figcaption>Editable caption</figcaption>
|
|
132
|
+
</figure>
|
|
133
|
+
<output></output>
|
|
134
|
+
</section>
|
|
135
|
+
|
|
136
|
+
<section class=case>
|
|
137
|
+
<h3><code><details contenteditable></code></h3>
|
|
138
|
+
<details class=rte-host contenteditable data-name=details open>
|
|
139
|
+
<summary>Editable summary in host</summary>
|
|
140
|
+
Editable details content
|
|
141
|
+
</details>
|
|
142
|
+
<output></output>
|
|
143
|
+
</section>
|
|
144
|
+
|
|
145
|
+
<section class=case>
|
|
146
|
+
<h3><code><x-editor contenteditable></code></h3>
|
|
147
|
+
<x-editor class=rte-host contenteditable data-name=custom>Editable custom element</x-editor>
|
|
148
|
+
<output></output>
|
|
149
|
+
</section>
|
|
150
|
+
|
|
151
|
+
<h2 class=group>Text and interactive hosts</h2>
|
|
152
|
+
|
|
153
|
+
<section class=case>
|
|
154
|
+
<h3><code><p contenteditable></code></h3>
|
|
155
|
+
<p class=rte-host contenteditable data-name=paragraph>Editable paragraph host</p>
|
|
156
|
+
<output></output>
|
|
157
|
+
</section>
|
|
158
|
+
|
|
159
|
+
<section class=case>
|
|
160
|
+
<h3><code><h2 contenteditable></code></h3>
|
|
161
|
+
<h2 class=rte-host contenteditable data-name=heading>Editable heading host</h2>
|
|
162
|
+
<output></output>
|
|
163
|
+
</section>
|
|
164
|
+
|
|
165
|
+
<section class=case>
|
|
166
|
+
<h3><code><pre contenteditable></code></h3>
|
|
167
|
+
<pre class=rte-host contenteditable data-name=pre>Editable preformatted host</pre>
|
|
168
|
+
<output></output>
|
|
169
|
+
</section>
|
|
170
|
+
|
|
171
|
+
<section class=case>
|
|
172
|
+
<h3><code><span contenteditable></code></h3>
|
|
173
|
+
<span class=rte-host contenteditable data-name=span>Editable inline host</span>
|
|
174
|
+
<output></output>
|
|
175
|
+
</section>
|
|
176
|
+
|
|
177
|
+
<section class=case>
|
|
178
|
+
<h3><code><code contenteditable></code></h3>
|
|
179
|
+
<code class=rte-host contenteditable data-name=code>Editable code host</code>
|
|
180
|
+
<output></output>
|
|
181
|
+
</section>
|
|
182
|
+
|
|
183
|
+
<section class=case>
|
|
184
|
+
<h3><code><label contenteditable></code></h3>
|
|
185
|
+
<label for="native-input" class=rte-host contenteditable data-name=label>Editable label host</label>
|
|
186
|
+
<input id="native-input" type=text placeholder="Native input" />
|
|
187
|
+
<output></output>
|
|
188
|
+
</section>
|
|
189
|
+
|
|
190
|
+
<section class=case>
|
|
191
|
+
<h3><code><output contenteditable></code></h3>
|
|
192
|
+
<p><output class=rte-host contenteditable data-name=output>Editable output host</output></p>
|
|
193
|
+
<output></output>
|
|
194
|
+
</section>
|
|
195
|
+
|
|
196
|
+
<section class=case>
|
|
197
|
+
<h3><code><summary contenteditable></code></h3>
|
|
198
|
+
<details open>
|
|
199
|
+
<summary class=rte-host contenteditable data-name=summary>Editable summary host</summary>
|
|
200
|
+
Non-editable details content
|
|
201
|
+
</details>
|
|
202
|
+
<output></output>
|
|
203
|
+
</section>
|
|
204
|
+
|
|
205
|
+
<section class=case>
|
|
206
|
+
<h3><code><button contenteditable></code></h3>
|
|
207
|
+
<button class=rte-host contenteditable data-name=button type=button>Editable button</button>
|
|
208
|
+
<output></output>
|
|
209
|
+
</section>
|
|
210
|
+
|
|
211
|
+
<section class=case id=links>
|
|
212
|
+
<h3><code><a contenteditable></code></h3>
|
|
213
|
+
<a class=rte-host contenteditable data-name=link href=#links>Editable link host</a>
|
|
214
|
+
<output></output>
|
|
215
|
+
</section>
|
|
216
|
+
|
|
217
|
+
<section class=case>
|
|
218
|
+
<h3><code><a> <span contenteditable></code></h3>
|
|
219
|
+
<a href=#links>
|
|
220
|
+
Before <span class=rte-host contenteditable data-name=inside-link>editable host</span> after
|
|
221
|
+
</a>
|
|
222
|
+
<output></output>
|
|
223
|
+
</section>
|
|
224
|
+
|
|
225
|
+
<section class=case>
|
|
226
|
+
<h3><code><div contenteditable> <a></code></h3>
|
|
227
|
+
<div class=rte-host contenteditable data-name=around-link>
|
|
228
|
+
Editable host around <a href=#links>a link</a>
|
|
229
|
+
</div>
|
|
230
|
+
<output></output>
|
|
231
|
+
</section>
|
|
232
|
+
|
|
233
|
+
<h2 class=group>Lists</h2>
|
|
234
|
+
|
|
235
|
+
<section class=case>
|
|
236
|
+
<h3><code><ul contenteditable></code></h3>
|
|
237
|
+
<ul class=rte-host contenteditable data-name=ul>
|
|
238
|
+
<li>First item
|
|
239
|
+
<li>Second item
|
|
240
|
+
</ul>
|
|
241
|
+
<output></output>
|
|
242
|
+
</section>
|
|
243
|
+
|
|
244
|
+
<section class=case>
|
|
245
|
+
<h3><code><ol contenteditable></code></h3>
|
|
246
|
+
<ol class=rte-host contenteditable data-name=ol>
|
|
247
|
+
<li>First item
|
|
248
|
+
<li>Second item
|
|
249
|
+
</ol>
|
|
250
|
+
<output></output>
|
|
251
|
+
</section>
|
|
252
|
+
|
|
253
|
+
<section class=case>
|
|
254
|
+
<h3><code><li contenteditable></code></h3>
|
|
255
|
+
<ul class=shell>
|
|
256
|
+
<li class=rte-host contenteditable data-name=li>Editable list item
|
|
257
|
+
</ul>
|
|
258
|
+
<output></output>
|
|
259
|
+
</section>
|
|
260
|
+
|
|
261
|
+
<section class=case>
|
|
262
|
+
<h3><code><dl contenteditable></code></h3>
|
|
263
|
+
<dl class=rte-host contenteditable data-name=description-list>
|
|
264
|
+
<dt>Term
|
|
265
|
+
<dd>Description
|
|
266
|
+
</dl>
|
|
267
|
+
<output></output>
|
|
268
|
+
</section>
|
|
269
|
+
|
|
270
|
+
<section class=case>
|
|
271
|
+
<h3><code><dt contenteditable></code></h3>
|
|
272
|
+
<dl>
|
|
273
|
+
<dt class=rte-host contenteditable data-name=term>Editable term
|
|
274
|
+
<dd>Description
|
|
275
|
+
</dl>
|
|
276
|
+
<output></output>
|
|
277
|
+
</section>
|
|
278
|
+
|
|
279
|
+
<section class=case>
|
|
280
|
+
<h3><code><dd contenteditable></code></h3>
|
|
281
|
+
<dl>
|
|
282
|
+
<dt>Term
|
|
283
|
+
<dd class=rte-host contenteditable data-name=description>Editable description
|
|
284
|
+
</dl>
|
|
285
|
+
<output></output>
|
|
286
|
+
</section>
|
|
287
|
+
|
|
288
|
+
<h2 class=group>Tables</h2>
|
|
289
|
+
|
|
290
|
+
<section class=case>
|
|
291
|
+
<h3><code><table contenteditable></code></h3>
|
|
292
|
+
<table class=rte-host contenteditable data-name=table>
|
|
293
|
+
<tbody>
|
|
294
|
+
<tr><th>One<th>Two
|
|
295
|
+
<tr><td>Alpha<td>Beta
|
|
296
|
+
</tbody>
|
|
297
|
+
</table>
|
|
298
|
+
<output></output>
|
|
299
|
+
</section>
|
|
300
|
+
|
|
301
|
+
<section class=case>
|
|
302
|
+
<h3><code><thead contenteditable></code></h3>
|
|
303
|
+
<table class=shell-table>
|
|
304
|
+
<thead class=rte-host contenteditable data-name=thead><tr><th>Editable head<th>Second cell
|
|
305
|
+
<tbody><tr><td>Body<td>Body
|
|
306
|
+
</table>
|
|
307
|
+
<output></output>
|
|
308
|
+
</section>
|
|
309
|
+
|
|
310
|
+
<section class=case>
|
|
311
|
+
<h3><code><tbody contenteditable></code></h3>
|
|
312
|
+
<table class=shell-table>
|
|
313
|
+
<tbody class=rte-host contenteditable data-name=tbody><tr><td>Editable body<td>Second cell
|
|
314
|
+
</table>
|
|
315
|
+
<output></output>
|
|
316
|
+
</section>
|
|
317
|
+
|
|
318
|
+
<section class=case>
|
|
319
|
+
<h3><code><tfoot contenteditable></code></h3>
|
|
320
|
+
<table class=shell-table>
|
|
321
|
+
<tbody><tr><td>Body<td>Body
|
|
322
|
+
<tfoot class=rte-host contenteditable data-name=tfoot><tr><td>Editable foot<td>Second cell
|
|
323
|
+
</table>
|
|
324
|
+
<output></output>
|
|
325
|
+
</section>
|
|
326
|
+
|
|
327
|
+
<section class=case>
|
|
328
|
+
<h3><code><tr contenteditable></code></h3>
|
|
329
|
+
<table class=shell-table>
|
|
330
|
+
<tbody><tr class=rte-host contenteditable data-name=row><td>Editable row<td>Second cell
|
|
331
|
+
</table>
|
|
332
|
+
<output></output>
|
|
333
|
+
</section>
|
|
334
|
+
|
|
335
|
+
<section class=case>
|
|
336
|
+
<h3><code><th contenteditable></code></h3>
|
|
337
|
+
<table class=shell-table>
|
|
338
|
+
<tbody><tr><th class=rte-host contenteditable data-name=header-cell>Editable header cell<th>Peer
|
|
339
|
+
</table>
|
|
340
|
+
<output></output>
|
|
341
|
+
</section>
|
|
342
|
+
|
|
343
|
+
<section class=case>
|
|
344
|
+
<h3><code><td contenteditable></code></h3>
|
|
345
|
+
<table class=shell-table>
|
|
346
|
+
<tbody><tr><td class=rte-host contenteditable data-name=cell>Editable cell<td>Peer
|
|
347
|
+
</table>
|
|
348
|
+
<output></output>
|
|
349
|
+
</section>
|
|
350
|
+
|
|
351
|
+
<section class=case>
|
|
352
|
+
<h3><code><caption contenteditable></code></h3>
|
|
353
|
+
<table class=shell-table>
|
|
354
|
+
<caption class=rte-host contenteditable data-name=caption>Editable table caption</caption>
|
|
355
|
+
<tbody><tr><td>Body<td>Body
|
|
356
|
+
</table>
|
|
357
|
+
<output></output>
|
|
358
|
+
</section>
|
|
359
|
+
|
|
360
|
+
<h2 class=group>Dialogs and editing boundaries</h2>
|
|
361
|
+
|
|
362
|
+
<section class=case>
|
|
363
|
+
<h3><code><dialog open contenteditable></code></h3>
|
|
364
|
+
<dialog class=rte-host contenteditable data-name=dialog open>Editable non-modal dialog</dialog>
|
|
365
|
+
<output></output>
|
|
366
|
+
</section>
|
|
367
|
+
|
|
368
|
+
<section class=case>
|
|
369
|
+
<h3><code>command="show-modal"</code></h3>
|
|
370
|
+
<button commandfor=modal-host command=show-modal type=button>Show modal editor</button>
|
|
371
|
+
<dialog class=rte-host contenteditable data-name=modal-dialog data-modal id=modal-host tabindex=-1>
|
|
372
|
+
<p>Edit this modal dialog.</p>
|
|
373
|
+
<button commandfor=modal-host command=close contenteditable=false type=button>Close</button>
|
|
374
|
+
</dialog>
|
|
375
|
+
<output></output>
|
|
376
|
+
</section>
|
|
377
|
+
|
|
378
|
+
<section class=case>
|
|
379
|
+
<h3><code>showPopover()</code></h3>
|
|
380
|
+
<button id=show-popover-host type=button>Show popover editor</button>
|
|
381
|
+
<div class=rte-host contenteditable data-name=popover id=popover-host popover=manual tabindex=-1>
|
|
382
|
+
Edit this popover host.
|
|
383
|
+
<button popovertarget=popover-host popovertargetaction=hide contenteditable=false type=button>Close</button>
|
|
384
|
+
</div>
|
|
385
|
+
<output></output>
|
|
386
|
+
</section>
|
|
387
|
+
|
|
388
|
+
<section class=case>
|
|
389
|
+
<h3><code>requestFullscreen()</code></h3>
|
|
390
|
+
<button id=show-fullscreen-host type=button>Show fullscreen editor</button>
|
|
391
|
+
<div class=rte-host contenteditable data-name=fullscreen id=fullscreen-host tabindex=-1>
|
|
392
|
+
<p>Edit this fullscreen host.</p>
|
|
393
|
+
<button id=hide-fullscreen-host contenteditable=false type=button>Exit fullscreen</button>
|
|
394
|
+
</div>
|
|
395
|
+
<output></output>
|
|
396
|
+
</section>
|
|
397
|
+
|
|
398
|
+
<section class=case>
|
|
399
|
+
<h3><code>contenteditable="plaintext-only"</code></h3>
|
|
400
|
+
<div class=rte-host contenteditable=plaintext-only data-name=plain-text>Native plain-text host</div>
|
|
401
|
+
<output></output>
|
|
402
|
+
</section>
|
|
403
|
+
|
|
404
|
+
<section class=case>
|
|
405
|
+
<h3><code>contenteditable="false"</code> island</h3>
|
|
406
|
+
<div class=rte-host contenteditable data-name=false-island>
|
|
407
|
+
Editable before <span contenteditable=false>fixed island</span> editable after
|
|
408
|
+
</div>
|
|
409
|
+
<output></output>
|
|
410
|
+
</section>
|
|
411
|
+
|
|
412
|
+
<section class=case>
|
|
413
|
+
<h3>Empty editing host</h3>
|
|
414
|
+
<div class=rte-host contenteditable data-name=empty></div>
|
|
415
|
+
<output></output>
|
|
416
|
+
</section>
|
|
417
|
+
</main>
|
|
418
|
+
|
|
419
|
+
<section class=inspector>
|
|
420
|
+
<header>
|
|
421
|
+
<h2>Live inspector</h2>
|
|
422
|
+
<button id=clear type=button>Clear events</button>
|
|
423
|
+
</header>
|
|
424
|
+
<div class=readout>
|
|
425
|
+
<section><h3>Active surface</h3><pre id=active>None — focus a surface.</pre></section>
|
|
426
|
+
<section><h3>Selection</h3><pre id=selection>None</pre></section>
|
|
427
|
+
<section><h3>HTML</h3><pre id=html>None</pre></section>
|
|
428
|
+
<section><h3>Recent events</h3><pre id=events>None</pre></section>
|
|
429
|
+
</div>
|
|
430
|
+
</section>
|
|
431
|
+
|
|
432
|
+
<script type=module>
|
|
433
|
+
import {config, rte, Source} from '../rte.js';
|
|
434
|
+
|
|
435
|
+
const hosts = [...document.querySelectorAll('.rte-host')];
|
|
436
|
+
const events = [];
|
|
437
|
+
const active = document.querySelector('#active');
|
|
438
|
+
const selection = document.querySelector('#selection');
|
|
439
|
+
const html = document.querySelector('#html');
|
|
440
|
+
const eventLog = document.querySelector('#events');
|
|
441
|
+
|
|
442
|
+
const name = host => host?.dataset.name || 'none';
|
|
443
|
+
const node = value => {
|
|
444
|
+
if (!value) return 'none';
|
|
445
|
+
if (value.nodeType === Node.TEXT_NODE) {
|
|
446
|
+
const text = value.data.replace(/\s+/g, ' ').trim();
|
|
447
|
+
return `#text "${text.slice(0, 32)}"`;
|
|
448
|
+
}
|
|
449
|
+
return `<${value.localName}>`;
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
function render() {
|
|
453
|
+
for (const host of hosts) {
|
|
454
|
+
const surface = rte.get(host);
|
|
455
|
+
const settings = config(host);
|
|
456
|
+
const state = surface?.active ? 'active' : surface ? 'registered' : 'focus to register';
|
|
457
|
+
const mode = host.getAttribute('contenteditable') === 'plaintext-only' ? ' · plain text' : '';
|
|
458
|
+
host.closest('.case').dataset.active = surface?.active || false;
|
|
459
|
+
host.closest('.case').querySelector(':scope > output').textContent =
|
|
460
|
+
`${state}${mode} · block ${settings.block || 'none'} · Enter ${settings.enter}`;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const host = rte.active?.element;
|
|
464
|
+
if (!host) {
|
|
465
|
+
active.textContent = 'None — focus a surface.';
|
|
466
|
+
selection.textContent = 'None';
|
|
467
|
+
html.textContent = 'None';
|
|
468
|
+
} else {
|
|
469
|
+
const settings = rte.active.config;
|
|
470
|
+
active.textContent = `${name(host)}\nblock: ${settings.block || 'none'}\nEnter: ${settings.enter}`;
|
|
471
|
+
html.textContent = new Source(rte.active).read().html;
|
|
472
|
+
const range = getSelection();
|
|
473
|
+
selection.textContent = range?.rangeCount
|
|
474
|
+
? `anchor: ${node(range.anchorNode)} @ ${range.anchorOffset}\nfocus: ${node(range.focusNode)} @ ${range.focusOffset}\ncollapsed: ${range.isCollapsed}`
|
|
475
|
+
: 'None';
|
|
476
|
+
}
|
|
477
|
+
eventLog.textContent = events.length ? events.join('\n') : 'None';
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function record(event) {
|
|
481
|
+
const host = event.composedPath().find(item => item?.matches?.('.rte-host'));
|
|
482
|
+
if (!host) return;
|
|
483
|
+
const detail = event.inputType || event.key || '';
|
|
484
|
+
events.push(`${name(host)} · ${event.type}${detail ? ` · ${detail}` : ''}`);
|
|
485
|
+
events.splice(0, Math.max(0, events.length - 16));
|
|
486
|
+
queueMicrotask(render);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
for (const type of ['focusin', 'focusout', 'beforeinput', 'input', 'keydown', 'click', 'cancel', 'close']) {
|
|
490
|
+
document.addEventListener(type, record, true);
|
|
491
|
+
}
|
|
492
|
+
rte.addEventListener('u2-rte-add', event => {
|
|
493
|
+
events.push(`${name(event.detail.surface.element)} · registered`);
|
|
494
|
+
render();
|
|
495
|
+
});
|
|
496
|
+
rte.addEventListener('u2-rte-activechange', render);
|
|
497
|
+
document.addEventListener('selectionchange', render);
|
|
498
|
+
document.querySelector('#clear').addEventListener('click', () => {
|
|
499
|
+
events.length = 0;
|
|
500
|
+
render();
|
|
501
|
+
});
|
|
502
|
+
const popover = document.querySelector('#popover-host');
|
|
503
|
+
document.querySelector('#show-popover-host').addEventListener('click', () => {
|
|
504
|
+
popover.showPopover();
|
|
505
|
+
popover.focus();
|
|
506
|
+
});
|
|
507
|
+
const fullscreen = document.querySelector('#fullscreen-host');
|
|
508
|
+
const enterFullscreen = document.querySelector('#show-fullscreen-host');
|
|
509
|
+
enterFullscreen.disabled = typeof fullscreen.requestFullscreen !== 'function';
|
|
510
|
+
enterFullscreen.addEventListener('click', async () => {
|
|
511
|
+
await fullscreen.requestFullscreen();
|
|
512
|
+
fullscreen.focus();
|
|
513
|
+
});
|
|
514
|
+
document.querySelector('#hide-fullscreen-host').addEventListener('click', () => document.exitFullscreen());
|
|
515
|
+
render();
|
|
516
|
+
</script>
|
|
517
|
+
</body>
|
|
518
|
+
</html>
|