@prismicio/vue 4.3.0 → 5.0.0-alpha.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.
Files changed (245) hide show
  1. package/README.md +4 -4
  2. package/dist/PrismicEmbed.vue.cjs +25 -0
  3. package/dist/PrismicEmbed.vue.cjs.map +1 -0
  4. package/dist/PrismicEmbed.vue.d.ts +19 -0
  5. package/dist/PrismicEmbed.vue.js +26 -0
  6. package/dist/PrismicEmbed.vue.js.map +1 -0
  7. package/dist/PrismicEmbed.vue2.cjs +4 -0
  8. package/dist/PrismicEmbed.vue2.cjs.map +1 -0
  9. package/dist/PrismicEmbed.vue2.js +5 -0
  10. package/dist/PrismicEmbed.vue2.js.map +1 -0
  11. package/dist/PrismicImage.vue.cjs +84 -0
  12. package/dist/PrismicImage.vue.cjs.map +1 -0
  13. package/dist/PrismicImage.vue.d.ts +224 -0
  14. package/dist/PrismicImage.vue.js +85 -0
  15. package/dist/PrismicImage.vue.js.map +1 -0
  16. package/dist/PrismicImage.vue2.cjs +4 -0
  17. package/dist/PrismicImage.vue2.cjs.map +1 -0
  18. package/dist/PrismicImage.vue2.js +5 -0
  19. package/dist/PrismicImage.vue2.js.map +1 -0
  20. package/dist/PrismicLink.vue.cjs +100 -0
  21. package/dist/PrismicLink.vue.cjs.map +1 -0
  22. package/dist/PrismicLink.vue.d.ts +278 -0
  23. package/dist/PrismicLink.vue.js +101 -0
  24. package/dist/PrismicLink.vue.js.map +1 -0
  25. package/dist/PrismicLink.vue2.cjs +4 -0
  26. package/dist/PrismicLink.vue2.cjs.map +1 -0
  27. package/dist/PrismicLink.vue2.js +5 -0
  28. package/dist/PrismicLink.vue2.js.map +1 -0
  29. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue.cjs +90 -0
  30. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue.cjs.map +1 -0
  31. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue.d.ts +7 -0
  32. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue.js +91 -0
  33. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue.js.map +1 -0
  34. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue2.cjs +4 -0
  35. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue2.cjs.map +1 -0
  36. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue2.js +5 -0
  37. package/dist/PrismicRichText/DeprecatedPrismicRichText.vue2.js.map +1 -0
  38. package/dist/PrismicRichText/PrismicRichText.vue.cjs +85 -0
  39. package/dist/PrismicRichText/PrismicRichText.vue.cjs.map +1 -0
  40. package/dist/PrismicRichText/PrismicRichText.vue.d.ts +57 -0
  41. package/dist/PrismicRichText/PrismicRichText.vue.js +86 -0
  42. package/dist/PrismicRichText/PrismicRichText.vue.js.map +1 -0
  43. package/dist/PrismicRichText/PrismicRichText.vue2.cjs +4 -0
  44. package/dist/PrismicRichText/PrismicRichText.vue2.cjs.map +1 -0
  45. package/dist/PrismicRichText/PrismicRichText.vue2.js +5 -0
  46. package/dist/PrismicRichText/PrismicRichText.vue2.js.map +1 -0
  47. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue.cjs +133 -0
  48. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue.cjs.map +1 -0
  49. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue.d.ts +37 -0
  50. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue.js +134 -0
  51. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue.js.map +1 -0
  52. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue2.cjs +4 -0
  53. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue2.cjs.map +1 -0
  54. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue2.js +5 -0
  55. package/dist/PrismicRichText/PrismicRichTextDefaultComponent.vue2.js.map +1 -0
  56. package/dist/PrismicRichText/PrismicRichTextSerialize.vue.cjs +47 -0
  57. package/dist/PrismicRichText/PrismicRichTextSerialize.vue.cjs.map +1 -0
  58. package/dist/PrismicRichText/PrismicRichTextSerialize.vue.d.ts +10 -0
  59. package/dist/PrismicRichText/PrismicRichTextSerialize.vue.js +48 -0
  60. package/dist/PrismicRichText/PrismicRichTextSerialize.vue.js.map +1 -0
  61. package/dist/PrismicRichText/PrismicRichTextSerialize.vue2.cjs +4 -0
  62. package/dist/PrismicRichText/PrismicRichTextSerialize.vue2.cjs.map +1 -0
  63. package/dist/PrismicRichText/PrismicRichTextSerialize.vue2.js +5 -0
  64. package/dist/PrismicRichText/PrismicRichTextSerialize.vue2.js.map +1 -0
  65. package/dist/PrismicRichText/getRichTextComponentProps.cjs +10 -0
  66. package/dist/PrismicRichText/getRichTextComponentProps.cjs.map +1 -0
  67. package/dist/PrismicRichText/getRichTextComponentProps.d.ts +49 -0
  68. package/dist/PrismicRichText/getRichTextComponentProps.js +10 -0
  69. package/dist/PrismicRichText/getRichTextComponentProps.js.map +1 -0
  70. package/dist/PrismicRichText/index.d.ts +2 -0
  71. package/dist/PrismicRichText/types.d.ts +22 -0
  72. package/dist/PrismicText.vue.cjs +43 -0
  73. package/dist/PrismicText.vue.cjs.map +1 -0
  74. package/dist/PrismicText.vue.d.ts +31 -0
  75. package/dist/PrismicText.vue.js +44 -0
  76. package/dist/PrismicText.vue.js.map +1 -0
  77. package/dist/PrismicText.vue2.cjs +4 -0
  78. package/dist/PrismicText.vue2.cjs.map +1 -0
  79. package/dist/PrismicText.vue2.js +5 -0
  80. package/dist/PrismicText.vue2.js.map +1 -0
  81. package/dist/SliceZone/SliceZone.vue.cjs +63 -0
  82. package/dist/SliceZone/SliceZone.vue.cjs.map +1 -0
  83. package/dist/SliceZone/SliceZone.vue.d.ts +40 -0
  84. package/dist/SliceZone/SliceZone.vue.js +64 -0
  85. package/dist/SliceZone/SliceZone.vue.js.map +1 -0
  86. package/dist/SliceZone/SliceZone.vue2.cjs +4 -0
  87. package/dist/SliceZone/SliceZone.vue2.cjs.map +1 -0
  88. package/dist/SliceZone/SliceZone.vue2.js +5 -0
  89. package/dist/SliceZone/SliceZone.vue2.js.map +1 -0
  90. package/dist/SliceZone/TODOSliceComponent.cjs +29 -0
  91. package/dist/SliceZone/TODOSliceComponent.cjs.map +1 -0
  92. package/dist/SliceZone/TODOSliceComponent.d.ts +9 -0
  93. package/dist/SliceZone/TODOSliceComponent.js +29 -0
  94. package/dist/SliceZone/TODOSliceComponent.js.map +1 -0
  95. package/dist/SliceZone/defineSliceZoneComponents.cjs +14 -0
  96. package/dist/SliceZone/defineSliceZoneComponents.cjs.map +1 -0
  97. package/dist/SliceZone/defineSliceZoneComponents.d.ts +36 -0
  98. package/dist/SliceZone/defineSliceZoneComponents.js +14 -0
  99. package/dist/SliceZone/defineSliceZoneComponents.js.map +1 -0
  100. package/dist/SliceZone/getSliceComponentProps.cjs +22 -0
  101. package/dist/SliceZone/getSliceComponentProps.cjs.map +1 -0
  102. package/dist/SliceZone/getSliceComponentProps.d.ts +66 -0
  103. package/dist/SliceZone/getSliceComponentProps.js +22 -0
  104. package/dist/SliceZone/getSliceComponentProps.js.map +1 -0
  105. package/dist/SliceZone/index.d.ts +4 -0
  106. package/dist/SliceZone/types.d.ts +97 -0
  107. package/dist/createPrismic.cjs +17 -50
  108. package/dist/createPrismic.cjs.map +1 -1
  109. package/dist/createPrismic.d.ts +10 -0
  110. package/dist/createPrismic.js +16 -27
  111. package/dist/createPrismic.js.map +1 -1
  112. package/dist/index.cjs +21 -40
  113. package/dist/index.cjs.map +1 -1
  114. package/dist/index.d.ts +19 -9
  115. package/dist/index.js +19 -38
  116. package/dist/index.js.map +1 -1
  117. package/dist/lib/Wrapper.vue.cjs +20 -0
  118. package/dist/lib/Wrapper.vue.cjs.map +1 -0
  119. package/dist/lib/Wrapper.vue.d.ts +34 -0
  120. package/dist/lib/Wrapper.vue.js +21 -0
  121. package/dist/lib/Wrapper.vue.js.map +1 -0
  122. package/dist/lib/Wrapper.vue2.cjs +4 -0
  123. package/dist/lib/Wrapper.vue2.cjs.map +1 -0
  124. package/dist/lib/Wrapper.vue2.js +5 -0
  125. package/dist/lib/Wrapper.vue2.js.map +1 -0
  126. package/dist/lib/devMsg.cjs +8 -0
  127. package/dist/lib/devMsg.cjs.map +1 -0
  128. package/dist/lib/devMsg.d.ts +16 -0
  129. package/dist/lib/devMsg.js +8 -0
  130. package/dist/lib/devMsg.js.map +1 -0
  131. package/dist/lib/isInternalURL.cjs.map +1 -1
  132. package/dist/lib/isInternalURL.js.map +1 -1
  133. package/dist/package.json.cjs +5 -0
  134. package/dist/package.json.cjs.map +1 -0
  135. package/dist/package.json.js +5 -0
  136. package/dist/package.json.js.map +1 -0
  137. package/dist/types.d.ts +42 -58
  138. package/dist/usePrismic.cjs +3 -2
  139. package/dist/usePrismic.cjs.map +1 -1
  140. package/dist/usePrismic.d.ts +13 -5
  141. package/dist/usePrismic.js +2 -1
  142. package/dist/usePrismic.js.map +1 -1
  143. package/package.json +32 -35
  144. package/src/PrismicEmbed.vue +42 -0
  145. package/src/PrismicImage.vue +160 -0
  146. package/src/PrismicLink.vue +191 -0
  147. package/src/PrismicRichText/DeprecatedPrismicRichText.vue +130 -0
  148. package/src/PrismicRichText/PrismicRichText.vue +157 -0
  149. package/src/PrismicRichText/PrismicRichTextDefaultComponent.vue +63 -0
  150. package/src/PrismicRichText/PrismicRichTextSerialize.vue +52 -0
  151. package/src/PrismicRichText/getRichTextComponentProps.ts +63 -0
  152. package/src/PrismicRichText/index.ts +3 -0
  153. package/src/PrismicRichText/types.ts +37 -0
  154. package/src/PrismicText.vue +63 -0
  155. package/src/SliceZone/SliceZone.vue +113 -0
  156. package/src/SliceZone/TODOSliceComponent.ts +49 -0
  157. package/src/SliceZone/defineSliceZoneComponents.ts +67 -0
  158. package/src/SliceZone/getSliceComponentProps.ts +98 -0
  159. package/src/SliceZone/index.ts +13 -0
  160. package/src/SliceZone/types.ts +163 -0
  161. package/src/createPrismic.ts +54 -53
  162. package/src/index.ts +33 -58
  163. package/src/lib/Wrapper.vue +22 -0
  164. package/src/lib/devMsg.ts +20 -0
  165. package/src/lib/isInternalURL.ts +4 -4
  166. package/src/types.ts +91 -109
  167. package/src/usePrismic.ts +16 -9
  168. package/dist/components/PrismicEmbed.cjs +0 -36
  169. package/dist/components/PrismicEmbed.cjs.map +0 -1
  170. package/dist/components/PrismicEmbed.d.ts +0 -59
  171. package/dist/components/PrismicEmbed.js +0 -36
  172. package/dist/components/PrismicEmbed.js.map +0 -1
  173. package/dist/components/PrismicImage.cjs +0 -122
  174. package/dist/components/PrismicImage.cjs.map +0 -1
  175. package/dist/components/PrismicImage.d.ts +0 -163
  176. package/dist/components/PrismicImage.js +0 -122
  177. package/dist/components/PrismicImage.js.map +0 -1
  178. package/dist/components/PrismicLink.cjs +0 -120
  179. package/dist/components/PrismicLink.cjs.map +0 -1
  180. package/dist/components/PrismicLink.d.ts +0 -196
  181. package/dist/components/PrismicLink.js +0 -120
  182. package/dist/components/PrismicLink.js.map +0 -1
  183. package/dist/components/PrismicRichText.cjs +0 -108
  184. package/dist/components/PrismicRichText.cjs.map +0 -1
  185. package/dist/components/PrismicRichText.d.ts +0 -161
  186. package/dist/components/PrismicRichText.js +0 -108
  187. package/dist/components/PrismicRichText.js.map +0 -1
  188. package/dist/components/PrismicText.cjs +0 -57
  189. package/dist/components/PrismicText.cjs.map +0 -1
  190. package/dist/components/PrismicText.d.ts +0 -119
  191. package/dist/components/PrismicText.js +0 -57
  192. package/dist/components/PrismicText.js.map +0 -1
  193. package/dist/components/SliceZone.cjs +0 -156
  194. package/dist/components/SliceZone.cjs.map +0 -1
  195. package/dist/components/SliceZone.d.ts +0 -375
  196. package/dist/components/SliceZone.js +0 -156
  197. package/dist/components/SliceZone.js.map +0 -1
  198. package/dist/components/index.d.ts +0 -12
  199. package/dist/composables.cjs +0 -40
  200. package/dist/composables.cjs.map +0 -1
  201. package/dist/composables.d.ts +0 -330
  202. package/dist/composables.js +0 -40
  203. package/dist/composables.js.map +0 -1
  204. package/dist/globalExtensions.d.ts +0 -11
  205. package/dist/injectionSymbols.cjs +0 -5
  206. package/dist/injectionSymbols.cjs.map +0 -1
  207. package/dist/injectionSymbols.d.ts +0 -9
  208. package/dist/injectionSymbols.js +0 -5
  209. package/dist/injectionSymbols.js.map +0 -1
  210. package/dist/lib/__PRODUCTION__.cjs +0 -8
  211. package/dist/lib/__PRODUCTION__.cjs.map +0 -1
  212. package/dist/lib/__PRODUCTION__.d.ts +0 -7
  213. package/dist/lib/__PRODUCTION__.js +0 -8
  214. package/dist/lib/__PRODUCTION__.js.map +0 -1
  215. package/dist/lib/getSlots.cjs +0 -19
  216. package/dist/lib/getSlots.cjs.map +0 -1
  217. package/dist/lib/getSlots.d.ts +0 -14
  218. package/dist/lib/getSlots.js +0 -19
  219. package/dist/lib/getSlots.js.map +0 -1
  220. package/dist/lib/simplyResolveComponent.cjs +0 -8
  221. package/dist/lib/simplyResolveComponent.cjs.map +0 -1
  222. package/dist/lib/simplyResolveComponent.d.ts +0 -12
  223. package/dist/lib/simplyResolveComponent.js +0 -8
  224. package/dist/lib/simplyResolveComponent.js.map +0 -1
  225. package/dist/useStatefulPrismicClientMethod.cjs +0 -39
  226. package/dist/useStatefulPrismicClientMethod.cjs.map +0 -1
  227. package/dist/useStatefulPrismicClientMethod.d.ts +0 -64
  228. package/dist/useStatefulPrismicClientMethod.js +0 -39
  229. package/dist/useStatefulPrismicClientMethod.js.map +0 -1
  230. package/src/components/PrismicEmbed.ts +0 -91
  231. package/src/components/PrismicImage.ts +0 -309
  232. package/src/components/PrismicLink.ts +0 -326
  233. package/src/components/PrismicRichText.ts +0 -282
  234. package/src/components/PrismicText.ts +0 -167
  235. package/src/components/SliceZone.ts +0 -619
  236. package/src/components/index.ts +0 -46
  237. package/src/composables.ts +0 -474
  238. package/src/globalExtensions.ts +0 -12
  239. package/src/injectionSymbols.ts +0 -17
  240. package/src/lib/__PRODUCTION__.ts +0 -12
  241. package/src/lib/getSlots.ts +0 -37
  242. package/src/lib/simplyResolveComponent.ts +0 -23
  243. package/src/useStatefulPrismicClientMethod.ts +0 -156
  244. package/vetur/attributes.json +0 -113
  245. package/vetur/tags.json +0 -60
