Skip to content

Commit

Permalink
Set html[lang] during navigation
Browse files Browse the repository at this point in the history
Closes [hotwired#967][]

Change the `<html>` element's `[lang]` attribute during navigation.
Currently, this isn't possible from applications (without a lot of
trouble), since the [turbo:before-render][] event is scoped to the
`newBody`.

In order to support this behavior, change the `PageSnapshot` constructor
to accept an instance of [HTMLHtmlElement][] (the `<html>` element) so
that that element can be accessible from the `PageRenderer`.

[hotwired#967]: hotwired#967
[turbo:before-render]: https://turbo.hotwired.dev/reference/events
[HTMLHtmlElement]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLHtmlElement
  • Loading branch information
seanpdoyle committed Oct 12, 2023
1 parent c207f5b commit 1573ae3
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 5 deletions.
12 changes: 12 additions & 0 deletions src/core/drive/page_renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class PageRenderer extends Renderer {
}

async prepareToRender() {
this.#setLanguage()
await this.mergeHead()
}

Expand Down Expand Up @@ -57,6 +58,17 @@ export class PageRenderer extends Renderer {
return this.newSnapshot.element
}

#setLanguage() {
const { documentElement } = this.currentSnapshot
const { lang } = this.newSnapshot

if (lang) {
documentElement.setAttribute("lang", lang)
} else {
documentElement.removeAttribute("lang")
}
}

async mergeHead() {
const mergedHeadElements = this.mergeProvisionalElements()
const newStylesheetElements = this.copyNewHeadStylesheetElements()
Expand Down
15 changes: 10 additions & 5 deletions src/core/drive/page_snapshot.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ export class PageSnapshot extends Snapshot {
return this.fromDocument(element.ownerDocument)
}

static fromDocument({ head, body }) {
return new this(body, new HeadSnapshot(head))
static fromDocument({ documentElement, body, head }) {
return new this(documentElement, body, new HeadSnapshot(head))
}

constructor(element, headSnapshot) {
super(element)
constructor(documentElement, body, headSnapshot) {
super(body)
this.documentElement = documentElement
this.headSnapshot = headSnapshot
}

Expand All @@ -37,7 +38,11 @@ export class PageSnapshot extends Snapshot {
clonedPasswordInput.value = ""
}

return new PageSnapshot(clonedElement, this.headSnapshot)
return new PageSnapshot(this.documentElement, clonedElement, this.headSnapshot)
}

get lang() {
return this.documentElement.getAttribute("lang")
}

get html() {
Expand Down
12 changes: 12 additions & 0 deletions src/tests/fixtures/es_locale.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Turbo</title>
<script src="/dist/turbo.es2017-umd.js" data-turbo-track="reload"></script>
<script src="/src/tests/fixtures/test.js"></script>
</head>
<body>
<h1>html[lang="es"]</h1>
</body>
</html>
1 change: 1 addition & 0 deletions src/tests/fixtures/rendering.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ <h1>Rendering</h1>
<p><a id="permanent-in-frame-element-link" href="/src/tests/fixtures/permanent_element.html" data-turbo-frame="frame">Permanent element in frame</a></p>
<p><a id="delayed-link" href="/__turbo/delayed_response">Delayed link</a></p>
<p><a id="redirect-link" href="/__turbo/redirect">Redirect link</a></p>
<p><a id="es_locale_link" href="/src/tests/fixtures/es_locale.html">Change html[lang]</a></p>
<form>
<input type="text" id="text-input">
<input type="radio" id="radio-input">
Expand Down
7 changes: 7 additions & 0 deletions src/tests/functional/rendering_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,13 @@ test("test maintains scroll position before visit when turbo-visit-control setti
assert.equal(await visitAction(page), "load")
})

test("test changes the html[lang] attribute", async ({ page }) => {
await page.click("#es_locale_link")
await nextEventNamed(page, "turbo:load")

assert.equal(await page.getAttribute("html", "lang"), "es")
})

test("test accumulates asset elements in head", async ({ page }) => {
const assetElements = () => page.$$('script, style, link[rel="stylesheet"]')
const originalElements = await assetElements()
Expand Down

0 comments on commit 1573ae3

Please sign in to comment.