0
Fork 0
mirror of https://github.com/fastmail/Squire.git synced 2024-12-22 07:13:08 -05:00

Release v2.1.0

This commit is contained in:
Neil Jenkins 2023-09-19 14:35:11 +08:00
parent edde44a924
commit befb652039
11 changed files with 4674 additions and 4410 deletions

View file

@ -4,6 +4,15 @@ 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).
## [2.1.0] - 2023-09-19
### Added
- If you start a new line with "\*" then a space, Squire will now automatically
set the format to an unordered list.
- If you start a new line with "1." then a space, Squire will now automatically
set the format to an ordered list.
## [2.0.3] - 2023-04-20
### Fixed

23
dist/squire-raw.js vendored
View file

@ -1816,16 +1816,37 @@
};
// source/keyboard/Space.ts
var Space = (self, _, range) => {
var Space = (self, event, range) => {
var _a;
let node;
const root = self._root;
self._recordUndoState(range);
self._getRangeAndRemoveBookmark(range);
self._removeZWS();
if (!range.collapsed) {
deleteContentsOfRange(range, root);
self._ensureBottomLine();
self.setSelection(range);
self._updatePath(range, true);
} else if (rangeDoesEndAtBlockBoundary(range, root)) {
const block = getStartBlockOfRange(range, root);
if (block && block.nodeName !== "PRE") {
const text = (_a = block.textContent) == null ? void 0 : _a.trimEnd();
if (text === "*" || text === "1.") {
event.preventDefault();
const walker = new TreeIterator(block, SHOW_TEXT);
let textNode;
while (textNode = walker.nextNode()) {
textNode.data = cantFocusEmptyTextNodes ? ZWS : "";
}
if (text === "*") {
self.makeUnorderedList();
} else {
self.makeOrderedList();
}
return;
}
}
}
node = range.endContainer;
if (range.endOffset === getLength(node)) {

191
dist/squire-raw.mjs vendored
View file

@ -4,10 +4,6 @@ var SHOW_TEXT = 4;
var SHOW_ELEMENT_OR_TEXT = 5;
var always = () => true;
var TreeIterator = class {
root;
currentNode;
nodeType;
filter;
constructor(root, nodeType, filter) {
this.root = root;
this.currentNode = root;
@ -1818,16 +1814,36 @@ var ShiftTab = (self, event, range) => {
};
// source/keyboard/Space.ts
var Space = (self, _, range) => {
var Space = (self, event, range) => {
let node;
const root = self._root;
self._recordUndoState(range);
self._getRangeAndRemoveBookmark(range);
self._removeZWS();
if (!range.collapsed) {
deleteContentsOfRange(range, root);
self._ensureBottomLine();
self.setSelection(range);
self._updatePath(range, true);
} else if (rangeDoesEndAtBlockBoundary(range, root)) {
const block = getStartBlockOfRange(range, root);
if (block && block.nodeName !== "PRE") {
const text = block.textContent?.trimEnd();
if (text === "*" || text === "1.") {
event.preventDefault();
const walker = new TreeIterator(block, SHOW_TEXT);
let textNode;
while (textNode = walker.nextNode()) {
textNode.data = cantFocusEmptyTextNodes ? ZWS : "";
}
if (text === "*") {
self.makeUnorderedList();
} else {
self.makeOrderedList();
}
return;
}
}
}
node = range.endContainer;
if (range.endOffset === getLength(node)) {
@ -2029,26 +2045,80 @@ keyHandlers[ctrlKey + "y"] = keyHandlers[ctrlKey + "Shift-z"] = (self, event) =>
// source/Editor.ts
var Squire = class {
_root;
_config;
_isFocused;
_lastSelection;
_willRestoreSelection;
_mayHaveZWS;
_lastAnchorNode;
_lastFocusNode;
_path;
_events;
_undoIndex;
_undoStack;
_undoStackLength;
_isInUndoState;
_ignoreChange;
_ignoreAllChanges;
_isShiftDown;
_keyHandlers;
_mutation;
constructor(root, config) {
/**
* Subscribing to these events won't automatically add a listener to the
* document node, since these events are fired in a custom manner by the
* editor code.
*/
this.customEvents = /* @__PURE__ */ new Set([
"pathChange",
"select",
"input",
"pasteImage",
"undoStateChange"
]);
// ---
this.startSelectionId = "squire-selection-start";
this.endSelectionId = "squire-selection-end";
/*
linkRegExp = new RegExp(
// Only look on boundaries
'\\b(?:' +
// Capture group 1: URLs
'(' +
// Add links to URLS
// Starts with:
'(?:' +
// http(s):// or ftp://
'(?:ht|f)tps?:\\/\\/' +
// or
'|' +
// www.
'www\\d{0,3}[.]' +
// or
'|' +
// foo90.com/
'[a-z0-9][a-z0-9.\\-]*[.][a-z]{2,}\\/' +
')' +
// Then we get one or more:
'(?:' +
// Run of non-spaces, non ()<>
'[^\\s()<>]+' +
// or
'|' +
// balanced parentheses (one level deep only)
'\\([^\\s()<>]+\\)' +
')+' +
// And we finish with
'(?:' +
// Not a space or punctuation character
'[^\\s?&`!()\\[\\]{};:\'".,<>«»“”‘’]' +
// or
'|' +
// Balanced parentheses.
'\\([^\\s()<>]+\\)' +
')' +
// Capture group 2: Emails
')|(' +
// Add links to emails
'[\\w\\-.%+]+@(?:[\\w\\-]+\\.)+[a-z]{2,}\\b' +
// Allow query parameters in the mailto: style
'(?:' +
'[?][^&?\\s]+=[^\\s?&`!()\\[\\]{};:\'".,<>«»“”‘’]+' +
'(?:&[^&?\\s]+=[^\\s?&`!()\\[\\]{};:\'".,<>«»“”‘’]+)*' +
')?' +
'))',
'i'
);
*/
this.linkRegExp = /\b(?:((?:(?:ht|f)tps?:\/\/|www\d{0,3}[.]|[a-z0-9][a-z0-9.\-]*[.][a-z]{2,}\/)(?:[^\s()<>]+|\([^\s()<>]+\))+(?:[^\s?&`!()\[\]{};:'".,<>«»“”‘’]|\([^\s()<>]+\)))|([\w\-.%+]+@(?:[\w\-]+\.)+[a-z]{2,}\b(?:[?][^&?\s]+=[^\s?&`!()\[\]{};:'".,<>«»“”‘’]+(?:&[^&?\s]+=[^\s?&`!()\[\]{};:'".,<>«»“”‘’]+)*)?))/i;
this.tagAfterSplit = {
DT: "DD",
DD: "DT",
LI: "LI",
PRE: "PRE"
};
this._root = root;
this._config = this._makeConfig(config);
this._isFocused = false;
@ -2285,18 +2355,6 @@ var Squire = class {
}
return this;
}
/**
* Subscribing to these events won't automatically add a listener to the
* document node, since these events are fired in a custom manner by the
* editor code.
*/
customEvents = /* @__PURE__ */ new Set([
"pathChange",
"select",
"input",
"pasteImage",
"undoStateChange"
]);
addEventListener(type, fn) {
let handlers = this._events.get(type);
let target = this._root;
@ -2368,9 +2426,6 @@ var Squire = class {
removeZWS(this._root);
this._mayHaveZWS = false;
}
// ---
startSelectionId = "squire-selection-start";
endSelectionId = "squire-selection-end";
_saveRangeToBookmark(range) {
let startNode = createElement("INPUT", {
id: this.startSelectionId,
@ -3311,58 +3366,6 @@ var Squire = class {
true
);
}
/*
linkRegExp = new RegExp(
// Only look on boundaries
'\\b(?:' +
// Capture group 1: URLs
'(' +
// Add links to URLS
// Starts with:
'(?:' +
// http(s):// or ftp://
'(?:ht|f)tps?:\\/\\/' +
// or
'|' +
// www.
'www\\d{0,3}[.]' +
// or
'|' +
// foo90.com/
'[a-z0-9][a-z0-9.\\-]*[.][a-z]{2,}\\/' +
')' +
// Then we get one or more:
'(?:' +
// Run of non-spaces, non ()<>
'[^\\s()<>]+' +
// or
'|' +
// balanced parentheses (one level deep only)
'\\([^\\s()<>]+\\)' +
')+' +
// And we finish with
'(?:' +
// Not a space or punctuation character
'[^\\s?&`!()\\[\\]{};:\'".,<>«»“”‘’]' +
// or
'|' +
// Balanced parentheses.
'\\([^\\s()<>]+\\)' +
')' +
// Capture group 2: Emails
')|(' +
// Add links to emails
'[\\w\\-.%+]+@(?:[\\w\\-]+\\.)+[a-z]{2,}\\b' +
// Allow query parameters in the mailto: style
'(?:' +
'[?][^&?\\s]+=[^\\s?&`!()\\[\\]{};:\'".,<>«»“”‘’]+' +
'(?:&[^&?\\s]+=[^\\s?&`!()\\[\\]{};:\'".,<>«»“”‘’]+)*' +
')?' +
'))',
'i'
);
*/
linkRegExp = /\b(?:((?:(?:ht|f)tps?:\/\/|www\d{0,3}[.]|[a-z0-9][a-z0-9.\-]*[.][a-z]{2,}\/)(?:[^\s()<>]+|\([^\s()<>]+\))+(?:[^\s?&`!()\[\]{};:'".,<>«»“”‘’]|\([^\s()<>]+\)))|([\w\-.%+]+@(?:[\w\-]+\.)+[a-z]{2,}\b(?:[?][^&?\s]+=[^\s?&`!()\[\]{};:'".,<>«»“”‘’]+(?:&[^&?\s]+=[^\s?&`!()\[\]{};:'".,<>«»“”‘’]+)*)?))/i;
addDetectedLinks(searchInNode, root) {
const walker = new TreeIterator(
searchInNode,
@ -3480,12 +3483,6 @@ var Squire = class {
createElement(config.blockTag, config.blockAttributes, children)
);
}
tagAfterSplit = {
DT: "DD",
DD: "DT",
LI: "LI",
PRE: "PRE"
};
splitBlock(lineBreakOnly, range) {
if (!range) {
range = this.getSelection();

22
dist/squire.js vendored

File diff suppressed because one or more lines are too long

6
dist/squire.js.map vendored

File diff suppressed because one or more lines are too long

22
dist/squire.mjs vendored

File diff suppressed because one or more lines are too long

6
dist/squire.mjs.map vendored

File diff suppressed because one or more lines are too long

View file

@ -1,4 +1,4 @@
import type { Squire } from '../Editor';
declare const Space: (self: Squire, _: KeyboardEvent, range: Range) => void;
declare const Space: (self: Squire, event: KeyboardEvent, range: Range) => void;
export { Space };
//# sourceMappingURL=Space.d.ts.map

View file

@ -1 +1 @@
{"version":3,"file":"Space.d.ts","sourceRoot":"","sources":["../../../source/keyboard/Space.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAKxC,QAAA,MAAM,KAAK,SAAU,MAAM,KAAK,aAAa,SAAS,KAAK,KAAG,IA2C7D,CAAC;AAIF,OAAO,EAAE,KAAK,EAAE,CAAC"}
{"version":3,"file":"Space.d.ts","sourceRoot":"","sources":["../../../source/keyboard/Space.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAWxC,QAAA,MAAM,KAAK,SAAU,MAAM,SAAS,aAAa,SAAS,KAAK,KAAG,IA+DjE,CAAC;AAIF,OAAO,EAAE,KAAK,EAAE,CAAC"}

8783
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "squire-rte",
"version": "2.0.3",
"version": "2.1.0",
"description": "Squire is an HTML5 rich text editor, which provides powerful cross-browser normalisation, whilst being supremely lightweight and flexible.",
"main": "dist/squire.mjs",
"types": "dist/types/Squire.d.ts",
@ -32,17 +32,17 @@
"@babel/core": "^7.20.12",
"@babel/preset-env": "^7.20.2",
"@babel/preset-typescript": "^7.18.6",
"@types/jest": "^28.1.6",
"@typescript-eslint/eslint-plugin": "^5.48.1",
"@types/jest": "^29.5.5",
"@typescript-eslint/eslint-plugin": "^6.7.2",
"babel-jest": "^29.3.1",
"esbuild": "^0.16.17",
"esbuild": "^0.19.3",
"eslint": "^8.31.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^28.1.3",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.3.1",
"prettier": "^2.8.2",
"prettier": "^3.0.3",
"tslib": "^2.0.1",
"typescript": "^4.7.4"
"typescript": "^5.2.2"
}
}