mirror of
https://github.com/fastmail/Squire.git
synced 2024-12-22 07:13:08 -05:00
Release v2.2.0
This commit is contained in:
parent
950e122c5c
commit
9f3e2610a6
13 changed files with 217 additions and 239 deletions
13
CHANGELOG.md
13
CHANGELOG.md
|
@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file, starting fr
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.2.0] - 2023-10-02
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- The Squire config now has support for a toPlainText function, that takes an
|
||||||
|
HTML string and should return the plain text version of that content to be
|
||||||
|
added to the clipboard when cutting/copying.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- The default conversion of the HTML to plain text when cutting/copying now
|
||||||
|
uses the same algorithm as the getSelectedText method.
|
||||||
|
|
||||||
## [2.1.1] - 2023-09-27
|
## [2.1.1] - 2023-09-27
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
186
dist/squire-raw.js
vendored
186
dist/squire-raw.js
vendored
|
@ -1316,37 +1316,99 @@
|
||||||
moveRangeBoundariesDownTree(range);
|
moveRangeBoundariesDownTree(range);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// source/range/Contents.ts
|
||||||
|
var getTextContentsOfRange = (range) => {
|
||||||
|
if (range.collapsed) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const startContainer = range.startContainer;
|
||||||
|
const endContainer = range.endContainer;
|
||||||
|
const walker = new TreeIterator(
|
||||||
|
range.commonAncestorContainer,
|
||||||
|
SHOW_ELEMENT_OR_TEXT,
|
||||||
|
(node2) => {
|
||||||
|
return isNodeContainedInRange(range, node2, true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
walker.currentNode = startContainer;
|
||||||
|
let node = startContainer;
|
||||||
|
let textContent = "";
|
||||||
|
let addedTextInBlock = false;
|
||||||
|
let value;
|
||||||
|
if (!(node instanceof Element) && !(node instanceof Text) || !walker.filter(node)) {
|
||||||
|
node = walker.nextNode();
|
||||||
|
}
|
||||||
|
while (node) {
|
||||||
|
if (node instanceof Text) {
|
||||||
|
value = node.data;
|
||||||
|
if (value && /\S/.test(value)) {
|
||||||
|
if (node === endContainer) {
|
||||||
|
value = value.slice(0, range.endOffset);
|
||||||
|
}
|
||||||
|
if (node === startContainer) {
|
||||||
|
value = value.slice(range.startOffset);
|
||||||
|
}
|
||||||
|
textContent += value;
|
||||||
|
addedTextInBlock = true;
|
||||||
|
}
|
||||||
|
} else if (node.nodeName === "BR" || addedTextInBlock && !isInline(node)) {
|
||||||
|
textContent += "\n";
|
||||||
|
addedTextInBlock = false;
|
||||||
|
}
|
||||||
|
node = walker.nextNode();
|
||||||
|
}
|
||||||
|
textContent = textContent.replace(/ /g, " ");
|
||||||
|
return textContent;
|
||||||
|
};
|
||||||
|
|
||||||
// source/Clipboard.ts
|
// source/Clipboard.ts
|
||||||
var indexOf = Array.prototype.indexOf;
|
var indexOf = Array.prototype.indexOf;
|
||||||
var setClipboardData = (event, contents, root, toCleanHTML, toPlainText, plainTextOnly) => {
|
var extractRangeToClipboard = (event, range, root, removeRangeFromDocument, toCleanHTML, toPlainText, plainTextOnly) => {
|
||||||
const clipboardData = event.clipboardData;
|
const clipboardData = event.clipboardData;
|
||||||
const body = document.body;
|
if (isLegacyEdge || !clipboardData) {
|
||||||
const node = createElement("DIV");
|
return false;
|
||||||
|
}
|
||||||
|
let text = toPlainText ? "" : getTextContentsOfRange(range);
|
||||||
|
const startBlock = getStartBlockOfRange(range, root);
|
||||||
|
const endBlock = getEndBlockOfRange(range, root);
|
||||||
|
let copyRoot = root;
|
||||||
|
if (startBlock === endBlock && (startBlock == null ? void 0 : startBlock.contains(range.commonAncestorContainer))) {
|
||||||
|
copyRoot = startBlock;
|
||||||
|
}
|
||||||
|
let contents;
|
||||||
|
if (removeRangeFromDocument) {
|
||||||
|
contents = deleteContentsOfRange(range, root);
|
||||||
|
} else {
|
||||||
|
range = range.cloneRange();
|
||||||
|
moveRangeBoundariesDownTree(range);
|
||||||
|
moveRangeBoundariesUpTree(range, copyRoot, copyRoot, root);
|
||||||
|
contents = range.cloneContents();
|
||||||
|
}
|
||||||
|
let parent = range.commonAncestorContainer;
|
||||||
|
if (parent instanceof Text) {
|
||||||
|
parent = parent.parentNode;
|
||||||
|
}
|
||||||
|
while (parent && parent !== copyRoot) {
|
||||||
|
const newContents = parent.cloneNode(false);
|
||||||
|
newContents.appendChild(contents);
|
||||||
|
contents = newContents;
|
||||||
|
parent = parent.parentNode;
|
||||||
|
}
|
||||||
let html;
|
let html;
|
||||||
let text;
|
|
||||||
if (contents.childNodes.length === 1 && contents.childNodes[0] instanceof Text) {
|
if (contents.childNodes.length === 1 && contents.childNodes[0] instanceof Text) {
|
||||||
text = contents.childNodes[0].data.replace(/ /g, " ");
|
text = contents.childNodes[0].data.replace(/ /g, " ");
|
||||||
plainTextOnly = true;
|
plainTextOnly = true;
|
||||||
} else {
|
} else {
|
||||||
|
const node = createElement("DIV");
|
||||||
node.appendChild(contents);
|
node.appendChild(contents);
|
||||||
html = node.innerHTML;
|
html = node.innerHTML;
|
||||||
if (toCleanHTML) {
|
if (toCleanHTML) {
|
||||||
html = toCleanHTML(html);
|
html = toCleanHTML(html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (text !== void 0) {
|
if (plainTextOnly) {
|
||||||
} else if (toPlainText && html !== void 0) {
|
} else if (toPlainText && html !== void 0) {
|
||||||
text = toPlainText(html);
|
text = toPlainText(html);
|
||||||
} else {
|
|
||||||
cleanupBRs(node, root, true);
|
|
||||||
node.setAttribute(
|
|
||||||
"style",
|
|
||||||
"position:fixed;overflow:hidden;bottom:100%;right:100%;"
|
|
||||||
);
|
|
||||||
body.appendChild(node);
|
|
||||||
text = node.innerText || node.textContent;
|
|
||||||
text = text.replace(/ /g, " ");
|
|
||||||
body.removeChild(node);
|
|
||||||
}
|
}
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
text = text.replace(/\r?\n/g, "\r\n");
|
text = text.replace(/\r?\n/g, "\r\n");
|
||||||
|
@ -1356,45 +1418,7 @@
|
||||||
}
|
}
|
||||||
clipboardData.setData("text/plain", text);
|
clipboardData.setData("text/plain", text);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
return true;
|
||||||
var extractRangeToClipboard = (event, range, root, removeRangeFromDocument, toCleanHTML, toPlainText, plainTextOnly) => {
|
|
||||||
if (!isLegacyEdge && event.clipboardData) {
|
|
||||||
const startBlock = getStartBlockOfRange(range, root);
|
|
||||||
const endBlock = getEndBlockOfRange(range, root);
|
|
||||||
let copyRoot = root;
|
|
||||||
if (startBlock === endBlock && (startBlock == null ? void 0 : startBlock.contains(range.commonAncestorContainer))) {
|
|
||||||
copyRoot = startBlock;
|
|
||||||
}
|
|
||||||
let contents;
|
|
||||||
if (removeRangeFromDocument) {
|
|
||||||
contents = deleteContentsOfRange(range, root);
|
|
||||||
} else {
|
|
||||||
range = range.cloneRange();
|
|
||||||
moveRangeBoundariesDownTree(range);
|
|
||||||
moveRangeBoundariesUpTree(range, copyRoot, copyRoot, root);
|
|
||||||
contents = range.cloneContents();
|
|
||||||
}
|
|
||||||
let parent = range.commonAncestorContainer;
|
|
||||||
if (parent instanceof Text) {
|
|
||||||
parent = parent.parentNode;
|
|
||||||
}
|
|
||||||
while (parent && parent !== copyRoot) {
|
|
||||||
const newContents = parent.cloneNode(false);
|
|
||||||
newContents.appendChild(contents);
|
|
||||||
contents = newContents;
|
|
||||||
parent = parent.parentNode;
|
|
||||||
}
|
|
||||||
setClipboardData(
|
|
||||||
event,
|
|
||||||
contents,
|
|
||||||
root,
|
|
||||||
toCleanHTML,
|
|
||||||
toPlainText,
|
|
||||||
plainTextOnly
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
var _onCut = function(event) {
|
var _onCut = function(event) {
|
||||||
const range = this.getSelection();
|
const range = this.getSelection();
|
||||||
|
@ -1410,7 +1434,7 @@
|
||||||
root,
|
root,
|
||||||
true,
|
true,
|
||||||
this._config.willCutCopy,
|
this._config.willCutCopy,
|
||||||
null,
|
this._config.toPlainText,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
|
@ -1431,7 +1455,7 @@
|
||||||
this._root,
|
this._root,
|
||||||
false,
|
false,
|
||||||
this._config.willCutCopy,
|
this._config.willCutCopy,
|
||||||
null,
|
this._config.toPlainText,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2169,11 +2193,6 @@
|
||||||
});
|
});
|
||||||
this._mutation = mutation;
|
this._mutation = mutation;
|
||||||
root.setAttribute("contenteditable", "true");
|
root.setAttribute("contenteditable", "true");
|
||||||
try {
|
|
||||||
document.execCommand("enableObjectResizing", false, "false");
|
|
||||||
document.execCommand("enableInlineTableEditing", false, "false");
|
|
||||||
} catch (_) {
|
|
||||||
}
|
|
||||||
this.addEventListener(
|
this.addEventListener(
|
||||||
"beforeinput",
|
"beforeinput",
|
||||||
this._beforeInput
|
this._beforeInput
|
||||||
|
@ -2208,6 +2227,7 @@
|
||||||
},
|
},
|
||||||
addLinks: true,
|
addLinks: true,
|
||||||
willCutCopy: null,
|
willCutCopy: null,
|
||||||
|
toPlainText: null,
|
||||||
sanitizeToDOMFragment: (html) => {
|
sanitizeToDOMFragment: (html) => {
|
||||||
const frag = DOMPurify.sanitize(html, {
|
const frag = DOMPurify.sanitize(html, {
|
||||||
ALLOW_UNKNOWN_PROTOCOLS: true,
|
ALLOW_UNKNOWN_PROTOCOLS: true,
|
||||||
|
@ -3002,48 +3022,8 @@
|
||||||
}
|
}
|
||||||
return this.insertHTML(lines.join(""), isPaste);
|
return this.insertHTML(lines.join(""), isPaste);
|
||||||
}
|
}
|
||||||
getSelectedText() {
|
getSelectedText(range) {
|
||||||
const range = this.getSelection();
|
return getTextContentsOfRange(range || this.getSelection());
|
||||||
if (range.collapsed) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
const startContainer = range.startContainer;
|
|
||||||
const endContainer = range.endContainer;
|
|
||||||
const walker = new TreeIterator(
|
|
||||||
range.commonAncestorContainer,
|
|
||||||
SHOW_ELEMENT_OR_TEXT,
|
|
||||||
(node2) => {
|
|
||||||
return isNodeContainedInRange(range, node2, true);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
walker.currentNode = startContainer;
|
|
||||||
let node = startContainer;
|
|
||||||
let textContent = "";
|
|
||||||
let addedTextInBlock = false;
|
|
||||||
let value;
|
|
||||||
if (!(node instanceof Element) && !(node instanceof Text) || !walker.filter(node)) {
|
|
||||||
node = walker.nextNode();
|
|
||||||
}
|
|
||||||
while (node) {
|
|
||||||
if (node instanceof Text) {
|
|
||||||
value = node.data;
|
|
||||||
if (value && /\S/.test(value)) {
|
|
||||||
if (node === endContainer) {
|
|
||||||
value = value.slice(0, range.endOffset);
|
|
||||||
}
|
|
||||||
if (node === startContainer) {
|
|
||||||
value = value.slice(range.startOffset);
|
|
||||||
}
|
|
||||||
textContent += value;
|
|
||||||
addedTextInBlock = true;
|
|
||||||
}
|
|
||||||
} else if (node.nodeName === "BR" || addedTextInBlock && !isInline(node)) {
|
|
||||||
textContent += "\n";
|
|
||||||
addedTextInBlock = false;
|
|
||||||
}
|
|
||||||
node = walker.nextNode();
|
|
||||||
}
|
|
||||||
return textContent;
|
|
||||||
}
|
}
|
||||||
// --- Inline formatting
|
// --- Inline formatting
|
||||||
/**
|
/**
|
||||||
|
|
186
dist/squire-raw.mjs
vendored
186
dist/squire-raw.mjs
vendored
|
@ -1314,37 +1314,99 @@ var insertTreeFragmentIntoRange = (range, frag, root) => {
|
||||||
moveRangeBoundariesDownTree(range);
|
moveRangeBoundariesDownTree(range);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// source/range/Contents.ts
|
||||||
|
var getTextContentsOfRange = (range) => {
|
||||||
|
if (range.collapsed) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
const startContainer = range.startContainer;
|
||||||
|
const endContainer = range.endContainer;
|
||||||
|
const walker = new TreeIterator(
|
||||||
|
range.commonAncestorContainer,
|
||||||
|
SHOW_ELEMENT_OR_TEXT,
|
||||||
|
(node2) => {
|
||||||
|
return isNodeContainedInRange(range, node2, true);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
walker.currentNode = startContainer;
|
||||||
|
let node = startContainer;
|
||||||
|
let textContent = "";
|
||||||
|
let addedTextInBlock = false;
|
||||||
|
let value;
|
||||||
|
if (!(node instanceof Element) && !(node instanceof Text) || !walker.filter(node)) {
|
||||||
|
node = walker.nextNode();
|
||||||
|
}
|
||||||
|
while (node) {
|
||||||
|
if (node instanceof Text) {
|
||||||
|
value = node.data;
|
||||||
|
if (value && /\S/.test(value)) {
|
||||||
|
if (node === endContainer) {
|
||||||
|
value = value.slice(0, range.endOffset);
|
||||||
|
}
|
||||||
|
if (node === startContainer) {
|
||||||
|
value = value.slice(range.startOffset);
|
||||||
|
}
|
||||||
|
textContent += value;
|
||||||
|
addedTextInBlock = true;
|
||||||
|
}
|
||||||
|
} else if (node.nodeName === "BR" || addedTextInBlock && !isInline(node)) {
|
||||||
|
textContent += "\n";
|
||||||
|
addedTextInBlock = false;
|
||||||
|
}
|
||||||
|
node = walker.nextNode();
|
||||||
|
}
|
||||||
|
textContent = textContent.replace(/ /g, " ");
|
||||||
|
return textContent;
|
||||||
|
};
|
||||||
|
|
||||||
// source/Clipboard.ts
|
// source/Clipboard.ts
|
||||||
var indexOf = Array.prototype.indexOf;
|
var indexOf = Array.prototype.indexOf;
|
||||||
var setClipboardData = (event, contents, root, toCleanHTML, toPlainText, plainTextOnly) => {
|
var extractRangeToClipboard = (event, range, root, removeRangeFromDocument, toCleanHTML, toPlainText, plainTextOnly) => {
|
||||||
const clipboardData = event.clipboardData;
|
const clipboardData = event.clipboardData;
|
||||||
const body = document.body;
|
if (isLegacyEdge || !clipboardData) {
|
||||||
const node = createElement("DIV");
|
return false;
|
||||||
|
}
|
||||||
|
let text = toPlainText ? "" : getTextContentsOfRange(range);
|
||||||
|
const startBlock = getStartBlockOfRange(range, root);
|
||||||
|
const endBlock = getEndBlockOfRange(range, root);
|
||||||
|
let copyRoot = root;
|
||||||
|
if (startBlock === endBlock && startBlock?.contains(range.commonAncestorContainer)) {
|
||||||
|
copyRoot = startBlock;
|
||||||
|
}
|
||||||
|
let contents;
|
||||||
|
if (removeRangeFromDocument) {
|
||||||
|
contents = deleteContentsOfRange(range, root);
|
||||||
|
} else {
|
||||||
|
range = range.cloneRange();
|
||||||
|
moveRangeBoundariesDownTree(range);
|
||||||
|
moveRangeBoundariesUpTree(range, copyRoot, copyRoot, root);
|
||||||
|
contents = range.cloneContents();
|
||||||
|
}
|
||||||
|
let parent = range.commonAncestorContainer;
|
||||||
|
if (parent instanceof Text) {
|
||||||
|
parent = parent.parentNode;
|
||||||
|
}
|
||||||
|
while (parent && parent !== copyRoot) {
|
||||||
|
const newContents = parent.cloneNode(false);
|
||||||
|
newContents.appendChild(contents);
|
||||||
|
contents = newContents;
|
||||||
|
parent = parent.parentNode;
|
||||||
|
}
|
||||||
let html;
|
let html;
|
||||||
let text;
|
|
||||||
if (contents.childNodes.length === 1 && contents.childNodes[0] instanceof Text) {
|
if (contents.childNodes.length === 1 && contents.childNodes[0] instanceof Text) {
|
||||||
text = contents.childNodes[0].data.replace(/ /g, " ");
|
text = contents.childNodes[0].data.replace(/ /g, " ");
|
||||||
plainTextOnly = true;
|
plainTextOnly = true;
|
||||||
} else {
|
} else {
|
||||||
|
const node = createElement("DIV");
|
||||||
node.appendChild(contents);
|
node.appendChild(contents);
|
||||||
html = node.innerHTML;
|
html = node.innerHTML;
|
||||||
if (toCleanHTML) {
|
if (toCleanHTML) {
|
||||||
html = toCleanHTML(html);
|
html = toCleanHTML(html);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (text !== void 0) {
|
if (plainTextOnly) {
|
||||||
} else if (toPlainText && html !== void 0) {
|
} else if (toPlainText && html !== void 0) {
|
||||||
text = toPlainText(html);
|
text = toPlainText(html);
|
||||||
} else {
|
|
||||||
cleanupBRs(node, root, true);
|
|
||||||
node.setAttribute(
|
|
||||||
"style",
|
|
||||||
"position:fixed;overflow:hidden;bottom:100%;right:100%;"
|
|
||||||
);
|
|
||||||
body.appendChild(node);
|
|
||||||
text = node.innerText || node.textContent;
|
|
||||||
text = text.replace(/ /g, " ");
|
|
||||||
body.removeChild(node);
|
|
||||||
}
|
}
|
||||||
if (isWin) {
|
if (isWin) {
|
||||||
text = text.replace(/\r?\n/g, "\r\n");
|
text = text.replace(/\r?\n/g, "\r\n");
|
||||||
|
@ -1354,45 +1416,7 @@ var setClipboardData = (event, contents, root, toCleanHTML, toPlainText, plainTe
|
||||||
}
|
}
|
||||||
clipboardData.setData("text/plain", text);
|
clipboardData.setData("text/plain", text);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
};
|
return true;
|
||||||
var extractRangeToClipboard = (event, range, root, removeRangeFromDocument, toCleanHTML, toPlainText, plainTextOnly) => {
|
|
||||||
if (!isLegacyEdge && event.clipboardData) {
|
|
||||||
const startBlock = getStartBlockOfRange(range, root);
|
|
||||||
const endBlock = getEndBlockOfRange(range, root);
|
|
||||||
let copyRoot = root;
|
|
||||||
if (startBlock === endBlock && startBlock?.contains(range.commonAncestorContainer)) {
|
|
||||||
copyRoot = startBlock;
|
|
||||||
}
|
|
||||||
let contents;
|
|
||||||
if (removeRangeFromDocument) {
|
|
||||||
contents = deleteContentsOfRange(range, root);
|
|
||||||
} else {
|
|
||||||
range = range.cloneRange();
|
|
||||||
moveRangeBoundariesDownTree(range);
|
|
||||||
moveRangeBoundariesUpTree(range, copyRoot, copyRoot, root);
|
|
||||||
contents = range.cloneContents();
|
|
||||||
}
|
|
||||||
let parent = range.commonAncestorContainer;
|
|
||||||
if (parent instanceof Text) {
|
|
||||||
parent = parent.parentNode;
|
|
||||||
}
|
|
||||||
while (parent && parent !== copyRoot) {
|
|
||||||
const newContents = parent.cloneNode(false);
|
|
||||||
newContents.appendChild(contents);
|
|
||||||
contents = newContents;
|
|
||||||
parent = parent.parentNode;
|
|
||||||
}
|
|
||||||
setClipboardData(
|
|
||||||
event,
|
|
||||||
contents,
|
|
||||||
root,
|
|
||||||
toCleanHTML,
|
|
||||||
toPlainText,
|
|
||||||
plainTextOnly
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
var _onCut = function(event) {
|
var _onCut = function(event) {
|
||||||
const range = this.getSelection();
|
const range = this.getSelection();
|
||||||
|
@ -1408,7 +1432,7 @@ var _onCut = function(event) {
|
||||||
root,
|
root,
|
||||||
true,
|
true,
|
||||||
this._config.willCutCopy,
|
this._config.willCutCopy,
|
||||||
null,
|
this._config.toPlainText,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
if (!handled) {
|
if (!handled) {
|
||||||
|
@ -1429,7 +1453,7 @@ var _onCopy = function(event) {
|
||||||
this._root,
|
this._root,
|
||||||
false,
|
false,
|
||||||
this._config.willCutCopy,
|
this._config.willCutCopy,
|
||||||
null,
|
this._config.toPlainText,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -2166,11 +2190,6 @@ var Squire = class {
|
||||||
});
|
});
|
||||||
this._mutation = mutation;
|
this._mutation = mutation;
|
||||||
root.setAttribute("contenteditable", "true");
|
root.setAttribute("contenteditable", "true");
|
||||||
try {
|
|
||||||
document.execCommand("enableObjectResizing", false, "false");
|
|
||||||
document.execCommand("enableInlineTableEditing", false, "false");
|
|
||||||
} catch (_) {
|
|
||||||
}
|
|
||||||
this.addEventListener(
|
this.addEventListener(
|
||||||
"beforeinput",
|
"beforeinput",
|
||||||
this._beforeInput
|
this._beforeInput
|
||||||
|
@ -2205,6 +2224,7 @@ var Squire = class {
|
||||||
},
|
},
|
||||||
addLinks: true,
|
addLinks: true,
|
||||||
willCutCopy: null,
|
willCutCopy: null,
|
||||||
|
toPlainText: null,
|
||||||
sanitizeToDOMFragment: (html) => {
|
sanitizeToDOMFragment: (html) => {
|
||||||
const frag = DOMPurify.sanitize(html, {
|
const frag = DOMPurify.sanitize(html, {
|
||||||
ALLOW_UNKNOWN_PROTOCOLS: true,
|
ALLOW_UNKNOWN_PROTOCOLS: true,
|
||||||
|
@ -2999,48 +3019,8 @@ var Squire = class {
|
||||||
}
|
}
|
||||||
return this.insertHTML(lines.join(""), isPaste);
|
return this.insertHTML(lines.join(""), isPaste);
|
||||||
}
|
}
|
||||||
getSelectedText() {
|
getSelectedText(range) {
|
||||||
const range = this.getSelection();
|
return getTextContentsOfRange(range || this.getSelection());
|
||||||
if (range.collapsed) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
const startContainer = range.startContainer;
|
|
||||||
const endContainer = range.endContainer;
|
|
||||||
const walker = new TreeIterator(
|
|
||||||
range.commonAncestorContainer,
|
|
||||||
SHOW_ELEMENT_OR_TEXT,
|
|
||||||
(node2) => {
|
|
||||||
return isNodeContainedInRange(range, node2, true);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
walker.currentNode = startContainer;
|
|
||||||
let node = startContainer;
|
|
||||||
let textContent = "";
|
|
||||||
let addedTextInBlock = false;
|
|
||||||
let value;
|
|
||||||
if (!(node instanceof Element) && !(node instanceof Text) || !walker.filter(node)) {
|
|
||||||
node = walker.nextNode();
|
|
||||||
}
|
|
||||||
while (node) {
|
|
||||||
if (node instanceof Text) {
|
|
||||||
value = node.data;
|
|
||||||
if (value && /\S/.test(value)) {
|
|
||||||
if (node === endContainer) {
|
|
||||||
value = value.slice(0, range.endOffset);
|
|
||||||
}
|
|
||||||
if (node === startContainer) {
|
|
||||||
value = value.slice(range.startOffset);
|
|
||||||
}
|
|
||||||
textContent += value;
|
|
||||||
addedTextInBlock = true;
|
|
||||||
}
|
|
||||||
} else if (node.nodeName === "BR" || addedTextInBlock && !isInline(node)) {
|
|
||||||
textContent += "\n";
|
|
||||||
addedTextInBlock = false;
|
|
||||||
}
|
|
||||||
node = walker.nextNode();
|
|
||||||
}
|
|
||||||
return textContent;
|
|
||||||
}
|
}
|
||||||
// --- Inline formatting
|
// --- Inline formatting
|
||||||
/**
|
/**
|
||||||
|
|
20
dist/squire.js
vendored
20
dist/squire.js
vendored
File diff suppressed because one or more lines are too long
8
dist/squire.js.map
vendored
8
dist/squire.js.map
vendored
File diff suppressed because one or more lines are too long
22
dist/squire.mjs
vendored
22
dist/squire.mjs
vendored
File diff suppressed because one or more lines are too long
8
dist/squire.mjs.map
vendored
8
dist/squire.mjs.map
vendored
File diff suppressed because one or more lines are too long
2
dist/types/Clipboard.d.ts.map
vendored
2
dist/types/Clipboard.d.ts.map
vendored
|
@ -1 +1 @@
|
||||||
{"version":3,"file":"Clipboard.d.ts","sourceRoot":"","sources":["../../source/Clipboard.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAyEvC,QAAA,MAAM,uBAAuB,UAClB,cAAc,SACd,KAAK,QACN,WAAW,2BACQ,OAAO,uBACJ,MAAM,KAAK,MAAM,+BACjB,MAAM,KAAK,MAAM,yBAC9B,OAAO,KACvB,OAmDF,CAAC;AAIF,QAAA,MAAM,MAAM,SAAmB,MAAM,SAAS,cAAc,KAAG,IAkC9D,CAAC;AAEF,QAAA,MAAM,OAAO,SAAmB,MAAM,SAAS,cAAc,KAAG,IAU/D,CAAC;AAIF,QAAA,MAAM,gBAAgB,SAAmB,MAAM,SAAS,aAAa,KAAG,IAEvE,CAAC;AAEF,QAAA,MAAM,QAAQ,SAAmB,MAAM,SAAS,cAAc,KAAG,IAqLhE,CAAC;AAKF,QAAA,MAAM,OAAO,SAAmB,MAAM,SAAS,SAAS,KAAG,IAwB1D,CAAC;AAIF,OAAO,EACH,uBAAuB,EACvB,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,QAAQ,EACR,OAAO,GACV,CAAC"}
|
{"version":3,"file":"Clipboard.d.ts","sourceRoot":"","sources":["../../source/Clipboard.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAOvC,QAAA,MAAM,uBAAuB,UAClB,cAAc,SACd,KAAK,QACN,WAAW,2BACQ,OAAO,uBACJ,MAAM,KAAK,MAAM,+BACjB,MAAM,KAAK,MAAM,yBAC9B,OAAO,KACvB,OA2FF,CAAC;AAIF,QAAA,MAAM,MAAM,SAAmB,MAAM,SAAS,cAAc,KAAG,IAkC9D,CAAC;AAEF,QAAA,MAAM,OAAO,SAAmB,MAAM,SAAS,cAAc,KAAG,IAU/D,CAAC;AAIF,QAAA,MAAM,gBAAgB,SAAmB,MAAM,SAAS,aAAa,KAAG,IAEvE,CAAC;AAEF,QAAA,MAAM,QAAQ,SAAmB,MAAM,SAAS,cAAc,KAAG,IAqLhE,CAAC;AAKF,QAAA,MAAM,OAAO,SAAmB,MAAM,SAAS,SAAS,KAAG,IAwB1D,CAAC;AAIF,OAAO,EACH,uBAAuB,EACvB,MAAM,EACN,OAAO,EACP,gBAAgB,EAChB,QAAQ,EACR,OAAO,GACV,CAAC"}
|
3
dist/types/Editor.d.ts
vendored
3
dist/types/Editor.d.ts
vendored
|
@ -23,6 +23,7 @@ interface SquireConfig {
|
||||||
};
|
};
|
||||||
addLinks: boolean;
|
addLinks: boolean;
|
||||||
willCutCopy: null | ((html: string) => string);
|
willCutCopy: null | ((html: string) => string);
|
||||||
|
toPlainText: null | ((html: string) => string);
|
||||||
sanitizeToDOMFragment: (html: string, editor: Squire) => DocumentFragment;
|
sanitizeToDOMFragment: (html: string, editor: Squire) => DocumentFragment;
|
||||||
didError: (x: any) => void;
|
didError: (x: any) => void;
|
||||||
}
|
}
|
||||||
|
@ -104,7 +105,7 @@ declare class Squire {
|
||||||
insertElement(el: Element, range?: Range): Squire;
|
insertElement(el: Element, range?: Range): Squire;
|
||||||
insertImage(src: string, attributes: Record<string, string>): HTMLImageElement;
|
insertImage(src: string, attributes: Record<string, string>): HTMLImageElement;
|
||||||
insertPlainText(plainText: string, isPaste: boolean): Squire;
|
insertPlainText(plainText: string, isPaste: boolean): Squire;
|
||||||
getSelectedText(): string;
|
getSelectedText(range?: Range): string;
|
||||||
/**
|
/**
|
||||||
* Extracts the font-family and font-size (if any) of the element
|
* Extracts the font-family and font-size (if any) of the element
|
||||||
* holding the cursor. If there's a selection, returns an empty object.
|
* holding the cursor. If there's a selection, returns an empty object.
|
||||||
|
|
2
dist/types/Editor.d.ts.map
vendored
2
dist/types/Editor.d.ts.map
vendored
File diff suppressed because one or more lines are too long
3
dist/types/range/Contents.d.ts
vendored
Normal file
3
dist/types/range/Contents.d.ts
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
declare const getTextContentsOfRange: (range: Range) => string;
|
||||||
|
export { getTextContentsOfRange };
|
||||||
|
//# sourceMappingURL=Contents.d.ts.map
|
1
dist/types/range/Contents.d.ts.map
vendored
Normal file
1
dist/types/range/Contents.d.ts.map
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"Contents.d.ts","sourceRoot":"","sources":["../../../source/range/Contents.ts"],"names":[],"mappings":"AAMA,QAAA,MAAM,sBAAsB,UAAW,KAAK,WAsD3C,CAAC;AAIF,OAAO,EAAE,sBAAsB,EAAE,CAAC"}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "squire-rte",
|
"name": "squire-rte",
|
||||||
"version": "2.1.1",
|
"version": "2.2.0",
|
||||||
"description": "Squire is an HTML5 rich text editor, which provides powerful cross-browser normalisation, whilst being supremely lightweight and flexible.",
|
"description": "Squire is an HTML5 rich text editor, which provides powerful cross-browser normalisation, whilst being supremely lightweight and flexible.",
|
||||||
"main": "dist/squire.mjs",
|
"main": "dist/squire.mjs",
|
||||||
"types": "dist/types/Squire.d.ts",
|
"types": "dist/types/Squire.d.ts",
|
||||||
|
|
Loading…
Reference in a new issue