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.
@@ -1,22 +1,18 @@
1
1
  import Vue from 'vue';
2
- import type { AdSlot } from '../protocols/types.js';
3
- import type { AdConfig, PubId, RenderIssue, ResolveArticleButtonLink, ValidationResult } from '../types.js';
2
+ import type { ResolvedCustomSlot } from '../protocols/types.js';
3
+ import type { CustomSlot, RenderIssue, ResolveArticleButtonLink, ValidationResult } from '../types.js';
4
4
  declare const _default: import("vue/types/vue").ExtendedVue<Vue<Record<string, any>, Record<string, any>, never, never, (event: string, ...args: any[]) => Vue>, {
5
5
  reportedRuntimeIssues: Set<string>;
6
- reportedAdConfigIssue: string | null;
7
6
  }, {
7
+ resolveCustomSlots(): ResolvedCustomSlot[];
8
8
  reportRuntimeIssue(issue: RenderIssue): void;
9
9
  }, {
10
10
  validation: ValidationResult;
11
- adConfigIssue: RenderIssue | null;
12
- adSlots: readonly AdSlot[];
13
11
  }, {
14
12
  document: unknown;
15
13
  protocolVersion: number;
16
14
  strict: boolean;
17
- adConf: AdConfig;
18
- pubid: PubId;
19
- adTitle: string;
15
+ customSlots: CustomSlot[];
20
16
  imageBaseUrl: string;
21
17
  resolveArticleButtonLink: ResolveArticleButtonLink;
22
18
  }, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin>;
@@ -5,4 +5,4 @@ export default ArticleContentRenderer;
5
5
  export declare const ArticleContentRendererPlugin: PluginObject<never>;
6
6
  export { CURRENT_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, validateArticleDocument, } from './protocols/registry.js';
7
7
  export { ARTICLE_CONTENT_PROTOCOL_V1 } from './protocols/v1/metadata.js';
8
- export type { AdConfig, ArticleButtonAttrs, ArticleButtonClickPayload, ArticleButtonLink, ArticleButtonLinkDescriptor, ArticleButtonNode, ArticleButtonStyle, ArticleContentNode, ArticleDocument, ArticleMark, BlockNode, BlockquoteNode, BoldMark, BulletListNode, CodeBlockNode, CodeBlockTextNode, CodeMark, HeadingNode, HorizontalRuleNode, ImageAlign, ImageNode, ItalicMark, LinkMark, LinkTarget, ListItemNode, OrderedListNode, ParagraphNode, ProtocolVersion, PubId, RenderIssue, RenderIssueCode, ResolveArticleButtonLink, StrikeMark, TableCellNode, TableNode, TableRowNode, TextAlign, TextNode, UnderlineMark, ValidationResult, } from './types.js';
8
+ export type { ArticleButtonAttrs, ArticleButtonActionAttrs, ArticleButtonActionNode, ArticleButtonClickPayload, ArticleButtonLink, ArticleButtonLinkAttrs, ArticleButtonLinkDescriptor, ArticleButtonLinkNode, ArticleButtonNode, ArticleButtonStyle, ArticleContentNode, ArticleDocument, ArticleMark, BlockNode, BlockquoteNode, BoldMark, BulletListNode, CodeBlockNode, CodeBlockTextNode, CodeMark, CustomSlot, HeadingNode, HorizontalRuleNode, ImageAlign, ImageNode, ItalicMark, LinkMark, LinkTarget, ListItemNode, OrderedListNode, ParagraphNode, ProtocolVersion, RenderIssue, RenderIssueCode, ResolveArticleButtonLink, StrikeMark, TableCellNode, TableNode, TableRowNode, TextAlign, TextNode, UnderlineMark, ValidationResult, } from './types.js';
@@ -2,20 +2,16 @@ import type { CreateElement, VNode } from 'vue';
2
2
  import type { ArticleButtonClickPayload, RenderIssue, ResolveArticleButtonLink, ValidationResult } from '../types.js';
