From 8431dfbc51f189c35a4c7ba02ac20d505f6a711d Mon Sep 17 00:00:00 2001 From: Dikshita S Khandke <86658196+DikshitaKhandke@users.noreply.github.com> Date: Tue, 21 Apr 2026 09:58:10 +0530 Subject: [PATCH 1/5] feat(ceros): atc-7328 ceros flex support --- .../src/annotations/ceros-embed.ts | 28 ++++++- packages/@atjson/renderer-html/src/index.ts | 15 ++++ .../renderer-html/test/renderer.test.ts | 29 +++++++ .../src/converter/third-party-embeds.ts | 82 +++++++++++++++++-- .../source-html/test/ceros-embed.test.ts | 78 ++++++++++++++++++ tests/fixtures/html/ceros-flex.html | 7 ++ 6 files changed, 231 insertions(+), 8 deletions(-) create mode 100644 tests/fixtures/html/ceros-flex.html diff --git a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts index 22ce4939e..560dfd766 100644 --- a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts @@ -6,12 +6,38 @@ export class CerosEmbed extends BlockAnnotation<{ */ url: string; + /** + * The type of ceros embed. + */ + cerosType?: "studio" | "flex"; + + /** + * The URL to the Flex experience when represented separately + * from the canonical `url` field. + */ + experienceUrl?: string; + + /** + * The script URL required to bootstrap a Flex embed. + */ + scriptUrl?: string; + + /** + * The configured width for a Flex embed. + */ + width?: string; + + /** + * The configured height for a Flex embed. + */ + height?: string; + /** * The aspect ratio, as a fraction of the embed, which * is used so the embed can be scaled automatically * by the Ceros script tag. */ - aspectRatio: number; + aspectRatio?: number; /** * The mobile aspect ratio of the embed, which is chosen diff --git a/packages/@atjson/renderer-html/src/index.ts b/packages/@atjson/renderer-html/src/index.ts index 2ed1fe8de..c7a02025f 100644 --- a/packages/@atjson/renderer-html/src/index.ts +++ b/packages/@atjson/renderer-html/src/index.ts @@ -132,6 +132,21 @@ export default class HTMLRenderer extends Renderer { } *CerosEmbed(embed: Block) { + if (embed.attributes.cerosType === "flex") { + return `
`; + } + + if (embed.attributes.aspectRatio == null) { + throw new Error("Ceros studio embeds require an aspectRatio"); + } + return `
{ ); }); + test("flex", () => { + let doc = new OffsetSource({ + content: "\uFFFC", + annotations: [ + new CerosEmbed({ + id: "test", + start: 0, + end: 1, + attributes: { + cerosType: "flex", + url: "https://view.ceros.com/example/flex/index.html", + experienceUrl: "https://view.ceros.com/example/flex/index.html", + scriptUrl: "assets/scripts/embed_v1.js", + width: "100%", + height: "auto", + }, + }), + new ParseAnnotation({ + start: 0, + end: 1, + }), + ], + }); + + expect(Renderer.render(doc)).toMatchInlineSnapshot( + `"
"`, + ); + }); + test("with mobile aspect ratio", () => { let doc = new OffsetSource({ content: "\uFFFC", diff --git a/packages/@atjson/source-html/src/converter/third-party-embeds.ts b/packages/@atjson/source-html/src/converter/third-party-embeds.ts index ee0b60dee..7590ca539 100644 --- a/packages/@atjson/source-html/src/converter/third-party-embeds.ts +++ b/packages/@atjson/source-html/src/converter/third-party-embeds.ts @@ -12,6 +12,10 @@ function isCerosExperienceFrame(a: Annotation) { return a.type === "iframe" && a.attributes.class === "ceros-experience"; } +function isFlexCerosContainer(a: Annotation) { + return a.type === "div" && a.attributes.dataset?.["ceros-experience"] != null; +} + function isCerosOriginDomainsScript(a: Annotation) { if (a.type !== "script") { return false; @@ -37,6 +41,14 @@ function isCerosContainer(a: Annotation) { ); } +function isFlexCerosScript(a: Annotation) { + return ( + a.type === "script" && + typeof a.attributes.src === "string" && + /(?:^|\/)embed_v\d+\.js(?:[?#].*)?$/i.test(a.attributes.src) + ); +} + function isCneAudioScript(a: Annotation) { return ( a.attributes.src && @@ -48,6 +60,17 @@ function aCoversB(a: Annotation, b: Annotation) { return a.start < b.start && a.end > b.end; } +function adjacentSiblingWithOptionalWhitespace( + doc: Document, + first: Annotation, + second: Annotation, +) { + return ( + second.start >= first.end && + /^\s*$/.test(doc.content.slice(first.end, second.start)) + ); +} + function getCneAudioEnvironment(hostname: string): AudioEnvironments { const isCneAudioProduction = (hostname: string): boolean => { return /embed-audio\.cnevids\.com/.test(hostname); @@ -65,14 +88,20 @@ function getCneAudioEnvironment(hostname: string): AudioEnvironments { export default function convertThirdPartyEmbeds(doc: Document) { /** - * Ceros Embeds are iframes wrapped in divs: + * Ceros studio Embeds are iframes wrapped in divs: *
* *
* */ + /** + * Ceros flex embeds are wrapped in divs + *
+ * + */ let containers = doc.where(isCerosContainer).as("container"); let iframeTags = doc.where(isCerosExperienceFrame).as("iframes"); + let flexContainers = doc.where(isFlexCerosContainer).as("container"); doc.where(isCerosOriginDomainsScript).remove(); @@ -101,7 +130,46 @@ export default function convertThirdPartyEmbeds(doc: Document) { mobileAspectRatio, url: iframes[0].attributes.src, }, - }) + }), + ); + }); + + flexContainers + .join( + doc.where(isFlexCerosScript).as("scripts"), + function scriptAfterFlexContainer(container, script: Script) { + return adjacentSiblingWithOptionalWhitespace(doc, container, script); + }, + ) + .update(({ container, scripts }) => { + let script = scripts.find( + (annotation) => + typeof annotation.attributes.src === "string" && + annotation.attributes.src.length > 0, + ); + + if (!script) return; + + if (container.end !== script.start) { + doc.deleteText(container.end, script.start); + } + + doc.removeAnnotations(scripts); + + doc.replaceAnnotation( + container, + new CerosEmbed({ + start: container.start, + end: container.end, + attributes: { + cerosType: "flex", + url: container.attributes.dataset["ceros-experience"], + experienceUrl: container.attributes.dataset["ceros-experience"], + scriptUrl: script.attributes.src, + width: container.attributes.dataset["embed-width"], + height: container.attributes.dataset["embed-height"], + }, + }), ); }); @@ -120,7 +188,7 @@ export default function convertThirdPartyEmbeds(doc: Document) { src.match(/fwcdn\d\.com\//) != null || src.match(/fwpub\d\.com\//) != null) ); - } + }, ) .update(({ embed, scripts }) => { let playlist = embed.attributes.playlist; @@ -142,7 +210,7 @@ export default function convertThirdPartyEmbeds(doc: Document) { channel: channel, open: embed.attributes.open_in, }, - }) + }), ); // Remove newlines from embed code if (scripts.length) { @@ -184,7 +252,7 @@ export default function convertThirdPartyEmbeds(doc: Document) { audioId, anchorName, }, - }) + }), ); }); /** @@ -212,7 +280,7 @@ export default function convertThirdPartyEmbeds(doc: Document) { audioType, anchorName: iframe.attributes.id, }, - }) + }), ); }); /** @@ -238,7 +306,7 @@ export default function convertThirdPartyEmbeds(doc: Document) { attributes: { url: embed.attributes.url, }, - }) + }), ); }); diff --git a/packages/@atjson/source-html/test/ceros-embed.test.ts b/packages/@atjson/source-html/test/ceros-embed.test.ts index b44f803af..bd07a1613 100644 --- a/packages/@atjson/source-html/test/ceros-embed.test.ts +++ b/packages/@atjson/source-html/test/ceros-embed.test.ts @@ -96,4 +96,82 @@ describe("CerosEmbed", () => { } `); }); + + test("parses Flex embeds into a structured Ceros block", () => { + let doc = HTMLSource.fromRaw( + `
+`, + ).convertTo(OffsetSource); + + expect(serialize(doc, { withStableIds: true })).toMatchInlineSnapshot(` + { + "blocks": [ + { + "attributes": { + "cerosType": "flex", + "experienceUrl": "https://view.ceros.com/example/flex/index.html", + "height": "auto", + "scriptUrl": "assets/scripts/embed_v1.js", + "url": "https://view.ceros.com/example/flex/index.html", + "width": "100%", + }, + "id": "B00000000", + "parents": [], + "selfClosing": false, + "type": "ceros-embed", + }, + ], + "marks": [], + "text": "", + } + `); + }); + + test("mixed studio and flex scenarios keep both embeds and remove only matched scripts", () => { + let doc = HTMLSource.fromRaw( + `
`, + ).convertTo(OffsetSource); + + expect(serialize(doc, { withStableIds: true })).toMatchInlineSnapshot(` + { + "blocks": [ + { + "attributes": { + "aspectRatio": 2, + "url": "//view.ceros.com/ceros-inspire/carousel-3", + }, + "id": "B00000000", + "parents": [], + "selfClosing": false, + "type": "ceros-embed", + }, + { + "attributes": { + "cerosType": "flex", + "experienceUrl": "https://view.ceros.com/example/flex/index.html", + "height": "auto", + "scriptUrl": "assets/scripts/embed_v1.js", + "url": "https://view.ceros.com/example/flex/index.html", + "width": "100%", + }, + "id": "B00000001", + "parents": [], + "selfClosing": false, + "type": "ceros-embed", + }, + ], + "marks": [ + { + "attributes": { + "-html-src": "https://www.example.com/keep-me.js", + }, + "id": "M00000000", + "range": "(2..2]", + "type": "-html-script", + }, + ], + "text": "", + } + `); + }); }); diff --git a/tests/fixtures/html/ceros-flex.html b/tests/fixtures/html/ceros-flex.html new file mode 100644 index 000000000..de4c18852 --- /dev/null +++ b/tests/fixtures/html/ceros-flex.html @@ -0,0 +1,7 @@ +

This is the Flex Ceros embed:

+
+ +

+ This is some text after, to make sure that the converter doesn't strip the + HTML after the embed +

\ No newline at end of file From 9a37a5f7be8ffcef57a74389f29aea2798ed17e6 Mon Sep 17 00:00:00 2001 From: Dikshita S Khandke <86658196+DikshitaKhandke@users.noreply.github.com> Date: Thu, 23 Apr 2026 19:02:54 +0530 Subject: [PATCH 2/5] feat(ceros): atc-7328 updated review comments --- .../src/annotations/ceros-embed.ts | 62 ++++++++++++------- packages/@atjson/renderer-html/src/index.ts | 27 ++++---- .../renderer-html/test/renderer.test.ts | 8 +-- .../src/converter/third-party-embeds.ts | 26 ++++++-- .../source-html/test/ceros-embed.test.ts | 49 ++++++++++++--- 5 files changed, 118 insertions(+), 54 deletions(-) diff --git a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts index 560dfd766..6fc24d2b5 100644 --- a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts @@ -1,61 +1,79 @@ import { BlockAnnotation } from "@atjson/document"; -export class CerosEmbed extends BlockAnnotation<{ +type SharedCerosEmbedAttributes = { /** * The URL to the Ceros experience. */ url: string; /** - * The type of ceros embed. - */ - cerosType?: "studio" | "flex"; - - /** - * The URL to the Flex experience when represented separately - * from the canonical `url` field. + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. */ - experienceUrl?: string; + layout?: string; /** - * The script URL required to bootstrap a Flex embed. + * Accessible title for the generated iframe. For Flex embeds this + * is sourced from the container's `data-title` attribute. */ - scriptUrl?: string; + title?: string; /** - * The configured width for a Flex embed. + * A named identifier used to quickly jump to this item */ - width?: string; + anchorName?: string; +}; +type StudioCerosEmbedAttributes = SharedCerosEmbedAttributes & { /** - * The configured height for a Flex embed. + * The type of ceros embed. */ - height?: string; + cerosType?: "studio"; /** * The aspect ratio, as a fraction of the embed, which * is used so the embed can be scaled automatically * by the Ceros script tag. */ - aspectRatio?: number; + aspectRatio: number; /** * The mobile aspect ratio of the embed, which is chosen * by Ceros when on smaller screen sizes. */ mobileAspectRatio?: number; +}; +type FlexCerosEmbedAttributes = SharedCerosEmbedAttributes & { /** - * Layout information, used to indicate mutually - * exclusive layouts, for example sizes, floats, etc. + * The type of ceros embed. */ - layout?: string; + cerosType: "flex"; /** - * A named identifier used to quickly jump to this item + * The script URL required to bootstrap a Flex embed. */ - anchorName?: string; -}> { + scriptUrl?: string; + + /** + * The configured width for a Flex embed. Per Ceros docs this is + * typically a percentage value such as `100%`. + */ + width?: string; + + /** + * The configured height for a Flex embed. Per Ceros docs this is + * either `auto` for a full-height embed or a fixed pixel value + * such as `800px` for a scrolling embed. + */ + height?: string; +}; + +export type CerosEmbedAttributes = + | StudioCerosEmbedAttributes + | FlexCerosEmbedAttributes; + +export class CerosEmbed extends BlockAnnotation { static vendorPrefix = "offset"; static type = "ceros-embed"; } diff --git a/packages/@atjson/renderer-html/src/index.ts b/packages/@atjson/renderer-html/src/index.ts index c7a02025f..a58d42fb6 100644 --- a/packages/@atjson/renderer-html/src/index.ts +++ b/packages/@atjson/renderer-html/src/index.ts @@ -133,25 +133,25 @@ export default class HTMLRenderer extends Renderer { *CerosEmbed(embed: Block) { if (embed.attributes.cerosType === "flex") { + let { height, scriptUrl, title, url, width } = embed.attributes; return `
`; } - if (embed.attributes.aspectRatio == null) { - throw new Error("Ceros studio embeds require an aspectRatio"); - } + let { anchorName, aspectRatio, mobileAspectRatio, title, url } = + embed.attributes; return `
`, + `
`, ).convertTo(OffsetSource); expect(serialize(doc, { withStableIds: true })).toMatchInlineSnapshot(` @@ -138,6 +138,7 @@ describe("CerosEmbed", () => { { "attributes": { "aspectRatio": 2, + "title": "Studio carousel", "url": "//view.ceros.com/ceros-inspire/carousel-3", }, "id": "B00000000", @@ -148,10 +149,10 @@ describe("CerosEmbed", () => { { "attributes": { "cerosType": "flex", - "experienceUrl": "https://view.ceros.com/example/flex/index.html", "height": "auto", - "scriptUrl": "assets/scripts/embed_v1.js", - "url": "https://view.ceros.com/example/flex/index.html", + "scriptUrl": "https://assets.ceros.site/js/embed.v1.js", + "title": "Example Flex Experience", + "url": "https://flexamples.ceros.site/example-1", "width": "100%", }, "id": "B00000001", @@ -174,4 +175,34 @@ describe("CerosEmbed", () => { } `); }); + + test("does not treat non-ceros embed scripts as flex embeds", () => { + let doc = HTMLSource.fromRaw( + `
+`, + ).convertTo(OffsetSource); + + expect(serialize(doc, { withStableIds: true })).toMatchObject({ + blocks: [{ type: "text", attributes: {} }], + marks: [ + { + type: "-html-div", + attributes: { + "-html-dataset": { + "-html-ceros-experience": + "https://flexamples.ceros.site/example-1", + "-html-embed-height": "auto", + "-html-embed-width": "100%", + }, + }, + }, + { + type: "-html-script", + attributes: { + "-html-src": "https://www.example.com/js/embed.v1.js", + }, + }, + ], + }); + }); }); From 7a6a7a460208922b12a3e81d272759b2716b579e Mon Sep 17 00:00:00 2001 From: Dikshita S Khandke <86658196+DikshitaKhandke@users.noreply.github.com> Date: Thu, 23 Apr 2026 19:09:26 +0530 Subject: [PATCH 3/5] feat(ceros): atc-7328 updated test fixture --- tests/fixtures/html/ceros-flex.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/fixtures/html/ceros-flex.html b/tests/fixtures/html/ceros-flex.html index de4c18852..e5efbfc16 100644 --- a/tests/fixtures/html/ceros-flex.html +++ b/tests/fixtures/html/ceros-flex.html @@ -1,7 +1,7 @@

This is the Flex Ceros embed:

-
- +
+

This is some text after, to make sure that the converter doesn't strip the HTML after the embed -

\ No newline at end of file +

From fe6dafb5f6a66717a691f776a342664b588543ea Mon Sep 17 00:00:00 2001 From: Dikshita S Khandke <86658196+DikshitaKhandke@users.noreply.github.com> Date: Fri, 24 Apr 2026 17:47:11 +0530 Subject: [PATCH 4/5] feat(ceros): atc-7328 updated review comments from tim --- .../src/annotations/ceros-embed.ts | 9 ++------- packages/@atjson/renderer-html/src/index.ts | 12 ++++++------ packages/@atjson/renderer-html/test/renderer.test.ts | 5 ++--- .../source-html/src/converter/third-party-embeds.ts | 5 ++--- .../@atjson/source-html/test/ceros-embed.test.ts | 10 ++++------ 5 files changed, 16 insertions(+), 25 deletions(-) diff --git a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts index 6fc24d2b5..1b687656d 100644 --- a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts @@ -50,23 +50,18 @@ type FlexCerosEmbedAttributes = SharedCerosEmbedAttributes & { */ cerosType: "flex"; - /** - * The script URL required to bootstrap a Flex embed. - */ - scriptUrl?: string; - /** * The configured width for a Flex embed. Per Ceros docs this is * typically a percentage value such as `100%`. */ - width?: string; + embedWidth?: string; /** * The configured height for a Flex embed. Per Ceros docs this is * either `auto` for a full-height embed or a fixed pixel value * such as `800px` for a scrolling embed. */ - height?: string; + embedHeight?: string; }; export type CerosEmbedAttributes = diff --git a/packages/@atjson/renderer-html/src/index.ts b/packages/@atjson/renderer-html/src/index.ts index a58d42fb6..15f16c64b 100644 --- a/packages/@atjson/renderer-html/src/index.ts +++ b/packages/@atjson/renderer-html/src/index.ts @@ -133,15 +133,15 @@ export default class HTMLRenderer extends Renderer { *CerosEmbed(embed: Block) { if (embed.attributes.cerosType === "flex") { - let { height, scriptUrl, title, url, width } = embed.attributes; + let { embedHeight, embedWidth, title, url } = embed.attributes; return `
`; + }).join( + " ", + )}>
`; } let { anchorName, aspectRatio, mobileAspectRatio, title, url } = diff --git a/packages/@atjson/renderer-html/test/renderer.test.ts b/packages/@atjson/renderer-html/test/renderer.test.ts index 55dbac804..e1a3a5cad 100644 --- a/packages/@atjson/renderer-html/test/renderer.test.ts +++ b/packages/@atjson/renderer-html/test/renderer.test.ts @@ -521,9 +521,8 @@ describe("renderer-html", () => { attributes: { cerosType: "flex", url: "https://flexamples.ceros.site/example-1", - scriptUrl: "https://assets.ceros.site/js/embed.v1.js", - width: "100%", - height: "auto", + embedWidth: "100%", + embedHeight: "auto", title: "Example Flex Experience", }, }), diff --git a/packages/@atjson/source-html/src/converter/third-party-embeds.ts b/packages/@atjson/source-html/src/converter/third-party-embeds.ts index 3efe4bf0c..bf1a43543 100644 --- a/packages/@atjson/source-html/src/converter/third-party-embeds.ts +++ b/packages/@atjson/source-html/src/converter/third-party-embeds.ts @@ -178,9 +178,8 @@ export default function convertThirdPartyEmbeds(doc: Document) { attributes: { cerosType: "flex", url: container.attributes.dataset["ceros-experience"], - scriptUrl: script.attributes.src, - width: container.attributes.dataset["embed-width"], - height: container.attributes.dataset["embed-height"], + embedWidth: container.attributes.dataset["embed-width"], + embedHeight: container.attributes.dataset["embed-height"], title: container.attributes.dataset["title"], }, }), diff --git a/packages/@atjson/source-html/test/ceros-embed.test.ts b/packages/@atjson/source-html/test/ceros-embed.test.ts index 81c71c0ec..01d11f671 100644 --- a/packages/@atjson/source-html/test/ceros-embed.test.ts +++ b/packages/@atjson/source-html/test/ceros-embed.test.ts @@ -109,11 +109,10 @@ describe("CerosEmbed", () => { { "attributes": { "cerosType": "flex", - "height": "auto", - "scriptUrl": "https://assets.ceros.site/js/embed.v1.js", + "embedHeight": "auto", + "embedWidth": "100%", "title": "Example Flex Experience", "url": "https://flexamples.ceros.site/example-1", - "width": "100%", }, "id": "B00000000", "parents": [], @@ -149,11 +148,10 @@ describe("CerosEmbed", () => { { "attributes": { "cerosType": "flex", - "height": "auto", - "scriptUrl": "https://assets.ceros.site/js/embed.v1.js", + "embedHeight": "auto", + "embedWidth": "100%", "title": "Example Flex Experience", "url": "https://flexamples.ceros.site/example-1", - "width": "100%", }, "id": "B00000001", "parents": [], From 961e8941c6eb5023db130ce270e3090325079563 Mon Sep 17 00:00:00 2001 From: Dikshita S Khandke <86658196+DikshitaKhandke@users.noreply.github.com> Date: Mon, 11 May 2026 14:36:55 +0530 Subject: [PATCH 5/5] feat(ceros-flex): atc-7328 updated typecheck issue --- .../src/annotations/ceros-embed.ts | 131 ++++++++++-------- 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts index 1b687656d..2b901685b 100644 --- a/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts +++ b/packages/@atjson/offset-annotations/src/annotations/ceros-embed.ts @@ -1,74 +1,89 @@ import { BlockAnnotation } from "@atjson/document"; -type SharedCerosEmbedAttributes = { - /** - * The URL to the Ceros experience. - */ - url: string; +export class CerosEmbed extends BlockAnnotation< + | { + /** + * The URL to the Ceros experience. + */ + url: string; - /** - * Layout information, used to indicate mutually - * exclusive layouts, for example sizes, floats, etc. - */ - layout?: string; + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; - /** - * Accessible title for the generated iframe. For Flex embeds this - * is sourced from the container's `data-title` attribute. - */ - title?: string; + /** + * Accessible title for the generated iframe. For Flex embeds this + * is sourced from the container's `data-title` attribute. + */ + title?: string; - /** - * A named identifier used to quickly jump to this item - */ - anchorName?: string; -}; + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; -type StudioCerosEmbedAttributes = SharedCerosEmbedAttributes & { - /** - * The type of ceros embed. - */ - cerosType?: "studio"; + /** + * The type of ceros embed. + */ + cerosType?: "studio"; - /** - * The aspect ratio, as a fraction of the embed, which - * is used so the embed can be scaled automatically - * by the Ceros script tag. - */ - aspectRatio: number; + /** + * The aspect ratio, as a fraction of the embed, which + * is used so the embed can be scaled automatically + * by the Ceros script tag. + */ + aspectRatio: number; - /** - * The mobile aspect ratio of the embed, which is chosen - * by Ceros when on smaller screen sizes. - */ - mobileAspectRatio?: number; -}; + /** + * The mobile aspect ratio of the embed, which is chosen + * by Ceros when on smaller screen sizes. + */ + mobileAspectRatio?: number; + } + | { + /** + * The URL to the Ceros experience. + */ + url: string; -type FlexCerosEmbedAttributes = SharedCerosEmbedAttributes & { - /** - * The type of ceros embed. - */ - cerosType: "flex"; + /** + * Layout information, used to indicate mutually + * exclusive layouts, for example sizes, floats, etc. + */ + layout?: string; - /** - * The configured width for a Flex embed. Per Ceros docs this is - * typically a percentage value such as `100%`. - */ - embedWidth?: string; + /** + * Accessible title for the generated iframe. For Flex embeds this + * is sourced from the container's `data-title` attribute. + */ + title?: string; - /** - * The configured height for a Flex embed. Per Ceros docs this is - * either `auto` for a full-height embed or a fixed pixel value - * such as `800px` for a scrolling embed. - */ - embedHeight?: string; -}; + /** + * A named identifier used to quickly jump to this item + */ + anchorName?: string; -export type CerosEmbedAttributes = - | StudioCerosEmbedAttributes - | FlexCerosEmbedAttributes; + /** + * The type of ceros embed. + */ + cerosType: "flex"; -export class CerosEmbed extends BlockAnnotation { + /** + * The configured width for a Flex embed. Per Ceros docs this is + * typically a percentage value such as `100%`. + */ + embedWidth?: string; + + /** + * The configured height for a Flex embed. Per Ceros docs this is + * either `auto` for a full-height embed or a fixed pixel value + * such as `800px` for a scrolling embed. + */ + embedHeight?: string; + } +> { static vendorPrefix = "offset"; static type = "ceros-embed"; }