@studio-fes/layer-strapi 0.1.5 → 0.2.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @studio-fes/layer-strapi
2
2
 
3
+ ## 0.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Moved NuxtLinkProps type inline for nuxt resolution issue
8
+
9
+ ## 0.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - Media renderer is now stable, added Anchor component and CraftLink renderer. Replaced StrapiRichText with external dependency `vue-strapi-blocks-renderer`
14
+
3
15
  ## 0.1.5
4
16
 
5
17
  ### Patch Changes
@@ -1,30 +1,24 @@
1
1
  import type { SeoMetaFragment } from '~/types/graphql-operations'
2
2
 
3
3
  export function useStrapiSEO(seoData?: MaybeRefOrGetter<SeoMetaFragment>) {
4
- const nuxtApp = useNuxtApp()
5
4
  const runtimeConfig = useRuntimeConfig()
6
5
  const nuxtImage = useImage()
7
6
 
8
- const seo = computed(() => {
9
- if (!seoData)
10
- return {}
7
+ if (!seoData) {
8
+ return
9
+ }
11
10
 
12
- const { metaTitle, metaDescription, metaImage, openGraph, metaRobots, keywords } = toValue(seoData)
11
+ const { metaTitle, metaDescription, metaImage, openGraph, metaRobots, keywords } = toValue(seoData)
13
12
 
14
- return {
15
- title: metaTitle,
16
- meta: [
17
- { name: 'description', content: metaDescription },
18
- { name: 'robots', content: metaRobots },
19
- { name: 'keywords', content: keywords },
20
- { property: `og:title`, content: openGraph?.ogTitle || metaTitle },
21
- { property: `og:description`, content: openGraph?.ogDescription || metaDescription },
22
- { property: `og:image`, content: nuxtImage(runtimeConfig.public.imageDomain + (openGraph?.ogImage || metaImage)?.url, { width: 1200, height: 630, quality: 60 }) },
23
- { property: `og:image:alt`, content: (openGraph?.ogImage || metaImage)?.alternativeText || metaTitle },
24
- { property: 'twitter:card', content: 'summary_large_image' },
25
- ],
26
- }
13
+ useSeoMeta({
14
+ title: metaTitle,
15
+ description: metaDescription,
16
+ ogImage: nuxtImage(runtimeConfig.public.imageDomain + (openGraph?.ogImage || metaImage)?.url, { width: 1200, height: 630, quality: 60 }),
17
+ ogTitle: openGraph?.ogTitle || metaTitle,
18
+ ogDescription: openGraph?.ogDescription || metaDescription,
19
+ ogImageAlt: (openGraph?.ogImage || metaImage)?.alternativeText || metaTitle,
20
+ twitterCard: 'summary_large_image',
21
+ robots: metaRobots,
22
+ keywords,
27
23
  })
28
-
29
- nuxtApp.runWithContext(() => useHead(seo.value))
30
24
  }
@@ -0,0 +1,5 @@
1
+ import { StrapiBlocks } from 'vue-strapi-blocks-renderer'
2
+
3
+ export default defineNuxtPlugin((nuxtApp) => {
4
+ nuxtApp.vueApp.component('StrapiBlocks', StrapiBlocks)
5
+ })
package/nuxt.config.ts CHANGED
@@ -7,6 +7,13 @@ export default defineNuxtConfig({
7
7
  'nuxt-multi-cache',
8
8
  ],
9
9
 
10
+ imports: {
11
+ imports: [
12
+ { name: 'useStrapiBlocksContext', from: 'vue-strapi-blocks-renderer' },
13
+ { name: 'StrapiBlocks', from: 'vue-strapi-blocks-renderer', type: true },
14
+ ],
15
+ },
16
+
10
17
  runtimeConfig: {
11
18
  multiCacheEnabled: import.meta.env.NUXT_CACHE_ENABLED === 'true',
12
19
  },
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@studio-fes/layer-strapi",
3
3
  "type": "module",
4
- "version": "0.1.5",
4
+ "version": "0.2.1",
5
5
  "main": "./nuxt.config.ts",
6
6
  "scripts": {
7
7
  "dev": "nuxi dev",
@@ -16,7 +16,8 @@
16
16
  "dependencies": {
17
17
  "@nuxt/eslint": "latest",
18
18
  "nuxt-graphql-middleware": "^5.3.2",
19
- "nuxt-multi-cache": "^4.0.3"
19
+ "nuxt-multi-cache": "^4.0.3",
20
+ "vue-strapi-blocks-renderer": "1.1.1"
20
21
  },
21
22
  "devDependencies": {
22
23
  "@studio-fes/layer-base": "workspace:*",
@@ -1,47 +0,0 @@
1
- <script lang="ts">
2
- import type { PropType } from 'vue'
3
-
4
- import type * as StrapiRichText from '~/types/StrapiRichText'
5
-
6
- export type StrapiRichTextBlocks = StrapiRichText.BlockNode[]
7
-
8
- export default defineComponent({
9
- props: {
10
- blocks: { type: Array as PropType<StrapiRichTextBlocks>, default: () => [] },
11
- inline: { type: Boolean, default: false },
12
- tag: { type: String, default: undefined },
13
- },
14
- setup(props) {
15
- return () => {
16
- const tag = props.tag || (props.inline ? 'p' : 'div')
17
- const children = renderStrapiRichText(props.blocks, props.inline)
18
- const selector = props.inline ? 'inline-richtext' : 'richtext'
19
- return h(tag, {
20
- class: selector,
21
- }, children)
22
- }
23
- },
24
- })
25
- </script>
26
-
27
- <style scoped>
28
- [class*='richtext'] {
29
- &:not(.inline-richtext) {
30
- display: block;
31
-
32
- :deep(br) {
33
- display: block;
34
- height: 1em;
35
- line-height: 1;
36
-
37
- content: '';
38
- }
39
- }
40
-
41
- &.inline-richtext {
42
- :deep(span) {
43
- display: block;
44
- }
45
- }
46
- }
47
- </style>
@@ -1,52 +0,0 @@
1
- // import type { StrapiFileFragment } from '#graphql-operations'
2
- import type { StrapiFileFragment } from '~/types/graphql-operations'
3
-
4
- export interface HeadingNode {
5
- type: 'heading'
6
- level: 1 | 2 | 3 | 4 | 5 | 6
7
- children: (TextNode | LinkNode)[]
8
- }
9
-
10
- export interface ParagraphNode {
11
- type: 'paragraph'
12
- children: (TextNode | LinkNode)[]
13
- }
14
-
15
- export interface TextNode {
16
- text: string
17
- type: 'text'
18
- bold?: boolean
19
- underline?: boolean
20
- italic?: boolean
21
- strikethrough?: boolean
22
- code?: boolean
23
- }
24
-
25
- export interface LinkNode {
26
- url: string
27
- type: 'link'
28
- children: TextNode[]
29
- }
30
-
31
- export interface ListNode {
32
- type: 'list'
33
- format: 'unordered' | 'ordered'
34
- children: ListItemNode[]
35
- }
36
-
37
- export interface ListItemNode {
38
- type: 'list-item'
39
- children: (TextNode | LinkNode | ListNode)[]
40
- }
41
-
42
- export interface QuoteNode {
43
- type: 'quote'
44
- children: (TextNode | LinkNode)[]
45
- }
46
-
47
- export interface ImageNode {
48
- type: 'image'
49
- image: StrapiFileFragment
50
- }
51
-
52
- export type BlockNode = HeadingNode | ParagraphNode | TextNode | LinkNode | ListNode | ListItemNode | QuoteNode | ImageNode
@@ -1,97 +0,0 @@
1
- import type * as RichText from '~/types/StrapiRichText'
2
-
3
- import { Comment, Fragment } from 'vue'
4
-
5
- function renderParagraphBlock(block: RichText.ParagraphNode, inline?: boolean) {
6
- const children = renderStrapiRichText(block.children, inline)
7
- const tag = inline ? 'fragment' : 'p'
8
- return children.length ? h(tag, children) : h('br')
9
- }
10
-
11
- function renderTextBlock(block: RichText.TextNode) {
12
- const lines = block.text.split('\n')
13
- const children = lines.reduce((acc, line, i) => {
14
- if (i < lines.length - 1) {
15
- acc.push(`${line} `.replace(/\s+/g, ' '), h('br'))
16
- }
17
- else {
18
- acc.push(line)
19
- }
20
- return acc
21
- }, [] as (string | VNode)[])
22
-
23
- if (block.bold)
24
- return h('strong', children)
25
- if (block.code)
26
- return h('code', children)
27
- if (block.italic)
28
- return h('em', children)
29
- if (block.strikethrough)
30
- return h('span', { class: 'line-through' }, children)
31
- if (block.underline)
32
- return h('span', { class: 'underline' }, children)
33
- return h(Fragment, children)
34
- }
35
-
36
- export function renderInlineBlock(block: RichText.BlockNode): VNode {
37
- switch (block.type) {
38
- case 'heading':
39
- case 'list-item':
40
- case 'quote':
41
- return h('span', renderStrapiRichText(block.children, true))
42
- case 'image':
43
- return h(Fragment)
44
- case 'link':
45
- return h('a', { href: block.url, target: '_blank', rel: 'noopener noreferrer' }, renderStrapiRichText(block.children, true))
46
- case 'list':
47
- return h(Fragment, renderStrapiRichText(block.children, true))
48
- case 'paragraph':
49
- return renderParagraphBlock(block, true)
50
- case 'text':
51
- return renderTextBlock(block)
52
- default:
53
- return h(Comment, 'Unknown block type')
54
- }
55
- }
56
-
57
- export function renderBlock(block: RichText.BlockNode): VNode {
58
- switch (block.type) {
59
- case 'heading':
60
- return h(`h${block.level}`, renderStrapiRichText(block.children))
61
- case 'image':
62
- return h('img', { src: block.image.url, width: block.image.width, height: block.image.height, alt: block.image.alternativeText })
63
- case 'link':
64
- return h('a', { title: getPlainText(block.children), href: block.url, target: '_blank', rel: 'noopener noreferrer' }, h('span', renderStrapiRichText(block.children)))
65
- case 'list':
66
- return h(block.format === 'ordered' ? 'ol' : 'ul', renderStrapiRichText(block.children))
67
- case 'list-item':
68
- return h('li', renderStrapiRichText(block.children))
69
- case 'paragraph':
70
- return renderParagraphBlock(block)
71
- case 'quote':
72
- return h('blockquote', renderStrapiRichText(block.children))
73
- case 'text':
74
- return renderTextBlock(block)
75
- default:
76
- return h(Comment, 'Unknown block type')
77
- }
78
- }
79
-
80
- export function renderStrapiRichText(blocks: RichText.BlockNode[], inline?: boolean): VNode[] {
81
- const render = inline ? renderInlineBlock : renderBlock
82
- return blocks.map(render)
83
- }
84
-
85
- export function getPlainText(block: RichText.BlockNode[]) {
86
- if (!block)
87
- return ''
88
-
89
- const text: string = block.reduce((acc, node) => {
90
- if (node.type === 'text') {
91
- return acc + node.text
92
- }
93
- return acc + getPlainText(node.children)
94
- }, '')
95
-
96
- return text
97
- }