3
3
  export interface RenderContext {
4
4
  createElement: CreateElement;
5
- adSlots: readonly AdSlot[];
6
- admPublisherId: string;
7
- adsPublisherId: string;
8
- adTitle: string;
5
+ customSlots: readonly ResolvedCustomSlot[];
9
6
  imageBaseUrl: string;
10
7
  resolveArticleButtonLink?: ResolveArticleButtonLink;
11
8
  emitArticleButtonClick: (payload: ArticleButtonClickPayload) => void;
12
9
  reportIssue: (issue: RenderIssue) => void;
13
10
  }
14
- export interface AdSlot {
15
- index: number;
11
+ export interface ResolvedCustomSlot {
12
+ id: string;
16
13
  location: number;
17
- adm: unknown;
18
- ads: unknown;
14
+ content: readonly VNode[];
19
15
  }
20
16
  export interface ProtocolAdapter {
21
17
  version: number;
@@ -1,16 +1,11 @@
1
1
  export type ProtocolVersion = 1;
2
2
  export type TextAlign = 'left' | 'center' | 'right' | 'justify';
3
3
  export type ImageAlign = 'left' | 'center' | 'right';
4
- export type ArticleButtonStyle = 'text' | 'button';
4
+ export type ArticleButtonStyle = 'text' | 'button' | 'link';
5
5
  export type LinkTarget = '_blank' | '_self';
6
- export interface AdConfig {
7
- adm?: readonly unknown[];
8
- ads?: readonly unknown[];
9
- loc: readonly number[];
10
- }
11
- export interface PubId {
12
- adm: string;
13
- ads: string;
6
+ export interface CustomSlot {
7
+ id: string;
8
+ location: number;
14
9
  }
15
10
  export interface BoldMark {
16
11
  type: 'bold';
@@ -99,16 +94,30 @@ export interface ImageNode {
99
94
  imageAlign?: ImageAlign;
100
95
  };
101
96
  }
102
- export interface ArticleButtonAttrs {
103
- id: string;
97
+ interface ArticleButtonBaseAttrs {
104
98
  title?: string;
105
99
  text: string;
106
- style: ArticleButtonStyle;
107
100
  }
108
- export interface ArticleButtonNode {
101
+ export interface ArticleButtonActionAttrs extends ArticleButtonBaseAttrs {
102
+ id: string;
103
+ style: 'text' | 'button';
104
+ href?: never;
105
+ }
106
+ export interface ArticleButtonLinkAttrs extends ArticleButtonBaseAttrs {
107
+ id?: string;
108
+ style: 'link';
109
+ href?: string;
110
+ }
111
+ export type ArticleButtonAttrs = ArticleButtonActionAttrs | ArticleButtonLinkAttrs;
112
+ export interface ArticleButtonActionNode {
113
+ type: 'articleButton';
114
+ attrs: ArticleButtonActionAttrs;
115
+ }
116
+ export interface ArticleButtonLinkNode {
109
117
  type: 'articleButton';
110
- attrs: ArticleButtonAttrs;
118
+ attrs: ArticleButtonLinkAttrs;
111
119
  }
120
+ export type ArticleButtonNode = ArticleButtonActionNode | ArticleButtonLinkNode;
112
121
  export interface TableNode {
113
122
  type: 'table';
114
123
  content: TableRowNode[];
@@ -133,8 +142,8 @@ export interface ArticleButtonLinkDescriptor {
133
142
  rel?: string;
134
143
  }
135
144
  export type ArticleButtonLink = string | ArticleButtonLinkDescriptor | null;
136
- export type ResolveArticleButtonLink = (attrs: Readonly<ArticleButtonAttrs>, node: Readonly<ArticleButtonNode>) => ArticleButtonLink;
137
- export type RenderIssueCode = 'INVALID_ROOT' | 'INVALID_TYPE' | 'INVALID_CONTENT' | 'INVALID_VALUE' | 'MISSING_PROPERTY' | 'UNKNOWN_PROPERTY' | 'UNKNOWN_NODE' | 'UNKNOWN_MARK' | 'TABLE_COLUMN_MISMATCH' | 'UNSAFE_URL' | 'LINK_RESOLUTION_FAILED' | 'UNSUPPORTED_PROTOCOL' | 'AD_CONFIG_LENGTH_MISMATCH';
145
+ export type ResolveArticleButtonLink = (attrs: Readonly<ArticleButtonActionAttrs>, node: Readonly<ArticleButtonActionNode>) => ArticleButtonLink;
146
+ export type RenderIssueCode = 'INVALID_ROOT' | 'INVALID_TYPE' | 'INVALID_CONTENT' | 'INVALID_VALUE' | 'MISSING_PROPERTY' | 'UNKNOWN_PROPERTY' | 'UNKNOWN_NODE' | 'UNKNOWN_MARK' | 'TABLE_COLUMN_MISMATCH' | 'UNSAFE_URL' | 'LINK_RESOLUTION_FAILED' | 'UNSUPPORTED_PROTOCOL';
138
147
  export interface RenderIssue {
139
148
  code: RenderIssueCode;
140
149
  path: string;
@@ -151,3 +160,4 @@ export interface ArticleButtonClickPayload {
151
160
  href: string | null;
152
161
  event: MouseEvent;
153
162
  }
163
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "article-content-renderer-vue2",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "A safe Vue 2.7 renderer for the Article Content Protocol ProseMirror JSON format.",
5
5
  "author": "NovaVoyager",
6
6
  "license": "MIT",
@@ -257,14 +257,14 @@
257
257
  {
258
258
  "type": "articleButton",
259
259
  "kind": "block",
260
- "description": "An article action button identified by a business id and displayed with its text.",
260
+ "description": "An article action displayed with its text. Link actions may omit the business id.",
261
261
  "contentModel": "none",
262
262
  "attributes": [
263
263
  {
264
264
  "name": "id",
265
265
  "type": "string",
266
- "required": true,
267
- "description": "Business identifier used by the consuming application to handle the action."
266
+ "required": false,
267
+ "description": "Business identifier used by the consuming application. Required for text and button styles; optional for link style."
268
268
  },
269
269
  {
270
270
  "name": "title",
@@ -282,21 +282,45 @@
282
282
  "name": "style",
283
283
  "type": "string",
284
284
  "required": true,
285
- "description": "Controlled visual variant: text is rendered as a text-like action; button as a button-like action.",
285
+ "description": "Controlled variant: text is a text-like action, button is a button-like action, and link is a hyperlink action.",
286
286
  "allowedValues": [
287
287
  "text",
288
- "button"
288
+ "button",
289
+ "link"
289
290
  ]
291
+ },
292
+ {
293
+ "name": "href",
294
+ "type": "string",
295
+ "required": false,
296
+ "description": "Optional link destination. This attribute may only be present when style is link."
297
+ }
298
+ ],
299
+ "constraints": [
300
+ {
301
+ "name": "link-style-href",
302
+ "description": "The optional href attribute may only be present when style is link."
303
+ },
304
+ {
305
+ "name": "non-link-style-id",
306
+ "description": "The id attribute is required when style is text or button, and optional when style is link."
290
307
  }
291
308
  ],
292
309
  "render": {
293
310
  "mode": "element",
294
311
  "element": "button",
295
312
  "textBinding": "text",
313
+ "elementVariants": {
314
+ "attribute": "style",
315
+ "values": {
316
+ "link": "a"
317
+ }
318
+ },
296
319
  "attributeBindings": {
297
320
  "id": "data-article-button-id",
298
321
  "title": "title",
299
- "style": "data-article-button-style"
322
+ "style": "data-article-button-style",
323
+ "href": "href"
300
324
  }
301
325
  }
302
326
  },
@@ -404,7 +428,7 @@
404
428
  "name": "href",
405
429
  "type": "string",
406
430
  "required": true,
407
- "description": "Link destination."
431
+ "description": "Non-empty URI reference; fragment-only links such as # are valid."
408
432
  },
409
433
  {
410
434
  "name": "target",
@@ -753,7 +777,6 @@
753
777
  "type": "object",
754
778
  "additionalProperties": false,
755
779
  "required": [
756
- "id",
757
780
  "text",
758
781
  "style"
759
782
  ],
@@ -773,10 +796,57 @@
773
796
  "style": {
774
797
  "enum": [
775
798
  "text",
776
- "button"
799
+ "button",
800
+ "link"
777
801
  ]
802
+ },
803
+ "href": {
804
+ "type": "string",
805
+ "minLength": 1
778
806
  }
779
- }
807
+ },
808
+ "allOf": [
809
+ {
810
+ "if": {
811
+ "properties": {
812
+ "style": {
813
+ "enum": [
814
+ "text",
815
+ "button"
816
+ ]
817
+ }
818
+ },
819
+ "required": [
820
+ "style"
821
+ ]
822
+ },
823
+ "then": {
824
+ "properties": {
825
+ "id": {}
826
+ },
827
+ "required": [
828
+ "id"
829
+ ]
830
+ }
831
+ },
832
+ {
833
+ "if": {
834
+ "properties": {
835
+ "href": {}
836
+ },
837
+ "required": [
838
+ "href"
839
+ ]
840
+ },
841
+ "then": {
842
+ "properties": {
843
+ "style": {
844
+ "const": "link"
845
+ }
846
+ }
847
+ }
848
+ }
849
+ ]
780
850
  }
781
851
  }
782
852
  },
@@ -918,7 +988,8 @@
918
988
  "properties": {
919
989
  "href": {
920
990
  "type": "string",
921
- "minLength": 1
991
+ "minLength": 1,
992
+ "description": "Non-empty URI reference; fragment-only links such as # are valid."
922
993
  },
923
994
  "target": {
924
995
  "enum": [
@@ -935,5 +1006,3 @@
935
1006
  }
936
1007
  }
937
1008
  }
938
-
939
-
@@ -1,39 +0,0 @@
1
- import Vue from 'vue';
2
- interface GoogleTagSlot {
3
- addService: (service: GoogleTagPubAdsService) => GoogleTagSlot;
4
- }
5
- interface GoogleTagSlotRenderEndedEvent {
6
- slot: GoogleTagSlot;
7
- isEmpty: boolean;
8
- }
9
- interface GoogleTagPubAdsService {
10
- addEventListener: (eventName: 'slotRenderEnded', listener: (event: GoogleTagSlotRenderEndedEvent) => void) => void;
11
- removeEventListener?: (eventName: 'slotRenderEnded', listener: (event: GoogleTagSlotRenderEndedEvent) => void) => void;
12
- }
13
- export declare const AdManagerAd: import("vue/types/vue").ExtendedVue<Vue<Record<string, any>, Record<string, any>, never, never, (event: string, ...args: any[]) => Vue>, {
14
- observer: IntersectionObserver | null;
15
- definedSlot: GoogleTagSlot | null;
16
- pubAdsService: GoogleTagPubAdsService | null;
17
- slotRenderEnded: ((event: GoogleTagSlotRenderEndedEvent) => void) | null;
18
- emptyAdmKey: string | null;
19
- cancelled: boolean;
20
- }, {
21
- restartAdManager(): void;
22
- startObserver(): void;
23
- requestAd(): void;
24
- cleanupAdManager(): void;
25
- }, {
26
- admSlotId: string;
27
- adsSlotId: string;
28
- adUnitPath: string;
29
- fallbackKey: string;
30
- hasAdSenseFallback: boolean;
31
- shouldUseAdSense: boolean;
32
- }, {
33
- publisherId: string;
34
- slotId: string | number;
35
- title: string;
36
- fallbackPublisherId: string;
37
- fallbackSlotId: string | number;
38
- }, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin>;
39
- export default AdManagerAd;
@@ -1,18 +0,0 @@
1
- import Vue from 'vue';
2
- export declare const AdSenseAd: import("vue/types/vue").ExtendedVue<Vue<Record<string, any>, Record<string, any>, never, never, (event: string, ...args: any[]) => Vue>, {
3
- observer: IntersectionObserver | null;
4
- requestedKey: string | null;
5
- }, {
6
- requestAd(): void;
7
- startObserver(): void;
8
- stopObserver(): void;
9
- }, {
10
- adClient: string;
11
- adSlot: string;
12
- requestKey: string;
13
- }, {
14
- publisherId: string;
15
- slotId: string | number;
16
- title: string;
17
- }, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin>;
18
- export default AdSenseAd;