Skip to content

Commit dda3e02

Browse files
authored
Merge pull request rails#47679 from smridge/update-trix
Update Action Text's Trix dependency (2.0.4)
2 parents cf80ede + de317f9 commit dda3e02

File tree

6 files changed

+1216
-1151
lines changed

6 files changed

+1216
-1151
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ jobs:
4040
python -m pip install --upgrade pip
4141
pip install codespell==2.1.0
4242
- name: Check spelling with codespell
43-
run: codespell --ignore-words=codespell.txt --skip="./actionview/test/ujs/public/vendor/qunit.js" || exit 1
43+
run: codespell --ignore-words=codespell.txt --skip="./actionview/test/ujs/public/vendor/qunit.js,./actiontext/app/assets/javascripts/trix.js" || exit 1
4444

4545
notify:
4646
runs-on: ubuntu-latest

actiontext/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
* Update bundled Trix version from `1.3.1` to `2.0.4`.
1111

12-
*Sean Doyle*
12+
*Sarah Ridge*, *Sean Doyle*
1313

1414
* Apply `field_error_proc` to `rich_text_area` form fields.
1515

actiontext/app/assets/javascripts/trix.js

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
/*
2-
Trix 2.0.0
3-
Copyright © 2022 Basecamp, LLC
2+
Trix 2.0.4
3+
Copyright © 2022 37signals, LLC
44
*/
55
var name = "trix";
6-
var version = "2.0.0";
6+
var version = "2.0.4";
77
var description = "A rich text editor for everyday writing";
88
var main = "dist/trix.umd.min.js";
99
var module = "dist/trix.esm.min.js";
@@ -21,7 +21,7 @@ var keywords = [
2121
"wysiwyg",
2222
"editor"
2323
];
24-
var author = "Basecamp, LLC";
24+
var author = "37signals, LLC";
2525
var license = "MIT";
2626
var bugs = {
2727
url: "https://github.com/basecamp/trix/issues"
@@ -39,7 +39,7 @@ var devDependencies = {
3939
concurrently: "^7.4.0",
4040
eslint: "^7.32.0",
4141
esm: "^3.2.25",
42-
karma: "6.4.0",
42+
karma: "6.4.1",
4343
"karma-chrome-launcher": "3.1.1",
4444
"karma-qunit": "^4.1.2",
4545
"karma-sauce-launcher": "^4.3.6",
@@ -51,6 +51,9 @@ var devDependencies = {
5151
"rollup-plugin-terser": "^7.0.2",
5252
svgo: "^2.8.0"
5353
};
54+
var resolutions = {
55+
webdriverio: "^7.19.5"
56+
};
5457
var scripts = {
5558
"build-css": "node-sass --functions=./assets/trix/stylesheets/functions assets/trix.scss dist/trix.css",
5659
"build-js": "rollup -c",
@@ -83,6 +86,7 @@ var _package = {
8386
bugs: bugs,
8487
homepage: homepage,
8588
devDependencies: devDependencies,
89+
resolutions: resolutions,
8690
scripts: scripts,
8791
dependencies: dependencies
8892
};
@@ -170,26 +174,21 @@ const tagName$1 = element => {
170174
return element === null || element === void 0 ? void 0 : (_element$tagName = element.tagName) === null || _element$tagName === void 0 ? void 0 : _element$tagName.toLowerCase();
171175
};
172176

177+
const androidVersionMatch = navigator.userAgent.match(/android\s([0-9]+.*Chrome)/i);
178+
const androidVersion = androidVersionMatch && parseInt(androidVersionMatch[1]);
173179
var browser$1 = {
174180
// Android emits composition events when moving the cursor through existing text
175181
// Introduced in Chrome 65: https://bugs.chromium.org/p/chromium/issues/detail?id=764439#c9
176182
composesExistingText: /Android.*Chrome/.test(navigator.userAgent),
183+
// Android 13, especially on Samsung keyboards, emits extra compositionend and beforeinput events
184+
// that can make the input handler lose the the current selection or enter an infinite input -> render -> input
185+
// loop.
186+
recentAndroid: androidVersion && androidVersion > 12,
187+
samsungAndroid: androidVersion && navigator.userAgent.match(/Android.*SM-/),
177188
// IE 11 activates resizing handles on editable elements that have "layout"
178189
forcesObjectResizing: /Trident.*rv:11/.test(navigator.userAgent),
179190
// https://www.w3.org/TR/input-events-1/ + https://www.w3.org/TR/input-events-2/
180-
supportsInputEvents: function () {
181-
if (typeof InputEvent === "undefined") {
182-
return false;
183-
}
184-
185-
for (const property of ["data", "getTargetRanges", "inputType"]) {
186-
if (!(property in InputEvent.prototype)) {
187-
return false;
188-
}
189-
}
190-
191-
return true;
192-
}()
191+
supportsInputEvents: typeof InputEvent !== "undefined" && ["data", "getTargetRanges", "inputType"].every(prop => prop in InputEvent.prototype)
193192
};
194193

195194
var css$3 = {
@@ -10089,12 +10088,75 @@ class FileVerificationOperation extends Operation {
1008910088

1009010089
}
1009110090

10091+
// This class detects when some buggy events are being emmitted and lets know the input controller
10092+
// that they should be ignored.
10093+
10094+
class FlakyAndroidKeyboardDetector {
10095+
constructor(element) {
10096+
this.element = element;
10097+
}
10098+
10099+
shouldIgnore(event) {
10100+
if (!browser$1.samsungAndroid) return false;
10101+
this.previousEvent = this.event;
10102+
this.event = event;
10103+
this.checkSamsungKeyboardBuggyModeStart();
10104+
this.checkSamsungKeyboardBuggyModeEnd();
10105+
return this.buggyMode;
10106+
} // private
10107+
// The Samsung keyboard on Android can enter a buggy state in which it emmits a flurry of confused events that,
10108+
// if processed, corrupts the editor. The buggy mode always starts with an insertText event, right after a
10109+
// keydown event with for an "Unidentified" key, with the same text as the editor element, except for a few
10110+
// extra whitespace, or exotic utf8, characters.
10111+
10112+
10113+
checkSamsungKeyboardBuggyModeStart() {
10114+
if (this.insertingLongTextAfterUnidentifiedChar() && differsInWhitespace(this.element.innerText, this.event.data)) {
10115+
this.buggyMode = true;
10116+
this.event.preventDefault();
10117+
}
10118+
} // The flurry of buggy events are always insertText. If we see any other type, it means it's over.
10119+
10120+
10121+
checkSamsungKeyboardBuggyModeEnd() {
10122+
if (this.buggyMode && this.event.inputType !== "insertText") {
10123+
this.buggyMode = false;
10124+
}
10125+
}
10126+
10127+
insertingLongTextAfterUnidentifiedChar() {
10128+
var _this$event$data;
10129+
10130+
return this.isBeforeInputInsertText() && this.previousEventWasUnidentifiedKeydown() && ((_this$event$data = this.event.data) === null || _this$event$data === void 0 ? void 0 : _this$event$data.length) > 50;
10131+
}
10132+
10133+
isBeforeInputInsertText() {
10134+
return this.event.type === "beforeinput" && this.event.inputType === "insertText";
10135+
}
10136+
10137+
previousEventWasUnidentifiedKeydown() {
10138+
var _this$previousEvent, _this$previousEvent2;
10139+
10140+
return ((_this$previousEvent = this.previousEvent) === null || _this$previousEvent === void 0 ? void 0 : _this$previousEvent.type) === "keydown" && ((_this$previousEvent2 = this.previousEvent) === null || _this$previousEvent2 === void 0 ? void 0 : _this$previousEvent2.key) === "Unidentified";
10141+
}
10142+
10143+
}
10144+
10145+
const differsInWhitespace = (text1, text2) => {
10146+
return normalize(text1) === normalize(text2);
10147+
};
10148+
10149+
const whiteSpaceNormalizerRegexp = new RegExp("(".concat(OBJECT_REPLACEMENT_CHARACTER, "|").concat(ZERO_WIDTH_SPACE, "|").concat(NON_BREAKING_SPACE, "|\\s)+"), "g");
10150+
10151+
const normalize = text => text.replace(whiteSpaceNormalizerRegexp, " ").trim();
10152+
1009210153
class InputController extends BasicObject {
1009310154
constructor(element) {
1009410155
super(...arguments);
1009510156
this.element = element;
1009610157
this.mutationObserver = new MutationObserver(this.element);
1009710158
this.mutationObserver.delegate = this;
10159+
this.flakyKeyboardDetector = new FlakyAndroidKeyboardDetector(this.element);
1009810160

1009910161
for (const eventName in this.constructor.events) {
1010010162
handleEvent(eventName, {
@@ -10146,6 +10208,7 @@ class InputController extends BasicObject {
1014610208
if (!event.defaultPrevented) {
1014710209
this.handleInput(() => {
1014810210
if (!innerElementIsActive(this.element)) {
10211+
if (this.flakyKeyboardDetector.shouldIgnore(event)) return;
1014910212
this.eventName = eventName;
1015010213
this.constructor.events[eventName].call(this, event);
1015110214
}
@@ -11198,12 +11261,12 @@ _defineProperty(Level2InputController, "events", {
1119811261

1119911262
if (handler) {
1120011263
this.withEvent(event, handler);
11201-
return this.scheduleRender();
11264+
this.scheduleRender();
1120211265
}
1120311266
},
1120411267

1120511268
input(event) {
11206-
return selectionChangeObserver.reset();
11269+
selectionChangeObserver.reset();
1120711270
},
1120811271

1120911272
dragstart(event) {
@@ -11273,7 +11336,7 @@ _defineProperty(Level2InputController, "events", {
1127311336
compositionend(event) {
1127411337
if (this.composing) {
1127511338
this.composing = false;
11276-
return this.scheduleRender();
11339+
if (!browser$1.recentAndroid) this.scheduleRender();
1127711340
}
1127811341
}
1127911342

@@ -12996,7 +13059,9 @@ const Trix = {
1299613059
operations,
1299713060
elements,
1299813061
filters
12999-
};
13062+
}; // Expose models under the Trix constant for compatibility with v1
13063+
13064+
Object.assign(Trix, models);
1300013065

1300113066
function start() {
1300213067
if (!customElements.get("trix-toolbar")) {

actiontext/app/assets/stylesheets/trix.css

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ trix-toolbar .trix-button-group {
2424
border-radius: 3px; }
2525
trix-toolbar .trix-button-group:not(:first-child) {
2626
margin-left: 1.5vw; }
27-
@media (max-device-width: 768px) {
27+
@media (max-width: 768px) {
2828
trix-toolbar .trix-button-group:not(:first-child) {
2929
margin-left: 0; } }
3030

3131
trix-toolbar .trix-button-group-spacer {
3232
flex-grow: 1; }
33-
@media (max-device-width: 768px) {
33+
@media (max-width: 768px) {
3434
trix-toolbar .trix-button-group-spacer {
3535
display: none; } }
3636

@@ -57,7 +57,7 @@ trix-toolbar .trix-button {
5757
cursor: pointer; }
5858
trix-toolbar .trix-button:disabled {
5959
color: rgba(0, 0, 0, 0.125); }
60-
@media (max-device-width: 768px) {
60+
@media (max-width: 768px) {
6161
trix-toolbar .trix-button {
6262
letter-spacing: -0.01em;
6363
padding: 0 0.3em; } }
@@ -68,7 +68,7 @@ trix-toolbar .trix-button--icon {
6868
height: 1.6em;
6969
max-width: calc(0.8em + 4vw);
7070
text-indent: -9999px; }
71-
@media (max-device-width: 768px) {
71+
@media (max-width: 768px) {
7272
trix-toolbar .trix-button--icon {
7373
height: 2em;
7474
max-width: calc(0.8em + 3.5vw); } }
@@ -84,7 +84,7 @@ trix-toolbar .trix-button--icon {
8484
background-position: center;
8585
background-repeat: no-repeat;
8686
background-size: contain; }
87-
@media (max-device-width: 768px) {
87+
@media (max-width: 768px) {
8888
trix-toolbar .trix-button--icon::before {
8989
right: 6%;
9090
left: 6%; } }

actiontext/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
],
2323
"license": "MIT",
2424
"dependencies": {
25-
"@rails/activestorage": ">= 7.0.0-alpha1"
25+
"@rails/activestorage": ">= 7.0.0-alpha1",
26+
"webpack": "^4.17.1"
2627
},
2728
"peerDependencies": {
2829
"trix": "^2.0.0"

0 commit comments

Comments
 (0)