article-content-renderer-vue2 0.5.0 → 0.5.2

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.
@@ -6,6 +6,7 @@ interface ArticleContentRendererProps {
6
6
  strict: boolean;
7
7
  customSlots: CustomSlot[];
8
8
  imageBaseUrl: string;
9
+ resourceQuestionFooterText: string;
9
10
  resolveArticleButtonLink?: ResolveArticleButtonLink;
10
11
  resolveCustomLink?: ResolveCustomLink;
11
12
  revealedKeys: string[];
@@ -0,0 +1,2 @@
1
+ /** Keep question image URLs aligned with their schema, including the allowed raster data URLs. */
2
+ export declare function sanitizeResourceQuestionImageUrl(value: unknown): string | null;
@@ -6,4 +6,4 @@ export { getVisibleContent } from './core/resource-question.js';
6
6
  export declare const ArticleContentRendererPlugin: PluginObject<never>;
7
7
  export { CURRENT_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, validateArticleDocument, } from './protocols/registry.js';
8
8
  export { ARTICLE_CONTENT_PROTOCOL_V1 } from './protocols/v1/metadata.js';
9
- export type { ArticleButtonAttrs, ArticleButtonActionAttrs, ArticleButtonActionNode, ArticleButtonClickPayload, ArticleButtonLink, ArticleButtonLinkAttrs, ArticleButtonLinkDescriptor, ArticleButtonLinkNode, ArticleButtonNode, ArticleButtonStyle, ArticleContentNode, ArticleDocument, ArticleRendererRuntime, ArticleMark, BlockNode, BlockquoteNode, BoldMark, BulletListNode, CodeBlockNode, CodeBlockTextNode, CodeMark, CustomLink, CustomLinkDescriptor, CustomLinkMark, CustomLinkMarkAttrs, CustomSlot, HeadingNode, HighlightMark, HorizontalRuleNode, ImageAlign, ImageLayout, ImageNode, ItalicMark, HrefLinkMark, HrefLinkMarkAttrs, LinkMark, LinkTarget, ListItemNode, OrderedListNode, ParagraphNode, ProtocolVersion, RenderIssue, RenderIssueCode, ResolveArticleButtonLink, ResolveCustomLink, ResourceQuestionAttrs, ResourceQuestionNode, ResourceQuestionOption, ResourceQuestionSelectEvent, ResourceQuestionNavigationRequest, OnAnchorNavigate, StrikeMark, TableCellNode, TableNode, TableRowNode, TextAlign, TextNode, TextStyleMark, TopLevelNode, UnderlineMark, ValidationResult, } from './types.js';
9
+ export type { ArticleButtonAttrs, ArticleButtonActionAttrs, ArticleButtonActionNode, ArticleButtonClickPayload, ArticleButtonLink, ArticleButtonLinkAttrs, ArticleButtonLinkDescriptor, ArticleButtonLinkNode, ArticleButtonNode, ArticleButtonStyle, ArticleContentNode, ArticleDocument, ArticleRendererRuntime, ArticleMark, BlockNode, BlockquoteNode, BoldMark, BulletListNode, CodeBlockNode, CodeBlockTextNode, CodeMark, CustomLink, CustomLinkDescriptor, CustomLinkMark, CustomLinkMarkAttrs, CustomSlot, HeadingNode, HighlightMark, HorizontalRuleNode, ImageAlign, ImageLayout, ImageNode, ItalicMark, HrefLinkMark, HrefLinkMarkAttrs, LinkMark, LinkTarget, ListItemNode, OrderedListNode, ParagraphNode, ProtocolVersion, RenderIssue, RenderIssueCode, ResolveArticleButtonLink, ResolveCustomLink, ResourceQuestionAttrs, ResourceQuestionImage, ResourceQuestionNode, ResourceQuestionOption, ResourceQuestionSelectEvent, ResourceQuestionNavigationRequest, OnAnchorNavigate, StrikeMark, TableCellNode, TableNode, TableRowNode, TextAlign, TextNode, TextStyleMark, TopLevelNode, UnderlineMark, ValidationResult, } from './types.js';
@@ -5,6 +5,7 @@ export interface RenderContext {
5
5
  createElement: CreateElement;
6
6
  customSlots: readonly ResolvedCustomSlot[];
7
7
  imageBaseUrl: string;
8
+ resourceQuestionFooterText: string;
8
9
  resolveArticleButtonLink?: ResolveArticleButtonLink;
9
10
  resolveCustomLink?: ResolveCustomLink;
10
11
  emitArticleButtonClick: (payload: ArticleButtonClickPayload) => void;
@@ -156,11 +156,19 @@ export interface ResourceQuestionOption {
156
156
  label: string;
157
157
  targetAnchorId?: string;
158
158
  }
159
+ export interface ResourceQuestionImage {
160
+ src: string;
161
+ alt?: string;
162
+ title?: string;
163
+ width?: number;
164
+ height?: number;
165
+ }
159
166
  export interface ResourceQuestionAttrs {
160
167
  id: string;
161
168
  resourceId: string;
162
169
  title: string;
163
170
  description: string;
171
+ image?: ResourceQuestionImage;
164
172
  options: ResourceQuestionOption[];
165
173
  hideFollowing: boolean;
166
174
  revealKey: string;
@@ -173,6 +181,8 @@ export interface ResourceQuestionSelectEvent {
173
181
  questionId: string;
174
182
  resourceId: string;
175
183
  optionId: string;
184
+ /** Read-only copy of the selected option's saved protocol attributes. */
185
+ option: Readonly<ResourceQuestionOption>;
176
186
  revealKey: string;
177
187
  targetAnchorId?: string;
178
188
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "article-content-renderer-vue2",
3
- "version": "0.5.0",
3
+ "version": "0.5.2",
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",
@@ -40,7 +40,7 @@
40
40
  "name": "anchorId",
41
41
  "type": "string",
42
42
  "required": false,
43
- "description": "Stable paragraph/heading anchor, unique within the article."
43
+ "description": "Stable paragraph/heading anchor, unique within the article. New resource option bindings use the external option ID; existing anchors remain valid."
44
44
  },
45
45
  {
46
46
  "name": "fontSize",
@@ -104,7 +104,7 @@
104
104
  "name": "anchorId",
105
105
  "type": "string",
106
106
  "required": false,
107
- "description": "Stable paragraph/heading anchor, unique within the article."
107
+ "description": "Stable paragraph/heading anchor, unique within the article. New resource option bindings use the external option ID; existing anchors remain valid."
108
108
  }
109
109
  ],
110
110
  "render": {
@@ -446,6 +446,12 @@
446
446
  "required": true,
447
447
  "description": "See documentSchema.definitions.resourceQuestion.properties.attrs.properties.description"
448
448
  },
449
+ {
450
+ "name": "image",
451
+ "type": "object",
452
+ "required": false,
453
+ "description": "See documentSchema.definitions.resourceQuestion.properties.attrs.properties.image"
454
+ },
449
455
  {
450
456
  "name": "options",
451
457
  "type": "array",
@@ -718,7 +724,7 @@
718
724
  "type": "string",
719
725
  "minLength": 1,
720
726
  "pattern": "\\S",
721
- "description": "Stable paragraph/heading anchor, unique within the article."
727
+ "description": "Stable paragraph/heading anchor, unique within the article. New resource option bindings use the external option ID; existing anchors remain valid."
722
728
  }
723
729
  }
724
730
  },
