Skip to content

Commit e94cfb1

Browse files
authored
Merge branch 'basecamp:main' into main
2 parents 189194b + 1e214a7 commit e94cfb1

File tree

8 files changed

+123
-19
lines changed

8 files changed

+123
-19
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ For example, to apply bold styling to the selected text the button is:
7878

7979
Trix will determine that a range of text is selected and will apply the formatting defined in `Trix.config.textAttributes` (found in `config/text_attributes.js`).
8080

81-
`data-trix-key="b"` tells Trix that this attribute should be applied when you use <kbd>meta</kbd>+<kbd>b</kdb>
81+
`data-trix-key="b"` tells Trix that this attribute should be applied when you use <kbd>meta</kbd>+<kbd>b</kdb>.
8282

8383
If the attribute is defined in `Trix.config.blockAttributes`, Trix will apply the attribute to the current block of text.
8484

@@ -253,7 +253,7 @@ pseudo-class][:disabled].
253253
254254
## Providing an Accessible Name
255255
256-
Like other form controls, `<trix-editor>` elements should have an accessible name. The `<trix-editor>` element integrates with `<label>` elements and The `<trix-editor>` supports two styles of integrating with `<label>` elements:
256+
Like other form controls, `<trix-editor>` elements should have an accessible name. The `<trix-editor>` element integrates with `<label>` elements. It supports two styles of integrating with `<label>` elements:
257257
258258
1. render the `<trix-editor>` element with an `[id]` attribute that the `<label>` element references through its `[for]` attribute:
259259

