article-content-renderer-vue2 0.1.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.
@@ -0,0 +1,39 @@
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;
@@ -0,0 +1,18 @@
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;
@@ -0,0 +1,23 @@
1
+ import Vue from 'vue';
2
+ import type { AdSlot } from '../protocols/types.js';
3
+ import type { AdConfig, PubId, RenderIssue, ResolveArticleButtonLink, ValidationResult } from '../types.js';
4
+ declare const _default: import("vue/types/vue").ExtendedVue<Vue<Record<string, any>, Record<string, any>, never, never, (event: string, ...args: any[]) => Vue>, {
5
+ reportedRuntimeIssues: Set<string>;
6
+ reportedAdConfigIssue: string | null;
7
+ }, {
8
+ reportRuntimeIssue(issue: RenderIssue): void;
9
+ }, {
10
+ validation: ValidationResult;
11
+ adConfigIssue: RenderIssue | null;
12
+ adSlots: readonly AdSlot[];
13
+ }, {
14
+ document: unknown;
15
+ protocolVersion: number;
16
+ strict: boolean;
17
+ adConf: AdConfig;
18
+ pubid: PubId;
19
+ adTitle: string;
20
+ imageBaseUrl: string;
21
+ resolveArticleButtonLink: ResolveArticleButtonLink;
22
+ }, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin>;
23
+ export default _default;
@@ -0,0 +1,6 @@
1
+ type UrlKind = 'link' | 'image';
2
+ export declare const DEFAULT_IMAGE_BASE_URL = "https://www.doitme.link/";
3
+ export declare function replaceImageBaseUrl(value: unknown, imageBaseUrl: string): unknown;
4
+ export declare function sanitizeUrl(value: unknown, kind: UrlKind): string | null;
5
+ export declare function secureRel(rel: unknown, target: '_blank' | '_self'): string | undefined;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ import type { PluginObject } from 'vue';
2
+ import ArticleContentRenderer from './components/ArticleContentRenderer.vue';
3
+ export { ArticleContentRenderer };
4
+ export default ArticleContentRenderer;
5
+ export declare const ArticleContentRendererPlugin: PluginObject<never>;
6
+ export { CURRENT_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, validateArticleDocument, } from './protocols/registry.js';
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';
@@ -0,0 +1,8 @@
1
+ import type { ValidationResult } from '../types.js';
2
+ import type { ProtocolAdapter } from './types.js';
3
+ export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly number[];
4
+ export declare const CURRENT_PROTOCOL_VERSION: 1;
5
+ export declare function getProtocolAdapter(version: number): ProtocolAdapter | undefined;
6
+ export declare function validateArticleDocument(document: unknown, options?: {
7
+ protocolVersion?: number;
8
+ }): ValidationResult;
@@ -0,0 +1,24 @@
1
+ import type { CreateElement, VNode } from 'vue';
2
+ import type { ArticleButtonClickPayload, RenderIssue, ResolveArticleButtonLink, ValidationResult } from '../types.js';
3
+ export interface RenderContext {
4
+ createElement: CreateElement;
5
+ adSlots: readonly AdSlot[];
6
+ admPublisherId: string;
7
+ adsPublisherId: string;
8
+ adTitle: string;
9
+ imageBaseUrl: string;
10
+ resolveArticleButtonLink?: ResolveArticleButtonLink;
11
+ emitArticleButtonClick: (payload: ArticleButtonClickPayload) => void;
12
+ reportIssue: (issue: RenderIssue) => void;
13
+ }
14
+ export interface AdSlot {
15
+ index: number;
16
+ location: number;
17
+ adm: unknown;
18
+ ads: unknown;
19
+ }
20
+ export interface ProtocolAdapter {
21
+ version: number;
22
+ validate: (document: unknown) => ValidationResult;
23
+ render: (document: unknown, context: RenderContext) => VNode[];
24
+ }
@@ -0,0 +1,12 @@
1
+ export declare const ARTICLE_CONTENT_PROTOCOL_V1: Readonly<{
2
+ fileFormat: "article-content-protocol";
3
+ fileFormatVersion: 1;
4
+ mediaType: "application/vnd.article-content-protocol+json";
5
+ id: "article-content-v1";
6
+ version: 1;
7
+ name: "Article Content Protocol v1";
8
+ status: "draft";
9
+ rootNode: "doc";
10
+ nodeTypes: readonly string[];
11
+ markTypes: readonly string[];
12
+ }>;
@@ -0,0 +1,3 @@
1
+ import type { VNode } from 'vue';
2
+ import type { RenderContext } from '../types.js';
3
+ export declare function renderDocumentV1(document: unknown, context: RenderContext): VNode[];
@@ -0,0 +1,2 @@
1
+ import type { ValidationResult } from '../../types.js';
2
+ export declare function validateDocumentV1(document: unknown): ValidationResult;
@@ -0,0 +1,153 @@
1
+ export type ProtocolVersion = 1;
2
+ export type TextAlign = 'left' | 'center' | 'right' | 'justify';
3
+ export type ImageAlign = 'left' | 'center' | 'right';
4
+ export type ArticleButtonStyle = 'text' | 'button';
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;
14
+ }
15
+ export interface BoldMark {
16
+ type: 'bold';
17
+ }
18
+ export interface ItalicMark {
19
+ type: 'italic';
20
+ }
21
+ export interface StrikeMark {
22
+ type: 'strike';
23
+ }
24
+ export interface UnderlineMark {
25
+ type: 'underline';
26
+ }
27
+ export interface CodeMark {
28
+ type: 'code';
29
+ }
30
+ export interface LinkMark {
31
+ type: 'link';
32
+ attrs: {
33
+ href: string;
34
+ target?: LinkTarget;
35
+ };
36
+ }
37
+ export type ArticleMark = BoldMark | ItalicMark | StrikeMark | UnderlineMark | CodeMark | LinkMark;
38
+ export interface TextNode {
39
+ type: 'text';
40
+ text: string;
41
+ marks?: ArticleMark[];
42
+ }
43
+ export interface ParagraphNode {
44
+ type: 'paragraph';
45
+ attrs?: {
46
+ textAlign?: TextAlign;
47
+ };
48
+ content?: TextNode[];
49
+ }
50
+ export interface HeadingNode {
51
+ type: 'heading';
52
+ attrs: {
53
+ level: 1 | 2 | 3 | 4 | 5 | 6;
54
+ textAlign?: TextAlign;
55
+ };
56
+ content?: TextNode[];
57
+ }
58
+ export interface BlockquoteNode {
59
+ type: 'blockquote';
60
+ content: BlockNode[];
61
+ }
62
+ export interface BulletListNode {
63
+ type: 'bulletList';
64
+ content: ListItemNode[];
65
+ }
66
+ export interface OrderedListNode {
67
+ type: 'orderedList';
68
+ attrs?: {
69
+ start?: number;
70
+ };
71
+ content: ListItemNode[];
72
+ }
73
+ export interface ListItemNode {
74
+ type: 'listItem';
75
+ content: BlockNode[];
76
+ }
77
+ export interface CodeBlockTextNode {
78
+ type: 'text';
79
+ text: string;
80
+ }
81
+ export interface CodeBlockNode {
82
+ type: 'codeBlock';
83
+ attrs?: {
84
+ language?: string;
85
+ };
86
+ content?: CodeBlockTextNode[];
87
+ }
88
+ export interface HorizontalRuleNode {
89
+ type: 'horizontalRule';
90
+ }
91
+ export interface ImageNode {
92
+ type: 'image';
93
+ attrs: {
94
+ src: string;
95
+ alt?: string;
96
+ title?: string;
97
+ width?: number;
98
+ height?: number;
99
+ imageAlign?: ImageAlign;
100
+ };
101
+ }
102
+ export interface ArticleButtonAttrs {
103
+ id: string;
104
+ title?: string;
105
+ text: string;
106
+ style: ArticleButtonStyle;
107
+ }
108
+ export interface ArticleButtonNode {
109
+ type: 'articleButton';
110
+ attrs: ArticleButtonAttrs;
111
+ }
112
+ export interface TableNode {
113
+ type: 'table';
114
+ content: TableRowNode[];
115
+ }
116
+ export interface TableRowNode {
117
+ type: 'tableRow';
118
+ content: TableCellNode[];
119
+ }
120
+ export interface TableCellNode {
121
+ type: 'tableCell';
122
+ content: BlockNode[];
123
+ }
124
+ export type BlockNode = ParagraphNode | HeadingNode | BlockquoteNode | BulletListNode | OrderedListNode | CodeBlockNode | HorizontalRuleNode | ImageNode | ArticleButtonNode | TableNode;
125
+ export interface ArticleDocument {
126
+ type: 'doc';
127
+ content: BlockNode[];
128
+ }
129
+ export type ArticleContentNode = ArticleDocument | BlockNode | ListItemNode | TableRowNode | TableCellNode | TextNode;
130
+ export interface ArticleButtonLinkDescriptor {
131
+ href: string;
132
+ target?: LinkTarget;
133
+ rel?: string;
134
+ }
135
+ 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';
138
+ export interface RenderIssue {
139
+ code: RenderIssueCode;
140
+ path: string;
141
+ message: string;
142
+ nodeType?: string;
143
+ }
144
+ export interface ValidationResult {
145
+ valid: boolean;
146
+ issues: RenderIssue[];
147
+ }
148
+ export interface ArticleButtonClickPayload {
149
+ attrs: Readonly<ArticleButtonAttrs>;
150
+ node: Readonly<ArticleButtonNode>;
151
+ href: string | null;
152
+ event: MouseEvent;
153
+ }
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "article-content-renderer-vue2",
3
+ "version": "0.1.0",
4
+ "description": "A safe Vue 2.7 renderer for the Article Content Protocol ProseMirror JSON format.",
5
+ "author": "NovaVoyager",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "vue2",
9
+ "editor",
10
+ "tiptap",
11
+ "article-editor",
12
+ "rich-text-editor",
13
+ "render"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/sword-game-team/article-editor-render-vue2.git"
18
+ },
19
+ "homepage": "https://github.com/sword-game-team/article-editor-render-vue2#readme",
20
+ "bugs": {
21
+ "url": "https://github.com/sword-game-team/article-editor-render-vue2/issues"
22
+ },
23
+ "publishConfig": {
24
+ "access": "public",
25
+ "registry": "https://registry.npmjs.org/"
26
+ },
27
+ "type": "module",
28
+ "sideEffects": [
29
+ "**/*.css"
30
+ ],
31
+ "files": [
32
+ "dist",
33
+ "protocol"
34
+ ],
35
+ "main": "./dist/index.cjs",
36
+ "module": "./dist/index.js",
37
+ "types": "./dist/types/index.d.ts",
38
+ "exports": {
39
+ ".": {
40
+ "types": "./dist/types/index.d.ts",
41
+ "import": "./dist/index.js",
42
+ "require": "./dist/index.cjs"
43
+ },
44
+ "./style.css": "./dist/article-content-renderer-vue2.css"
45
+ },
46
+ "scripts": {
47
+ "dev": "vite --config demo/vite.config.ts",
48
+ "demo": "vite --config demo/vite.config.ts",
49
+ "demo:typecheck": "vue-tsc -p demo/tsconfig.json --noEmit",
50
+ "demo:build": "npm run demo:typecheck && vite build --config demo/vite.config.ts",
51
+ "build": "vue-tsc --noEmit && vite build && vue-tsc -p tsconfig.build.json",
52
+ "typecheck": "vue-tsc --noEmit",
53
+ "test": "vitest",
54
+ "test:run": "vitest run",
55
+ "check": "npm run typecheck && npm run test:run && npm run build",
56
+ "prepublishOnly": "npm run check"
57
+ },
58
+ "peerDependencies": {
59
+ "vue": "^2.7.16"
60
+ },
61
+ "devDependencies": {
62
+ "@types/node": "^22.10.0",
63
+ "@vitejs/plugin-vue2": "^2.3.3",
64
+ "@vue/test-utils": "^1.3.6",
65
+ "jsdom": "^24.1.3",
66
+ "typescript": "^5.7.2",
67
+ "vite": "^5.4.11",
68
+ "vitest": "^2.1.8",
69
+ "vue": "2.7.16",
70
+ "vue-server-renderer": "2.7.16",
71
+ "vue-template-compiler": "2.7.16",
72
+ "vue-tsc": "^2.2.0"
73
+ },
74
+ "engines": {
75
+ "node": ">=18.0.0"
76
+ }
77
+ }