@@ -760,7 +766,7 @@
760
766
  "type": "string",
761
767
  "minLength": 1,
762
768
  "pattern": "\\S",
763
- "description": "Stable paragraph/heading anchor, unique within the article."
769
+ "description": "Stable paragraph/heading anchor, unique within the article. New resource option bindings use the external option ID; existing anchors remain valid."
764
770
  }
765
771
  }
766
772
  },
@@ -1324,6 +1330,9 @@
1324
1330
  "description": {
1325
1331
  "type": "string"
1326
1332
  },
1333
+ "image": {
1334
+ "$ref": "urn:article-content-protocol:resource-question-image:v1"
1335
+ },
1327
1336
  "options": {
1328
1337
  "type": "array",
1329
1338
  "items": {
@@ -1347,7 +1356,8 @@
1347
1356
  "targetAnchorId": {
1348
1357
  "type": "string",
1349
1358
  "minLength": 1,
1350
- "pattern": "\\S"
1359
+ "pattern": "\\S",
1360
+ "description": "Target paragraph/heading anchorId. New editor bindings use this option's id; legacy anchor values remain supported."
1351
1361
  }
1352
1362
  }
1353
1363
  }
@@ -1401,6 +1411,38 @@
1401
1411
  ]
1402
1412
  }
1403
1413
  }
