Skip to content

Commit

Permalink
Introduce Turbo.config object
Browse files Browse the repository at this point in the history
The initial implementation aims to replace the ad hoc configurations
spread across `window.Turbo` and `Turbo.session`. Those objects
shouldn't be considered part of the public interface, especially for
extension.

This commit exports a single object from `src/core/config` to serve as a
centralized, user-facing repository for configuration values.

The main `src/core/config` object is composed of two constituent parts:

* `src/core/config/drive`
* `src/core/config/forms`

In the future, the directory structure can be expanded upon to suit the
needs of the project.

Any user-facing configuration outside of `Turbo.config` is deprecated.
  • Loading branch information
seanpdoyle committed Mar 29, 2024
1 parent 9fb05e3 commit 238ec26
Show file tree
Hide file tree
Showing 9 changed files with 53 additions and 18 deletions.
4 changes: 4 additions & 0 deletions src/core/config/drive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const drive = {
enabled: true,
progressBarDelay: 500
}
3 changes: 3 additions & 0 deletions src/core/config/forms.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const forms = {
mode: "on"
}
7 changes: 7 additions & 0 deletions src/core/config/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { drive } from "./drive"
import { forms } from "./forms"

export const config = {
drive,
forms
}
9 changes: 7 additions & 2 deletions src/core/drive/form_submission.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { expandURL } from "../url"
import { clearBusyState, dispatch, getAttribute, getMetaContent, hasAttribute, markAsBusy } from "../../util"
import { StreamMessage } from "../streams/stream_message"
import { prefetchCache } from "./prefetch_cache"
import { config } from "../config"

