Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,18 @@ To populate a `<trix-editor>` with stored content, include that content in the a
</form>
```

Always use an associated input element to safely populate an editor. Trix won’t load any HTML content inside a `<trix-editor>…</trix-editor>` tag.
Use an associated input element to initially populate an editor. When an associated input element is absent, Trix will safely sanitize then load any HTML content inside a `<trix-editor>…</trix-editor>` tag.

```html
<form …>
<trix-editor>Editor content goes here</trix-editor>
</form>
```

> [!WARNING]
> When a `<trix-editor>` element initially connects with both HTML content *and*
> an associated input element, Trix will *always* disregard the HTML content and
> load its initial content from the associated input element.

## Validating the Editor

Expand Down
3 changes: 2 additions & 1 deletion action_text-trix/app/assets/javascripts/trix.js
Original file line number Diff line number Diff line change
Expand Up @@ -13720,6 +13720,7 @@ $\
triggerEvent("trix-before-initialize", {
onElement: this
});
this.defaultValue = this.inputElement ? this.inputElement.value : this.innerHTML;
if (!this.hasAttribute("input") && this.parentNode && this.willCreateInput) {
const inputId = "trix-input-".concat(this.trixId);
this.setAttribute("input", inputId);
Expand All @@ -13731,7 +13732,7 @@ $\
}
this.editorController = new EditorController({
editorElement: this,
html: this.defaultValue = this.value
html: this.defaultValue
});
requestAnimationFrame(() => triggerEvent("trix-initialize", {
onElement: this
Expand Down
37 changes: 36 additions & 1 deletion src/test/system/installation_process_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import EditorController from "trix/controllers/editor_controller"

import { assert, test, testGroup } from "test/test_helper"
import { assert, setFixtureHTML, test, testGroup } from "test/test_helper"
import { nextFrame } from "../test_helpers/timing_helpers"

testGroup("Installation process", { template: "editor_html" }, () => {
Expand Down Expand Up @@ -62,3 +62,38 @@ testGroup("Installation process with specified elements", { template: "editor_wi
assert.equal(editorElement.value, "<div>Hello world</div>")
})
})

testGroup("Installation process with content and without specified elements", () => {
test("loads the trix-editor element's innerHTML on boot", async () => {
await setFixtureHTML("<trix-editor><div>Hello world</div></trix-editor>")

const editorElement = getEditorElement()

assert.equal(1, editorElement.childElementCount, "sanitzes HTML")
assert.equal(editorElement.value, "<div>Hello world</div>")
assert.equal(editorElement.value, editorElement.inputElement.value)
})

test("sanitizes the trix-editor element's innerHTML on boot", async () => {
await setFixtureHTML("<trix-editor><script>alert('xss')</script></trix-editor>")

const editorElement = getEditorElement()

assert.equal(0, editorElement.querySelectorAll("script").length, "sanitzes HTML")
assert.equal(editorElement.value, "")
assert.equal(editorElement.value, editorElement.inputElement.value)
})
})

testGroup("Installation process with content and input", () => {
test("prioritzes loading its initial state from the input over the content", async () => {
await setFixtureHTML(`
<trix-editor input="input"><div>from editor</div></trix-editor>
<textarea id="input"><div>from input</div></textarea>
`)

const editorElement = getEditorElement()

assert.equal(editorElement.value, "<div>from input</div>")
})
})
3 changes: 2 additions & 1 deletion src/trix/elements/trix_editor_element.js
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ export default class TrixEditorElement extends HTMLElement {

if (!this.editorController) {
triggerEvent("trix-before-initialize", { onElement: this })
this.defaultValue = this.inputElement ? this.inputElement.value : this.innerHTML
if (!this.hasAttribute("input") && this.parentNode && this.willCreateInput) {
const inputId = `trix-input-${this.trixId}`
this.setAttribute("input", inputId)
Expand All @@ -571,7 +572,7 @@ export default class TrixEditorElement extends HTMLElement {
}
this.editorController = new EditorController({
editorElement: this,
html: this.defaultValue = this.value
html: this.defaultValue
})
requestAnimationFrame(() => triggerEvent("trix-initialize", { onElement: this }))
}
Expand Down