karma.conf.js

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,25 +53,12 @@ if (process.env.SAUCE_ACCESS_KEY) {
5353
browserVersion: "latest",
5454
"moz:debuggerAddress": true
5555
},
56-
sl_safari_12_1: {
57-
base: "SauceLabs",
58-
browserName: "safari",
59-
platform: "macOS 10.13",
60-
version: "12.1"
61-
},
6256
sl_edge_latest: {
6357
base: "SauceLabs",
6458
browserName: "microsoftedge",
6559
platform: "Windows 10",
6660
version: "latest"
6761
},
68-
sl_ios_latest: {
69-
base: "SauceLabs",
70-
browserName: "safari",
71-
platform: "ios",
72-
device: "iPhone X Simulator",
73-
version: "13.0"
74-
},
7562
sl_android_9: {
7663
base: "SauceLabs",
7764
browserName: "chrome",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "trix",
3-
"version": "2.1.12",
3+
"version": "2.1.13",
44
"description": "A rich text editor for everyday writing",
55
"main": "dist/trix.umd.min.js",
66
"module": "dist/trix.esm.min.js",

src/test/system.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import "test/system/html_replacement_test"
1515
import "test/system/installation_process_test"
1616
import "test/system/level_2_input_test"
1717
import "test/system/list_formatting_test"
18+
import "test/system/morphing_test"
1819
import "test/system/mutation_input_test"
1920
import "test/system/pasting_test"
2021
import "test/system/set_selected_range_test"

src/test/system/morphing_test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { assert, test, testGroup } from "test/test_helper"
2+
import { nextFrame } from "../test_helpers/timing_helpers"
3+
4+
testGroup("morphing with internal toolbar", { template: "editor_empty" }, () => {
5+
test("removing the 'connected' attribute will reset the editor and recreate toolbar", async () => {
6+
const element = getEditorElement()
7+
8+
assert.ok(element.hasAttribute("connected"))
9+
10+
const originalToolbar = element.toolbarElement
11+
element.toolbarElement.remove()
12+
element.removeAttribute("toolbar")
13+
element.removeAttribute("connected")
14+
await nextFrame()
15+
16+
assert.ok(element.hasAttribute("connected"))
17+
assert.ok(element.toolbarElement)
18+
assert.notEqual(originalToolbar, element.toolbarElement)
19+
})
20+
})
21+
22+
testGroup("morphing with external toolbar", { template: "editor_with_toolbar_and_input" }, () => {
23+
test("removing the 'connected' attribute will reset the editor leave the toolbar untouched", async () => {
24+
const element = getEditorElement()
25+
26+
assert.ok(element.hasAttribute("connected"))
27+
28+
const originalToolbar = element.toolbarElement
29+
element.removeAttribute("connected")
30+
await nextFrame()
31+
32+
assert.ok(element.hasAttribute("connected"))
33+
assert.ok(element.toolbarElement)
34+
assert.equal(originalToolbar, element.toolbarElement)
35+
})
36+
})

src/test/unit.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import "test/unit/block_test"
44
import "test/unit/composition_test"
55
import "test/unit/document_test"
66
import "test/unit/document_view_test"
7+
import "test/unit/helpers/custom_elements_test"
78
import "test/unit/html_parser_test"
89
import "test/unit/html_sanitizer_test"
910
import "test/unit/location_mapper_test"
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { assert, test, testGroup } from "test/test_helper"
2+
import { installDefaultCSSForTagName, makeElement } from "trix/core/helpers"
3+
4+
let meta = null
5+
6+
const insertMeta = (attributes) => {
7+
meta = makeElement("meta", attributes)
8+
document.head.append(meta)
9+
}
10+
11+
const installDefaultCSS = (tagName, css) => {
12+
installDefaultCSSForTagName(tagName, css)
13+
14+
return document.querySelector(`style[data-tag-name=${tagName}]`)
15+
}
16+
17+
const teardown = () => meta.remove()
18+
19+
testGroup("Helpers: Custom Elements", { teardown }, () => {
20+
test("reads from meta[name=csp-nonce][content]", () => {
21+
insertMeta({ name: "csp-nonce", content: "abc123" })
22+
23+
const style = installDefaultCSS("trix-element", "trix-element { display: block; }")
24+
25+
assert.equal(style.getAttribute("nonce"), "abc123")
26+
assert.equal(style.innerHTML, "trix-element { display: block; }")
27+
})
28+
29+
test("reads from meta[name=trix-csp-nonce][content]", () => {
30+
insertMeta({ name: "trix-csp-nonce", content: "abc123" })
31+
32+
const style = installDefaultCSS("trix-element", "trix-element { display: block; }")
33+
34+
assert.equal(style.getAttribute("nonce"), "abc123")
35+
assert.equal(style.innerHTML, "trix-element { display: block; }")
36+
})
37+
38+
test("reads from meta[name=csp-nonce][nonce]", () => {
39+
insertMeta({ name: "csp-nonce", nonce: "abc123" })
40+
41+
const style = installDefaultCSS("trix-element", "trix-element { display: block; }")
42+
43+
assert.equal(style.getAttribute("nonce"), "abc123")
44+
assert.equal(style.innerHTML, "trix-element { display: block; }")
45+
})
46+
47+
test("reads from meta[name=trix-csp-nonce][nonce]", () => {
48+
insertMeta({ name: "trix-csp-nonce", nonce: "abc123" })
49+
50+
const style = installDefaultCSS("trix-element", "trix-element { display: block; }")
51+
52+
assert.equal(style.getAttribute("nonce"), "abc123")
53+
assert.equal(style.innerHTML, "trix-element { display: block; }")
54+
})
55+
})

src/trix/elements/trix_editor_element.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ class LegacyDelegate {
348348
export default class TrixEditorElement extends HTMLElement {
349349
static formAssociated = "ElementInternals" in window
350350

351+
static observedAttributes = [ "connected" ]
352+
351353
#delegate
352354

353355
constructor() {
@@ -410,9 +412,9 @@ export default class TrixEditorElement extends HTMLElement {
410412
} else if (this.parentNode) {
411413
const toolbarId = `trix-toolbar-${this.trixId}`
412414
this.setAttribute("toolbar", toolbarId)
413-
const element = makeElement("trix-toolbar", { id: toolbarId })
414-
this.parentNode.insertBefore(element, this)
415-
return element
415+
this.internalToolbar = makeElement("trix-toolbar", { id: toolbarId })
416+
this.parentNode.insertBefore(this.internalToolbar, this)
417+
return this.internalToolbar
416418
} else {
417419
return undefined
418420
}
@@ -453,6 +455,14 @@ export default class TrixEditorElement extends HTMLElement {
453455
this.editor?.loadHTML(this.defaultValue)
454456
}
455457

458+
// Element callbacks
459+
460+
attributeChangedCallback(name, oldValue, newValue) {
461+
if (name === "connected" && this.isConnected && oldValue != null && oldValue !== newValue) {
462+
requestAnimationFrame(() => this.reconnect())
463+
}
464+
}
465+
456466
// Controller delegate methods
457467

458468
notify(message, data) {
@@ -485,13 +495,27 @@ export default class TrixEditorElement extends HTMLElement {
485495
}
486496
this.editorController.registerSelectionManager()
487497
this.#delegate.connectedCallback()
498+
499+
this.toggleAttribute("connected", true)
488500
autofocus(this)
489501
}
490502
}
491503

492504
disconnectedCallback() {
493505
this.editorController?.unregisterSelectionManager()
494506
this.#delegate.disconnectedCallback()
507+
this.toggleAttribute("connected", false)
508+
}
509+
510+
reconnect() {
511+
this.removeInternalToolbar()
512+
this.disconnectedCallback()
513+
this.connectedCallback()
514+
}
515+
516+
removeInternalToolbar() {
517+
this.internalToolbar?.remove()
518+
this.internalToolbar = null
495519
}
496520

497521
// Form support

0 commit comments

Comments
 (0)