u2ui 1.5.11 → 1.5.12
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/js/rte/PLAN.md
CHANGED
|
@@ -71,10 +71,13 @@ command ever makes an element canonical — so a strict list would otherwise hav
|
|
|
71
71
|
turned every pasted emphasis into plain text.
|
|
72
72
|
|
|
73
73
|
Not every `text/html` flavor is html. A pdf viewer offers its selection as one
|
|
74
|
-
while putting plain text
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
while putting plain text inside it, and importing that as html collapsed every
|
|
75
|
+
line break into a single line. `ExternalInput` still decides by flavor list —
|
|
76
|
+
reading the payload before preventing native insertion would give a failed read
|
|
77
|
+
somewhere to fall back to — but the payload now decides what the flavor *is*:
|
|
78
|
+
without a single tag it is text, escaped and joined by breaks, which is all the
|
|
79
|
+
structure such a paste has. A `text/plain` paste with no html flavor beside it
|
|
80
|
+
stays native as before.
|
|
78
81
|
|
|
79
82
|
Keeping the content of an unlisted element is right for almost all of them, and
|
|
80
83
|
wrong for the few a browser never renders the children of: unwrapping a `<style>`
|
|
@@ -103,10 +103,12 @@ const external = new ExternalInput(surface, {
|
|
|
103
103
|
|
|
104
104
|
For `insertFromPaste` and `insertFromDrop`, the contenteditable Input Events
|
|
105
105
|
contract supplies rich and plain data in `dataTransfer` plus the DOM range that
|
|
106
|
-
would be replaced. The adapter takes over only when `text/html` is present and
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
would be replaced. The adapter takes over only when `text/html` is present, and
|
|
107
|
+
the payload then decides what that flavor is: markup is imported as it stands,
|
|
108
|
+
while a flavor carrying none is the text it is — a pdf viewer labels its plain
|
|
109
|
+
selection `text/html` — and its line breaks, the only structure such a text has,
|
|
110
|
+
become breaks instead of collapsing. Reading the payload happens after native
|
|
111
|
+
insertion is prevented, so a failing read cannot fall back to it. It
|
|
110
112
|
prevents native insertion first, sanitizes into a detached `DocumentFragment`,
|
|
111
113
|
optionally cleans presentation cumulatively through the selected level, and
|
|
112
114
|
passes the result and exact target range to the registered command. Drop thus
|
|
@@ -2,6 +2,7 @@ import {inputRange} from './input-pipeline.js';
|
|
|
2
2
|
import {editingHost, isPlainTextHost} from '../selection/ownership/ownership.js';
|
|
3
3
|
|
|
4
4
|
const INPUTS = new Set(['insertFromPaste', 'insertFromDrop']);
|
|
5
|
+
const ENTITIES = {'&': '&', '<': '<', '>': '>'};
|
|
5
6
|
|
|
6
7
|
// Owns rich external HTML before the browser can insert it. The selected
|
|
7
8
|
// sanitizer, optional presentation cleanup, and mapped insertion command stay
|
|
@@ -97,12 +98,11 @@ export class ExternalInput {
|
|
|
97
98
|
#beforeInput = event => {
|
|
98
99
|
if (!this.#owns(event) || !INPUTS.has(event.inputType) || !event.cancelable
|
|
99
100
|
|| event.defaultPrevented || event.isComposing || isPlainTextHost(this.#root)) return;
|
|
100
|
-
if (!
|
|
101
|
+
if (!hasHtml(event.dataTransfer)) return;
|
|
101
102
|
event.preventDefault();
|
|
102
103
|
try {
|
|
103
|
-
const html = event.dataTransfer.getData('text/html');
|
|
104
104
|
const range = inputRange(event, this.#surface);
|
|
105
|
-
this.insert(
|
|
105
|
+
this.insert(importHtml(event.dataTransfer), {range, inputType: event.inputType});
|
|
106
106
|
} catch (error) {
|
|
107
107
|
this.#surface.emit('u2-rte-error', {
|
|
108
108
|
transaction: null,
|
|
@@ -123,13 +123,18 @@ export class ExternalInput {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
//
|
|
127
|
-
//
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
126
|
+
// Reading the payload belongs after preventDefault, where a failure stays fail-closed, so the flavor
|
|
127
|
+
// list is all this may look at. Plain text without an html flavor is the browser's to insert.
|
|
128
|
+
function hasHtml(transfer) {
|
|
129
|
+
if (typeof transfer?.getData !== 'function') return false;
|
|
130
|
+
return [...(transfer.types || [])].some(type => String(type).toLowerCase() === 'text/html');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Markup as it is, an html flavor without any as the text it is: a pdf viewer labels its plain
|
|
134
|
+
// selection that way, and html would collapse the line breaks that are all the structure it has.
|
|
135
|
+
function importHtml(transfer) {
|
|
136
|
+
const html = String(transfer.getData('text/html') || '');
|
|
137
|
+
if (/<[a-z!/]/i.test(html)) return html;
|
|
138
|
+
const text = String(transfer.getData('text/plain') || '') || html;
|
|
139
|
+
return text.replace(/[&<>]/g, character => ENTITIES[character]).replace(/\r?\n/g, '<br>');
|
|
135
140
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "u2ui",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.12",
|
|
4
4
|
"description": "HTML Advanced: More Capabilities, Same Feel, Same Simplicity",
|
|
5
5
|
"keywords": ["web-components","pattern-library","component-library","ui-toolkit","design-system"],
|
|
6
6
|
"author": "Tobias Buschor",
|