diff --git a/src/core/frames/frame_controller.ts b/src/core/frames/frame_controller.ts index cf39a3af6..9282a597c 100644 --- a/src/core/frames/frame_controller.ts +++ b/src/core/frames/frame_controller.ts @@ -288,7 +288,11 @@ export class FrameController // View delegate - allowsImmediateRender({ element: newFrame }: Snapshot, options: ViewRenderOptions) { + allowsImmediateRender( + { element: newFrame }: Snapshot, + _isPreview: boolean, + options: ViewRenderOptions + ) { const event = dispatch("turbo:before-frame-render", { target: this.element, detail: { newFrame, ...options }, diff --git a/src/core/session.ts b/src/core/session.ts index d988ef3bb..31eab98f4 100644 --- a/src/core/session.ts +++ b/src/core/session.ts @@ -26,14 +26,16 @@ import { Preloader, PreloaderDelegate } from "./drive/preloader" export type FormMode = "on" | "off" | "optin" export type TimingData = unknown export type TurboBeforeCacheEvent = CustomEvent -export type TurboBeforeRenderEvent = CustomEvent<{ newBody: HTMLBodyElement } & PageViewRenderOptions> +export type TurboBeforeRenderEvent = CustomEvent< + { newBody: HTMLBodyElement; isPreview: boolean } & PageViewRenderOptions +> export type TurboBeforeVisitEvent = CustomEvent<{ url: string }> export type TurboClickEvent = CustomEvent<{ url: string; originalEvent: MouseEvent }> export type TurboFrameLoadEvent = CustomEvent export type TurboBeforeFrameRenderEvent = CustomEvent<{ newFrame: FrameElement } & FrameViewRenderOptions> export type TurboFrameRenderEvent = CustomEvent<{ fetchResponse: FetchResponse }> export type TurboLoadEvent = CustomEvent<{ url: string; timing: TimingData }> -export type TurboRenderEvent = CustomEvent +export type TurboRenderEvent = CustomEvent<{ isPreview: boolean }> export type TurboVisitEvent = CustomEvent<{ url: string; action: Action }> export class Session @@ -276,8 +278,8 @@ export class Session } } - allowsImmediateRender({ element }: PageSnapshot, options: PageViewRenderOptions) { - const event = this.notifyApplicationBeforeRender(element, options) + allowsImmediateRender({ element }: PageSnapshot, isPreview: boolean, options: PageViewRenderOptions) { + const event = this.notifyApplicationBeforeRender(element, isPreview, options) const { defaultPrevented, detail: { render }, @@ -290,9 +292,9 @@ export class Session return !defaultPrevented } - viewRenderedSnapshot(_snapshot: PageSnapshot, _isPreview: boolean) { + viewRenderedSnapshot(_snapshot: PageSnapshot, isPreview: boolean) { this.view.lastRenderedLocation = this.history.location - this.notifyApplicationAfterRender() + this.notifyApplicationAfterRender(isPreview) } preloadOnLoadLinksForView(element: Element) { @@ -348,15 +350,15 @@ export class Session return dispatch("turbo:before-cache") } - notifyApplicationBeforeRender(newBody: HTMLBodyElement, options: PageViewRenderOptions) { + notifyApplicationBeforeRender(newBody: HTMLBodyElement, isPreview: boolean, options: PageViewRenderOptions) { return dispatch("turbo:before-render", { - detail: { newBody, ...options }, + detail: { newBody, isPreview, ...options }, cancelable: true, }) } - notifyApplicationAfterRender() { - return dispatch("turbo:render") + notifyApplicationAfterRender(isPreview: boolean) { + return dispatch("turbo:render", { detail: { isPreview } }) } notifyApplicationAfterPageLoad(timing: TimingData = {}) { diff --git a/src/core/view.ts b/src/core/view.ts index 16834570a..20109a35d 100644 --- a/src/core/view.ts +++ b/src/core/view.ts @@ -10,7 +10,7 @@ export interface ViewRenderOptions { } export interface ViewDelegate> { - allowsImmediateRender(snapshot: S, options: ViewRenderOptions): boolean + allowsImmediateRender(snapshot: S, isPreview: boolean, options: ViewRenderOptions): boolean preloadOnLoadLinksForView(element: Element): void viewRenderedSnapshot(snapshot: S, isPreview: boolean): void viewInvalidated(reason: ReloadReason): void @@ -91,7 +91,7 @@ export abstract class View< const renderInterception = new Promise((resolve) => (this.resolveInterceptionPromise = resolve)) const options = { resume: this.resolveInterceptionPromise, render: this.renderer.renderElement } - const immediateRender = this.delegate.allowsImmediateRender(snapshot, options) + const immediateRender = this.delegate.allowsImmediateRender(snapshot, isPreview, options) if (!immediateRender) await renderInterception await this.renderSnapshot(renderer) diff --git a/src/tests/functional/rendering_tests.ts b/src/tests/functional/rendering_tests.ts index a0c2a0cea..a621191d8 100644 --- a/src/tests/functional/rendering_tests.ts +++ b/src/tests/functional/rendering_tests.ts @@ -36,6 +36,16 @@ test("test triggers before-render and render events", async ({ page }) => { assert.equal(await newBody, await page.evaluate(() => document.body.outerHTML)) }) +test("test includes isPreview in render event details", async ({ page }) => { + await page.click("#same-origin-link") + + const { isPreview } = await nextEventNamed(page, "turbo:before-render") + assert.equal(isPreview, false) + + await nextEventNamed(page, "turbo:render") + assert.equal(await isPreview, false) +}) + test("test triggers before-render and render events for error pages", async ({ page }) => { await page.click("#nonexistent-link") const { newBody } = await nextEventNamed(page, "turbo:before-render")