@wpnuxt/blocks 2.0.0-alpha.1 → 2.0.0-alpha.11
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/LICENSE +9 -0
- package/dist/module.d.mts +5 -0
- package/dist/module.d.ts +29 -0
- package/dist/module.json +4 -1
- package/dist/module.mjs +44 -3
- package/dist/runtime/components/BlockComponent.vue +29 -6
- package/dist/runtime/components/blocks/CoreButton.vue +24 -3
- package/dist/runtime/components/blocks/CoreGallery.vue +6 -6
- package/dist/runtime/queries/fragments/Page.fragment.gql +18 -0
- package/dist/runtime/queries/fragments/Post.fragment.gql +22 -0
- package/dist/runtime/util/index.js +4 -3
- package/package.json +13 -9
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-present - WPNuxt Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/dist/module.d.mts
CHANGED
|
@@ -17,6 +17,11 @@ interface WPNuxtBlocksConfig {
|
|
|
17
17
|
* @default 'auto' - uses Nuxt UI if available
|
|
18
18
|
*/
|
|
19
19
|
nuxtUI?: boolean | 'auto';
|
|
20
|
+
/**
|
|
21
|
+
* Skip the WPGraphQL Content Blocks plugin check
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
skipPluginCheck?: boolean;
|
|
20
25
|
}
|
|
21
26
|
declare const _default: _nuxt_schema.NuxtModule<WPNuxtBlocksConfig, WPNuxtBlocksConfig, false>;
|
|
22
27
|
|
package/dist/module.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface WPNuxtBlocksConfig {
|
|
4
|
+
/**
|
|
5
|
+
* Enable or disable the module
|
|
6
|
+
* @default true
|
|
7
|
+
*/
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Domains to allow for @nuxt/image
|
|
11
|
+
* @default []
|
|
12
|
+
*/
|
|
13
|
+
imageDomains?: string[];
|
|
14
|
+
/**
|
|
15
|
+
* Enable Nuxt UI integration for enhanced button styling
|
|
16
|
+
* Set to false to use native HTML elements
|
|
17
|
+
* @default 'auto' - uses Nuxt UI if available
|
|
18
|
+
*/
|
|
19
|
+
nuxtUI?: boolean | 'auto';
|
|
20
|
+
/**
|
|
21
|
+
* Skip the WPGraphQL Content Blocks plugin check
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
skipPluginCheck?: boolean;
|
|
25
|
+
}
|
|
26
|
+
declare const _default: _nuxt_schema.NuxtModule<WPNuxtBlocksConfig, WPNuxtBlocksConfig, false>;
|
|
27
|
+
|
|
28
|
+
export { _default as default };
|
|
29
|
+
export type { WPNuxtBlocksConfig };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
1
|
import { existsSync, cpSync, promises } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { defineNuxtModule, createResolver, hasNuxtModule, installModule, addComponentsDir, addTemplate } from '@nuxt/kit';
|
|
3
|
+
import { useLogger, defineNuxtModule, createResolver, hasNuxtModule, installModule, addComponentsDir, addTemplate } from '@nuxt/kit';
|
|
4
4
|
|
|
5
|
+
const logger = useLogger("@wpnuxt/blocks");
|
|
5
6
|
const module$1 = defineNuxtModule({
|
|
6
7
|
meta: {
|
|
7
8
|
name: "@wpnuxt/blocks",
|
|
8
|
-
configKey: "wpNuxtBlocks"
|
|
9
|
+
configKey: "wpNuxtBlocks",
|
|
10
|
+
compatibility: {
|
|
11
|
+
nuxt: ">=3.0.0"
|
|
12
|
+
}
|
|
9
13
|
},
|
|
10
14
|
defaults: {
|
|
11
15
|
enabled: true,
|
|
12
16
|
imageDomains: [],
|
|
13
|
-
nuxtUI: "auto"
|
|
17
|
+
nuxtUI: "auto",
|
|
18
|
+
skipPluginCheck: false
|
|
14
19
|
},
|
|
15
20
|
async setup(options, nuxt) {
|
|
16
21
|
if (!options.enabled) {
|
|
@@ -26,6 +31,42 @@ const module$1 = defineNuxtModule({
|
|
|
26
31
|
domains: options.imageDomains
|
|
27
32
|
});
|
|
28
33
|
await installModule("@radya/nuxt-dompurify");
|
|
34
|
+
if (!options.skipPluginCheck) {
|
|
35
|
+
const wpNuxtConfig = nuxt.options.runtimeConfig?.public?.wpNuxt;
|
|
36
|
+
const wordpressUrl = wpNuxtConfig?.wordpressUrl || process.env.WPNUXT_WORDPRESS_URL;
|
|
37
|
+
const graphqlEndpoint = wpNuxtConfig?.graphqlEndpoint || process.env.WPNUXT_GRAPHQL_ENDPOINT || "/graphql";
|
|
38
|
+
if (wordpressUrl) {
|
|
39
|
+
const graphqlUrl = `${wordpressUrl}${graphqlEndpoint}`;
|
|
40
|
+
const introspectionQuery = `
|
|
41
|
+
query CheckEditorBlocks {
|
|
42
|
+
__type(name: "Post") {
|
|
43
|
+
fields {
|
|
44
|
+
name
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
`;
|
|
49
|
+
try {
|
|
50
|
+
const response = await fetch(graphqlUrl, {
|
|
51
|
+
method: "POST",
|
|
52
|
+
headers: { "Content-Type": "application/json" },
|
|
53
|
+
body: JSON.stringify({ query: introspectionQuery })
|
|
54
|
+
});
|
|
55
|
+
if (response.ok) {
|
|
56
|
+
const data = await response.json();
|
|
57
|
+
const fields = data?.data?.__type?.fields || [];
|
|
58
|
+
const hasEditorBlocks = fields.some((f) => f.name === "editorBlocks");
|
|
59
|
+
if (!hasEditorBlocks) {
|
|
60
|
+
logger.warn("WPGraphQL Content Blocks plugin not detected on WordPress.");
|
|
61
|
+
logger.warn("Install it from: https://github.com/wpengine/wp-graphql-content-blocks");
|
|
62
|
+
logger.warn("Without this plugin, BlockRenderer will not work correctly.");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
logger.debug("Could not check for WPGraphQL Content Blocks plugin:", error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
29
70
|
const blocksQueriesPath = resolveRuntimeModule("./queries");
|
|
30
71
|
const mergedQueriesFolder = join(nuxt.options.srcDir, ".queries");
|
|
31
72
|
if (existsSync(mergedQueriesFolder) && existsSync(blocksQueriesPath)) {
|
|
@@ -1,22 +1,45 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { pascalCase } from "scule";
|
|
3
|
-
import { resolveComponent } from "
|
|
3
|
+
import { computed, resolveComponent, getCurrentInstance } from "vue";
|
|
4
4
|
const props = defineProps({
|
|
5
5
|
block: { type: null, required: true }
|
|
6
6
|
});
|
|
7
|
-
const
|
|
7
|
+
const registrationCache = /* @__PURE__ */ new Map();
|
|
8
|
+
const instance = getCurrentInstance();
|
|
9
|
+
function isComponentRegistered(name) {
|
|
10
|
+
if (registrationCache.has(name)) {
|
|
11
|
+
return registrationCache.get(name);
|
|
12
|
+
}
|
|
13
|
+
if (!instance) {
|
|
14
|
+
registrationCache.set(name, false);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
const appComponents = instance.appContext.components;
|
|
18
|
+
const isGlobal = name in appComponents;
|
|
19
|
+
const localComponents = instance.type.components;
|
|
20
|
+
const isLocal = !!(localComponents && name in localComponents);
|
|
21
|
+
const result = isGlobal || isLocal;
|
|
22
|
+
registrationCache.set(name, result);
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
const hot = import.meta.hot;
|
|
26
|
+
if (hot) {
|
|
27
|
+
hot.on("vite:beforeUpdate", () => {
|
|
28
|
+
registrationCache.clear();
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
const componentToRender = computed(() => {
|
|
8
32
|
if (props.block.parentClientId === null || props.block.parentClientId === void 0) {
|
|
9
33
|
if (props.block.name) {
|
|
10
34
|
const componentName = pascalCase(props.block.name);
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
return resolved;
|
|
35
|
+
if (isComponentRegistered(componentName)) {
|
|
36
|
+
return resolveComponent(componentName);
|
|
14
37
|
}
|
|
15
38
|
}
|
|
16
39
|
return resolveComponent("EditorBlock");
|
|
17
40
|
}
|
|
18
41
|
return void 0;
|
|
19
|
-
})
|
|
42
|
+
});
|
|
20
43
|
</script>
|
|
21
44
|
|
|
22
45
|
<template>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import { convertFontSize, getCssClasses } from "../../util";
|
|
3
|
-
import { ref, useNuxtApp } from "#imports";
|
|
3
|
+
import { computed, ref, useNuxtApp, useRuntimeConfig, isInternalLink, toRelativePath } from "#imports";
|
|
4
4
|
const props = defineProps({
|
|
5
5
|
block: { type: null, required: true }
|
|
6
6
|
});
|
|
@@ -13,13 +13,24 @@ if (props.block.attributes?.metadata) {
|
|
|
13
13
|
}
|
|
14
14
|
const nuxtApp = useNuxtApp();
|
|
15
15
|
const hasNuxtUI = !!nuxtApp.vueApp.component("UButton");
|
|
16
|
+
const config = useRuntimeConfig();
|
|
17
|
+
const wordpressUrl = config.public.wpNuxt?.wordpressUrl;
|
|
18
|
+
const isInternal = computed(() => {
|
|
19
|
+
const url = props.block.attributes?.url;
|
|
20
|
+
return !!url && isInternalLink(url, wordpressUrl);
|
|
21
|
+
});
|
|
22
|
+
const buttonUrl = computed(() => {
|
|
23
|
+
const url = props.block.attributes?.url;
|
|
24
|
+
if (!url) return void 0;
|
|
25
|
+
return isInternal.value ? toRelativePath(url) : url;
|
|
26
|
+
});
|
|
16
27
|
</script>
|
|
17
28
|
|
|
18
29
|
<template>
|
|
19
30
|
<!-- Use Nuxt UI UButton when available -->
|
|
20
31
|
<UButton
|
|
21
32
|
v-if="hasNuxtUI"
|
|
22
|
-
:to="
|
|
33
|
+
:to="buttonUrl"
|
|
23
34
|
:target="block.attributes.linkTarget"
|
|
24
35
|
:rel="block.attributes.rel"
|
|
25
36
|
:style="block.attributes.style"
|
|
@@ -30,7 +41,17 @@ const hasNuxtUI = !!nuxtApp.vueApp.component("UButton");
|
|
|
30
41
|
<span v-sanitize-html="block.attributes.text" />
|
|
31
42
|
</UButton>
|
|
32
43
|
|
|
33
|
-
<!-- Fallback
|
|
44
|
+
<!-- Fallback: use NuxtLink for internal, <a> for external -->
|
|
45
|
+
<NuxtLink
|
|
46
|
+
v-else-if="block.attributes.url && isInternal"
|
|
47
|
+
:to="buttonUrl"
|
|
48
|
+
:target="block.attributes.linkTarget ?? void 0"
|
|
49
|
+
:rel="block.attributes.rel ?? void 0"
|
|
50
|
+
:style="block.attributes.style"
|
|
51
|
+
:class="['wp-block-button__link', getCssClasses(block)]"
|
|
52
|
+
>
|
|
53
|
+
<span v-sanitize-html="block.attributes.text" />
|
|
54
|
+
</NuxtLink>
|
|
34
55
|
<a
|
|
35
56
|
v-else-if="block.attributes.url"
|
|
36
57
|
:href="block.attributes.url"
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { computed } from "vue";
|
|
2
3
|
const props = defineProps({
|
|
3
4
|
block: { type: null, required: true }
|
|
4
5
|
});
|
|
5
|
-
const imageBlocks =
|
|
6
|
-
props.block?.innerBlocks
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
6
|
+
const imageBlocks = computed(() => {
|
|
7
|
+
if (!props.block?.innerBlocks) return [];
|
|
8
|
+
return props.block.innerBlocks.filter(
|
|
9
|
+
(block) => block !== null && block.__typename === "CoreImage"
|
|
10
|
+
);
|
|
11
11
|
});
|
|
12
12
|
</script>
|
|
13
13
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#import "~/.queries/fragments/ContentNode.fragment.gql"
|
|
2
|
+
#import "~/.queries/fragments/NodeWithFeaturedImage.fragment.gql"
|
|
3
|
+
#import "~/.queries/fragments/NodeWithContentEditor.fragment.gql"
|
|
4
|
+
#import "~/.queries/fragments/NodeWithEditorBlocks.fragment.gql"
|
|
5
|
+
|
|
6
|
+
fragment Page on Page {
|
|
7
|
+
...ContentNode
|
|
8
|
+
...NodeWithFeaturedImage
|
|
9
|
+
...NodeWithContentEditor
|
|
10
|
+
...NodeWithEditorBlocks
|
|
11
|
+
isFrontPage
|
|
12
|
+
isPostsPage
|
|
13
|
+
isPreview
|
|
14
|
+
isPrivacyPage
|
|
15
|
+
isRestricted
|
|
16
|
+
isRevision
|
|
17
|
+
title
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#import "~/.queries/fragments/NodeWithExcerpt.fragment.gql"
|
|
2
|
+
#import "~/.queries/fragments/ContentNode.fragment.gql"
|
|
3
|
+
#import "~/.queries/fragments/NodeWithFeaturedImage.fragment.gql"
|
|
4
|
+
#import "~/.queries/fragments/NodeWithContentEditor.fragment.gql"
|
|
5
|
+
#import "~/.queries/fragments/NodeWithEditorBlocks.fragment.gql"
|
|
6
|
+
|
|
7
|
+
fragment Post on Post {
|
|
8
|
+
...NodeWithExcerpt
|
|
9
|
+
...ContentNode
|
|
10
|
+
...NodeWithFeaturedImage
|
|
11
|
+
...NodeWithContentEditor
|
|
12
|
+
...NodeWithEditorBlocks
|
|
13
|
+
title
|
|
14
|
+
categories {
|
|
15
|
+
nodes {
|
|
16
|
+
id
|
|
17
|
+
name
|
|
18
|
+
uri
|
|
19
|
+
description
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { convertFontSize } from "./attributeFontSize.js";
|
|
2
2
|
import { getColor } from "./attributeColor.js";
|
|
3
3
|
const getCssClasses = function getCssClasses2(block) {
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
4
|
+
const attrs = block.attributes;
|
|
5
|
+
const text = convertFontSize(attrs?.fontSize, "text-");
|
|
6
|
+
const color = getColor(attrs?.textColor);
|
|
7
|
+
const passedOn = attrs?.className != null ? attrs.className + " " : " ";
|
|
7
8
|
return passedOn + text + " " + color;
|
|
8
9
|
};
|
|
9
10
|
export { getCssClasses, convertFontSize, getColor };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wpnuxt/blocks",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.11",
|
|
4
4
|
"description": "Vue components for rendering WordPress Gutenberg blocks in Nuxt",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nuxt",
|
|
@@ -33,21 +33,23 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@nuxt/kit": "4.2.2",
|
|
37
36
|
"@nuxt/image": "^2.0.0",
|
|
37
|
+
"@nuxt/kit": "4.3.1",
|
|
38
38
|
"@radya/nuxt-dompurify": "^1.0.5",
|
|
39
39
|
"scule": "^1.3.0"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
42
|
"@nuxt/module-builder": "^1.0.2",
|
|
43
|
-
"@nuxt/schema": "4.
|
|
44
|
-
"@
|
|
45
|
-
"
|
|
46
|
-
"
|
|
43
|
+
"@nuxt/schema": "4.3.1",
|
|
44
|
+
"@nuxt/test-utils": "^4.0.0",
|
|
45
|
+
"@types/node": "^25.2.2",
|
|
46
|
+
"nuxt": "4.3.1",
|
|
47
|
+
"vitest": "^4.0.18",
|
|
48
|
+
"vue-tsc": "^3.2.3"
|
|
47
49
|
},
|
|
48
50
|
"peerDependencies": {
|
|
49
|
-
"nuxt": "^4.0.0",
|
|
50
|
-
"
|
|
51
|
+
"@nuxt/ui": "^4.0.0",
|
|
52
|
+
"nuxt": "^4.0.0"
|
|
51
53
|
},
|
|
52
54
|
"peerDependenciesMeta": {
|
|
53
55
|
"@nuxt/ui": {
|
|
@@ -56,7 +58,9 @@
|
|
|
56
58
|
},
|
|
57
59
|
"scripts": {
|
|
58
60
|
"build": "nuxt-module-build build",
|
|
59
|
-
"dev:prepare": "nuxt-module-build build --stub
|
|
61
|
+
"dev:prepare": "nuxt-module-build build --stub",
|
|
62
|
+
"test": "vitest run",
|
|
63
|
+
"test:watch": "vitest watch",
|
|
60
64
|
"typecheck": "vue-tsc --noEmit",
|
|
61
65
|
"clean": "rm -rf dist .nuxt node_modules"
|
|
62
66
|
}
|