article-content-renderer-vue2 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,8 @@
10
10
  - 使用 Vue 2 `CreateElement` 和 `VNodeData`,不是 Vue 3 兼容层。
11
11
  - 支持严格模式和非严格容错渲染。
12
12
  - 拦截危险链接和图片 URL。
13
- - articleButton 的完整 href 由使用者回调生成。
13
+ - articleButton text/button 完整 href 由使用者回调生成。
14
+ - articleButton 的 link 样式直接使用协议节点中的 href,不调用 resolver。
14
15
  - 支持 Vue 2 SSR。
15
16
  - 提供 TypeScript 类型、结构化错误和 CSS Variables。
16
17
  - Vue 作为 peer dependency,不会打入组件包。
@@ -110,92 +111,103 @@ import 'article-content-renderer-vue2/style.css'
110
111
  Vue.use(ArticleContentRendererPlugin)
111
112
  ```
112
113
 
113
- ## 广告与图片地址
114
+ ## 自定义插槽与图片地址
114
115
 
115
- 广告参数与 React 版保持一致:
116
+ 通过 `customSlots` 描述插槽位置,再使用与 `id` 同名的具名插槽传入任意 Vue 内容:
116
117
 
117
118
  ```ts
118
- interface AdConfig {
119
- adm?: readonly unknown[]
120
- ads?: readonly unknown[]
121
- loc: readonly number[]
122
- }
123
-
124
- interface PubId {
125
- adm: string
126
- ads: string
119
+ interface CustomSlot {
120
+ id: string
121
+ location: number
127
122
  }
128
123
  ```
129
124
 
130
125
  ```vue
131
- <ArticleContentRenderer
132
- :document="article"
133
- :ad-conf="{
134
- adm: ['banner-1', 'banner-2'],
135
- ads: ['123', '456'],
136
- loc: [2, 5],
137
- }"
138
- :pubid="{
139
- adm: '/23054585162/newsflowly/',
140
- ads: '3887371527059481',
141
- }"
142
- ad-title="Advertisement"
143
- image-base-url="https://cdn.example.com/"
144
- @render-error="handleRenderError"
145
- />
146
- ```
147
-
148
- `loc` 使用从 1 开始的 `document.content` 顶层位置,广告会插入在对应元素前面。位置超出文档长度时直接忽略。每个非空 `adm`/`ads` 数组的长度都必须与 `loc` 一致,否则不生成广告占位,并通过 `render-error` 上报 `AD_CONFIG_LENGTH_MISMATCH`。
149
-
150
- 广告选择规则:
151
-
152
- - 同一位置同时有 `adm` 和 `ads`:先请求 ADM;只有 ADM 返回空广告时才请求对应 AdSense。
153
- - 只有 `adm`:只请求 ADM,空广告也不回退。
154
- - 只有 `ads`:直接请求 AdSense。
155
-
156
- 宿主项目需要分别加载一次 Google Publisher Tag 和 Google AdSense SDK。组件通过 `googletag.cmd` 和 `adsbygoogle` 队列请求广告,不会为每个广告位重复插入 `<script>`。
157
-
158
- ADM 和 AdSense 共用稳定的全局 class,样式由宿主项目覆盖:
126
+ <script lang="ts">
127
+ import Vue from 'vue'
128
+ import type { CustomSlot } from 'article-content-renderer-vue2'
159
129
 
160
- ```css
161
- .article-ad-wrapper {
162
- max-width: 728px;
163
- height: 110px;
164
- margin: 0 auto;
165
- }
130
+ export default Vue.extend({
131
+ data() {
132
+ return {
133
+ customSlots: [
134
+ { id: 'article-ad-1', location: 2 },
135
+ { id: 'recommendation', location: 5 },
136
+ { id: 'article-ad-2', location: 5 },
137
+ ] as CustomSlot[],
138
+ }
139
+ },
140
+ })
141
+ </script>
166
142
 
167
- .article-ad-title {
168
- flex-shrink: 0;
169
- font-size: 12px;
170
- line-height: 20px;
171
- text-align: center;
172
- }
143
+ <template>
144
+ <ArticleContentRenderer
145
+ :document="article"
146
+ :custom-slots="customSlots"
147
+ >
148
+ <template #article-ad-1>
149
+ <MyAd slot-id="top" />
150
+ </template>
151
+
152
+ <template #recommendation>
153
+ <RecommendationCard />
154
+ </template>
155
+
156
+ <template #article-ad-2>
157
+ <MyAd slot-id="middle" />
158
+ </template>
159
+ </ArticleContentRenderer>
160
+ </template>
173
161
  ```
174
162
 
175
- 外层使用纵向 flex 布局,广告单元自动占满标题之外的剩余高度。上例中外层为 `110px`、标题为 `20px`,广告实际高度为 `90px`。如果宿主使用 `<style scoped>`,请使用 Vue 2 的深度选择器,或将这些广告规则放到非 scoped 样式中。
176
-
177
- `adTitle` 默认为 `Advertisement`。`imageBaseUrl` 默认为 `https://www.doitme.link/`;传入新地址时,只替换文档图片中该默认前缀,其他图片 URL 保持不变。
163
+ 插槽规则:
178
164
 
179
- ## articleButton 链接
180
-
181
- `style: "button"``style: "text"` 都使用 `<a>` 渲染,只改变视觉样式。resolver 接收当前节点的完整只读属性:
165
+ - `location` 从 1 开始;`location: 5` 表示插入到 `document.content[4]` 之前。
166
+ - 同一个 `location` 可以配置多个不同 `id`,并按照数组中的顺序渲染。
167
+ - `id` 应当唯一,并且必须与具名插槽名称一致。
168
+ - 非正整数或超过 `document.content` 长度的位置会被忽略。
169
+ - 渲染器不会为插槽额外创建包装 DOM,样式和生命周期由插槽组件自行控制。
170
+ - 具名插槽会收到 `{ id, location }` 作为作用域参数。
182
171
 
183
- ```ts
184
- interface ArticleButtonAttrs {
185
- id: string
186
- title?: string
187
- text: string
188
- style: 'text' | 'button'
189
- }
190
- ```
172
+ 广告组件也通过具名插槽传入,并自行负责 SDK 加载、广告请求、空广告回退、唯一 DOM ID 和卸载清理。
191
173
 
192
- resolver 类型:
174
+ `imageBaseUrl` 默认为 `https://www.doitme.link/`;传入新地址时,只替换文档图片中该默认前缀,其他图片 URL 保持不变。
175
+ ## articleButton 链接
193
176
 
194
- ```ts
195
- type ResolveArticleButtonLink = (
196
- attrs: Readonly<ArticleButtonAttrs>,
197
- node: Readonly<ArticleButtonNode>,
198
- ) =>
177
+ `style: "button"`、`style: "text"` 和 `style: "link"` 都使用 `<a>` 渲染。它们的链接来源不同:
178
+
179
+ - text/button:必须提供 `id`,通过 `resolveArticleButtonLink` 生成完整 `href`。
180
+ - link:`id` 可省略,直接使用节点的 `href`,不会调用 `resolveArticleButtonLink`。
181
+
182
+ 对应的 TypeScript 类型是可辨识联合:
183
+
184
+ ```ts
185
+ interface ArticleButtonActionAttrs {
186
+ id: string
187
+ title?: string
188
+ text: string
189
+ style: 'text' | 'button'
190
+ href?: never
191
+ }
192
+
193
+ interface ArticleButtonLinkAttrs {
194
+ id?: string
195
+ title?: string
196
+ text: string
197
+ style: 'link'
198
+ href?: string
199
+ }
200
+
201
+ type ArticleButtonAttrs = ArticleButtonActionAttrs | ArticleButtonLinkAttrs
202
+ ```
203
+
204
+ resolver 只处理 text/button,因此回调中的 `attrs.id` 始终是 `string`:
205
+
206
+ ```ts
207
+ type ResolveArticleButtonLink = (
208
+ attrs: Readonly<ArticleButtonActionAttrs>,
209
+ node: Readonly<ArticleButtonActionNode>,
210
+ ) =>
199
211
  | string
