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
5 changes: 5 additions & 0 deletions .changeset/range-wrapper-more-shapes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@monetizationos/proxy": minor
---

More pages use the one-callback range cut. Content other components insert inside the range is removed with it, whatever the component order, and a marker removed by another component still marks where the range starts or ends. A container holding raw text, such as `textarea` or `script`, is left alone, and only the outermost of nested containers is cut. Selector lists, several range components in one decision, and other content on the range component all use the one-callback path. Selector lists also apply per part when cutting element by element. A start marker nested inside its container now uses the one-callback path too, when its range is the only one in the decision.
3 changes: 2 additions & 1 deletion src/stages/buildReplacementHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { SubSurfaceBehaviorApi } from '../types'
import { renderElement } from './elements'
import type { ComponentRange } from './findMarkerPositions'
import { isVoidElement } from './voidElements'
import { combineSelectors } from './wrappedRange'

type ReplacementState = {
// `IN_START`: a start marker nested in the first one doesn't start the range again
Expand Down Expand Up @@ -160,6 +161,6 @@ export const buildReplacementHandlers = (
}
return [
{ selector, handler: parentHandler },
{ selector: `${selector} *`, handler: { element: onChildElement } },
{ selector: combineSelectors(selector, ' ', '*'), handler: { element: onChildElement } },
]
}
7 changes: 4 additions & 3 deletions src/stages/findMarkerPositions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ElementHandlers, HtmlRewriterAdapter, RewriterElement } from '../a
import type { HtmlStageContext } from '../context'
import type { SurfaceDecisionResponse } from '../types'
import { isVoidElement } from './voidElements'
import { combineSelectors } from './wrappedRange'

export type SurfaceMarkers = {
componentsWithInvalidSelectors: string[]
Expand Down Expand Up @@ -81,7 +82,7 @@ export const findMarkerPositions = async (
},
},
{
selector: `${componentBehavior.metadata.cssSelector} *`,
selector: combineSelectors(componentBehavior.metadata.cssSelector, ' ', '*'),
componentKey,
handler: {
element(element: RewriterElement) {
Expand Down Expand Up @@ -113,7 +114,7 @@ export const findMarkerPositions = async (
},
toMarker
? {
selector: `${componentBehavior.metadata.cssSelector} ${toMarker}`,
selector: combineSelectors(componentBehavior.metadata.cssSelector, ' ', toMarker),
componentKey,
handler: {
element() {
Expand All @@ -139,7 +140,7 @@ export const findMarkerPositions = async (
: null,
fromMarker
? {
selector: `${componentBehavior.metadata.cssSelector} ${fromMarker}`,
selector: combineSelectors(componentBehavior.metadata.cssSelector, ' ', fromMarker),
componentKey,
handler: {
element() {
Expand Down
18 changes: 12 additions & 6 deletions src/stages/surfaceComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@ export default async function handleSurfaceComponents(
headers.delete('content-length')
const init = { status: response.status, statusText: response.statusText, headers }
const wrapped = await applyComponents(ctx, new Response(page, init), surfaceDecisions, rewriter, wrapper)
const wrappedPage = await wrapped.arrayBuffer()
if (wrapper.unsupported()) {
let wrappedPage: Uint8Array<ArrayBuffer> | null = new Uint8Array(await wrapped.arrayBuffer())
if (!wrapper.unsupported() && wrapper.nested() > 0) {
wrappedPage = await wrapper.splice(wrappedPage, rewriter, headers)
}
if (wrapper.unsupported() || !wrappedPage) {
return applyComponents(ctx, new Response(page, init), surfaceDecisions, rewriter, null)
}
if (wrapper.wrapped() === 0) {
return new Response(wrappedPage, init)
}
return rewriter.create().on(wrapper.unwrap.selector, wrapper.unwrap.handler).transform(new Response(wrappedPage, init))
let unwrap = rewriter.create()
for (const { selector, handler } of wrapper.unwrap) {
unwrap = unwrap.on(selector, handler)
}
return unwrap.transform(new Response(wrappedPage, init))
}

/** With no `wrapper`, ranges are cut element by element. */
Expand Down Expand Up @@ -89,9 +96,8 @@ export async function applyComponents(
},
]

if (wrapper && componentKey === wrapper.componentKey) {
registerWrapper(wrapper.checks)
} else if (supportsRangeReplacement && !componentsWithInvalidSelectors.includes(componentKey)) {
const cutByWrapper = wrapper?.componentKeys.includes(componentKey)
if (supportsRangeReplacement && !cutByWrapper && !componentsWithInvalidSelectors.includes(componentKey)) {
handlers.push(...buildReplacementHandlers(ctx, componentBehavior, markers[componentKey]))
} else if (!supportsRangeReplacement && componentBehavior.content.replaceRange) {
logger.log({
Expand Down
Loading
Loading