export const FormSubmissionState = {
initialized: "initialized",
Expand All @@ -22,7 +23,7 @@ export const FormEnctype = {
export class FormSubmission {
state = FormSubmissionState.initialized

static confirmMethod(message, _element, _submitter) {
static confirmMethod(message) {
return Promise.resolve(confirm(message))
}

Expand Down Expand Up @@ -78,7 +79,11 @@ export class FormSubmission {
const confirmationMessage = getAttribute("data-turbo-confirm", this.submitter, this.formElement)

if (typeof confirmationMessage === "string") {
const answer = await FormSubmission.confirmMethod(confirmationMessage, this.formElement, this.submitter)
const confirmMethod = typeof config.forms.confirm === "function" ?
config.forms.confirm :
FormSubmission.confirmMethod

const answer = await confirmMethod(confirmationMessage, this.formElement, this.submitter)
if (!answer) {
return
}
Expand Down
19 changes: 14 additions & 5 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { Session } from "./session"
import { PageRenderer } from "./drive/page_renderer"
import { PageSnapshot } from "./drive/page_snapshot"
import { FrameRenderer } from "./frames/frame_renderer"
import { FormSubmission } from "./drive/form_submission"
import { fetch, recentRequests } from "../http/fetch"
import { config } from "./config"

const session = new Session(recentRequests)
const { cache, navigator } = session
export { navigator, session, cache, PageRenderer, PageSnapshot, FrameRenderer, fetch }
export { navigator, session, cache, PageRenderer, PageSnapshot, FrameRenderer, fetch, config }

/**
* Starts the main session.
Expand Down Expand Up @@ -97,13 +97,22 @@ export function clearCache() {
* @param delay Time to delay in milliseconds
*/
export function setProgressBarDelay(delay) {
session.setProgressBarDelay(delay)
console.warn(
"Please replace `Turbo.setProgressBarDelay(delay)` with `Turbo.config.drive.progressBarDelay = delay`. The top-level function is deprecated and will be removed in a future version of Turbo.`"
)
config.drive.progressBarDelay = delay
}

export function setConfirmMethod(confirmMethod) {
FormSubmission.confirmMethod = confirmMethod
console.warn(
"Please replace `Turbo.setConfirmMethod(confirmMethod)` with `Turbo.config.forms.confirm = confirmMethod`. The top-level function is deprecated and will be removed in a future version of Turbo.`"
)
config.forms.confirm = confirmMethod
}

export function setFormMode(mode) {
session.setFormMode(mode)
console.warn(
"Please replace `Turbo.setFormMode(mode)` with `Turbo.config.forms.mode = mode`. The top-level function is deprecated and will be removed in a future version of Turbo.`"
)
config.forms.mode = mode
}
22 changes: 14 additions & 8 deletions src/core/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { PageView } from "./drive/page_view"
import { FrameElement } from "../elements/frame_element"
import { Preloader } from "./drive/preloader"
import { Cache } from "./cache"
import { config } from "./config"

export class Session {
navigator = new Navigator(this)
Expand All @@ -37,11 +38,8 @@ export class Session {
streamMessageRenderer = new StreamMessageRenderer()
cache = new Cache(this)

drive = true
enabled = true
progressBarDelay = 500
started = false
formMode = "on"
#pageRefreshDebouncePeriod = 150

constructor(recentRequests) {
Expand Down Expand Up @@ -131,11 +129,19 @@ export class Session {
}

setProgressBarDelay(delay) {
console.warn(
"Please replace `session.setProgressBarDelay(delay)` with `session.progressBarDelay = delay`. The function is deprecated and will be removed in a future version of Turbo.`"
)

this.progressBarDelay = delay
}

setFormMode(mode) {
this.formMode = mode
set progressBarDelay(delay) {
config.drive.progressBarDelay = delay
}

get progressBarDelay() {
return config.drive.progressBarDelay
}

get location() {
Expand Down Expand Up @@ -425,12 +431,12 @@ export class Session {
// Helpers

submissionIsNavigatable(form, submitter) {
if (this.formMode == "off") {
if (config.forms.mode == "off") {
return false
} else {
const submitterIsNavigatable = submitter ? this.elementIsNavigatable(submitter) : true

if (this.formMode == "optin") {
if (config.forms.mode == "optin") {
return submitterIsNavigatable && form.closest('[data-turbo="true"]') != null
} else {
return submitterIsNavigatable && this.elementIsNavigatable(form)
Expand All @@ -443,7 +449,7 @@ export class Session {
const withinFrame = findClosestRecursively(element, "turbo-frame")

// Check if Drive is enabled on the session or we're within a Frame.
if (this.drive || withinFrame) {
if (config.drive.enabled || withinFrame) {
// Element is navigatable by default, unless `data-turbo="false"`.
if (container) {
return container.getAttribute("data-turbo") != "false"
Expand Down
2 changes: 1 addition & 1 deletion src/tests/fixtures/drive_disabled.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
})
</script>
<script>
Turbo.session.drive = false
Turbo.config.drive = false
</script>
</head>
<body>
Expand Down
4 changes: 2 additions & 2 deletions src/tests/functional/form_submission_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -1142,7 +1142,7 @@ test("following a link with [data-turbo-method] and [data-turbo=true] set when h
test("following a link with [data-turbo-method] and [data-turbo=true] set when Turbo.session.drive = false", async ({
page
}) => {
await page.evaluate(() => (window.Turbo.session.drive = false))
await page.evaluate(() => (window.Turbo.config.drive = false))

const link = await page.locator("#turbo-method-post-to-targeted-frame")
await link.evaluate((link) => link.setAttribute("data-turbo", "true"))
Expand All @@ -1163,7 +1163,7 @@ test("following a link with [data-turbo-method] set when html[data-turbo=false]"
})

test("following a link with [data-turbo-method] set when Turbo.session.drive = false", async ({ page }) => {
await page.evaluate(() => (window.Turbo.session.drive = false))
await page.evaluate(() => (window.Turbo.config.drive = false))
await page.click("#turbo-method-post-to-targeted-frame")

assert.equal(await page.textContent("h1"), "Hello", "treats link full-page navigation")
Expand Down
1 change: 1 addition & 0 deletions src/tests/unit/export_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ test("Turbo interface", () => {
assert.equal(typeof Turbo.setConfirmMethod, "function")
assert.equal(typeof Turbo.setFormMode, "function")
assert.equal(typeof Turbo.cache, "object")
assert.equal(typeof Turbo.config, "object")
assert.equal(typeof Turbo.cache.clear, "function")
assert.equal(typeof Turbo.navigator, "object")
assert.equal(typeof Turbo.session, "object")
Expand Down

0 comments on commit 238ec26

Please sign in to comment.