200
212
  | {
201
213
  href: string
@@ -219,7 +231,35 @@ const resolveArticleButtonLink: ResolveArticleButtonLink = (attrs) => {
219
231
  <a href="/detail/view-more">...</a>
220
232
  ```
221
233
 
222
- 组件不会自动添加 `?`,也不会自动把节点属性转换成查询参数。
234
+ 组件不会自动添加 `?`,也不会自动把节点属性转换成查询参数。
235
+
236
+ ### link 样式直接使用 href
237
+
238
+ link 类型的地址完整写在协议节点中,不经过 resolver,也不会被自动改写:
239
+
240
+ ```ts
241
+ const article: ArticleDocument = {
242
+ type: 'doc',
243
+ content: [
244
+ {
245
+ type: 'articleButton',
246
+ attrs: {
247
+ text: '查看协议说明',
248
+ style: 'link',
249
+ href: '/docs/article-content-protocol#article-button',
250
+ },
251
+ },
252
+ ],
253
+ }
254
+ ```
255
+
256
+ 最终 DOM:
257
+
258
+ ```html
259
+ <a href="/docs/article-content-protocol#article-button">查看协议说明</a>
260
+ ```
261
+
262
+ 协议允许 link 类型省略 `href`;此时会渲染不带 `href` 的禁用态 `<a>`。`javascript:`、`data:` 等不安全地址也会被拦截,并通过 `render-error` 事件报告 `UNSAFE_URL`。
223
263
 
224
264
  ### 使用闭包
225
265
 
@@ -257,11 +297,9 @@ function handleArticleButtonClick(payload: ArticleButtonClickPayload): void {
257
297
  | `document` | `unknown` | 必填 | Article Content Protocol 文档 |
258
298
  | `protocolVersion` | `number` | `1` | 协议适配器版本 |
259
299
  | `strict` | `boolean` | `false` | 校验失败时是否停止整篇正文渲染 |
260
- | `adConf` | `AdConfig` | `{ adm: [], ads: [], loc: [] }` | 广告配置;非空广告数组长度须与 `loc` 一致 |
261
- | `pubid` | `PubId` | `{ adm: '', ads: '' }` | ADM/AdSense 发布标识 |
262
- | `adTitle` | `string` | `"Advertisement"` | ADM 和 AdSense 共用的广告标题 |
300
+ | `customSlots` | `CustomSlot[]` | `[]` | 配置一个或多个具名插槽的顶层正文插入位置 |
263
301
  | `imageBaseUrl` | `string` | `"https://www.doitme.link/"` | 替换文档图片的默认地址前缀 |
264
- | `resolveArticleButtonLink` | `ResolveArticleButtonLink` | `undefined` | 由使用者生成 articleButton 完整链接 |
302
+ | `resolveArticleButtonLink` | `ResolveArticleButtonLink` | `undefined` | text/button 生成完整链接;link 类型不调用 |
265
303
 
266
304
  ## Events
267
305
 
@@ -276,7 +314,7 @@ interface ArticleButtonClickPayload {
276
314
  }
277
315
  ```
278
316
 
279
- 事件在原生跳转前同步触发。调用 `payload.event.preventDefault()` 可以由 Vue Router 3 接管跳转。
317
+ 三种样式都会在原生跳转前同步触发事件。调用 `payload.event.preventDefault()` 可以由 Vue Router 3 接管跳转。
280
318
 
281
319
  ### render-error
282
320
 
@@ -1 +1 @@
1
- :root{--acp-color-text: inherit;--acp-color-muted: #667085;--acp-color-border: #d0d5dd;--acp-color-surface: #f8fafc;--acp-color-accent: #2563eb;--acp-color-accent-hover: #1d4ed8;--acp-color-on-accent: #ffffff;--acp-radius: .375rem;--acp-spacing-block: 1rem;--acp-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace}.acp-document{display:contents}.acp-paragraph,.acp-heading,.acp-blockquote,.acp-list,.acp-code-block,.acp-horizontal-rule,.acp-image,.acp-article-button,.acp-table-wrapper{box-sizing:border-box}.acp-paragraph,.acp-heading,.acp-blockquote,.acp-list,.acp-code-block,.acp-horizontal-rule,.acp-image,.acp-table-wrapper{margin-block:0 var(--acp-spacing-block)}.acp-paragraph:first-child,.acp-heading:first-child,.acp-blockquote:first-child,.acp-list:first-child,.acp-code-block:first-child,.acp-horizontal-rule:first-child,.acp-image:first-child,.acp-table-wrapper:first-child{margin-block-start:0}.acp-paragraph{color:var(--acp-color-text)}.acp-blockquote{margin-inline:0;padding-inline-start:1rem;border-inline-start:.25rem solid var(--acp-color-border);color:var(--acp-color-muted)}.acp-list{padding-inline-start:1.5rem}.acp-list-item>:last-child{margin-block-end:0}.acp-code-block{overflow-x:auto;padding:1rem;border-radius:var(--acp-radius);background:var(--acp-color-surface);font-family:var(--acp-font-mono);white-space:pre}.acp-mark--code{padding:.1em .25em;border-radius:calc(var(--acp-radius) / 2);background:var(--acp-color-surface);font-family:var(--acp-font-mono)}.acp-horizontal-rule{border:0;border-block-start:1px solid var(--acp-color-border)}.acp-image{display:flex;width:100%}.acp-image--left{justify-content:flex-start}.acp-image--center{justify-content:center}.acp-image--right{justify-content:flex-end}.acp-image__element{display:block;max-width:100%;height:auto}.acp-link,.acp-article-button--text{color:var(--acp-color-accent);text-decoration:underline;text-underline-offset:.15em}.acp-link:hover,.acp-article-button--text:hover{color:var(--acp-color-accent-hover)}.acp-article-button{display:inline-flex;align-items:center;justify-content:center;margin-block:0 var(--acp-spacing-block);cursor:pointer}.acp-article-button--button{min-height:2.5rem;padding:.5rem 1rem;border-radius:var(--acp-radius);background:var(--acp-color-accent);color:var(--acp-color-on-accent);text-decoration:none}.acp-article-button--button:hover{background:var(--acp-color-accent-hover)}.acp-article-button--disabled{cursor:not-allowed;opacity:.55}.acp-table-wrapper{width:100%;overflow-x:auto}.acp-ad-slot{box-sizing:border-box;width:100%}.article-ad-wrapper{display:flex;flex-direction:column;overflow:hidden}.article-ad-title{flex:0 0 auto}.article-ad-unit{flex:1 1 0;min-height:0;width:100%}.acp-table{width:100%;border-collapse:collapse}.acp-table-cell{padding:.625rem .75rem;border:1px solid var(--acp-color-border);vertical-align:top}.acp-table-cell>:last-child{margin-block-end:0}.acp-render-error{padding:.75rem 1rem;border:1px solid #fda29b;border-radius:var(--acp-radius);background:#fffbfa;color:#b42318}
1
+ :root{--acp-color-text: inherit;--acp-color-muted: #667085;--acp-color-border: #d0d5dd;--acp-color-surface: #f8fafc;--acp-color-accent: #2563eb;--acp-color-accent-hover: #1d4ed8;--acp-color-on-accent: #ffffff;--acp-radius: .375rem;--acp-spacing-block: 1rem;--acp-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace}.acp-document{display:contents}.acp-paragraph,.acp-heading,.acp-blockquote,.acp-list,.acp-code-block,.acp-horizontal-rule,.acp-image,.acp-article-button,.acp-table-wrapper{box-sizing:border-box}.acp-paragraph,.acp-heading,.acp-blockquote,.acp-list,.acp-code-block,.acp-horizontal-rule,.acp-image,.acp-table-wrapper{margin-block:0 var(--acp-spacing-block)}.acp-paragraph:first-child,.acp-heading:first-child,.acp-blockquote:first-child,.acp-list:first-child,.acp-code-block:first-child,.acp-horizontal-rule:first-child,.acp-image:first-child,.acp-table-wrapper:first-child{margin-block-start:0}.acp-paragraph{color:var(--acp-color-text)}.acp-blockquote{margin-inline:0;padding-inline-start:1rem;border-inline-start:.25rem solid var(--acp-color-border);color:var(--acp-color-muted)}.acp-list{padding-inline-start:1.5rem}.acp-list-item>:last-child{margin-block-end:0}.acp-code-block{overflow-x:auto;padding:1rem;border-radius:var(--acp-radius);background:var(--acp-color-surface);font-family:var(--acp-font-mono);white-space:pre}.acp-mark--code{padding:.1em .25em;border-radius:calc(var(--acp-radius) / 2);background:var(--acp-color-surface);font-family:var(--acp-font-mono)}.acp-horizontal-rule{border:0;border-block-start:1px solid var(--acp-color-border)}.acp-image{display:flex;width:100%}.acp-image--left{justify-content:flex-start}.acp-image--center{justify-content:center}.acp-image--right{justify-content:flex-end}.acp-image__element{display:block;max-width:100%;height:auto}.acp-link,.acp-article-button--text,.acp-article-button--link{color:var(--acp-color-accent);text-decoration:underline;text-underline-offset:.15em}.acp-link:hover,.acp-article-button--text:hover,.acp-article-button--link:hover{color:var(--acp-color-accent-hover)}.acp-article-button{display:inline-flex;align-items:center;justify-content:center;margin-block:0 var(--acp-spacing-block);cursor:pointer}.acp-article-button--button{min-height:2.5rem;padding:.5rem 1rem;border-radius:var(--acp-radius);background:var(--acp-color-accent);color:var(--acp-color-on-accent);text-decoration:none}.acp-article-button--button:hover{background:var(--acp-color-accent-hover)}.acp-article-button--disabled{cursor:not-allowed;opacity:.55}.acp-table-wrapper{width:100%;overflow-x:auto}.acp-table{width:100%;border-collapse:collapse}.acp-table-cell{padding:.625rem .75rem;border:1px solid var(--acp-color-border);vertical-align:top}.acp-table-cell>:last-child{margin-block-end:0}.acp-render-error{padding:.75rem 1rem;border:1px solid #fda29b;border-radius:var(--acp-radius);background:#fffbfa;color:#b42318}
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var Y=Object.defineProperty,G=Object.defineProperties;var H=Object.getOwnPropertyDescriptors;var v=Object.getOwnPropertySymbols;var W=Object.prototype.hasOwnProperty,Q=Object.prototype.propertyIsEnumerable;var k=(i,e,t)=>e in i?Y(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t,m=(i,e)=>{for(var t in e||(e={}))W.call(e,t)&&k(i,t,e[t]);if(v)for(var t of v(e))Q.call(e,t)&&k(i,t,e[t]);return i},S=(i,e)=>G(i,H(e));var O=(i,e,t)=>k(i,typeof e!="symbol"?e+"":e,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const N=require("vue"),X=new Set(["http:","https:","mailto:","tel:"]),J=new Set(["http:","https:","blob:"]),Z="https://article-content-renderer.invalid/",I="https://www.doitme.link/";function tt(i,e){if(typeof i!="string")return i;const t=i.trim();if(!t.startsWith(I))return t;const n=(e.trim()||I).replace(/\/+$/u,""),s=t.slice(I.length).replace(/^\/+/,"");return`${n}/${s}`}function E(i,e){if(typeof i!="string")return null;const t=i.trim();if(!t||/[\u0000-\u001F\u007F]/u.test(t))return null;try{const r=new URL(t,Z);return(e==="link"?X:J).has(r.protocol)?t:null}catch(r){return null}}function D(i,e){const t=new Set(typeof i=="string"?i.trim().split(/\s+/u).filter(Boolean):[]);return e==="_blank"&&(t.add("noopener"),t.add("noreferrer")),t.size>0?[...t].join(" "):void 0}function et(i){const e=i.trim();return e?e.startsWith("ca-pub-")?e:`ca-pub-${e}`:""}const x=N.extend({name:"ArticleAdSenseAd",props:{publisherId:{type:String,required:!0},slotId:{type:[String,Number],required:!0},title:{type:String,default:"Advertisement"}},data(){return{observer:null,requestedKey:null}},computed:{adClient(){return et(this.publisherId)},adSlot(){return String(this.slotId).trim()},requestKey(){return`${this.adClient}:${this.adSlot}`}},watch:{requestKey(){this.requestedKey=null,this.stopObserver(),this.$nextTick(()=>this.startObserver())}},mounted(){this.startObserver()},beforeDestroy(){this.stopObserver()},methods:{requestAd(){var i;if(!(!this.adClient||!this.adSlot||this.requestedKey===this.requestKey))try{const e=window;((i=e.adsbygoogle)!=null?i:e.adsbygoogle=[]).push({}),this.requestedKey=this.requestKey}catch(e){console.error("[ArticleContentRenderer] Failed to request AdSense ad:",e)}},startObserver(){const i=this.$refs.root;if(!(!i||!this.adClient||!this.adSlot)){if(typeof IntersectionObserver=="undefined"){this.requestAd();return}this.observer=new IntersectionObserver(e=>{e.some(t=>t.isIntersecting)&&(this.requestAd(),this.stopObserver())},{rootMargin:"200px 0px"}),this.observer.observe(i)}},stopObserver(){var i;(i=this.observer)==null||i.disconnect(),this.observer=null}},render(i){return!this.adClient||!this.adSlot?i():i("div",{ref:"root",staticClass:"article-ad-wrapper",attrs:{"data-google-ad":"true"}},[i("div",{staticClass:"article-ad-title"},this.title),i("ins",{key:this.requestKey,staticClass:"adsbygoogle article-ad-unit",style:{display:"block",width:"100%"},attrs:{"data-ad-client":this.adClient,"data-ad-slot":this.adSlot}})])}});function C(){var e;const i=window;return(e=i.googletag)!=null||(i.googletag={cmd:[]}),i.googletag}function rt(i,e){const t=i.trim().replace(/\/+$/u,""),r=e.replace(/^\/+|\/+$/gu,"");return t&&r?`${t}/${r}`:""}const it=N.extend({name:"ArticleAdManagerAd",props:{publisherId:{type:String,required:!0},slotId:{type:[String,Number],required:!0},title:{type:String,default:"Advertisement"},fallbackPublisherId:{type:String,default:""},fallbackSlotId:{type:[String,Number],default:void 0}},data(){return{observer:null,definedSlot:null,pubAdsService:null,slotRenderEnded:null,emptyAdmKey:null,cancelled:!1}},computed:{admSlotId(){return String(this.slotId).trim()},adsSlotId(){return this.fallbackSlotId===void 0?"":String(this.fallbackSlotId).trim()},adUnitPath(){return rt(this.publisherId,this.admSlotId)},fallbackKey(){return`${this.adUnitPath}:${this.admSlotId}:${this.fallbackPublisherId}:${this.adsSlotId}`},hasAdSenseFallback(){return!!(this.fallbackPublisherId.trim()&&this.adsSlotId)},shouldUseAdSense(){return this.hasAdSenseFallback&&this.emptyAdmKey===this.fallbackKey}},watch:{fallbackKey(){this.restartAdManager()}},mounted(){this.startObserver()},beforeDestroy(){this.cleanupAdManager()},methods:{restartAdManager(){this.cleanupAdManager(),this.emptyAdmKey=null,this.$nextTick(()=>this.startObserver())},startObserver(){const i=this.$refs.root;if(!(!i||!this.adUnitPath||!this.admSlotId||this.shouldUseAdSense)){if(this.cancelled=!1,typeof IntersectionObserver=="undefined"){this.requestAd();return}this.observer=new IntersectionObserver(e=>{var t;e.some(r=>r.isIntersecting)&&(this.requestAd(),(t=this.observer)==null||t.disconnect(),this.observer=null)},{rootMargin:"200px 0px"}),this.observer.observe(i)}},requestAd(){const i=this.$refs.unit;if(!i)return;const e=C();e.cmd.push(()=>{if(this.cancelled)return;const t=i.clientWidth,r=i.clientHeight,n=t>0&&r>0?["fluid",[t,r]]:"fluid",s=e.defineSlot(this.adUnitPath,n,this.admSlotId);if(!s)return;const a=e.pubads(),o=c=>{if(this.cancelled||c.slot!==s||!c.isEmpty||!this.hasAdSenseFallback)return;const d=this.fallbackKey;this.cleanupAdManager(),this.emptyAdmKey=d};this.definedSlot=s,this.pubAdsService=a,this.slotRenderEnded=o,a.addEventListener("slotRenderEnded",o),s.addService(a),e.enableServices(),e.display(this.admSlotId)})},cleanupAdManager(){var n;this.cancelled=!0,(n=this.observer)==null||n.disconnect(),this.observer=null;const i=this.definedSlot,e=this.pubAdsService,t=this.slotRenderEnded;if(this.definedSlot=null,this.pubAdsService=null,this.slotRenderEnded=null,!i&&!t)return;const r=C();r.cmd.push(()=>{var s,a;e&&t&&((s=e.removeEventListener)==null||s.call(e,"slotRenderEnded",t)),i&&((a=r.destroySlots)==null||a.call(r,[i]))})}},render(i){return this.shouldUseAdSense?i(x,{props:{publisherId:this.fallbackPublisherId,slotId:this.adsSlotId,title:this.title}}):!this.adUnitPath||!this.admSlotId?i():i("div",{ref:"root",staticClass:"article-ad-wrapper article-adm-wrapper",attrs:{"data-google-ad-manager":"true","data-ad-unit-path":this.adUnitPath}},[i("div",{staticClass:"article-ad-title"},this.title),i("div",{ref:"unit",staticClass:"article-ad-unit article-adm-unit",attrs:{id:this.admSlotId}})])}}),nt=new Set(["paragraph","heading","blockquote","bulletList","orderedList","codeBlock","horizontalRule","image","articleButton","table"]);function g(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function R(i){return g(i)?i:{}}function h(i,e,t,r){var c;const n=g(t)?t:{},s=g(t)?r:t,a={},o={};for(const[d,f]of Object.entries(n))if(d==="class")a.class=f;else if(d==="style")a.style=f;else if(d.startsWith("on")&&typeof f=="function"){const F=d.slice(2).toLowerCase();a.on=S(m({},(c=a.on)!=null?c:{}),{[F]:f})}else f!==void 0&&f!==!1&&(o[d]=f);return Object.keys(o).length>0&&(a.attrs=o),i.createElement(e,a,s)}function y(i){return Array.isArray(i)?i:[]}function p(i,...e){return`${i}/${e.map(String).join("/")}`}function q(i){return i==="left"||i==="center"||i==="right"||i==="justify"}function st(i){return i==="left"||i==="center"||i==="right"}function L(i){return i==="_blank"||i==="_self"}function A(i,e){i.reportIssue(e)}function at(i,e,t){if(!g(i)||i.type!=="text"||typeof i.text!="string"||!i.text)return null;let r=i.text;const n=y(i.marks);for(let s=0;s<n.length;s+=1){const a=n[s];if(!g(a)||typeof a.type!="string")continue;const o=p(e,"marks",s);switch(a.type){case"bold":r=h(t,"strong",{class:"acp-mark acp-mark--bold"},[r]);break;case"italic":r=h(t,"em",{class:"acp-mark acp-mark--italic"},[r]);break;case"strike":r=h(t,"s",{class:"acp-mark acp-mark--strike"},[r]);break;case"underline":r=h(t,"u",{class:"acp-mark acp-mark--underline"},[r]);break;case"code":r=h(t,"code",{class:"acp-mark acp-mark--code"},[r]);break;case"link":{const c=R(a.attrs),d=E(c.href,"link");if(!d){A(t,{code:"UNSAFE_URL",path:p(o,"attrs","href"),message:"The link URL is empty, malformed, or uses a disallowed protocol.",nodeType:"link"});break}const f=L(c.target)?c.target:"_blank";r=h(t,"a",{class:"acp-link",href:d,target:f,rel:D(void 0,f)},[r]);break}}}return r}function w(i,e,t){return y(i).map((r,n)=>at(r,p(e,n),t)).filter(r=>r!==null)}function B(i,e,t){return!g(i)||i.type!=="listItem"?null:h(t,"li",{class:"acp-list-item","data-node-type":"listItem"},P(i.content,p(e,"content"),t))}function ot(i,e,t){return!g(i)||i.type!=="tableCell"?null:h(t,"td",{class:"acp-table-cell","data-node-type":"tableCell"},P(i.content,p(e,"content"),t))}function lt(i,e,t){if(!g(i)||i.type!=="tableRow")return null;const r=y(i.content).map((n,s)=>ot(n,p(e,"content",s),t)).filter(n=>n!==null);return h(t,"tr",{class:"acp-table-row","data-node-type":"tableRow"},r)}function dt(i){var n;if(g(i)&&i.target!==void 0&&!L(i.target)||g(i)&&i.rel!==void 0&&typeof i.rel!="string")return null;const e=typeof i=="string"?{href:i}:g(i)&&typeof i.href=="string"?m(m({href:i.href},L(i.target)?{target:i.target}:{}),typeof i.rel=="string"?{rel:i.rel}:{}):null;if(!e)return null;const t=E(e.href,"link");if(!t)return null;const r=(n=e.target)!=null?n:"_self";return{href:t,target:r,rel:D(e.rel,r)}}function ct(i,e,t){var c;const r=R(i.attrs);if(typeof r.id!="string"||!r.id||typeof r.text!="string"||!r.text||r.style!=="text"&&r.style!=="button")return null;const n=Object.freeze(S(m({id:r.id},typeof r.title=="string"?{title:r.title}:{}),{text:r.text,style:r.style})),s=Object.freeze({type:"articleButton",attrs:n});let a=null;if(!t.resolveArticleButtonLink)A(t,{code:"LINK_RESOLUTION_FAILED",path:e,message:"No resolveArticleButtonLink callback was provided for an articleButton node.",nodeType:"articleButton"});else try{const d=t.resolveArticleButtonLink(n,s);a=dt(d),a||A(t,{code:typeof d=="string"||g(d)&&typeof d.href=="string"?"UNSAFE_URL":"LINK_RESOLUTION_FAILED",path:e,message:"The articleButton link resolver returned no usable safe URL.",nodeType:"articleButton"})}catch(d){A(t,{code:"LINK_RESOLUTION_FAILED",path:e,message:`The articleButton link resolver threw an error: ${d instanceof Error?d.message:String(d)}`,nodeType:"articleButton"})}const o=(c=a==null?void 0:a.href)!=null?c:null;return h(t,"a",{class:["acp-article-button",`acp-article-button--${n.style}`,!o&&"acp-article-button--disabled"],href:o!=null?o:void 0,target:a==null?void 0:a.target,rel:a==null?void 0:a.rel,title:n.title,"data-node-type":"articleButton","data-article-button-id":n.id,"data-article-button-style":n.style,"aria-disabled":o?void 0:"true",onClick:d=>{o||d.preventDefault(),t.emitArticleButtonClick({attrs:n,node:s,href:o,event:d})}},n.text)}function M(i,e,t){if(!g(i)||typeof i.type!="string"||!nt.has(i.type))return null;const r=R(i.attrs);switch(i.type){case"paragraph":{const n=q(r.textAlign)?r.textAlign:void 0;return h(t,"p",{class:"acp-paragraph","data-node-type":"paragraph",style:n?{textAlign:n}:void 0},w(i.content,p(e,"content"),t))}case"heading":{const n=Number.isInteger(r.level)&&Number(r.level)>=1&&Number(r.level)<=6?Number(r.level):1,s=q(r.textAlign)?r.textAlign:void 0;return h(t,`h${n}`,{class:["acp-heading",`acp-heading--${n}`],"data-node-type":"heading",style:s?{textAlign:s}:void 0},w(i.content,p(e,"content"),t))}case"blockquote":return h(t,"blockquote",{class:"acp-blockquote","data-node-type":"blockquote"},P(i.content,p(e,"content"),t));case"bulletList":{const n=y(i.content).map((s,a)=>B(s,p(e,"content",a),t)).filter(s=>s!==null);return h(t,"ul",{class:"acp-list acp-list--bullet","data-node-type":"bulletList"},n)}case"orderedList":{const n=Number.isInteger(r.start)&&Number(r.start)>=1?Number(r.start):1,s=y(i.content).map((a,o)=>B(a,p(e,"content",o),t)).filter(a=>a!==null);return h(t,"ol",{class:"acp-list acp-list--ordered","data-node-type":"orderedList",start:n},s)}case"codeBlock":{const n=typeof r.language=="string"&&r.language?r.language:void 0,s=y(i.content).filter(a=>g(a)&&a.type==="text"&&typeof a.text=="string").map(a=>a.text).join("");return h(t,"pre",{class:"acp-code-block","data-node-type":"codeBlock","data-language":n},[h(t,"code",{class:n?`language-${n}`:void 0},s)])}case"horizontalRule":return h(t,"hr",{class:"acp-horizontal-rule","data-node-type":"horizontalRule"});case"image":{const n=E(tt(r.src,t.imageBaseUrl),"image");if(!n)return A(t,{code:"UNSAFE_URL",path:p(e,"attrs","src"),message:"The image URL is empty, malformed, or uses a disallowed protocol.",nodeType:"image"}),null;const s=st(r.imageAlign)?r.imageAlign:"center",a=Number.isInteger(r.width)&&Number(r.width)>=1&&Number(r.width)<=1e4?Number(r.width):void 0,o=Number.isInteger(r.height)&&Number(r.height)>=1&&Number(r.height)<=1e4?Number(r.height):void 0;return h(t,"div",{class:["acp-image",`acp-image--${s}`],"data-node-type":"image","data-image-align":s},[h(t,"img",{class:"acp-image__element",src:n,alt:typeof r.alt=="string"?r.alt:"",title:typeof r.title=="string"?r.title:void 0,width:a,height:o,"data-image-align":s})])}case"articleButton":return ct(i,e,t);case"table":{const n=y(i.content).map((s,a)=>lt(s,p(e,"content",a),t)).filter(s=>s!==null);return h(t,"div",{class:"acp-table-wrapper","data-node-type":"table"},[h(t,"table",{class:"acp-table"},[h(t,"tbody",n)])])}}return null}function P(i,e,t){return y(i).map((r,n)=>M(r,p(e,n),t)).filter(r=>r!==null)}function $(i){return typeof i=="string"||typeof i=="number"?i:void 0}function ut(i,e){const t=$(i.adm),r=$(i.ads),n=t!==void 0&&e.admPublisherId?e.createElement(it,{key:`adm:${i.index}:${String(t)}`,props:{publisherId:e.admPublisherId,slotId:t,title:e.adTitle,fallbackPublisherId:r!==void 0?e.adsPublisherId:void 0,fallbackSlotId:r}}):r!==void 0&&e.adsPublisherId?e.createElement(x,{key:`ads:${i.index}:${String(r)}`,props:{publisherId:e.adsPublisherId,slotId:r,title:e.adTitle}}):null;return e.createElement("div",{key:`/adConf/${i.index}`,staticClass:"acp-ad-slot",attrs:{"data-node-type":"adSlot","data-ad-slot":"true","data-ad-index":i.index,"data-ad-location":i.location,"data-adm":t,"data-ads":r}},n?[n]:[])}function ht(i,e){const t=y(i.content),r=new Map;e.adSlots.forEach(s=>{var o;if(s.location>t.length)return;const a=(o=r.get(s.location))!=null?o:[];a.push(s),r.set(s.location,a)});const n=[];return t.forEach((s,a)=>{var d;const o=a+1;(d=r.get(o))==null||d.forEach(f=>n.push(ut(f,e)));const c=M(s,p("/content",a),e);c&&typeof c!="string"&&n.push(c)}),n}function ft(i,e){return!g(i)||i.type!=="doc"?[]:ht(i,e)}const pt=new Set(["paragraph","heading","blockquote","bulletList","orderedList","codeBlock","horizontalRule","image","articleButton","table"]),gt=new Set(["left","center","right","justify"]),yt=new Set(["left","center","right"]),mt=new Set(["bold","italic","strike","underline","code"]);function b(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function l(i,e){return`${i}/${String(e).replaceAll("~","~0").replaceAll("/","~1")}`}function u(i,...e){let t=i;for(const r of e)t=l(t,r);return t}class bt{constructor(){O(this,"issues",[])}validate(e){if(!b(e))return this.add("INVALID_ROOT","","The document must be an object."),this.result();this.checkProperties(e,"",["type","content"],["type","content"]),e.type!=="doc"&&this.add("INVALID_ROOT","/type",'The root node type must be "doc".');const t=this.requireArray(e.content,"/content");return t==null||t.forEach((r,n)=>this.validateBlock(r,l("/content",n))),this.result()}result(){return{valid:this.issues.length===0,issues:this.issues}}add(e,t,r,n){this.issues.push(m({code:e,path:t,message:r},n?{nodeType:n}:{}))}checkProperties(e,t,r,n=[],s){const a=new Set(r);for(const o of Object.keys(e))a.has(o)||this.add("UNKNOWN_PROPERTY",l(t,o),`Property "${o}" is not allowed.`,s);for(const o of n)o in e||this.add("MISSING_PROPERTY",l(t,o),`Required property "${o}" is missing.`,s)}requireArray(e,t,r){return Array.isArray(e)?e:(this.add("INVALID_TYPE",t,"Expected an array.",r),null)}optionalArray(e,t,r){return e===void 0?[]:this.requireArray(e,t,r)}requireNonEmptyArray(e,t,r){const n=this.requireArray(e,t,r);return n&&n.length===0&&this.add("INVALID_CONTENT",t,`Node "${r}" must contain at least one child.`,r),n}requireRecord(e,t,r){return b(e)?e:(this.add("INVALID_TYPE",t,"Expected an object.",r),null)}optionalRecord(e,t,r){return e===void 0?{}:this.requireRecord(e,t,r)}requireString(e,t,r,n={}){return typeof e!="string"?(this.add("INVALID_TYPE",t,"Expected a string.",r),!1):!n.allowEmpty&&e.length===0?(this.add("INVALID_VALUE",t,"The string must not be empty.",r),!1):n.maxLength!==void 0&&e.length>n.maxLength?(this.add("INVALID_VALUE",t,`The string must contain at most ${n.maxLength} characters.`,r),!1):!0}optionalString(e,t,r,n={}){e!==void 0&&this.requireString(e,t,r,n)}requireInteger(e,t,r,n,s){if(!Number.isInteger(e))return this.add("INVALID_TYPE",t,"Expected an integer.",r),!1;const a=e;return n!==void 0&&a<n?(this.add("INVALID_VALUE",t,`Value must be at least ${n}.`,r),!1):s!==void 0&&a>s?(this.add("INVALID_VALUE",t,`Value must be at most ${s}.`,r),!1):!0}validateBlock(e,t){if(!b(e)){this.add("INVALID_TYPE",t,"A block node must be an object.");return}const r=e.type;if(typeof r!="string"){this.add("MISSING_PROPERTY",l(t,"type"),"A block node requires a type.");return}if(!pt.has(r)){this.add("UNKNOWN_NODE",l(t,"type"),`Unknown block node "${r}".`,r);return}switch(r){case"paragraph":this.validateParagraph(e,t);break;case"heading":this.validateHeading(e,t);break;case"blockquote":this.validateBlockquote(e,t);break;case"bulletList":this.validateBulletList(e,t);break;case"orderedList":this.validateOrderedList(e,t);break;case"codeBlock":this.validateCodeBlock(e,t);break;case"horizontalRule":this.checkProperties(e,t,["type"],["type"],r);break;case"image":this.validateImage(e,t);break;case"articleButton":this.validateArticleButton(e,t);break;case"table":this.validateTable(e,t);break}}validateParagraph(e,t){const r="paragraph";this.checkProperties(e,t,["type","attrs","content"],["type"],r),this.validateTextAlignAttrs(e.attrs,l(t,"attrs"),r,!1),this.validateInlineContent(e.content,l(t,"content"),r)}validateHeading(e,t){const r="heading";this.checkProperties(e,t,["type","attrs","content"],["type","attrs"],r);const n=this.requireRecord(e.attrs,l(t,"attrs"),r);n&&(this.checkProperties(n,l(t,"attrs"),["level","textAlign"],["level"],r),this.requireInteger(n.level,u(t,"attrs","level"),r,1,6),this.validateTextAlign(n.textAlign,u(t,"attrs","textAlign"),r)),this.validateInlineContent(e.content,l(t,"content"),r)}validateTextAlignAttrs(e,t,r,n){const s=n?this.requireRecord(e,t,r):this.optionalRecord(e,t,r);s&&(this.checkProperties(s,t,["textAlign"],[],r),this.validateTextAlign(s.textAlign,l(t,"textAlign"),r))}validateTextAlign(e,t,r){e!==void 0&&(typeof e!="string"?this.add("INVALID_TYPE",t,"Text alignment must be a string.",r):gt.has(e)||this.add("INVALID_VALUE",t,`Unsupported text alignment "${e}".`,r))}validateInlineContent(e,t,r){const n=this.optionalArray(e,t,r);n==null||n.forEach((s,a)=>this.validateText(s,l(t,a),!0))}validateText(e,t,r){if(!b(e)){this.add("INVALID_TYPE",t,"A text node must be an object.","text");return}const n=r?["type","text","marks"]:["type","text"];if(this.checkProperties(e,t,n,["type","text"],"text"),e.type!=="text"&&this.add("INVALID_CONTENT",l(t,"type"),"Expected a text node.","text"),this.requireString(e.text,l(t,"text"),"text"),r&&e.marks!==void 0){const s=this.requireArray(e.marks,l(t,"marks"),"text");s==null||s.forEach((a,o)=>this.validateMark(a,u(t,"marks",o)))}}validateMark(e,t){if(!b(e)){this.add("INVALID_TYPE",t,"A mark must be an object.");return}if(typeof e.type!="string"){this.add("MISSING_PROPERTY",l(t,"type"),"A mark requires a type.");return}if(mt.has(e.type)){this.checkProperties(e,t,["type"],["type"],e.type);return}if(e.type!=="link"){this.add("UNKNOWN_MARK",l(t,"type"),`Unknown mark "${e.type}".`,e.type);return}this.checkProperties(e,t,["type","attrs"],["type","attrs"],"link");const r=this.requireRecord(e.attrs,l(t,"attrs"),"link");r&&(this.checkProperties(r,l(t,"attrs"),["href","target"],["href"],"link"),this.requireString(r.href,u(t,"attrs","href"),"link"),r.target!==void 0&&r.target!=="_blank"&&r.target!=="_self"&&this.add("INVALID_VALUE",u(t,"attrs","target"),'Link target must be "_blank" or "_self".',"link"))}validateBlockquote(e,t){const r="blockquote";this.checkProperties(e,t,["type","content"],["type","content"],r);const n=this.requireNonEmptyArray(e.content,l(t,"content"),r);n==null||n.forEach((s,a)=>this.validateBlock(s,u(t,"content",a)))}validateBulletList(e,t){const r="bulletList";this.checkProperties(e,t,["type","content"],["type","content"],r);const n=this.requireNonEmptyArray(e.content,l(t,"content"),r);n==null||n.forEach((s,a)=>this.validateListItem(s,u(t,"content",a)))}validateOrderedList(e,t){const r="orderedList";this.checkProperties(e,t,["type","attrs","content"],["type","content"],r);const n=this.optionalRecord(e.attrs,l(t,"attrs"),r);n&&(this.checkProperties(n,l(t,"attrs"),["start"],[],r),n.start!==void 0&&this.requireInteger(n.start,u(t,"attrs","start"),r,1));const s=this.requireNonEmptyArray(e.content,l(t,"content"),r);s==null||s.forEach((a,o)=>this.validateListItem(a,u(t,"content",o)))}validateListItem(e,t){const r="listItem",n=this.requireRecord(e,t,r);if(!n)return;this.checkProperties(n,t,["type","content"],["type","content"],r),n.type!==r&&this.add("INVALID_CONTENT",l(t,"type"),"Expected a listItem node.",r);const s=this.requireNonEmptyArray(n.content,l(t,"content"),r);s==null||s.forEach((a,o)=>this.validateBlock(a,u(t,"content",o)))}validateCodeBlock(e,t){const r="codeBlock";this.checkProperties(e,t,["type","attrs","content"],["type"],r);const n=this.optionalRecord(e.attrs,l(t,"attrs"),r);n&&(this.checkProperties(n,l(t,"attrs"),["language"],[],r),this.optionalString(n.language,u(t,"attrs","language"),r,{maxLength:32}));const s=this.optionalArray(e.content,l(t,"content"),r);s&&(s.length>1&&this.add("INVALID_CONTENT",l(t,"content"),"A codeBlock may contain at most one text node.",r),s.forEach((a,o)=>this.validateText(a,u(t,"content",o),!1)))}validateImage(e,t){const r="image";this.checkProperties(e,t,["type","attrs"],["type","attrs"],r);const n=this.requireRecord(e.attrs,l(t,"attrs"),r);n&&(this.checkProperties(n,l(t,"attrs"),["src","alt","title","width","height","imageAlign"],["src"],r),this.requireString(n.src,u(t,"attrs","src"),r),this.optionalString(n.alt,u(t,"attrs","alt"),r,{allowEmpty:!0}),this.optionalString(n.title,u(t,"attrs","title"),r,{allowEmpty:!0}),n.width!==void 0&&this.requireInteger(n.width,u(t,"attrs","width"),r,1,1e4),n.height!==void 0&&this.requireInteger(n.height,u(t,"attrs","height"),r,1,1e4),n.imageAlign!==void 0&&(typeof n.imageAlign!="string"?this.add("INVALID_TYPE",u(t,"attrs","imageAlign"),"Image alignment must be a string.",r):yt.has(n.imageAlign)||this.add("INVALID_VALUE",u(t,"attrs","imageAlign"),`Unsupported image alignment "${n.imageAlign}".`,r)))}validateArticleButton(e,t){const r="articleButton";this.checkProperties(e,t,["type","attrs"],["type","attrs"],r);const n=this.requireRecord(e.attrs,l(t,"attrs"),r);n&&(this.checkProperties(n,l(t,"attrs"),["id","title","text","style"],["id","text","style"],r),this.requireString(n.id,u(t,"attrs","id"),r),this.optionalString(n.title,u(t,"attrs","title"),r),this.requireString(n.text,u(t,"attrs","text"),r),n.style!=="text"&&n.style!=="button"&&this.add("INVALID_VALUE",u(t,"attrs","style"),'Article button style must be "text" or "button".',r))}validateTable(e,t){const r="table";this.checkProperties(e,t,["type","content"],["type","content"],r);const n=this.requireNonEmptyArray(e.content,l(t,"content"),r);if(!n)return;let s=null;n.forEach((a,o)=>{const c=u(t,"content",o),d=this.validateTableRow(a,c);d!==null&&(s===null?s=d:d!==s&&this.add("TABLE_COLUMN_MISMATCH",l(c,"content"),`Expected ${s} table cells but received ${d}.`,"tableRow"))})}validateTableRow(e,t){var a;const r="tableRow",n=this.requireRecord(e,t,r);if(!n)return null;this.checkProperties(n,t,["type","content"],["type","content"],r),n.type!==r&&this.add("INVALID_CONTENT",l(t,"type"),"Expected a tableRow node.",r);const s=this.requireNonEmptyArray(n.content,l(t,"content"),r);return s==null||s.forEach((o,c)=>this.validateTableCell(o,u(t,"content",c))),(a=s==null?void 0:s.length)!=null?a:null}validateTableCell(e,t){const r="tableCell",n=this.requireRecord(e,t,r);if(!n)return;this.checkProperties(n,t,["type","content"],["type","content"],r),n.type!==r&&this.add("INVALID_CONTENT",l(t,"type"),"Expected a tableCell node.",r);const s=this.requireNonEmptyArray(n.content,l(t,"content"),r);s==null||s.forEach((a,o)=>this.validateBlock(a,u(t,"content",o)))}}function At(i){return new bt().validate(i)}const V=Object.freeze({version:1,validate:At,render:ft}),K=new Map([[V.version,V]]),It=Object.freeze([...K.keys()]),T=1;function j(i){return K.get(i)}function z(i,e={}){var s;const t=(s=e.protocolVersion)!=null?s:T,r=j(t);return r?r.validate(i):{valid:!1,issues:[{code:"UNSUPPORTED_PROTOCOL",path:"",message:`Article Content Protocol version ${t} is not supported.`}]}}const kt="Advertisement";function St(){return{adm:[],ads:[],loc:[]}}function Lt(){return{adm:"",ads:""}}function U(i){return`${i.code}:${i.path}:${i.message}`}function Nt(i){var o,c,d,f;const e=(c=(o=i.adm)==null?void 0:o.length)!=null?c:0,t=(f=(d=i.ads)==null?void 0:d.length)!=null?f:0,r=i.loc.length,n=e===0||e===r,s=t===0||t===r,a=e>0||t>0;return r===0&&!a||a&&n&&s?null:{code:"AD_CONFIG_LENGTH_MISMATCH",path:"/adConf",message:`Each non-empty adConf.adm or adConf.ads array must have the same length as adConf.loc, and at least one ad array must contain values when loc is non-empty. Received adm length ${e}, ads length ${t}, and loc length ${r}.`}}function Et(i,e){return e?[]:i.loc.map((t,r)=>{var n,s;return{index:r+1,location:t,adm:(n=i.adm)==null?void 0:n[r],ads:(s=i.ads)==null?void 0:s[r]}}).filter(t=>Number.isInteger(t.location)&&t.location>=1)}const Rt=N.extend({name:"ArticleContentRenderer",props:{document:{type:null,required:!0},protocolVersion:{type:Number,default:T},strict:{type:Boolean,default:!1},adConf:{type:Object,default:St},pubid:{type:Object,default:Lt},adTitle:{type:String,default:kt},imageBaseUrl:{type:String,default:I},resolveArticleButtonLink:{type:Function,default:void 0}},data(){return{reportedRuntimeIssues:new Set,reportedAdConfigIssue:null}},computed:{validation(){return z(this.document,{protocolVersion:this.protocolVersion})},adConfigIssue(){return Nt(this.adConf)},adSlots(){return Et(this.adConf,this.adConfigIssue)}},watch:{validation:{immediate:!0,deep:!0,handler(i){i.issues.forEach(e=>this.$emit("render-error",e))}},document:{deep:!0,handler(){this.reportedRuntimeIssues.clear()}},protocolVersion(){this.reportedRuntimeIssues.clear()},resolveArticleButtonLink(){this.reportedRuntimeIssues.clear()},imageBaseUrl(){this.reportedRuntimeIssues.clear()},adConfigIssue:{immediate:!0,handler(i){if(!i){this.reportedAdConfigIssue=null;return}const e=U(i);this.reportedAdConfigIssue!==e&&(this.reportedAdConfigIssue=e,console.error("[ArticleContentRenderer] Invalid adConf:",i),this.$emit("render-error",i))}}},methods:{reportRuntimeIssue(i){const e=U(i);this.reportedRuntimeIssues.has(e)||(this.reportedRuntimeIssues.add(e),this.$nextTick(()=>this.$emit("render-error",i)))}},render(i){const e=j(this.protocolVersion);if(!e||this.strict&&!this.validation.valid)return i("div",{class:"acp-render-error",attrs:{role:"alert","data-render-error":"true"}},"Invalid article content");const t=e.render(this.document,{createElement:i,adSlots:this.adSlots,admPublisherId:this.pubid.adm,adsPublisherId:this.pubid.ads,adTitle:this.adTitle,imageBaseUrl:this.imageBaseUrl,resolveArticleButtonLink:this.resolveArticleButtonLink,emitArticleButtonClick:r=>this.$emit("article-button-click",r),reportIssue:this.reportRuntimeIssue});return i("div",{class:"acp-document",attrs:{"data-node-type":"doc","data-protocol-version":this.protocolVersion}},t)}});function Pt(i,e,t,r,n,s,a,o){var c=typeof i=="function"?i.options:i;return{exports:i,options:c}}var Tt=Pt(Rt);const _=Tt.exports,_t=Object.freeze({fileFormat:"article-content-protocol",fileFormatVersion:1,mediaType:"application/vnd.article-content-protocol+json",id:"article-content-v1",version:1,name:"Article Content Protocol v1",status:"draft",rootNode:"doc",nodeTypes:Object.freeze(["doc","paragraph","heading","blockquote","bulletList","orderedList","listItem","codeBlock","horizontalRule","image","articleButton","table","tableRow","tableCell","text"]),markTypes:Object.freeze(["bold","italic","strike","underline","code","link"])}),vt={install(i){i.component("ArticleContentRenderer",_)}};exports.ARTICLE_CONTENT_PROTOCOL_V1=_t;exports.ArticleContentRenderer=_;exports.ArticleContentRendererPlugin=vt;exports.CURRENT_PROTOCOL_VERSION=T;exports.SUPPORTED_PROTOCOL_VERSIONS=It;exports.default=_;exports.validateArticleDocument=z;
1
+ "use strict";var M=Object.defineProperty,Y=Object.defineProperties;var F=Object.getOwnPropertyDescriptors;var B=Object.getOwnPropertySymbols;var K=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var R=(i,r,t)=>r in i?M(i,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[r]=t,m=(i,r)=>{for(var t in r||(r={}))K.call(r,t)&&R(i,t,r[t]);if(B)for(var t of B(r))G.call(r,t)&&R(i,t,r[t]);return i},A=(i,r)=>Y(i,F(r));var w=(i,r,t)=>R(i,typeof r!="symbol"?r+"":r,t);Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});const W=require("vue"),H=new Set(["http:","https:","mailto:","tel:"]),X=new Set(["http:","https:","blob:"]),J="https://article-content-renderer.invalid/",N="https://www.doitme.link/";function Q(i,r){if(typeof i!="string")return i;const t=i.trim();if(!t.startsWith(N))return t;const n=(r.trim()||N).replace(/\/+$/u,""),s=t.slice(N.length).replace(/^\/+/,"");return`${n}/${s}`}function T(i,r){if(typeof i!="string")return null;const t=i.trim();if(!t||/[\u0000-\u001F\u007F]/u.test(t))return null;try{const e=new URL(t,J);return(r==="link"?H:X).has(e.protocol)?t:null}catch(e){return null}}function v(i,r){const t=new Set(typeof i=="string"?i.trim().split(/\s+/u).filter(Boolean):[]);return r==="_blank"&&(t.add("noopener"),t.add("noreferrer")),t.size>0?[...t].join(" "):void 0}const Z=new Set(["paragraph","heading","blockquote","bulletList","orderedList","codeBlock","horizontalRule","image","articleButton","table"]);function p(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function _(i){return p(i)?i:{}}function f(i,r,t,e){var c;const n=p(t)?t:{},s=p(t)?e:t,o={},l={};for(const[u,h]of Object.entries(n))if(u==="class")o.class=h;else if(u==="style")o.style=h;else if(u.startsWith("on")&&typeof h=="function"){const y=u.slice(2).toLowerCase();o.on=A(m({},(c=o.on)!=null?c:{}),{[y]:h})}else h!==void 0&&h!==!1&&(l[u]=h);return Object.keys(l).length>0&&(o.attrs=l),i.createElement(r,o,s)}function k(i){return Array.isArray(i)?i:[]}function g(i,...r){return`${i}/${r.map(String).join("/")}`}function V(i){return i==="left"||i==="center"||i==="right"||i==="justify"}function tt(i){return i==="left"||i==="center"||i==="right"}function E(i){return i==="_blank"||i==="_self"}function b(i,r){i.reportIssue(r)}function et(i,r,t){if(!p(i)||i.type!=="text"||typeof i.text!="string"||!i.text)return null;let e=i.text;const n=k(i.marks);for(let s=0;s<n.length;s+=1){const o=n[s];if(!p(o)||typeof o.type!="string")continue;const l=g(r,"marks",s);switch(o.type){case"bold":e=f(t,"strong",{class:"acp-mark acp-mark--bold"},[e]);break;case"italic":e=f(t,"em",{class:"acp-mark acp-mark--italic"},[e]);break;case"strike":e=f(t,"s",{class:"acp-mark acp-mark--strike"},[e]);break;case"underline":e=f(t,"u",{class:"acp-mark acp-mark--underline"},[e]);break;case"code":e=f(t,"code",{class:"acp-mark acp-mark--code"},[e]);break;case"link":{const c=_(o.attrs),u=T(c.href,"link");if(!u){b(t,{code:"UNSAFE_URL",path:g(l,"attrs","href"),message:"The link URL is empty, malformed, or uses a disallowed protocol.",nodeType:"link"});break}const h=E(c.target)?c.target:"_blank";e=f(t,"a",{class:"acp-link",href:u,target:h,rel:v(void 0,h)},[e]);break}}}return e}function C(i,r,t){return k(i).map((e,n)=>et(e,g(r,n),t)).filter(e=>e!==null)}function q(i,r,t){return!p(i)||i.type!=="listItem"?null:f(t,"li",{class:"acp-list-item","data-node-type":"listItem"},P(i.content,g(r,"content"),t))}function rt(i,r,t){return!p(i)||i.type!=="tableCell"?null:f(t,"td",{class:"acp-table-cell","data-node-type":"tableCell"},P(i.content,g(r,"content"),t))}function it(i,r,t){if(!p(i)||i.type!=="tableRow")return null;const e=k(i.content).map((n,s)=>rt(n,g(r,"content",s),t)).filter(n=>n!==null);return f(t,"tr",{class:"acp-table-row","data-node-type":"tableRow"},e)}function U(i){var n;if(p(i)&&i.target!==void 0&&!E(i.target)||p(i)&&i.rel!==void 0&&typeof i.rel!="string")return null;const r=typeof i=="string"?{href:i}:p(i)&&typeof i.href=="string"?m(m({href:i.href},E(i.target)?{target:i.target}:{}),typeof i.rel=="string"?{rel:i.rel}:{}):null;if(!r)return null;const t=T(r.href,"link");if(!t)return null;const e=(n=r.target)!=null?n:"_self";return{href:t,target:e,rel:v(r.rel,e)}}function nt(i,r,t){var h;const e=_(i.attrs),n=e.style==="text"||e.style==="button",s=e.style==="link";if(typeof e.text!="string"||!e.text||!n&&!s||n&&(typeof e.id!="string"||!e.id)||s&&e.id!==void 0&&(typeof e.id!="string"||!e.id))return null;const o=Object.freeze(s?m(A(m(m({},typeof e.id=="string"?{id:e.id}:{}),typeof e.title=="string"?{title:e.title}:{}),{text:e.text,style:"link"}),typeof e.href=="string"?{href:e.href}:{}):A(m({id:e.id},typeof e.title=="string"?{title:e.title}:{}),{text:e.text,style:e.style})),l=Object.freeze({type:"articleButton",attrs:o});let c=null;if(o.style==="link")o.href!==void 0&&(c=U(o.href),c||b(t,{code:"UNSAFE_URL",path:`${r}/attrs/href`,message:"The articleButton link href is not a usable safe URL.",nodeType:"articleButton"}));else if(!t.resolveArticleButtonLink)b(t,{code:"LINK_RESOLUTION_FAILED",path:r,message:"No resolveArticleButtonLink callback was provided for an articleButton node.",nodeType:"articleButton"});else try{const y=Object.freeze({type:"articleButton",attrs:o}),L=t.resolveArticleButtonLink(o,y);c=U(L),c||b(t,{code:typeof L=="string"||p(L)&&typeof L.href=="string"?"UNSAFE_URL":"LINK_RESOLUTION_FAILED",path:r,message:"The articleButton link resolver returned no usable safe URL.",nodeType:"articleButton"})}catch(y){b(t,{code:"LINK_RESOLUTION_FAILED",path:r,message:`The articleButton link resolver threw an error: ${y instanceof Error?y.message:String(y)}`,nodeType:"articleButton"})}const u=(h=c==null?void 0:c.href)!=null?h:null;return f(t,"a",{class:["acp-article-button",`acp-article-button--${o.style}`,!u&&"acp-article-button--disabled"],href:u!=null?u:void 0,target:c==null?void 0:c.target,rel:c==null?void 0:c.rel,title:o.title,"data-node-type":"articleButton","data-article-button-id":o.id,"data-article-button-style":o.style,"aria-disabled":u?void 0:"true",onClick:y=>{u||y.preventDefault(),t.emitArticleButtonClick({attrs:o,node:l,href:u,event:y})}},o.text)}function $(i,r,t){if(!p(i)||typeof i.type!="string"||!Z.has(i.type))return null;const e=_(i.attrs);switch(i.type){case"paragraph":{const n=V(e.textAlign)?e.textAlign:void 0;return f(t,"p",{class:"acp-paragraph","data-node-type":"paragraph",style:n?{textAlign:n}:void 0},C(i.content,g(r,"content"),t))}case"heading":{const n=Number.isInteger(e.level)&&Number(e.level)>=1&&Number(e.level)<=6?Number(e.level):1,s=V(e.textAlign)?e.textAlign:void 0;return f(t,`h${n}`,{class:["acp-heading",`acp-heading--${n}`],"data-node-type":"heading",style:s?{textAlign:s}:void 0},C(i.content,g(r,"content"),t))}case"blockquote":return f(t,"blockquote",{class:"acp-blockquote","data-node-type":"blockquote"},P(i.content,g(r,"content"),t));case"bulletList":{const n=k(i.content).map((s,o)=>q(s,g(r,"content",o),t)).filter(s=>s!==null);return f(t,"ul",{class:"acp-list acp-list--bullet","data-node-type":"bulletList"},n)}case"orderedList":{const n=Number.isInteger(e.start)&&Number(e.start)>=1?Number(e.start):1,s=k(i.content).map((o,l)=>q(o,g(r,"content",l),t)).filter(o=>o!==null);return f(t,"ol",{class:"acp-list acp-list--ordered","data-node-type":"orderedList",start:n},s)}case"codeBlock":{const n=typeof e.language=="string"&&e.language?e.language:void 0,s=k(i.content).filter(o=>p(o)&&o.type==="text"&&typeof o.text=="string").map(o=>o.text).join("");return f(t,"pre",{class:"acp-code-block","data-node-type":"codeBlock","data-language":n},[f(t,"code",{class:n?`language-${n}`:void 0},s)])}case"horizontalRule":return f(t,"hr",{class:"acp-horizontal-rule","data-node-type":"horizontalRule"});case"image":{const n=T(Q(e.src,t.imageBaseUrl),"image");if(!n)return b(t,{code:"UNSAFE_URL",path:g(r,"attrs","src"),message:"The image URL is empty, malformed, or uses a disallowed protocol.",nodeType:"image"}),null;const s=tt(e.imageAlign)?e.imageAlign:"center",o=Number.isInteger(e.width)&&Number(e.width)>=1&&Number(e.width)<=1e4?Number(e.width):void 0,l=Number.isInteger(e.height)&&Number(e.height)>=1&&Number(e.height)<=1e4?Number(e.height):void 0;return f(t,"div",{class:["acp-image",`acp-image--${s}`],"data-node-type":"image","data-image-align":s},[f(t,"img",{class:"acp-image__element",src:n,alt:typeof e.alt=="string"?e.alt:"",title:typeof e.title=="string"?e.title:void 0,width:o,height:l,"data-image-align":s})])}case"articleButton":return nt(i,r,t);case"table":{const n=k(i.content).map((s,o)=>it(s,g(r,"content",o),t)).filter(s=>s!==null);return f(t,"div",{class:"acp-table-wrapper","data-node-type":"table"},[f(t,"table",{class:"acp-table"},[f(t,"tbody",n)])])}}return null}function P(i,r,t){return k(i).map((e,n)=>$(e,g(r,n),t)).filter(e=>e!==null)}function st(i,r){const t=k(i.content),e=new Map;r.customSlots.forEach(s=>{var l;if(!Number.isInteger(s.location)||s.location<1||s.location>t.length)return;const o=(l=e.get(s.location))!=null?l:[];o.push(s),e.set(s.location,o)});const n=[];return t.forEach((s,o)=>{var u;const l=o+1;(u=e.get(l))==null||u.forEach(h=>n.push(...h.content));const c=$(s,g("/content",o),r);c&&typeof c!="string"&&n.push(c)}),n}function ot(i,r){return!p(i)||i.type!=="doc"?[]:st(i,r)}const at=new Set(["paragraph","heading","blockquote","bulletList","orderedList","codeBlock","horizontalRule","image","articleButton","table"]),lt=new Set(["left","center","right","justify"]),ct=new Set(["left","center","right"]),dt=new Set(["bold","italic","strike","underline","code"]);function I(i){return typeof i=="object"&&i!==null&&!Array.isArray(i)}function a(i,r){return`${i}/${String(r).replaceAll("~","~0").replaceAll("/","~1")}`}function d(i,...r){let t=i;for(const e of r)t=a(t,e);return t}class ut{constructor(){w(this,"issues",[])}validate(r){if(!I(r))return this.add("INVALID_ROOT","","The document must be an object."),this.result();this.checkProperties(r,"",["type","content"],["type","content"]),r.type!=="doc"&&this.add("INVALID_ROOT","/type",'The root node type must be "doc".');const t=this.requireArray(r.content,"/content");return t==null||t.forEach((e,n)=>this.validateBlock(e,a("/content",n))),this.result()}result(){return{valid:this.issues.length===0,issues:this.issues}}add(r,t,e,n){this.issues.push(m({code:r,path:t,message:e},n?{nodeType:n}:{}))}checkProperties(r,t,e,n=[],s){const o=new Set(e);for(const l of Object.keys(r))o.has(l)||this.add("UNKNOWN_PROPERTY",a(t,l),`Property "${l}" is not allowed.`,s);for(const l of n)l in r||this.add("MISSING_PROPERTY",a(t,l),`Required property "${l}" is missing.`,s)}requireArray(r,t,e){return Array.isArray(r)?r:(this.add("INVALID_TYPE",t,"Expected an array.",e),null)}optionalArray(r,t,e){return r===void 0?[]:this.requireArray(r,t,e)}requireNonEmptyArray(r,t,e){const n=this.requireArray(r,t,e);return n&&n.length===0&&this.add("INVALID_CONTENT",t,`Node "${e}" must contain at least one child.`,e),n}requireRecord(r,t,e){return I(r)?r:(this.add("INVALID_TYPE",t,"Expected an object.",e),null)}optionalRecord(r,t,e){return r===void 0?{}:this.requireRecord(r,t,e)}requireString(r,t,e,n={}){return typeof r!="string"?(this.add("INVALID_TYPE",t,"Expected a string.",e),!1):!n.allowEmpty&&r.length===0?(this.add("INVALID_VALUE",t,"The string must not be empty.",e),!1):n.maxLength!==void 0&&r.length>n.maxLength?(this.add("INVALID_VALUE",t,`The string must contain at most ${n.maxLength} characters.`,e),!1):!0}optionalString(r,t,e,n={}){r!==void 0&&this.requireString(r,t,e,n)}requireInteger(r,t,e,n,s){if(!Number.isInteger(r))return this.add("INVALID_TYPE",t,"Expected an integer.",e),!1;const o=r;return n!==void 0&&o<n?(this.add("INVALID_VALUE",t,`Value must be at least ${n}.`,e),!1):s!==void 0&&o>s?(this.add("INVALID_VALUE",t,`Value must be at most ${s}.`,e),!1):!0}validateBlock(r,t){if(!I(r)){this.add("INVALID_TYPE",t,"A block node must be an object.");return}const e=r.type;if(typeof e!="string"){this.add("MISSING_PROPERTY",a(t,"type"),"A block node requires a type.");return}if(!at.has(e)){this.add("UNKNOWN_NODE",a(t,"type"),`Unknown block node "${e}".`,e);return}switch(e){case"paragraph":this.validateParagraph(r,t);break;case"heading":this.validateHeading(r,t);break;case"blockquote":this.validateBlockquote(r,t);break;case"bulletList":this.validateBulletList(r,t);break;case"orderedList":this.validateOrderedList(r,t);break;case"codeBlock":this.validateCodeBlock(r,t);break;case"horizontalRule":this.checkProperties(r,t,["type"],["type"],e);break;case"image":this.validateImage(r,t);break;case"articleButton":this.validateArticleButton(r,t);break;case"table":this.validateTable(r,t);break}}validateParagraph(r,t){const e="paragraph";this.checkProperties(r,t,["type","attrs","content"],["type"],e),this.validateTextAlignAttrs(r.attrs,a(t,"attrs"),e,!1),this.validateInlineContent(r.content,a(t,"content"),e)}validateHeading(r,t){const e="heading";this.checkProperties(r,t,["type","attrs","content"],["type","attrs"],e);const n=this.requireRecord(r.attrs,a(t,"attrs"),e);n&&(this.checkProperties(n,a(t,"attrs"),["level","textAlign"],["level"],e),this.requireInteger(n.level,d(t,"attrs","level"),e,1,6),this.validateTextAlign(n.textAlign,d(t,"attrs","textAlign"),e)),this.validateInlineContent(r.content,a(t,"content"),e)}validateTextAlignAttrs(r,t,e,n){const s=n?this.requireRecord(r,t,e):this.optionalRecord(r,t,e);s&&(this.checkProperties(s,t,["textAlign"],[],e),this.validateTextAlign(s.textAlign,a(t,"textAlign"),e))}validateTextAlign(r,t,e){r!==void 0&&(typeof r!="string"?this.add("INVALID_TYPE",t,"Text alignment must be a string.",e):lt.has(r)||this.add("INVALID_VALUE",t,`Unsupported text alignment "${r}".`,e))}validateInlineContent(r,t,e){const n=this.optionalArray(r,t,e);n==null||n.forEach((s,o)=>this.validateText(s,a(t,o),!0))}validateText(r,t,e){if(!I(r)){this.add("INVALID_TYPE",t,"A text node must be an object.","text");return}const n=e?["type","text","marks"]:["type","text"];if(this.checkProperties(r,t,n,["type","text"],"text"),r.type!=="text"&&this.add("INVALID_CONTENT",a(t,"type"),"Expected a text node.","text"),this.requireString(r.text,a(t,"text"),"text"),e&&r.marks!==void 0){const s=this.requireArray(r.marks,a(t,"marks"),"text");s==null||s.forEach((o,l)=>this.validateMark(o,d(t,"marks",l)))}}validateMark(r,t){if(!I(r)){this.add("INVALID_TYPE",t,"A mark must be an object.");return}if(typeof r.type!="string"){this.add("MISSING_PROPERTY",a(t,"type"),"A mark requires a type.");return}if(dt.has(r.type)){this.checkProperties(r,t,["type"],["type"],r.type);return}if(r.type!=="link"){this.add("UNKNOWN_MARK",a(t,"type"),`Unknown mark "${r.type}".`,r.type);return}this.checkProperties(r,t,["type","attrs"],["type","attrs"],"link");const e=this.requireRecord(r.attrs,a(t,"attrs"),"link");e&&(this.checkProperties(e,a(t,"attrs"),["href","target"],["href"],"link"),this.requireString(e.href,d(t,"attrs","href"),"link"),e.target!==void 0&&e.target!=="_blank"&&e.target!=="_self"&&this.add("INVALID_VALUE",d(t,"attrs","target"),'Link target must be "_blank" or "_self".',"link"))}validateBlockquote(r,t){const e="blockquote";this.checkProperties(r,t,["type","content"],["type","content"],e);const n=this.requireNonEmptyArray(r.content,a(t,"content"),e);n==null||n.forEach((s,o)=>this.validateBlock(s,d(t,"content",o)))}validateBulletList(r,t){const e="bulletList";this.checkProperties(r,t,["type","content"],["type","content"],e);const n=this.requireNonEmptyArray(r.content,a(t,"content"),e);n==null||n.forEach((s,o)=>this.validateListItem(s,d(t,"content",o)))}validateOrderedList(r,t){const e="orderedList";this.checkProperties(r,t,["type","attrs","content"],["type","content"],e);const n=this.optionalRecord(r.attrs,a(t,"attrs"),e);n&&(this.checkProperties(n,a(t,"attrs"),["start"],[],e),n.start!==void 0&&this.requireInteger(n.start,d(t,"attrs","start"),e,1));const s=this.requireNonEmptyArray(r.content,a(t,"content"),e);s==null||s.forEach((o,l)=>this.validateListItem(o,d(t,"content",l)))}validateListItem(r,t){const e="listItem",n=this.requireRecord(r,t,e);if(!n)return;this.checkProperties(n,t,["type","content"],["type","content"],e),n.type!==e&&this.add("INVALID_CONTENT",a(t,"type"),"Expected a listItem node.",e);const s=this.requireNonEmptyArray(n.content,a(t,"content"),e);s==null||s.forEach((o,l)=>this.validateBlock(o,d(t,"content",l)))}validateCodeBlock(r,t){const e="codeBlock";this.checkProperties(r,t,["type","attrs","content"],["type"],e);const n=this.optionalRecord(r.attrs,a(t,"attrs"),e);n&&(this.checkProperties(n,a(t,"attrs"),["language"],[],e),this.optionalString(n.language,d(t,"attrs","language"),e,{maxLength:32}));const s=this.optionalArray(r.content,a(t,"content"),e);s&&(s.length>1&&this.add("INVALID_CONTENT",a(t,"content"),"A codeBlock may contain at most one text node.",e),s.forEach((o,l)=>this.validateText(o,d(t,"content",l),!1)))}validateImage(r,t){const e="image";this.checkProperties(r,t,["type","attrs"],["type","attrs"],e);const n=this.requireRecord(r.attrs,a(t,"attrs"),e);n&&(this.checkProperties(n,a(t,"attrs"),["src","alt","title","width","height","imageAlign"],["src"],e),this.requireString(n.src,d(t,"attrs","src"),e),this.optionalString(n.alt,d(t,"attrs","alt"),e,{allowEmpty:!0}),this.optionalString(n.title,d(t,"attrs","title"),e,{allowEmpty:!0}),n.width!==void 0&&this.requireInteger(n.width,d(t,"attrs","width"),e,1,1e4),n.height!==void 0&&this.requireInteger(n.height,d(t,"attrs","height"),e,1,1e4),n.imageAlign!==void 0&&(typeof n.imageAlign!="string"?this.add("INVALID_TYPE",d(t,"attrs","imageAlign"),"Image alignment must be a string.",e):ct.has(n.imageAlign)||this.add("INVALID_VALUE",d(t,"attrs","imageAlign"),`Unsupported image alignment "${n.imageAlign}".`,e)))}validateArticleButton(r,t){const e="articleButton";this.checkProperties(r,t,["type","attrs"],["type","attrs"],e);const n=this.requireRecord(r.attrs,a(t,"attrs"),e);n&&(this.checkProperties(n,a(t,"attrs"),["id","title","text","style","href"],["text","style"],e),n.style==="text"||n.style==="button"?"id"in n?this.requireString(n.id,d(t,"attrs","id"),e):this.add("MISSING_PROPERTY",d(t,"attrs","id"),'Required property "id" is missing for an articleButton with text or button style.',e):this.optionalString(n.id,d(t,"attrs","id"),e),this.optionalString(n.title,d(t,"attrs","title"),e),this.requireString(n.text,d(t,"attrs","text"),e),this.optionalString(n.href,d(t,"attrs","href"),e),n.style!=="text"&&n.style!=="button"&&n.style!=="link"&&this.add("INVALID_VALUE",d(t,"attrs","style"),'Article button style must be "text", "button", or "link".',e),n.href!==void 0&&n.style!=="link"&&this.add("INVALID_VALUE",d(t,"attrs","href"),'Article button href may only be present when style is "link".',e))}validateTable(r,t){const e="table";this.checkProperties(r,t,["type","content"],["type","content"],e);const n=this.requireNonEmptyArray(r.content,a(t,"content"),e);if(!n)return;let s=null;n.forEach((o,l)=>{const c=d(t,"content",l),u=this.validateTableRow(o,c);u!==null&&(s===null?s=u:u!==s&&this.add("TABLE_COLUMN_MISMATCH",a(c,"content"),`Expected ${s} table cells but received ${u}.`,"tableRow"))})}validateTableRow(r,t){var o;const e="tableRow",n=this.requireRecord(r,t,e);if(!n)return null;this.checkProperties(n,t,["type","content"],["type","content"],e),n.type!==e&&this.add("INVALID_CONTENT",a(t,"type"),"Expected a tableRow node.",e);const s=this.requireNonEmptyArray(n.content,a(t,"content"),e);return s==null||s.forEach((l,c)=>this.validateTableCell(l,d(t,"content",c))),(o=s==null?void 0:s.length)!=null?o:null}validateTableCell(r,t){const e="tableCell",n=this.requireRecord(r,t,e);if(!n)return;this.checkProperties(n,t,["type","content"],["type","content"],e),n.type!==e&&this.add("INVALID_CONTENT",a(t,"type"),"Expected a tableCell node.",e);const s=this.requireNonEmptyArray(n.content,a(t,"content"),e);s==null||s.forEach((o,l)=>this.validateBlock(o,d(t,"content",l)))}}function ft(i){return new ut().validate(i)}const D=Object.freeze({version:1,validate:ft,render:ot}),x=new Map([[D.version,D]]),ht=Object.freeze([...x.keys()]),S=1;function j(i){return x.get(i)}function z(i,r={}){var s;const t=(s=r.protocolVersion)!=null?s:S,e=j(t);return e?e.validate(i):{valid:!1,issues:[{code:"UNSUPPORTED_PROTOCOL",path:"",message:`Article Content Protocol version ${t} is not supported.`}]}}function gt(){return[]}function pt(i){return`${i.code}:${i.path}:${i.message}`}const yt=W.extend({name:"ArticleContentRenderer",props:{document:{type:null,required:!0},protocolVersion:{type:Number,default:S},strict:{type:Boolean,default:!1},customSlots:{type:Array,default:gt},imageBaseUrl:{type:String,default:N},resolveArticleButtonLink:{type:Function,default:void 0}},data(){return{reportedRuntimeIssues:new Set}},computed:{validation(){return z(this.document,{protocolVersion:this.protocolVersion})}},watch:{validation:{immediate:!0,deep:!0,handler(i){i.issues.forEach(r=>this.$emit("render-error",r))}},document:{deep:!0,handler(){this.reportedRuntimeIssues.clear()}},protocolVersion(){this.reportedRuntimeIssues.clear()},resolveArticleButtonLink(){this.reportedRuntimeIssues.clear()},imageBaseUrl(){this.reportedRuntimeIssues.clear()}},methods:{resolveCustomSlots(){return this.customSlots.map(i=>{var e,n,s,o;const r={id:i.id,location:i.location},t=(o=(s=(n=(e=this.$scopedSlots)[i.id])==null?void 0:n.call(e,r))!=null?s:this.$slots[i.id])!=null?o:[];return A(m({},i),{content:t})})},reportRuntimeIssue(i){const r=pt(i);this.reportedRuntimeIssues.has(r)||(this.reportedRuntimeIssues.add(r),this.$nextTick(()=>this.$emit("render-error",i)))}},render(i){const r=j(this.protocolVersion);if(!r||this.strict&&!this.validation.valid)return i("div",{class:"acp-render-error",attrs:{role:"alert","data-render-error":"true"}},"Invalid article content");const t=r.render(this.document,{createElement:i,customSlots:this.resolveCustomSlots(),imageBaseUrl:this.imageBaseUrl,resolveArticleButtonLink:this.resolveArticleButtonLink,emitArticleButtonClick:e=>this.$emit("article-button-click",e),reportIssue:this.reportRuntimeIssue});return i("div",{class:"acp-document",attrs:{"data-node-type":"doc","data-protocol-version":this.protocolVersion}},t)}});function mt(i,r,t,e,n,s,o,l){var c=typeof i=="function"?i.options:i;return{exports:i,options:c}}var kt=mt(yt);const O=kt.exports,bt=Object.freeze({fileFormat:"article-content-protocol",fileFormatVersion:1,mediaType:"application/vnd.article-content-protocol+json",id:"article-content-v1",version:1,name:"Article Content Protocol v1",status:"draft",rootNode:"doc",nodeTypes:Object.freeze(["doc","paragraph","heading","blockquote","bulletList","orderedList","listItem","codeBlock","horizontalRule","image","articleButton","table","tableRow","tableCell","text"]),markTypes:Object.freeze(["bold","italic","strike","underline","code","link"])}),At={install(i){i.component("ArticleContentRenderer",O)}};exports.ARTICLE_CONTENT_PROTOCOL_V1=bt;exports.ArticleContentRenderer=O;exports.ArticleContentRendererPlugin=At;exports.CURRENT_PROTOCOL_VERSION=S;exports.SUPPORTED_PROTOCOL_VERSIONS=ht;exports.default=O;exports.validateArticleDocument=z;