@@ -0,0 +1,191 @@
1
+ <script lang="ts" setup>
2
+ import type { AsLinkAttrsConfig } from "@prismicio/client"
3
+ import {
4
+ type LinkField,
5
+ type LinkResolverFunction,
6
+ type PrismicDocument,
7
+ asLinkAttrs,
8
+ } from "@prismicio/client"
9
+ import { DEV } from "esm-env"
10
+ import { computed, watchEffect } from "vue"
11
+
12
+ import { devMsg } from "./lib/devMsg"
13
+ import { isInternalURL } from "./lib/isInternalURL"
14
+
15
+ import type { ComponentOrTagName } from "./types"
16
+
17
+ import { usePrismic } from "./usePrismic"
18
+
19
+ /**
20
+ * The default component rendered for internal URLs.
21
+ */
22
+ const defaultInternalComponent = "router-link"
23
+
24
+ /**
25
+ * The default component rendered for external URLs.
26
+ */
27
+ const defaultExternalComponent = "a"
28
+
29
+ /**
30
+ * The default rel attribute rendered for external URLs.
31
+ */
32
+ const defaultExternalRelAttribute = "noreferrer"
33
+
34
+ /**
35
+ * Props for `<PrismicLink />`.
36
+ */
37
+ export type PrismicLinkProps = {
38
+ /**
39
+ * A link resolver function used to resolve links when not using the route
40
+ * resolver parameter with `@prismicio/client`.
41
+ *
42
+ * @defaultValue The link resolver provided to `@prismicio/vue` plugin if configured.
43
+ *
44
+ * @see Link resolver documentation {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver#link-resolver}
45
+ */
46
+ linkResolver?: LinkResolverFunction
47
+
48
+ /**
49
+ * The `rel` attribute for the link. By default, `"noreferrer"` is provided if
50
+ * the link's URL is external. This prop can be provided a function to use the
51
+ * link's metadata to determine the `rel` value.
52
+ *
53
+ * @defaultValue The one provided to `@prismicio/vue` plugin if configured.
54
+ */
55
+ rel?: string | AsLinkAttrsConfig["rel"]
56
+
57
+ /**
58
+ * An HTML tag name or a component used to render internal links.
59
+ *
60
+ * @remarks
61
+ * HTML tag names will be rendered using the anchor tag interface (`href`,
62
+ * `target`, and `rel` attributes).
63
+ * @remarks
64
+ * Components will be rendered using Vue Router {@link RouterLink} interface
65
+ * (`to` props).
66
+ *
67
+ * @defaultValue The one provided to `@prismicio/vue` plugin if configured, {@link RouterLink} otherwise.
68
+ */
69
+ internalComponent?: ComponentOrTagName
70
+
71
+ /**
72
+ * An HTML tag name or a component used to render external links.
73
+ *
74
+ * @remarks
75
+ * HTML tag names will be rendered using the anchor tag interface (`href`,
76
+ * `target`, and `rel` attributes).
77
+ * @remarks
78
+ * Components will be rendered using Vue Router {@link RouterLink} interface
79
+ * (`to` props).
80
+ *
81
+ * @defaultValue The one provided to `@prismicio/vue` plugin if configured, `"a"` otherwise.
82
+ */
83
+ externalComponent?: ComponentOrTagName
84
+ } & (
85
+ | {
86
+ /**
87
+ * The Prismic link field to render.
88
+ */
89
+ field: LinkField
90
+ document?: never
91
+ }
92
+ | {
93
+ /**
94
+ * The Prismic document to render as a link.
95
+ */
96
+ document: PrismicDocument
97
+ field?: never
98
+ }
99
+ )
100
+
101
+ const props = defineProps<PrismicLinkProps>()
102
+ defineOptions({ name: "PrismicLink" })
103
+
104
+ const { options } = usePrismic()
105
+
106
+ if (DEV) {
107
+ watchEffect(() => {
108
+ if (props.field) {
109
+ if (!props.field.link_type) {
110
+ console.error(
111
+ `[PrismicLink] This "field" prop value caused an error to be thrown.\n`,
112
+ props.field,
113
+ )
114
+ throw new Error(
115
+ `[PrismicLink] The provided field is missing required properties to properly render a link. The link will not render. For more details, see ${devMsg(
116
+ "missing-link-properties",
117
+ )}`,
118
+ )
119
+ } else if (
120
+ ("text" in props.field
121
+ ? Object.keys(props.field).length > 2
122
+ : Object.keys(props.field).length > 1) &&
123
+ !("url" in props.field || "uid" in props.field || "id" in props.field)
124
+ ) {
125
+ console.warn(
126
+ `[PrismicLink] The provided field is missing required properties to properly render a link. The link may not render correctly. For more details, see ${devMsg(
127
+ "missing-link-properties",
128
+ )}`,
129
+ props.field,
130
+ )
131
+ }
132
+ } else if (props.document) {
133
+ if (!("url" in props.document || "id" in props.document)) {
134
+ console.warn(
135
+ `[PrismicLink] The provided document is missing required properties to properly render a link. The link may not render correctly. For more details, see ${devMsg(
136
+ "missing-link-properties",
137
+ )}`,
138
+ props.document,
139
+ )
140
+ }
141
+ }
142
+ })
143
+ }
144
+
145
+ const rawAttrs = computed(() => {
146
+ return asLinkAttrs(props.field || props.document, {
147
+ linkResolver: props.linkResolver || options.linkResolver,
148
+ rel(args) {
149
+ const maybeRel = props.rel || options.components?.linkRel
150
+ if (maybeRel) {
151
+ return typeof maybeRel === "function" ? maybeRel(args) : maybeRel
152
+ }
153
+
154
+ return args.isExternal ? defaultExternalRelAttribute : undefined
155
+ },
156
+ })
157
+ })
158
+
159
+ const component = computed(() => {
160
+ return isInternalURL(rawAttrs.value.href || "")
161
+ ? props.internalComponent ||
162
+ options.components?.linkInternalComponent ||
163
+ defaultInternalComponent
164
+ : props.externalComponent ||
165
+ options.components?.linkExternalComponent ||
166
+ defaultExternalComponent
167
+ })
168
+
169
+ // Match Vue Router's `<RouterLink />` interface unless the component is an anchor tag.
170
+ const attrs = computed(() => {
171
+ return component.value === "a"
172
+ ? {
173
+ href: rawAttrs.value.href,
174
+ target: rawAttrs.value.target,
175
+ rel: rawAttrs.value.rel,
176
+ }
177
+ : {
178
+ to: rawAttrs.value.href,
179
+ target: rawAttrs.value.target,
180
+ rel: rawAttrs.value.rel,
181
+ }
182
+ })
183
+ </script>
184
+
185
+ <template>
186
+ <component :is="component" v-bind="attrs">
187
+ <slot>
188
+ {{ props.field && "text" in props.field ? props.field.text : undefined }}
189
+ </slot>
190
+ </component>
191
+ </template>
@@ -0,0 +1,130 @@
1
+ <script lang="ts" setup>
2
+ // TODO: Remove in v6
3
+ import { asHTML, isFilled } from "@prismicio/client"
4
+ import { DEV } from "esm-env"
5
+ import type { Component } from "vue"
6
+ import {
7
+ computed,
8
+ inject,
9
+ nextTick,
10
+ onBeforeUnmount,
11
+ onMounted,
12
+ ref,
13
+ watch,
14
+ } from "vue"
15
+ import { routerKey } from "vue-router"
16
+
17
+ import { devMsg } from "../lib/devMsg"
18
+ import { isInternalURL } from "../lib/isInternalURL"
19
+
20
+ import { usePrismic } from "../usePrismic"
21
+
22
+ import type { PrismicRichTextProps } from "./PrismicRichText.vue"
23
+
24
+ /**
25
+ * The default component rendered to wrap the HTML output.
26
+ */
27
+ const defaultWrapper = "div"
28
+
29
+ const props = defineProps<
30
+ Pick<
31
+ PrismicRichTextProps,
32
+ "field" | "linkResolver" | "serializer" | "wrapper"
33
+ > & { fallback?: string }
34
+ >()
35
+ defineOptions({ name: "DeprecatedPrismicRichText" })
36
+
37
+ const { options } = usePrismic()
38
+
39
+ if (DEV) {
40
+ onMounted(() => {
41
+ console.warn(
42
+ `[PrismicRichText] You're using the deprecated version of \`<PrismicRichText>\` because either the \`serializer\` prop or the plugin \`richTextSerializer\` option were provided. This API will be removed in a future major. For more details, see ${devMsg(
43
+ "html-serialization-is-deprecated-with-prismic-rich-text.md",
44
+ )}`,
45
+ )
46
+ })
47
+ }
48
+
49
+ const html = computed(() => {
50
+ if (!isFilled.richText(props.field)) {
51
+ return props.fallback ?? ""
52
+ }
53
+
54
+ const linkResolver = props.linkResolver ?? options.linkResolver
55
+ const serializer = props.serializer ?? options.richTextSerializer
56
+
57
+ return asHTML(props.field, { linkResolver, serializer })
58
+ })
59
+
60
+ // Internal links handling
61
+ const root = ref<HTMLElement | Comment | Component | null>(null)
62
+
63
+ const maybeRouter = inject(routerKey, null)
64
+
65
+ type InternalLink = {
66
+ element: HTMLAnchorElement
67
+ listener: EventListener
68
+ }
69
+
70
+ let links: InternalLink[] = []
71
+
72
+ const navigate: EventListener = function (
73
+ this: { href: string },
74
+ event: Event,
75
+ ) {
76
+ event.preventDefault()
77
+ maybeRouter?.push(this.href)
78
+ }
79
+
80
+ const addListeners = () => {
81
+ const node: HTMLElement | Comment | null =
82
+ root.value && "$el" in root.value ? root.value.$el : root.value
83
+ if (node && "querySelectorAll" in node) {
84
+ // Get all internal link tags and add listeners on them
85
+ links = Array.from(node.querySelectorAll("a"))
86
+ .map((element) => {
87
+ const href = element.getAttribute("href")
88
+
89
+ if (href && isInternalURL(href)) {
90
+ const listener = navigate.bind({ href })
91
+ element.addEventListener("click", listener)
92
+
93
+ return { element, listener }
94
+ } else {
95
+ return false
96
+ }
97
+ })
98
+ .filter((link): link is InternalLink => link as boolean)
99
+ }
100
+ }
101
+
102
+ const removeListeners = () => {
103
+ links.forEach(({ element, listener }) =>
104
+ element.removeEventListener("click", listener),
105
+ )
106
+ links = []
107
+ }
108
+
109
+ watch(
110
+ html,
111
+ () => {
112
+ removeListeners()
113
+ nextTick(addListeners)
114
+ },
115
+ { immediate: true },
116
+ )
117
+
118
+ onBeforeUnmount(() => {
119
+ removeListeners()
120
+ })
121
+ </script>
122
+
123
+ <template>
124
+ <component
125
+ v-if="isFilled.richText(field) || fallback"
126
+ ref="root"
127
+ :is="wrapper || defaultWrapper"
128
+ v-html="html"
129
+ />
130
+ </template>
@@ -0,0 +1,157 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ type HTMLRichTextFunctionSerializer,
4
+ type HTMLRichTextMapSerializer,
5
+ type LinkResolverFunction,
6
+ type RichTextField,
7
+ isFilled,
8
+ } from "@prismicio/client"
9
+ import { asTree } from "@prismicio/client/richtext"
10
+ import { DEV } from "esm-env"
11
+ import { computed, watchEffect } from "vue"
12
+
13
+ import Wrapper from "../lib/Wrapper.vue"
14
+
15
+ import type { ComponentOrTagName } from "../types"
16
+ import type { VueRichTextSerializer } from "./types"
17
+
18
+ import { usePrismic } from "../usePrismic"
19
+
20
+ import DeprecatedPrismicRichText from "./DeprecatedPrismicRichText.vue"
21
+ import PrismicRichTextSerialize from "./PrismicRichTextSerialize.vue"
22
+
23
+ /**
24
+ * Props for `<PrismicRichText />`.
25
+ */
26
+ export type PrismicRichTextProps = {
27
+ /**
28
+ * The Prismic rich text or title field to render.
29
+ */
30
+ field: RichTextField | null | undefined
31
+
32
+ /**
33
+ * The value to be rendered when the field is empty. If a fallback is not
34
+ * given, `null` (nothing) will be rendered.
35
+ */
36
+ fallback?: ComponentOrTagName
37
+
38
+ /**
39
+ * An object that maps a rich text block type to a Vue component.
40
+ *
41
+ * @example
42
+ *
43
+ * ```javascript
44
+ * {
45
+ * heading1: Heading1,
46
+ * }
47
+ * ```
48
+ */
49
+ components?: VueRichTextSerializer
50
+
51
+ /**
52
+ * A link resolver function used to resolve link when not using the route
53
+ * resolver parameter with `@prismicio/client`.
54
+ *
55
+ * @defaultValue The link resolver provided to `@prismicio/vue` plugin if configured.
56
+ *
57
+ * @see Link resolver documentation {@link https://prismic.io/docs/core-concepts/link-resolver-route-resolver#link-resolver}
58
+ */
59
+ linkResolver?: LinkResolverFunction
60
+
61
+ /**
62
+ * An HTML serializer to customize the way rich text fields are rendered.
63
+ *
64
+ * @deprecated Use `components` instead.
65
+ *
66
+ * @defaultValue The HTML serializer provided to `@prismicio/vue` plugin if configured.
67
+ *
68
+ * @see HTML serializer documentation {@link https://prismic.io/docs/core-concepts/html-serializer}
69
+ */
70
+ // TODO: Remove in v6
71
+ serializer?: HTMLRichTextFunctionSerializer | HTMLRichTextMapSerializer
72
+
73
+ /**
74
+ * An HTML tag name or a component used to wrap the output. `<PrismicText />`
75
+ * is not wrapped by default.
76
+ *
77
+ * @defaultValue `"template"` (no wrapper)
78
+ */
79
+ wrapper?: ComponentOrTagName
80
+ }
81
+
82
+ const props = defineProps<PrismicRichTextProps>()
83
+ defineOptions({ name: "PrismicRichText" })
84
+
85
+ const { options } = usePrismic()
86
+
87
+ const resolvedComponents = computed(() => {
88
+ return props.components || options.components?.richTextComponents
89
+ })
90
+
91
+ const resolvedLinkResolver = computed(() => {
92
+ return props.linkResolver || options.linkResolver
93
+ })
94
+
95
+ const children = computed(() => {
96
+ return asTree(props.field || []).children
97
+ })
98
+
99
+ const isModern = computed(() => {
100
+ // Explicit components prop
101
+ if (props.components) {
102
+ return true
103
+ }
104
+
105
+ // Explicit serializer prop
106
+ if (props.serializer) {
107
+ return false
108
+ }
109
+
110
+ // Global components option
111
+ if (options.components?.richTextComponents) {
112
+ return true
113
+ }
114
+
115
+ // Global serializer option
116
+ if (options.richTextSerializer) {
117
+ return false
118
+ }
119
+
120
+ // Default to modern
121
+ return true
122
+ })
123
+
124
+ if (DEV) {
125
+ watchEffect(() => {
126
+ // TODO: Remove in v6
127
+ if (props.components && props.serializer) {
128
+ console.warn(
129
+ `[PrismicRichText] Only one of "components" or "serializer" (deprecated) props can be provided. You can resolve this warning by removing either the "components" or "serializer" prop. "components" will be used in this case.`,
130
+ )
131
+ }
132
+ })
133
+ }
134
+ </script>
135
+
136
+ <template>
137
+ <Wrapper
138
+ v-if="isModern && (isFilled.richText(field) || fallback)"
139
+ :wrapper="wrapper"
140
+ >
141
+ <PrismicRichTextSerialize
142
+ v-if="children.length"
143
+ :children="children"
144
+ :components="resolvedComponents"
145
+ :link-resolver="resolvedLinkResolver"
146
+ />
147
+ <component v-else :is="fallback" />
148
+ </Wrapper>
149
+ <DeprecatedPrismicRichText
150
+ v-else-if="!isModern"
151
+ :field="field"
152
+ :fallback="typeof fallback === 'string' ? fallback : undefined"
153
+ :link-resolver="linkResolver"
154
+ :serializer="serializer"
155
+ :wrapper="wrapper"
156
+ />
157
+ </template>
@@ -0,0 +1,63 @@
1
+ <script lang="ts" setup>
2
+ import type { LinkResolverFunction } from "@prismicio/client"
3
+ import { computed } from "vue"
4
+
5
+ import type { RichTextComponentProps } from "./types"
6
+
7
+ import PrismicEmbed from "../PrismicEmbed.vue"
8
+ import PrismicImage from "../PrismicImage.vue"
9
+ import PrismicLink from "../PrismicLink.vue"
10
+
11
+ const props = defineProps<
12
+ RichTextComponentProps & {
13
+ linkResolver?: LinkResolverFunction
14
+ }
15
+ >()
16
+ defineOptions({ name: "PrismicRichTextDefaultComponent" })
17
+
18
+ const dir = computed(() => {
19
+ return "direction" in props.node && props.node.direction === "rtl"
20
+ ? "rtl"
21
+ : undefined
22
+ })
23
+ </script>
24
+
25
+ <template>
26
+ <h1 v-if="node.type === 'heading1'" :dir="dir"><slot /></h1>
27
+ <h2 v-else-if="node.type === 'heading2'" :dir="dir"><slot /></h2>
28
+ <h3 v-else-if="node.type === 'heading3'" :dir="dir"><slot /></h3>
29
+ <h4 v-else-if="node.type === 'heading4'" :dir="dir"><slot /></h4>
30
+ <h5 v-else-if="node.type === 'heading5'" :dir="dir"><slot /></h5>
31
+ <h6 v-else-if="node.type === 'heading6'" :dir="dir"><slot /></h6>
32
+ <p v-else-if="node.type === 'paragraph'" :dir="dir"><slot /></p>
33
+ <pre v-else-if="node.type === 'preformatted'"><slot /></pre>
34
+ <strong v-else-if="node.type === 'strong'"><slot /></strong>
35
+ <em v-else-if="node.type === 'em'"><slot /></em>
36
+ <li v-else-if="node.type === 'list-item'" :dir="dir"><slot /></li>
37
+ <li v-else-if="node.type === 'o-list-item'" :dir="dir"><slot /></li>
38
+ <ul v-else-if="node.type === 'group-list-item'">
39
+ <slot />
40
+ </ul>
41
+ <ol v-else-if="node.type === 'group-o-list-item'">
42
+ <slot />
43
+ </ol>
44
+ <p class="block-img" v-else-if="node.type === 'image'">
45
+ <PrismicLink v-if="node.linkTo" :field="node.linkTo"
46
+ ><PrismicImage :field="node"
47
+ /></PrismicLink>
48
+ <PrismicImage v-else :field="node" />
49
+ </p>
50
+ <PrismicEmbed v-else-if="node.type === 'embed'" :field="node.oembed" />
51
+ <PrismicLink
52
+ v-else-if="node.type === 'hyperlink'"
53
+ :field="node.data"
54
+ :link-resolver="linkResolver"
55
+ ><slot
56
+ /></PrismicLink>
57
+ <span v-else-if="node.type === 'label'" :class="node.data.label"
58
+ ><slot
59
+ /></span>
60
+ <template v-else v-for="(line, index) in node.text.split('\n')" :key="line"
61
+ ><br v-if="index > 0" />{{ line }}</template
62
+ >
63
+ </template>
@@ -0,0 +1,52 @@
1
+ <script lang="ts" setup>
2
+ import type { LinkResolverFunction } from "@prismicio/client"
3
+ import type { asTree } from "@prismicio/client/richtext"
4
+
5
+ import type { VueRichTextSerializer } from "./types"
6
+
7
+ import PrismicRichTextDefaultComponent from "./PrismicRichTextDefaultComponent.vue"
8
+
9
+ const CHILD_TYPE_RENAMES = {
10
+ "list-item": "listItem",
11
+ "o-list-item": "oListItem",
12
+ "group-list-item": "list",
13
+ "group-o-list-item": "oList",
14
+ } as const
15
+
16
+ type PrismicRichTextSerializeProps = {
17
+ components?: VueRichTextSerializer
18
+ children: ReturnType<typeof asTree>["children"]
19
+ linkResolver?: LinkResolverFunction
20
+ }
21
+
22
+ const props = defineProps<PrismicRichTextSerializeProps>()
23
+ defineOptions({ name: "PrismicRichTextSerialize" })
24
+
25
+ function getComponent(child: ReturnType<typeof asTree>["children"][number]) {
26
+ return (
27
+ props.components?.[
28
+ CHILD_TYPE_RENAMES[child.type as keyof typeof CHILD_TYPE_RENAMES] ||
29
+ (child.type as keyof typeof props.components)
30
+ ] || PrismicRichTextDefaultComponent
31
+ )
32
+ }
33
+ </script>
34
+
35
+ <template>
36
+ <component
37
+ v-for="child in props.children"
38
+ :key="JSON.stringify(child)"
39
+ :is="getComponent(child)"
40
+ :node="child.node"
41
+ :link-resolver="
42
+ getComponent(child) === PrismicRichTextDefaultComponent
43
+ ? props.linkResolver
44
+ : undefined
45
+ "
46
+ ><PrismicRichTextSerialize
47
+ v-if="child.children.length"
48
+ :children="child.children"
49
+ :components="components"
50
+ :link-resolver="linkResolver"
51
+ /></component>
52
+ </template>
@@ -0,0 +1,63 @@
1
+ import type { RTAnyNode } from "@prismicio/client"
2
+ import type { PropType } from "vue"
3
+
4
+ import type { RichTextComponentProps } from "./types"
5
+
6
+ /**
7
+ * Native Vue props for a component rendering nodes from a Prismic rich text
8
+ * field using the `<PrismicRichText />` component.
9
+ *
10
+ * @typeParam TRTNode - The type of rich text node(s) this component handles
11
+ */
12
+ type DefineComponentRichTextComponentProps<
13
+ TRTNode extends RTAnyNode = RTAnyNode,
14
+ > = {
15
+ node: {
16
+ type: PropType<RichTextComponentProps<TRTNode>["node"]>
17
+ required: true
18
+ }
19
+ }
20
+
21
+ /**
22
+ * Gets native Vue props for a component rendering nodes from a Prismic rich
23
+ * text field using the `<PrismicRichText />` component.
24
+ *
25
+ * Props are: `["node"]`
26
+ *
27
+ * @example
28
+ *
29
+ * ```javascript
30
+ * // Defining a new rich text component
31
+ * import { getRichTextComponentProps } from "@prismicio/vue"
32
+ *
33
+ * defineProps(getRichTextComponentProps())
34
+ * ```
35
+ *
36
+ * @example
37
+ *
38
+ * ```typescript
39
+ * // Defining a new rich text component for a specific node type
40
+ * import { getRichTextComponentProps } from "@prismicio/vue"
41
+ *
42
+ * defineProps(getRichTextComponentProps("heading1"))
43
+ * ```
44
+ *
45
+ * @typeParam TRTType - The type of rich text node(s) this component handles
46
+ *
47
+ * @param type - The type of rich text node this component handles
48
+ *
49
+ * @returns Props object to use with `defineProps()`
50
+ */
51
+ export const getRichTextComponentProps = <TRTType extends RTAnyNode["type"]>(
52
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
53
+ type?: TRTType,
54
+ ): DefineComponentRichTextComponentProps<
55
+ Extract<RTAnyNode, { type: TRTType }>
56
+ > => ({
57
+ node: {
58
+ type: Object as PropType<
59
+ RichTextComponentProps<Extract<RTAnyNode, { type: TRTType }>>["node"]
60
+ >,
61
+ required: true,
62
+ },
63
+ })
@@ -0,0 +1,3 @@
1
+ export { getRichTextComponentProps } from "./getRichTextComponentProps"
2
+
3
+ export type { VueRichTextSerializer, RichTextComponentProps } from "./types"
@@ -0,0 +1,37 @@
1
+ import type { RTAnyNode, RichTextNodeType } from "@prismicio/client"
2
+ import type {
3
+ DefineComponent,
4
+ FunctionalComponent,
5
+ defineAsyncComponent,
6
+ } from "vue"
7
+
8
+ /**
9
+ * A map of Rich Text block types to Vue Components. It is used to render Rich
10
+ * Text or title fields.
11
+ *
12
+ * @see Templating Rich Text and title fields from Prismic {@link https://prismic.io/docs/rich-text}
13
+ */
14
+ export type VueRichTextSerializer = Partial<
15
+ Record<keyof typeof RichTextNodeType, VueRichTextComponent>
16
+ >
17
+
18
+ /**
19
+ * Props for a component rendering nodes from a Prismic rich text field.
20
+ */
21
+ export type RichTextComponentProps<TRTNode extends RTAnyNode = RTAnyNode> = {
22
+ node: TRTNode
23
+ }
24
+
25
+ /**
26
+ * A Vue component rendering a node from a Prismic rich text field.
27
+ *
28
+ * @typeParam TRTNode - The type of rich text node(s) this component handles
29
+ */
30
+ type VueRichTextComponent<TRTNode extends RTAnyNode = RTAnyNode> =
31
+ // For reference within TypeScript files when `*.vue` type cannot be inferred
32
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type, @typescript-eslint/no-explicit-any
33
+ | DefineComponent<{}, {}, any>
34
+ // Likewise, for reference with TypeScript files.
35
+ | ReturnType<typeof defineAsyncComponent>
36
+ | DefineComponent<RichTextComponentProps<TRTNode>>
37
+ | FunctionalComponent<RichTextComponentProps<TRTNode>>