@obelism/content-vue 0.1.0 → 0.1.1

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,157 @@
1
+ import * as _obelism_content_bridge from '@obelism/content/bridge';
2
+ import { BridgeOptions, ContentBridge as ContentBridge$1, BridgeState, PromptResult, CreatePageResult, BridgeEvent, BridgeListener } from '@obelism/content/bridge';
3
+ export { BridgeEvent, BridgeEvents, BridgeOptions, BridgeState, PromptBoxOptions, PromptLabels, PromptResult } from '@obelism/content/bridge';
4
+ import * as vue from 'vue';
5
+ import { PropType, ComputedRef, MaybeRefOrGetter, Component, VNodeChild } from 'vue';
6
+ import { Entry, RichTextNode, RichTextMark, EntryStub, Asset } from '@obelism/content';
7
+ export { Asset, Block, Entry, EntryStub, RichTextDocument, RichTextNode, editable } from '@obelism/content';
8
+
9
+ type ContentBridgeProps = BridgeOptions;
10
+ declare const ContentBridge: vue.DefineComponent<vue.ExtractPropTypes<{
11
+ url: {
12
+ type: StringConstructor;
13
+ default: undefined;
14
+ };
15
+ prompt: {
16
+ type: PropType<BridgeOptions["prompt"]>;
17
+ default: undefined;
18
+ };
19
+ pagePath: {
20
+ type: PropType<BridgeOptions["pagePath"]>;
21
+ default: undefined;
22
+ };
23
+ productPath: {
24
+ type: PropType<BridgeOptions["productPath"]>;
25
+ default: undefined;
26
+ };
27
+ collectionPath: {
28
+ type: PropType<BridgeOptions["collectionPath"]>;
29
+ default: undefined;
30
+ };
31
+ }>, () => null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
32
+ url: {
33
+ type: StringConstructor;
34
+ default: undefined;
35
+ };
36
+ prompt: {
37
+ type: PropType<BridgeOptions["prompt"]>;
38
+ default: undefined;
39
+ };
40
+ pagePath: {
41
+ type: PropType<BridgeOptions["pagePath"]>;
42
+ default: undefined;
43
+ };
44
+ productPath: {
45
+ type: PropType<BridgeOptions["productPath"]>;
46
+ default: undefined;
47
+ };
48
+ collectionPath: {
49
+ type: PropType<BridgeOptions["collectionPath"]>;
50
+ default: undefined;
51
+ };
52
+ }>> & Readonly<{}>, {
53
+ prompt: boolean | (Omit<_obelism_content_bridge.PromptBoxOptions, "labels"> & {
54
+ labels?: Partial<_obelism_content_bridge.PromptLabels & _obelism_content_bridge.SiteEditorLabels> | undefined;
55
+ }) | undefined;
56
+ pagePath: ((path: string, locale: string) => string) | undefined;
57
+ productPath: ((handle: string, locale: string) => string) | undefined;
58
+ collectionPath: ((handle: string, locale: string) => string) | undefined;
59
+ url: string;
60
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
61
+ type ContentBridgeState = Pick<ContentBridge$1, 'isEditing' | 'mode' | 'entryId' | 'environment'>;
62
+ declare const useContentBridge: ({ url, }?: BridgeOptions) => ComputedRef<ContentBridgeState>;
63
+ declare const useContentBridgeEvent: <E extends BridgeEvent>(event: E, listener: BridgeListener<E>, { url }?: BridgeOptions) => void;
64
+ declare function useLiveEntry<TEntry extends Entry>(entry: MaybeRefOrGetter<TEntry>, options?: BridgeOptions): ComputedRef<TEntry>;
65
+ declare function useLiveEntry<TEntry extends Entry>(entry: MaybeRefOrGetter<TEntry | null | undefined>, options?: BridgeOptions): ComputedRef<TEntry | null>;
66
+ type ContentPromptState = BridgeState & {
67
+ available: boolean;
68
+ mode: ContentBridge$1['mode'];
69
+ prompt: (prompt: string, options?: {
70
+ uid?: string | null;
71
+ }) => Promise<PromptResult>;
72
+ createPage: (path: string, prompt: string) => Promise<CreatePageResult>;
73
+ undo: () => void;
74
+ select: (uid: string | null) => void;
75
+ save: () => Promise<void>;
76
+ publish: () => Promise<void>;
77
+ signOut: () => void;
78
+ setSelecting: (selecting: boolean) => void;
79
+ };
80
+ declare const useContentPrompt: ({ url, }?: Pick<BridgeOptions, "url">) => ComputedRef<ContentPromptState>;
81
+
82
+ type RichTextNodeProps = {
83
+ node: RichTextNode;
84
+ };
85
+ type RichTextMarkProps = {
86
+ mark: RichTextMark;
87
+ };
88
+ type RichTextEmbeddedEntryProps = {
89
+ entry: Entry | EntryStub;
90
+ node: RichTextNode;
91
+ };
92
+ type RichTextEmbeddedAssetProps = {
93
+ asset: Asset;
94
+ node: RichTextNode;
95
+ };
96
+ type RichTextComponents = {
97
+ nodes?: Partial<Record<string, Component<RichTextNodeProps>>> | undefined;
98
+ marks?: Partial<Record<string, Component<RichTextMarkProps>>> | undefined;
99
+ embeddedEntry?: Component<RichTextEmbeddedEntryProps> | undefined;
100
+ embeddedAsset?: Component<RichTextEmbeddedAssetProps> | undefined;
101
+ };
102
+ type RichTextProps = RichTextComponents & {
103
+ document: RichTextNode | null | undefined;
104
+ };
105
+ declare const RichText: vue.DefineComponent<vue.ExtractPropTypes<{
106
+ document: {
107
+ type: PropType<RichTextNode | null | undefined>;
108
+ default: null;
109
+ };
110
+ nodes: {
111
+ type: PropType<RichTextComponents["nodes"]>;
112
+ default: undefined;
113
+ };
114
+ marks: {
115
+ type: PropType<RichTextComponents["marks"]>;
116
+ default: undefined;
117
+ };
118
+ embeddedEntry: {
119
+ type: PropType<RichTextComponents["embeddedEntry"]>;
120
+ default: undefined;
121
+ };
122
+ embeddedAsset: {
123
+ type: PropType<RichTextComponents["embeddedAsset"]>;
124
+ default: undefined;
125
+ };
126
+ }>, () => VNodeChild, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
127
+ document: {
128
+ type: PropType<RichTextNode | null | undefined>;
129
+ default: null;
130
+ };
131
+ nodes: {
132
+ type: PropType<RichTextComponents["nodes"]>;
133
+ default: undefined;
134
+ };
135
+ marks: {
136
+ type: PropType<RichTextComponents["marks"]>;
137
+ default: undefined;
138
+ };
139
+ embeddedEntry: {
140
+ type: PropType<RichTextComponents["embeddedEntry"]>;
141
+ default: undefined;
142
+ };
143
+ embeddedAsset: {
144
+ type: PropType<RichTextComponents["embeddedAsset"]>;
145
+ default: undefined;
146
+ };
147
+ }>> & Readonly<{}>, {
148
+ nodes: Partial<Record<string, Component<RichTextNodeProps>>> | undefined;
149
+ marks: Partial<Record<string, Component<RichTextMarkProps>>> | undefined;
150
+ embeddedEntry: Component<RichTextEmbeddedEntryProps> | undefined;
151
+ embeddedAsset: Component<RichTextEmbeddedAssetProps> | undefined;
152
+ document: RichTextNode | null | undefined;
153
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
154
+
155
+ export { ContentBridge, RichText, useContentBridge, useContentBridgeEvent, useContentPrompt, useLiveEntry };
156
+ export type { ContentBridgeProps, ContentBridgeState, ContentPromptState, RichTextComponents, RichTextEmbeddedAssetProps, RichTextEmbeddedEntryProps, RichTextMarkProps, RichTextNodeProps, RichTextProps };
157
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","sources":["../src/bridge.ts","../src/RichText.ts"],"mappings":"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","names":["Bridge"]}
@@ -0,0 +1,157 @@
1
+ import * as _obelism_content_bridge from '@obelism/content/bridge';
2
+ import { BridgeOptions, ContentBridge as ContentBridge$1, BridgeState, PromptResult, CreatePageResult, BridgeEvent, BridgeListener } from '@obelism/content/bridge';
3
+ export { BridgeEvent, BridgeEvents, BridgeOptions, BridgeState, PromptBoxOptions, PromptLabels, PromptResult } from '@obelism/content/bridge';
4
+ import * as vue from 'vue';
5
+ import { PropType, ComputedRef, MaybeRefOrGetter, Component, VNodeChild } from 'vue';
6
+ import { Entry, RichTextNode, RichTextMark, EntryStub, Asset } from '@obelism/content';
7
+ export { Asset, Block, Entry, EntryStub, RichTextDocument, RichTextNode, editable } from '@obelism/content';
8
+
9
+ type ContentBridgeProps = BridgeOptions;
10
+ declare const ContentBridge: vue.DefineComponent<vue.ExtractPropTypes<{
11
+ url: {
12
+ type: StringConstructor;
13
+ default: undefined;
14
+ };
15
+ prompt: {
16
+ type: PropType<BridgeOptions["prompt"]>;
17
+ default: undefined;
18
+ };
19
+ pagePath: {
20
+ type: PropType<BridgeOptions["pagePath"]>;
21
+ default: undefined;
22
+ };
23
+ productPath: {
24
+ type: PropType<BridgeOptions["productPath"]>;
25
+ default: undefined;
26
+ };
27
+ collectionPath: {
28
+ type: PropType<BridgeOptions["collectionPath"]>;
29
+ default: undefined;
30
+ };
31
+ }>, () => null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
32
+ url: {
33
+ type: StringConstructor;
34
+ default: undefined;
35
+ };
36
+ prompt: {
37
+ type: PropType<BridgeOptions["prompt"]>;
38
+ default: undefined;
39
+ };
40
+ pagePath: {
41
+ type: PropType<BridgeOptions["pagePath"]>;
42
+ default: undefined;
43
+ };
44
+ productPath: {
45
+ type: PropType<BridgeOptions["productPath"]>;
46
+ default: undefined;
47
+ };
48
+ collectionPath: {
49
+ type: PropType<BridgeOptions["collectionPath"]>;
50
+ default: undefined;
51
+ };
52
+ }>> & Readonly<{}>, {
53
+ prompt: boolean | (Omit<_obelism_content_bridge.PromptBoxOptions, "labels"> & {
54
+ labels?: Partial<_obelism_content_bridge.PromptLabels & _obelism_content_bridge.SiteEditorLabels> | undefined;
55
+ }) | undefined;
56
+ pagePath: ((path: string, locale: string) => string) | undefined;
57
+ productPath: ((handle: string, locale: string) => string) | undefined;
58
+ collectionPath: ((handle: string, locale: string) => string) | undefined;
59
+ url: string;
60
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
61
+ type ContentBridgeState = Pick<ContentBridge$1, 'isEditing' | 'mode' | 'entryId' | 'environment'>;
62
+ declare const useContentBridge: ({ url, }?: BridgeOptions) => ComputedRef<ContentBridgeState>;
63
+ declare const useContentBridgeEvent: <E extends BridgeEvent>(event: E, listener: BridgeListener<E>, { url }?: BridgeOptions) => void;
64
+ declare function useLiveEntry<TEntry extends Entry>(entry: MaybeRefOrGetter<TEntry>, options?: BridgeOptions): ComputedRef<TEntry>;
65
+ declare function useLiveEntry<TEntry extends Entry>(entry: MaybeRefOrGetter<TEntry | null | undefined>, options?: BridgeOptions): ComputedRef<TEntry | null>;
66
+ type ContentPromptState = BridgeState & {
67
+ available: boolean;
68
+ mode: ContentBridge$1['mode'];
69
+ prompt: (prompt: string, options?: {
70
+ uid?: string | null;
71
+ }) => Promise<PromptResult>;
72
+ createPage: (path: string, prompt: string) => Promise<CreatePageResult>;
73
+ undo: () => void;
74
+ select: (uid: string | null) => void;
75
+ save: () => Promise<void>;
76
+ publish: () => Promise<void>;
77
+ signOut: () => void;
78
+ setSelecting: (selecting: boolean) => void;
79
+ };
80
+ declare const useContentPrompt: ({ url, }?: Pick<BridgeOptions, "url">) => ComputedRef<ContentPromptState>;
81
+
82
+ type RichTextNodeProps = {
83
+ node: RichTextNode;
84
+ };
85
+ type RichTextMarkProps = {
86
+ mark: RichTextMark;
87
+ };
88
+ type RichTextEmbeddedEntryProps = {
89
+ entry: Entry | EntryStub;
90
+ node: RichTextNode;
91
+ };
92
+ type RichTextEmbeddedAssetProps = {
93
+ asset: Asset;
94
+ node: RichTextNode;
95
+ };
96
+ type RichTextComponents = {
97
+ nodes?: Partial<Record<string, Component<RichTextNodeProps>>> | undefined;
98
+ marks?: Partial<Record<string, Component<RichTextMarkProps>>> | undefined;
99
+ embeddedEntry?: Component<RichTextEmbeddedEntryProps> | undefined;
100
+ embeddedAsset?: Component<RichTextEmbeddedAssetProps> | undefined;
101
+ };
102
+ type RichTextProps = RichTextComponents & {
103
+ document: RichTextNode | null | undefined;
104
+ };
105
+ declare const RichText: vue.DefineComponent<vue.ExtractPropTypes<{
106
+ document: {
107
+ type: PropType<RichTextNode | null | undefined>;
108
+ default: null;
109
+ };
110
+ nodes: {
111
+ type: PropType<RichTextComponents["nodes"]>;
112
+ default: undefined;
113
+ };
114
+ marks: {
115
+ type: PropType<RichTextComponents["marks"]>;
116
+ default: undefined;
117
+ };
118
+ embeddedEntry: {
119
+ type: PropType<RichTextComponents["embeddedEntry"]>;
120
+ default: undefined;
121
+ };
122
+ embeddedAsset: {
123
+ type: PropType<RichTextComponents["embeddedAsset"]>;
124
+ default: undefined;
125
+ };
126
+ }>, () => VNodeChild, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
127
+ document: {
128
+ type: PropType<RichTextNode | null | undefined>;
129
+ default: null;
130
+ };
131
+ nodes: {
132
+ type: PropType<RichTextComponents["nodes"]>;
133
+ default: undefined;
134
+ };
135
+ marks: {
136
+ type: PropType<RichTextComponents["marks"]>;
137
+ default: undefined;
138
+ };
139
+ embeddedEntry: {
140
+ type: PropType<RichTextComponents["embeddedEntry"]>;
141
+ default: undefined;
142
+ };
143
+ embeddedAsset: {
144
+ type: PropType<RichTextComponents["embeddedAsset"]>;
145
+ default: undefined;
146
+ };
147
+ }>> & Readonly<{}>, {
148
+ nodes: Partial<Record<string, Component<RichTextNodeProps>>> | undefined;
149
+ marks: Partial<Record<string, Component<RichTextMarkProps>>> | undefined;
150
+ embeddedEntry: Component<RichTextEmbeddedEntryProps> | undefined;
151
+ embeddedAsset: Component<RichTextEmbeddedAssetProps> | undefined;
152
+ document: RichTextNode | null | undefined;
153
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
154
+
155
+ export { ContentBridge, RichText, useContentBridge, useContentBridgeEvent, useContentPrompt, useLiveEntry };
156
+ export type { ContentBridgeProps, ContentBridgeState, ContentPromptState, RichTextComponents, RichTextEmbeddedAssetProps, RichTextEmbeddedEntryProps, RichTextMarkProps, RichTextNodeProps, RichTextProps };
157
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sources":["../src/bridge.ts","../src/RichText.ts"],"mappings":"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","names":["Bridge"]}
package/dist/index.js ADDED
@@ -0,0 +1,347 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true });
2
+
3
+ var vue = require('vue');
4
+ var bridge = require('@obelism/content/bridge');
5
+ var content = require('@obelism/content');
6
+
7
+ const noop = ()=>{};
8
+ // Started after mount, never during setup, so it is null on the server and
9
+ // while hydrating, and markup matches. Call the composables in `setup`.
10
+ const useBridge = (options)=>{
11
+ const bridge$1 = vue.shallowRef(null);
12
+ vue.onMounted(()=>{
13
+ bridge$1.value = bridge.getContentBridge(options);
14
+ });
15
+ return bridge$1;
16
+ };
17
+ // Starts the visual editor bridge. Put it in the root (`app.vue` or a
18
+ // layout), so clicking a block selects it in the editor on every page, also
19
+ // those without `useLiveEntry`, and editors get the prompt box
20
+ // (`:prompt="false"` leaves it out). Renders nothing, and does nothing
21
+ // outside the editor. Its options apply when it is the first to start the
22
+ // bridge, which in the root it is.
23
+ const ContentBridge = vue.defineComponent({
24
+ name: 'ContentBridge',
25
+ props: {
26
+ url: {
27
+ type: String,
28
+ default: undefined
29
+ },
30
+ prompt: {
31
+ type: [
32
+ Boolean,
33
+ Object
34
+ ],
35
+ default: undefined
36
+ },
37
+ pagePath: {
38
+ type: Function,
39
+ default: undefined
40
+ },
41
+ productPath: {
42
+ type: Function,
43
+ default: undefined
44
+ },
45
+ collectionPath: {
46
+ type: Function,
47
+ default: undefined
48
+ }
49
+ },
50
+ setup (props) {
51
+ useBridge({
52
+ url: props.url,
53
+ prompt: props.prompt,
54
+ pagePath: props.pagePath,
55
+ productPath: props.productPath,
56
+ collectionPath: props.collectionPath
57
+ });
58
+ return ()=>null;
59
+ }
60
+ });
61
+ const NOT_EDITING = {
62
+ isEditing: false,
63
+ mode: null,
64
+ entryId: null,
65
+ environment: null
66
+ };
67
+ // Whether the page is open in the visual editor (or signed in to edit on the
68
+ // site), and on which entry. Always "not editing" during server rendering
69
+ // and hydration; the real state follows right after.
70
+ const useContentBridge = ({ url } = {})=>{
71
+ const bridge = useBridge({
72
+ url
73
+ });
74
+ return vue.computed(()=>{
75
+ const current = bridge.value;
76
+ if (!current?.isEditing) return NOT_EDITING;
77
+ const { isEditing, mode, entryId, environment } = current;
78
+ return {
79
+ isEditing,
80
+ mode,
81
+ entryId,
82
+ environment
83
+ };
84
+ });
85
+ };
86
+ // Calls `listener` on a bridge event, e.g. to refetch server data once the
87
+ // editor saved or published:
88
+ //
89
+ // const { refresh } = await useAsyncData(…)
90
+ // useContentBridgeEvent('saved', () => refresh())
91
+ const useContentBridgeEvent = (event, listener, { url } = {})=>{
92
+ const bridge = useBridge({
93
+ url
94
+ });
95
+ vue.watch(bridge, (current, _previous, onCleanup)=>{
96
+ if (current) onCleanup(current.on(event, listener));
97
+ }, {
98
+ immediate: true
99
+ });
100
+ };
101
+ function useLiveEntry(entry, { url } = {}) {
102
+ const bridge = useBridge({
103
+ url
104
+ });
105
+ const live = vue.shallowRef(null);
106
+ const id = vue.computed(()=>vue.toValue(entry)?.id);
107
+ vue.watch([
108
+ bridge,
109
+ id
110
+ ], ([current, currentId], _previous, onCleanup)=>{
111
+ if (!current || !currentId) return;
112
+ onCleanup(current.on('update', ({ entry: next })=>{
113
+ if (next.id === currentId) live.value = next;
114
+ }));
115
+ }, {
116
+ immediate: true
117
+ });
118
+ // A live version only stands in for the entry it was sent for.
119
+ return vue.computed(()=>{
120
+ const current = vue.toValue(entry);
121
+ if (live.value && live.value.id === current?.id) return live.value;
122
+ return current ?? null;
123
+ });
124
+ }
125
+ const notStarted = ()=>Promise.reject(new Error('Prompts only work inside the visual editor'));
126
+ const notOnSite = ()=>Promise.reject(new Error('Only while signed in to edit on the site'));
127
+ // For your own prompt UI instead of the built-in box (render
128
+ // `<ContentBridge :prompt="false" />`):
129
+ //
130
+ // const prompt = useContentPrompt()
131
+ // // <button v-if="prompt.available" @click="prompt.prompt('Make it shorter')">
132
+ const useContentPrompt = ({ url } = {})=>{
133
+ const bridge$1 = useBridge({
134
+ url
135
+ });
136
+ const state = vue.shallowRef(bridge.INITIAL_STATE);
137
+ vue.watch(bridge$1, (current, _previous, onCleanup)=>{
138
+ if (!current) return;
139
+ state.value = current.getState();
140
+ onCleanup(current.on('change', ()=>{
141
+ state.value = current.getState();
142
+ }));
143
+ }, {
144
+ immediate: true
145
+ });
146
+ return vue.computed(()=>{
147
+ const current = bridge$1.value;
148
+ return {
149
+ ...state.value,
150
+ available: state.value.features.includes('prompt'),
151
+ mode: current?.mode ?? null,
152
+ prompt: current ? current.prompt : notStarted,
153
+ createPage: current ? current.createPage : notOnSite,
154
+ undo: current ? current.undo : noop,
155
+ select: current ? current.select : noop,
156
+ save: current ? current.save : notOnSite,
157
+ publish: current ? current.publish : notOnSite,
158
+ signOut: current ? current.signOut : noop,
159
+ setSelecting: current ? current.setSelecting : noop
160
+ };
161
+ });
162
+ };
163
+
164
+ const defaultAsset = (asset)=>{
165
+ if (asset.mimeType.startsWith('image/')) {
166
+ return vue.h('figure', [
167
+ vue.h('img', {
168
+ src: asset.url,
169
+ alt: typeof asset.alt === 'string' ? asset.alt : '',
170
+ width: asset.width ?? undefined,
171
+ height: asset.height ?? undefined
172
+ })
173
+ ]);
174
+ }
175
+ return vue.h('p', [
176
+ vue.h('a', {
177
+ href: asset.url
178
+ }, asset.filename)
179
+ ]);
180
+ };
181
+ const renderMark = (mark, children, marks)=>{
182
+ const Custom = marks?.[mark.type];
183
+ if (Custom) return vue.h(Custom, {
184
+ mark
185
+ }, {
186
+ default: ()=>children
187
+ });
188
+ switch(mark.type){
189
+ case 'bold':
190
+ return vue.h('strong', [
191
+ children
192
+ ]);
193
+ case 'italic':
194
+ return vue.h('em', [
195
+ children
196
+ ]);
197
+ case 'underline':
198
+ return vue.h('u', [
199
+ children
200
+ ]);
201
+ case 'strike':
202
+ return vue.h('s', [
203
+ children
204
+ ]);
205
+ case 'code':
206
+ return vue.h('code', [
207
+ children
208
+ ]);
209
+ case 'link':
210
+ {
211
+ const href = String(mark.attrs?.href ?? '');
212
+ if (!content.SAFE_HREF.test(href)) return children;
213
+ const blank = mark.attrs?.target === '_blank';
214
+ return vue.h('a', {
215
+ href,
216
+ title: mark.attrs?.title ? String(mark.attrs.title) : undefined,
217
+ target: blank ? '_blank' : undefined,
218
+ rel: blank ? 'noopener noreferrer' : undefined
219
+ }, [
220
+ children
221
+ ]);
222
+ }
223
+ default:
224
+ return children;
225
+ }
226
+ };
227
+ // Renders a rich text document as Vue elements: no HTML strings, links
228
+ // limited to safe schemes, and every node, mark and embed overridable.
229
+ //
230
+ // <RichText
231
+ // :document="entry.fields.body"
232
+ // :embedded-entry="Card"
233
+ // :nodes="{ heading: Heading }"
234
+ // />
235
+ const RichText = vue.defineComponent({
236
+ name: 'RichText',
237
+ props: {
238
+ document: {
239
+ type: Object,
240
+ default: null
241
+ },
242
+ nodes: {
243
+ type: Object,
244
+ default: undefined
245
+ },
246
+ marks: {
247
+ type: Object,
248
+ default: undefined
249
+ },
250
+ embeddedEntry: {
251
+ type: [
252
+ Object,
253
+ Function
254
+ ],
255
+ default: undefined
256
+ },
257
+ embeddedAsset: {
258
+ type: [
259
+ Object,
260
+ Function
261
+ ],
262
+ default: undefined
263
+ }
264
+ },
265
+ setup (props) {
266
+ const render = (node)=>{
267
+ if (node.type === 'text') {
268
+ return (node.marks ?? []).reduceRight((inner, mark)=>renderMark(mark, inner, props.marks), node.text ?? '');
269
+ }
270
+ const children = node.content && node.content.length > 0 ? node.content.map(render).filter((child)=>child != null) : undefined;
271
+ const Custom = props.nodes?.[node.type];
272
+ if (Custom) {
273
+ return vue.h(Custom, {
274
+ node
275
+ }, children ? {
276
+ default: ()=>children
277
+ } : undefined);
278
+ }
279
+ switch(node.type){
280
+ case 'doc':
281
+ return children ?? null;
282
+ case 'paragraph':
283
+ return vue.h('p', children);
284
+ case 'heading':
285
+ return vue.h(`h${content.headingLevel(node)}`, children);
286
+ case 'blockquote':
287
+ return vue.h('blockquote', children);
288
+ case 'bulletList':
289
+ return vue.h('ul', children);
290
+ case 'orderedList':
291
+ {
292
+ const start = Number(node.attrs?.start ?? 1);
293
+ return vue.h('ol', {
294
+ start: start !== 1 ? start : undefined
295
+ }, children);
296
+ }
297
+ case 'listItem':
298
+ return vue.h('li', children);
299
+ case 'codeBlock':
300
+ {
301
+ const language = node.attrs?.language;
302
+ return vue.h('pre', [
303
+ vue.h('code', {
304
+ class: language ? `language-${String(language)}` : undefined
305
+ }, children)
306
+ ]);
307
+ }
308
+ case 'hardBreak':
309
+ return vue.h('br');
310
+ case 'horizontalRule':
311
+ return vue.h('hr');
312
+ case 'embeddedEntry':
313
+ {
314
+ const entry = node.attrs?.entry;
315
+ if (!entry || !props.embeddedEntry) return null;
316
+ return vue.h(props.embeddedEntry, {
317
+ entry,
318
+ node
319
+ });
320
+ }
321
+ case 'embeddedAsset':
322
+ {
323
+ const asset = node.attrs?.asset;
324
+ if (!asset) return null;
325
+ return props.embeddedAsset ? vue.h(props.embeddedAsset, {
326
+ asset,
327
+ node
328
+ }) : defaultAsset(asset);
329
+ }
330
+ default:
331
+ return null;
332
+ }
333
+ };
334
+ return ()=>props.document ? render(props.document) : null;
335
+ }
336
+ });
337
+
338
+ Object.defineProperty(exports, "editable", {
339
+ enumerable: true,
340
+ get: function () { return content.editable; }
341
+ });
342
+ exports.ContentBridge = ContentBridge;
343
+ exports.RichText = RichText;
344
+ exports.useContentBridge = useContentBridge;
345
+ exports.useContentBridgeEvent = useContentBridgeEvent;
346
+ exports.useContentPrompt = useContentPrompt;
347
+ exports.useLiveEntry = useLiveEntry;
package/dist/index.mjs ADDED
@@ -0,0 +1,337 @@
1
+ import { defineComponent, shallowRef, onMounted, computed, watch, toValue, h } from 'vue';
2
+ import { getContentBridge, INITIAL_STATE } from '@obelism/content/bridge';
3
+ import { headingLevel, SAFE_HREF } from '@obelism/content';
4
+ export { editable } from '@obelism/content';
5
+
6
+ const noop = ()=>{};
7
+ // Started after mount, never during setup, so it is null on the server and
8
+ // while hydrating, and markup matches. Call the composables in `setup`.
9
+ const useBridge = (options)=>{
10
+ const bridge = shallowRef(null);
11
+ onMounted(()=>{
12
+ bridge.value = getContentBridge(options);
13
+ });
14
+ return bridge;
15
+ };
16
+ // Starts the visual editor bridge. Put it in the root (`app.vue` or a
17
+ // layout), so clicking a block selects it in the editor on every page, also
18
+ // those without `useLiveEntry`, and editors get the prompt box
19
+ // (`:prompt="false"` leaves it out). Renders nothing, and does nothing
20
+ // outside the editor. Its options apply when it is the first to start the
21
+ // bridge, which in the root it is.
22
+ const ContentBridge = defineComponent({
23
+ name: 'ContentBridge',
24
+ props: {
25
+ url: {
26
+ type: String,
27
+ default: undefined
28
+ },
29
+ prompt: {
30
+ type: [
31
+ Boolean,
32
+ Object
33
+ ],
34
+ default: undefined
35
+ },
36
+ pagePath: {
37
+ type: Function,
38
+ default: undefined
39
+ },
40
+ productPath: {
41
+ type: Function,
42
+ default: undefined
43
+ },
44
+ collectionPath: {
45
+ type: Function,
46
+ default: undefined
47
+ }
48
+ },
49
+ setup (props) {
50
+ useBridge({
51
+ url: props.url,
52
+ prompt: props.prompt,
53
+ pagePath: props.pagePath,
54
+ productPath: props.productPath,
55
+ collectionPath: props.collectionPath
56
+ });
57
+ return ()=>null;
58
+ }
59
+ });
60
+ const NOT_EDITING = {
61
+ isEditing: false,
62
+ mode: null,
63
+ entryId: null,
64
+ environment: null
65
+ };
66
+ // Whether the page is open in the visual editor (or signed in to edit on the
67
+ // site), and on which entry. Always "not editing" during server rendering
68
+ // and hydration; the real state follows right after.
69
+ const useContentBridge = ({ url } = {})=>{
70
+ const bridge = useBridge({
71
+ url
72
+ });
73
+ return computed(()=>{
74
+ const current = bridge.value;
75
+ if (!current?.isEditing) return NOT_EDITING;
76
+ const { isEditing, mode, entryId, environment } = current;
77
+ return {
78
+ isEditing,
79
+ mode,
80
+ entryId,
81
+ environment
82
+ };
83
+ });
84
+ };
85
+ // Calls `listener` on a bridge event, e.g. to refetch server data once the
86
+ // editor saved or published:
87
+ //
88
+ // const { refresh } = await useAsyncData(…)
89
+ // useContentBridgeEvent('saved', () => refresh())
90
+ const useContentBridgeEvent = (event, listener, { url } = {})=>{
91
+ const bridge = useBridge({
92
+ url
93
+ });
94
+ watch(bridge, (current, _previous, onCleanup)=>{
95
+ if (current) onCleanup(current.on(event, listener));
96
+ }, {
97
+ immediate: true
98
+ });
99
+ };
100
+ function useLiveEntry(entry, { url } = {}) {
101
+ const bridge = useBridge({
102
+ url
103
+ });
104
+ const live = shallowRef(null);
105
+ const id = computed(()=>toValue(entry)?.id);
106
+ watch([
107
+ bridge,
108
+ id
109
+ ], ([current, currentId], _previous, onCleanup)=>{
110
+ if (!current || !currentId) return;
111
+ onCleanup(current.on('update', ({ entry: next })=>{
112
+ if (next.id === currentId) live.value = next;
113
+ }));
114
+ }, {
115
+ immediate: true
116
+ });
117
+ // A live version only stands in for the entry it was sent for.
118
+ return computed(()=>{
119
+ const current = toValue(entry);
120
+ if (live.value && live.value.id === current?.id) return live.value;
121
+ return current ?? null;
122
+ });
123
+ }
124
+ const notStarted = ()=>Promise.reject(new Error('Prompts only work inside the visual editor'));
125
+ const notOnSite = ()=>Promise.reject(new Error('Only while signed in to edit on the site'));
126
+ // For your own prompt UI instead of the built-in box (render
127
+ // `<ContentBridge :prompt="false" />`):
128
+ //
129
+ // const prompt = useContentPrompt()
130
+ // // <button v-if="prompt.available" @click="prompt.prompt('Make it shorter')">
131
+ const useContentPrompt = ({ url } = {})=>{
132
+ const bridge = useBridge({
133
+ url
134
+ });
135
+ const state = shallowRef(INITIAL_STATE);
136
+ watch(bridge, (current, _previous, onCleanup)=>{
137
+ if (!current) return;
138
+ state.value = current.getState();
139
+ onCleanup(current.on('change', ()=>{
140
+ state.value = current.getState();
141
+ }));
142
+ }, {
143
+ immediate: true
144
+ });
145
+ return computed(()=>{
146
+ const current = bridge.value;
147
+ return {
148
+ ...state.value,
149
+ available: state.value.features.includes('prompt'),
150
+ mode: current?.mode ?? null,
151
+ prompt: current ? current.prompt : notStarted,
152
+ createPage: current ? current.createPage : notOnSite,
153
+ undo: current ? current.undo : noop,
154
+ select: current ? current.select : noop,
155
+ save: current ? current.save : notOnSite,
156
+ publish: current ? current.publish : notOnSite,
157
+ signOut: current ? current.signOut : noop,
158
+ setSelecting: current ? current.setSelecting : noop
159
+ };
160
+ });
161
+ };
162
+
163
+ const defaultAsset = (asset)=>{
164
+ if (asset.mimeType.startsWith('image/')) {
165
+ return h('figure', [
166
+ h('img', {
167
+ src: asset.url,
168
+ alt: typeof asset.alt === 'string' ? asset.alt : '',
169
+ width: asset.width ?? undefined,
170
+ height: asset.height ?? undefined
171
+ })
172
+ ]);
173
+ }
174
+ return h('p', [
175
+ h('a', {
176
+ href: asset.url
177
+ }, asset.filename)
178
+ ]);
179
+ };
180
+ const renderMark = (mark, children, marks)=>{
181
+ const Custom = marks?.[mark.type];
182
+ if (Custom) return h(Custom, {
183
+ mark
184
+ }, {
185
+ default: ()=>children
186
+ });
187
+ switch(mark.type){
188
+ case 'bold':
189
+ return h('strong', [
190
+ children
191
+ ]);
192
+ case 'italic':
193
+ return h('em', [
194
+ children
195
+ ]);
196
+ case 'underline':
197
+ return h('u', [
198
+ children
199
+ ]);
200
+ case 'strike':
201
+ return h('s', [
202
+ children
203
+ ]);
204
+ case 'code':
205
+ return h('code', [
206
+ children
207
+ ]);
208
+ case 'link':
209
+ {
210
+ const href = String(mark.attrs?.href ?? '');
211
+ if (!SAFE_HREF.test(href)) return children;
212
+ const blank = mark.attrs?.target === '_blank';
213
+ return h('a', {
214
+ href,
215
+ title: mark.attrs?.title ? String(mark.attrs.title) : undefined,
216
+ target: blank ? '_blank' : undefined,
217
+ rel: blank ? 'noopener noreferrer' : undefined
218
+ }, [
219
+ children
220
+ ]);
221
+ }
222
+ default:
223
+ return children;
224
+ }
225
+ };
226
+ // Renders a rich text document as Vue elements: no HTML strings, links
227
+ // limited to safe schemes, and every node, mark and embed overridable.
228
+ //
229
+ // <RichText
230
+ // :document="entry.fields.body"
231
+ // :embedded-entry="Card"
232
+ // :nodes="{ heading: Heading }"
233
+ // />
234
+ const RichText = defineComponent({
235
+ name: 'RichText',
236
+ props: {
237
+ document: {
238
+ type: Object,
239
+ default: null
240
+ },
241
+ nodes: {
242
+ type: Object,
243
+ default: undefined
244
+ },
245
+ marks: {
246
+ type: Object,
247
+ default: undefined
248
+ },
249
+ embeddedEntry: {
250
+ type: [
251
+ Object,
252
+ Function
253
+ ],
254
+ default: undefined
255
+ },
256
+ embeddedAsset: {
257
+ type: [
258
+ Object,
259
+ Function
260
+ ],
261
+ default: undefined
262
+ }
263
+ },
264
+ setup (props) {
265
+ const render = (node)=>{
266
+ if (node.type === 'text') {
267
+ return (node.marks ?? []).reduceRight((inner, mark)=>renderMark(mark, inner, props.marks), node.text ?? '');
268
+ }
269
+ const children = node.content && node.content.length > 0 ? node.content.map(render).filter((child)=>child != null) : undefined;
270
+ const Custom = props.nodes?.[node.type];
271
+ if (Custom) {
272
+ return h(Custom, {
273
+ node
274
+ }, children ? {
275
+ default: ()=>children
276
+ } : undefined);
277
+ }
278
+ switch(node.type){
279
+ case 'doc':
280
+ return children ?? null;
281
+ case 'paragraph':
282
+ return h('p', children);
283
+ case 'heading':
284
+ return h(`h${headingLevel(node)}`, children);
285
+ case 'blockquote':
286
+ return h('blockquote', children);
287
+ case 'bulletList':
288
+ return h('ul', children);
289
+ case 'orderedList':
290
+ {
291
+ const start = Number(node.attrs?.start ?? 1);
292
+ return h('ol', {
293
+ start: start !== 1 ? start : undefined
294
+ }, children);
295
+ }
296
+ case 'listItem':
297
+ return h('li', children);
298
+ case 'codeBlock':
299
+ {
300
+ const language = node.attrs?.language;
301
+ return h('pre', [
302
+ h('code', {
303
+ class: language ? `language-${String(language)}` : undefined
304
+ }, children)
305
+ ]);
306
+ }
307
+ case 'hardBreak':
308
+ return h('br');
309
+ case 'horizontalRule':
310
+ return h('hr');
311
+ case 'embeddedEntry':
312
+ {
313
+ const entry = node.attrs?.entry;
314
+ if (!entry || !props.embeddedEntry) return null;
315
+ return h(props.embeddedEntry, {
316
+ entry,
317
+ node
318
+ });
319
+ }
320
+ case 'embeddedAsset':
321
+ {
322
+ const asset = node.attrs?.asset;
323
+ if (!asset) return null;
324
+ return props.embeddedAsset ? h(props.embeddedAsset, {
325
+ asset,
326
+ node
327
+ }) : defaultAsset(asset);
328
+ }
329
+ default:
330
+ return null;
331
+ }
332
+ };
333
+ return ()=>props.document ? render(props.document) : null;
334
+ }
335
+ });
336
+
337
+ export { ContentBridge, RichText, useContentBridge, useContentBridgeEvent, useContentPrompt, useLiveEntry };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@obelism/content-vue",
3
3
  "description": "Obelism Content Vue SDK: live preview in the visual editor and rich text, for Vue and Nuxt",
4
- "version": "0.1.0",
4
+ "version": "0.1.1",
5
5
  "keywords": [
6
6
  "cms",
7
7
  "headless-cms",
@@ -47,7 +47,7 @@
47
47
  "vue": ">=3.3.0"
48
48
  },
49
49
  "dependencies": {
50
- "@obelism/content": "^0.29.0"
50
+ "@obelism/content": "^0.30.0"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@obelism/sdk-typescript-config": "^0.0.0",