1414
+ },
1415
+ "resourceQuestionImage": {
1416
+ "$id": "urn:article-content-protocol:resource-question-image:v1",
1417
+ "type": "object",
1418
+ "additionalProperties": false,
1419
+ "required": [
1420
+ "src"
1421
+ ],
1422
+ "description": "Optional image snapshot above the resource question title. Omit the image attribute when absent. Fit container width with proportional height, without cropping.",
1423
+ "properties": {
1424
+ "src": {
1425
+ "type": "string",
1426
+ "minLength": 1,
1427
+ "pattern": "^(?!.*[\\u0000-\\u0020\\u007f\\\\])(?:(?:[hH][tT][tT][pP][sS]?:)?//[^/?#]+\\S*|(?!(?:[a-zA-Z][a-zA-Z0-9+.-]*):)\\S+|data:image/(?:png|jpeg|webp|gif|avif|bmp);base64,[a-zA-Z0-9+/=]+)$"
1428
+ },
1429
+ "alt": {
1430
+ "type": "string"
1431
+ },
1432
+ "title": {
1433
+ "type": "string"
1434
+ },
1435
+ "width": {
1436
+ "type": "integer",
1437
+ "minimum": 1,
1438
+ "maximum": 10000
1439
+ },
1440
+ "height": {
1441
+ "type": "integer",
1442
+ "minimum": 1,
1443
+ "maximum": 10000
1444
+ }
1445
+ }
1404
1446
  }
1405
1447
  }
1406
1448
  },
@@ -1436,9 +1478,11 @@
1436
1478
  ],
1437
1479
  "resourceQuestionRules": {
1438
1480
  "data": "Save the selected resourceId, title, description and options as a snapshot. Option IDs are stable strings supplied by the resource. Do not fetch on render.",
1481
+ "image": "Optional attrs.image={src,alt?,title?,width?,height?} is a snapshot from the resource or a separate upload. Render it above the title, fit width to the container and preserve aspect ratio without cropping. Omit when absent; older documents need no image. Selecting a resource replaces the image (omission clears it); uploading only replaces image, not question/bindings/gate settings.",
1439
1482
  "identity": "Question id, revealKey and paragraph/heading anchorId must each be unique within the document; option id must be unique within its question. Enforce these semantic checks in addition to JSON Schema.",
1440
1483
  "draft": "resourceId=\"\" with empty title, description and options is an unconfigured placeholder. Render a neutral placeholder; never unlock automatically.",
1441
1484
  "placement": "resourceQuestion is allowed only as a direct child of doc.",
1485
+ "binding": "New editor bindings set paragraph/heading anchorId and option.targetAnchorId to option.id. Existing documents are not automatically migrated; explicitly rebind/convert to use the option ID. Renaming a target with different-option references or relocating a key referenced by another question is rejected without changing data. Unshared option anchors may move to a new target atomically. Same-ID references to a renamed legacy target are updated together. Clearing a binding keeps its anchor; copies receive fresh anchors. Always preserve targetAnchorId for legacy compatibility.",
1442
1486
  "navigation": "Match the selected option.targetAnchorId to a paragraph or heading in this article instance. Missing/unbound targets do not navigate. After business-controlled reveal, wait for layout before scrolling.",
1443
1487
  "visibility": "Scan top-level nodes in order. Include a resourceQuestion, then stop if hideFollowing=true and its revealKey is absent from the host-supplied revealed keys. Recompute from the original document when keys change. Clicking an option does not automatically unlock.",
1444
1488
  "security": "Visibility is presentation only, not authorization. Hidden article data remains in the JSON; sensitive data must be protected on the server."