article-content-renderer-vue2 0.4.0 → 0.5.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 +239 -7
- package/dist/article-content-renderer-vue2.css +1 -1
- package/dist/index.cjs +8 -1
- package/dist/index.js +6575 -683
- package/dist/types/components/ArticleContentRenderer.vue.d.ts +6 -1
- package/dist/types/core/resource-question.d.ts +45 -0
- package/dist/types/index.d.ts +2 -1
- package/dist/types/protocols/types.d.ts +2 -0
- package/dist/types/protocols/v1/metadata.d.ts +3 -2
- package/dist/types/protocols/v1/schema.d.ts +2 -0
- package/dist/types/types.d.ts +60 -4
- package/package.json +4 -1
- package/protocol/article-content-protocol-v1.json +372 -8
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
|
-
import type { CustomSlot, ResolveArticleButtonLink, ResolveCustomLink } from '../types.js';
|
|
2
|
+
import type { CustomSlot, ResolveArticleButtonLink, ResolveCustomLink, OnAnchorNavigate } from '../types.js';
|
|
3
3
|
interface ArticleContentRendererProps {
|
|
4
4
|
document: unknown;
|
|
5
5
|
protocolVersion: number;
|
|
@@ -8,6 +8,11 @@ interface ArticleContentRendererProps {
|
|
|
8
8
|
imageBaseUrl: string;
|
|
9
9
|
resolveArticleButtonLink?: ResolveArticleButtonLink;
|
|
10
10
|
resolveCustomLink?: ResolveCustomLink;
|
|
11
|
+
revealedKeys: string[];
|
|
12
|
+
articleKey?: string | number;
|
|
13
|
+
scrollContainer?: HTMLElement | (() => HTMLElement | null);
|
|
14
|
+
scrollOffset: number;
|
|
15
|
+
onAnchorNavigate?: OnAnchorNavigate;
|
|
11
16
|
}
|
|
12
17
|
declare const _default: import("vue/types/vue").ExtendedVue<Vue<Record<string, any>, Record<string, any>, never, never, (event: string, ...args: any[]) => Vue>, {}, {}, {}, ArticleContentRendererProps, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin>;
|
|
13
18
|
export default _default;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { type VNode } from 'vue';
|
|
2
|
+
import type { ArticleDocument, ArticleRendererRuntime, OnAnchorNavigate, RenderIssue, ResourceQuestionSelectEvent, TopLevelNode } from '../types.js';
|
|
3
|
+
type RecordValue = Record<string, unknown>;
|
|
4
|
+
export declare function isRecord(value: unknown): value is RecordValue;
|
|
5
|
+
export declare function getVisibleContent(document: ArticleDocument, revealedKeys?: readonly string[]): TopLevelNode[];
|
|
6
|
+
export interface NavigationSessionOptions {
|
|
7
|
+
document: unknown;
|
|
8
|
+
articleKey?: string | number;
|
|
9
|
+
revealedKeys: readonly string[];
|
|
10
|
+
scrollContainer?: HTMLElement | (() => HTMLElement | null);
|
|
11
|
+
scrollOffset: number;
|
|
12
|
+
onAnchorNavigate?: OnAnchorNavigate;
|
|
13
|
+
reportNavigationIssue(issue: RenderIssue): void;
|
|
14
|
+
emitSelect(event: ResourceQuestionSelectEvent): void;
|
|
15
|
+
}
|
|
16
|
+
/** A fresh render's registry; only its owning lifecycle component can activate it. */
|
|
17
|
+
export declare class NavigationSession {
|
|
18
|
+
readonly options: NavigationSessionOptions;
|
|
19
|
+
readonly anchors: Map<string, HTMLElement>;
|
|
20
|
+
readonly allAnchors: Set<string>;
|
|
21
|
+
readonly selections: Map<string, Map<string, ResourceQuestionSelectEvent>>;
|
|
22
|
+
select: (event: ResourceQuestionSelectEvent) => void;
|
|
23
|
+
constructor(options: NavigationSessionOptions);
|
|
24
|
+
anchorHooks(id: string): {
|
|
25
|
+
insert: (vnode: VNode) => void;
|
|
26
|
+
postpatch: (_old: VNode, vnode: VNode) => void;
|
|
27
|
+
destroy: (vnode: VNode) => void;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/** Persistent state owned by the renderer's existing, DOM-free lifecycle component. */
|
|
31
|
+
export declare class ResourceNavigation {
|
|
32
|
+
private session?;
|
|
33
|
+
private pending?;
|
|
34
|
+
private generation;
|
|
35
|
+
private frame?;
|
|
36
|
+
private disposed;
|
|
37
|
+
readonly api: ArticleRendererRuntime;
|
|
38
|
+
constructor();
|
|
39
|
+
update(session: NavigationSession): void;
|
|
40
|
+
cancelPendingNavigation(): void;
|
|
41
|
+
schedule(): void;
|
|
42
|
+
private navigate;
|
|
43
|
+
dispose(): void;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ import type { PluginObject } from 'vue';
|
|
|
2
2
|
import ArticleContentRenderer from './components/ArticleContentRenderer.vue';
|
|
3
3
|
export { ArticleContentRenderer };
|
|
4
4
|
export default ArticleContentRenderer;
|
|
5
|
+
export { getVisibleContent } from './core/resource-question.js';
|
|
5
6
|
export declare const ArticleContentRendererPlugin: PluginObject<never>;
|
|
6
7
|
export { CURRENT_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, validateArticleDocument, } from './protocols/registry.js';
|
|
7
8
|
export { ARTICLE_CONTENT_PROTOCOL_V1 } from './protocols/v1/metadata.js';
|
|
8
|
-
export type { ArticleButtonAttrs, ArticleButtonActionAttrs, ArticleButtonActionNode, ArticleButtonClickPayload, ArticleButtonLink, ArticleButtonLinkAttrs, ArticleButtonLinkDescriptor, ArticleButtonLinkNode, ArticleButtonNode, ArticleButtonStyle, ArticleContentNode, ArticleDocument, ArticleMark, BlockNode, BlockquoteNode, BoldMark, BulletListNode, CodeBlockNode, CodeBlockTextNode, CodeMark, CustomLink, CustomLinkDescriptor, CustomLinkMark, CustomLinkMarkAttrs, CustomSlot, HeadingNode, HorizontalRuleNode, ImageAlign, ImageNode, ItalicMark, HrefLinkMark, HrefLinkMarkAttrs, LinkMark, LinkTarget, ListItemNode, OrderedListNode, ParagraphNode, ProtocolVersion, RenderIssue, RenderIssueCode, ResolveArticleButtonLink, ResolveCustomLink, StrikeMark, TableCellNode, TableNode, TableRowNode, TextAlign, TextNode, 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, ResourceQuestionNode, ResourceQuestionOption, ResourceQuestionSelectEvent, ResourceQuestionNavigationRequest, OnAnchorNavigate, StrikeMark, TableCellNode, TableNode, TableRowNode, TextAlign, TextNode, TextStyleMark, TopLevelNode, UnderlineMark, ValidationResult, } from './types.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CreateElement, VNode } from 'vue';
|
|
2
|
+
import type { NavigationSession } from '../core/resource-question.js';
|
|
2
3
|
import type { ArticleButtonClickPayload, RenderIssue, ResolveArticleButtonLink, ResolveCustomLink, ValidationResult } from '../types.js';
|
|
3
4
|
export interface RenderContext {
|
|
4
5
|
createElement: CreateElement;
|
|
@@ -8,6 +9,7 @@ export interface RenderContext {
|
|
|
8
9
|
resolveCustomLink?: ResolveCustomLink;
|
|
9
10
|
emitArticleButtonClick: (payload: ArticleButtonClickPayload) => void;
|
|
10
11
|
reportIssue: (issue: RenderIssue) => void;
|
|
12
|
+
navigation: NavigationSession;
|
|
11
13
|
}
|
|
12
14
|
export interface ResolvedCustomSlot {
|
|
13
15
|
id: string;
|
|
@@ -2,11 +2,12 @@ export declare const ARTICLE_CONTENT_PROTOCOL_V1: Readonly<{
|
|
|
2
2
|
fileFormat: "article-content-protocol";
|
|
3
3
|
fileFormatVersion: 1;
|
|
4
4
|
mediaType: "application/vnd.article-content-protocol+json";
|
|
5
|
-
id: "article-content-v1";
|
|
5
|
+
id: "article-content-v1-with-extensions";
|
|
6
6
|
version: 1;
|
|
7
|
-
name: "Article Content Protocol v1";
|
|
7
|
+
name: "Article Content Protocol v1 + Extensions";
|
|
8
8
|
status: "draft";
|
|
9
9
|
rootNode: "doc";
|
|
10
10
|
nodeTypes: readonly string[];
|
|
11
11
|
markTypes: readonly string[];
|
|
12
|
+
extensions: readonly string[];
|
|
12
13
|
}>;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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 ImageLayout = 'two-column';
|
|
4
5
|
export type ArticleButtonStyle = 'text' | 'button' | 'link';
|
|
5
6
|
export type LinkTarget = '_blank' | '_self';
|
|
6
7
|
export interface CustomSlot {
|
|
@@ -45,7 +46,19 @@ export interface CustomLinkMark {
|
|
|
45
46
|
attrs: CustomLinkMarkAttrs;
|
|
46
47
|
}
|
|
47
48
|
export type LinkMark = HrefLinkMark | CustomLinkMark;
|
|
48
|
-
export
|
|
49
|
+
export interface TextStyleMark {
|
|
50
|
+
type: 'textStyle';
|
|
51
|
+
attrs: {
|
|
52
|
+
color: string;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export interface HighlightMark {
|
|
56
|
+
type: 'highlight';
|
|
57
|
+
attrs: {
|
|
58
|
+
color: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export type ArticleMark = BoldMark | ItalicMark | StrikeMark | UnderlineMark | CodeMark | LinkMark | TextStyleMark | HighlightMark;
|
|
49
62
|
export interface TextNode {
|
|
50
63
|
type: 'text';
|
|
51
64
|
text: string;
|
|
@@ -55,6 +68,8 @@ export interface ParagraphNode {
|
|
|
55
68
|
type: 'paragraph';
|
|
56
69
|
attrs?: {
|
|
57
70
|
textAlign?: TextAlign;
|
|
71
|
+
anchorId?: string;
|
|
72
|
+
fontSize?: number;
|
|
58
73
|
};
|
|
59
74
|
content?: TextNode[];
|
|
60
75
|
}
|
|
@@ -63,6 +78,7 @@ export interface HeadingNode {
|
|
|
63
78
|
attrs: {
|
|
64
79
|
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
65
80
|
textAlign?: TextAlign;
|
|
81
|
+
anchorId?: string;
|
|
66
82
|
};
|
|
67
83
|
content?: TextNode[];
|
|
68
84
|
}
|
|
@@ -108,6 +124,7 @@ export interface ImageNode {
|
|
|
108
124
|
width?: number;
|
|
109
125
|
height?: number;
|
|
110
126
|
imageAlign?: ImageAlign;
|
|
127
|
+
imageLayout?: ImageLayout;
|
|
111
128
|
};
|
|
112
129
|
}
|
|
113
130
|
interface ArticleButtonBaseAttrs {
|
|
@@ -134,6 +151,43 @@ export interface ArticleButtonLinkNode {
|
|
|
134
151
|
attrs: ArticleButtonLinkAttrs;
|
|
135
152
|
}
|
|
136
153
|
export type ArticleButtonNode = ArticleButtonActionNode | ArticleButtonLinkNode;
|
|
154
|
+
export interface ResourceQuestionOption {
|
|
155
|
+
id: string;
|
|
156
|
+
label: string;
|
|
157
|
+
targetAnchorId?: string;
|
|
158
|
+
}
|
|
159
|
+
export interface ResourceQuestionAttrs {
|
|
160
|
+
id: string;
|
|
161
|
+
resourceId: string;
|
|
162
|
+
title: string;
|
|
163
|
+
description: string;
|
|
164
|
+
options: ResourceQuestionOption[];
|
|
165
|
+
hideFollowing: boolean;
|
|
166
|
+
revealKey: string;
|
|
167
|
+
}
|
|
168
|
+
export interface ResourceQuestionNode {
|
|
169
|
+
type: 'resourceQuestion';
|
|
170
|
+
attrs: ResourceQuestionAttrs;
|
|
171
|
+
}
|
|
172
|
+
export interface ResourceQuestionSelectEvent {
|
|
173
|
+
questionId: string;
|
|
174
|
+
resourceId: string;
|
|
175
|
+
optionId: string;
|
|
176
|
+
revealKey: string;
|
|
177
|
+
targetAnchorId?: string;
|
|
178
|
+
}
|
|
179
|
+
/** One option click's navigation request. Methods become no-ops after cancellation or replacement. */
|
|
180
|
+
export interface ResourceQuestionNavigationRequest extends ResourceQuestionSelectEvent {
|
|
181
|
+
targetAnchorId: string;
|
|
182
|
+
scrollToAnchor(): void;
|
|
183
|
+
cancel(): void;
|
|
184
|
+
}
|
|
185
|
+
/** Suppresses automatic navigation; call request.scrollToAnchor() when the host is ready. */
|
|
186
|
+
export type OnAnchorNavigate = (request: Readonly<ResourceQuestionNavigationRequest>) => void | Promise<void>;
|
|
187
|
+
/** Delivered through renderer-ready; keep one handle per renderer instance. */
|
|
188
|
+
export interface ArticleRendererRuntime {
|
|
189
|
+
cancelPendingNavigation(): void;
|
|
190
|
+
}
|
|
137
191
|
export interface TableNode {
|
|
138
192
|
type: 'table';
|
|
139
193
|
content: TableRowNode[];
|
|
@@ -149,9 +203,10 @@ export interface TableCellNode {
|
|
|
149
203
|
export type BlockNode = ParagraphNode | HeadingNode | BlockquoteNode | BulletListNode | OrderedListNode | CodeBlockNode | HorizontalRuleNode | ImageNode | ArticleButtonNode | TableNode;
|
|
150
204
|
export interface ArticleDocument {
|
|
151
205
|
type: 'doc';
|
|
152
|
-
content:
|
|
206
|
+
content: TopLevelNode[];
|
|
153
207
|
}
|
|
154
|
-
export type
|
|
208
|
+
export type TopLevelNode = BlockNode | ResourceQuestionNode;
|
|
209
|
+
export type ArticleContentNode = ArticleDocument | BlockNode | ResourceQuestionNode | ListItemNode | TableRowNode | TableCellNode | TextNode;
|
|
155
210
|
export interface ArticleButtonLinkDescriptor {
|
|
156
211
|
href: string;
|
|
157
212
|
target?: LinkTarget;
|
|
@@ -166,12 +221,13 @@ export interface CustomLinkDescriptor {
|
|
|
166
221
|
}
|
|
167
222
|
export type CustomLink = string | CustomLinkDescriptor | null;
|
|
168
223
|
export type ResolveCustomLink = (attrs: Readonly<CustomLinkMarkAttrs>, mark: Readonly<CustomLinkMark>) => CustomLink;
|
|
169
|
-
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';
|
|
224
|
+
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' | 'DUPLICATE_IDENTITY' | 'MISSING_ANCHOR' | 'NAVIGATION_CALLBACK_FAILED';
|
|
170
225
|
export interface RenderIssue {
|
|
171
226
|
code: RenderIssueCode;
|
|
172
227
|
path: string;
|
|
173
228
|
message: string;
|
|
174
229
|
nodeType?: string;
|
|
230
|
+
severity?: 'error' | 'warning';
|
|
175
231
|
}
|
|
176
232
|
export interface ValidationResult {
|
|
177
233
|
valid: boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "article-content-renderer-vue2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.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",
|
|
@@ -73,5 +73,8 @@
|
|
|
73
73
|
},
|
|
74
74
|
"engines": {
|
|
75
75
|
"node": ">=18.0.0"
|
|
76
|
+
},
|
|
77
|
+
"dependencies": {
|
|
78
|
+
"ajv": "^8.20.0"
|
|
76
79
|
}
|
|
77
80
|
}
|