@storyblok/astro 4.1.0-next.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -1
- package/dist/storyblok-astro.js +22 -9
- package/dist/storyblok-astro.mjs +800 -739
- package/dist/types/index.d.ts +6 -2
- package/dist/types/live-preview/handleStoryblokMessage.d.ts +11 -1
- package/dist/types/utils/generateFinalBridgeObject.d.ts +3 -3
- package/dist/types/utils/parseAstCode.d.ts +7 -1
- package/dist/types/vite-plugins/vite-plugin-storyblok-bridge.d.ts +11 -1
- package/live-preview/handleStoryblokMessage.ts +23 -41
- package/package.json +9 -6
- package/utils/generateFinalBridgeObject.ts +12 -11
- package/utils/parseAstCode.ts +43 -18
- package/vite-plugins/vite-plugin-storyblok-bridge.ts +0 -69
- package/vite-plugins/vite-plugin-storyblok-components.ts +0 -124
- package/vite-plugins/vite-plugin-storyblok-init.ts +0 -33
- package/vite-plugins/vite-plugin-storyblok-options.ts +0 -20
package/dist/types/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AstroGlobal, AstroIntegration } from "astro";
|
|
2
2
|
import type { ISbConfig, ISbRichtext, ISbStoriesParams, ISbStoryData, SbRichTextOptions, StoryblokBridgeConfigV2, StoryblokClient } from "./types";
|
|
3
|
-
export { storyblokEditable, loadStoryblokBridge, RichTextResolver, RichTextSchema, } from "@storyblok/js";
|
|
4
3
|
export { handleStoryblokMessage } from "./live-preview/handleStoryblokMessage";
|
|
4
|
+
export { storyblokEditable, loadStoryblokBridge, RichTextResolver, RichTextSchema, } from "@storyblok/js";
|
|
5
5
|
export declare function useStoryblokApi(): StoryblokClient;
|
|
6
6
|
export declare function useStoryblok(slug: string, apiOptions: ISbStoriesParams, bridgeOptions: StoryblokBridgeConfigV2, Astro: AstroGlobal): Promise<ISbStoryData<import("@storyblok/js").StoryblokComponentType<string> & {
|
|
7
7
|
[index: string]: any;
|
|
@@ -50,6 +50,10 @@ export type IntegrationOptions = {
|
|
|
50
50
|
* Please note: the path takes into account the `componentsDir` option.
|
|
51
51
|
*/
|
|
52
52
|
customFallbackComponent?: string;
|
|
53
|
+
/**
|
|
54
|
+
* A boolean to enable/disable the Experimental Live Preview feature. Disabled by default.
|
|
55
|
+
*/
|
|
56
|
+
livePreview?: boolean;
|
|
53
57
|
};
|
|
54
58
|
export default function storyblokIntegration(options: IntegrationOptions): AstroIntegration;
|
|
55
59
|
export * from "./types";
|
|
@@ -1 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ISbStoryData } from "@storyblok/js";
|
|
2
|
+
/**
|
|
3
|
+
* Our current tests indicate that the post request section
|
|
4
|
+
* is the bottleneck in terms of time consumption.
|
|
5
|
+
* We should explore alternative methods to optimize
|
|
6
|
+
* this process and improve efficiency.
|
|
7
|
+
*/
|
|
8
|
+
export declare function handleStoryblokMessage(event: {
|
|
9
|
+
action: string;
|
|
10
|
+
story: ISbStoryData;
|
|
11
|
+
}): Promise<void>;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { StoryblokBridgeConfigV2 } from "@storyblok/js";
|
|
2
|
+
import type { RawCode } from "../vite-plugins/vite-plugin-storyblok-bridge";
|
|
3
|
+
export declare function generateFinalBridgeObject(rawCode: RawCode): StoryblokBridgeConfigV2;
|
|
@@ -1 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import type { RawCodeItemOptions } from "../vite-plugins/vite-plugin-storyblok-bridge";
|
|
2
|
+
import type { Rollup } from "vite";
|
|
3
|
+
/**
|
|
4
|
+
* Parses through the Abstract Syntax Tree (AST) code to locate the 'useStoryblok' function and its properties.
|
|
5
|
+
* This functionality is crucial for generating a virtual module that can be utilized during the initialization of the Storyblok bridge.
|
|
6
|
+
*/
|
|
7
|
+
export declare function parseAstRawCode(astCode: Rollup.ProgramNode): RawCodeItemOptions;
|
|
@@ -1,2 +1,12 @@
|
|
|
1
|
+
import type { ISbStoriesParams, StoryblokBridgeConfigV2 } from "@storyblok/js";
|
|
1
2
|
import type { Plugin } from "vite";
|
|
2
|
-
export
|
|
3
|
+
export interface RawCodeItem {
|
|
4
|
+
url: string;
|
|
5
|
+
options?: RawCodeItemOptions;
|
|
6
|
+
}
|
|
7
|
+
export type RawCode = RawCodeItem[];
|
|
8
|
+
export interface RawCodeItemOptions {
|
|
9
|
+
apiOptions?: ISbStoriesParams;
|
|
10
|
+
bridgeOptions?: StoryblokBridgeConfigV2;
|
|
11
|
+
}
|
|
12
|
+
export declare function vitePluginStoryblokBridge(experimentalLivePreview: boolean, output: string): Plugin;
|
|
@@ -1,57 +1,43 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ISbStoryData } from "@storyblok/js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
let timeout: NodeJS.Timeout;
|
|
4
|
+
/**
|
|
5
|
+
* Our current tests indicate that the post request section
|
|
6
|
+
* is the bottleneck in terms of time consumption.
|
|
7
|
+
* We should explore alternative methods to optimize
|
|
8
|
+
* this process and improve efficiency.
|
|
9
|
+
*/
|
|
10
|
+
export async function handleStoryblokMessage(event: {
|
|
11
|
+
action: string;
|
|
12
|
+
story: ISbStoryData;
|
|
13
|
+
}) {
|
|
4
14
|
const { action, story } = event || {};
|
|
5
15
|
|
|
6
16
|
if (action === "input" && story) {
|
|
7
17
|
// Debounce the getNewHTMLBody function
|
|
8
18
|
const debouncedGetNewHTMLBody = async () => {
|
|
9
|
-
const t0 = performance.now();
|
|
10
19
|
const newBody = await getNewHTMLBody(story);
|
|
11
|
-
const t1 = performance.now();
|
|
12
|
-
console.log(`getNewHTMLBody took ${t1 - t0} milliseconds.`);
|
|
13
20
|
const currentBody = document.body;
|
|
14
21
|
if (newBody.outerHTML === currentBody.outerHTML) return;
|
|
15
22
|
// Get current focused element in Storyblok
|
|
16
23
|
const focusedElem = document.querySelector('[data-blok-focused="true"]');
|
|
17
24
|
updateDOMWithNewBody(currentBody, newBody, focusedElem);
|
|
18
|
-
const t2 = performance.now();
|
|
19
|
-
console.log(`updateDOMWithNewBody took ${t2 - t1} milliseconds.`);
|
|
20
|
-
console.log(`total time took ${t2 - t0} milliseconds.`);
|
|
21
25
|
};
|
|
22
|
-
|
|
23
|
-
// Execute the debounced function after a delay
|
|
24
|
-
const debounceDelay = 1500; // Adjust the delay as needed
|
|
26
|
+
const debounceDelay = 500; // Adjust the delay as needed
|
|
25
27
|
clearTimeout(timeout);
|
|
26
28
|
timeout = setTimeout(debouncedGetNewHTMLBody, debounceDelay);
|
|
27
29
|
}
|
|
28
30
|
|
|
29
|
-
if (["published", "change"].includes(event?.
|
|
31
|
+
if (["published", "change"].includes(event?.action)) {
|
|
30
32
|
location.reload();
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// const newBody = await getNewHTMLBody(story);
|
|
40
|
-
// const t1 = performance.now();
|
|
41
|
-
// console.log(`getNewHTMLBody took ${t1 - t0} milliseconds.`);
|
|
42
|
-
// const currentBody = document.body;
|
|
43
|
-
// if (newBody.outerHTML === currentBody.outerHTML) return;
|
|
44
|
-
// //Get current focused element in storyblok
|
|
45
|
-
// const focusedElem = document.querySelector('[data-blok-focused="true"]');
|
|
46
|
-
// updateDOMWithNewBody(currentBody, newBody, focusedElem);
|
|
47
|
-
// const t2 = performance.now();
|
|
48
|
-
// console.log(`updateDOMWithNewBody took ${t2 - t1} milliseconds.`);
|
|
49
|
-
// console.log(`total time took ${t2 - t0} milliseconds.`);
|
|
50
|
-
// } else if (["published", "change"].includes(event?.data?.action)) {
|
|
51
|
-
// location.reload();
|
|
52
|
-
// }
|
|
53
|
-
// }
|
|
54
|
-
function updateDOMWithNewBody(currentBody, newBody, focusedElem) {
|
|
36
|
+
function updateDOMWithNewBody(
|
|
37
|
+
currentBody: HTMLElement,
|
|
38
|
+
newBody: HTMLElement,
|
|
39
|
+
focusedElem: Element | null
|
|
40
|
+
) {
|
|
55
41
|
if (focusedElem) {
|
|
56
42
|
//Get the [data-blok-uid] of the focused element in storyblok
|
|
57
43
|
const focusedElementID = focusedElem.getAttribute("data-blok-uid");
|
|
@@ -62,21 +48,17 @@ function updateDOMWithNewBody(currentBody, newBody, focusedElem) {
|
|
|
62
48
|
if (newDomFocusElem) {
|
|
63
49
|
// Add the [data-blok-focused] attribute to the above element
|
|
64
50
|
newDomFocusElem.setAttribute("data-blok-focused", "true");
|
|
65
|
-
console.log("Doing partial replace");
|
|
51
|
+
// console.log("Doing partial replace");
|
|
66
52
|
focusedElem.replaceWith(newDomFocusElem);
|
|
67
53
|
}
|
|
68
54
|
} else {
|
|
69
|
-
//
|
|
70
|
-
// const allStoryblokElem =
|
|
71
|
-
// document.querySelectorAll('[data-blok-uid]')
|
|
72
|
-
// console.log({ allStoryblokElem })
|
|
73
|
-
|
|
74
|
-
console.log("Doing full replace");
|
|
55
|
+
// console.log("Doing full replace");
|
|
75
56
|
currentBody.replaceWith(newBody);
|
|
76
57
|
}
|
|
77
58
|
}
|
|
78
59
|
|
|
79
|
-
async function getNewHTMLBody(story) {
|
|
60
|
+
async function getNewHTMLBody(story: ISbStoryData) {
|
|
61
|
+
//TODO How to handel (50x, 405, etc.)
|
|
80
62
|
const result = await fetch(location.href, {
|
|
81
63
|
method: "POST",
|
|
82
64
|
body: JSON.stringify({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyblok/astro",
|
|
3
|
-
"version": "4.1.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Official Astro integration for the Storyblok Headless CMS",
|
|
5
5
|
"main": "./dist/storyblok-astro.js",
|
|
6
6
|
"module": "./dist/storyblok-astro.mjs",
|
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
"components",
|
|
10
10
|
"dev-toolbar",
|
|
11
11
|
"live-preview",
|
|
12
|
-
"utils"
|
|
13
|
-
"vite-plugins"
|
|
12
|
+
"utils"
|
|
14
13
|
],
|
|
15
14
|
"exports": {
|
|
16
15
|
".": {
|
|
@@ -65,10 +64,10 @@
|
|
|
65
64
|
"@cypress/vite-dev-server": "^5.0.7",
|
|
66
65
|
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
|
|
67
66
|
"@types/lodash.mergewith": "^4.6.9",
|
|
68
|
-
"@types/node": "20.12.
|
|
67
|
+
"@types/node": "20.12.11",
|
|
69
68
|
"astro": "^4.6.3",
|
|
70
|
-
"cypress": "^13.8.
|
|
71
|
-
"eslint-plugin-cypress": "^2.
|
|
69
|
+
"cypress": "^13.8.1",
|
|
70
|
+
"eslint-plugin-cypress": "^3.2.0",
|
|
72
71
|
"start-server-and-test": "^2.0.3",
|
|
73
72
|
"typescript": "5.4.5",
|
|
74
73
|
"vite": "^5.2.10",
|
|
@@ -97,6 +96,10 @@
|
|
|
97
96
|
{
|
|
98
97
|
"name": "next",
|
|
99
98
|
"prerelease": true
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"name": "alpha",
|
|
102
|
+
"prerelease": true
|
|
100
103
|
}
|
|
101
104
|
]
|
|
102
105
|
},
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import type { StoryblokBridgeConfigV2 } from "@storyblok/js";
|
|
2
|
+
import type { RawCode } from "../vite-plugins/vite-plugin-storyblok-bridge";
|
|
3
|
+
|
|
4
|
+
export function generateFinalBridgeObject(rawCode: RawCode) {
|
|
5
|
+
let mergedOptions: StoryblokBridgeConfigV2 = {
|
|
3
6
|
resolveRelations: [],
|
|
4
7
|
};
|
|
5
8
|
|
|
6
|
-
function addToResolveRelations(
|
|
7
|
-
resolveRelations
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
mergedOptions.resolveRelations.push(resolveRelations);
|
|
14
|
-
}
|
|
9
|
+
function addToResolveRelations(resolveRelations?: string[] | string) {
|
|
10
|
+
if (resolveRelations && Array.isArray(mergedOptions.resolveRelations)) {
|
|
11
|
+
mergedOptions.resolveRelations.push(
|
|
12
|
+
...(Array.isArray(resolveRelations)
|
|
13
|
+
? resolveRelations
|
|
14
|
+
: [resolveRelations])
|
|
15
|
+
);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
package/utils/parseAstCode.ts
CHANGED
|
@@ -1,23 +1,37 @@
|
|
|
1
1
|
import mergeWith from "lodash.mergewith";
|
|
2
|
+
import type { ISbStoriesParams, StoryblokBridgeConfigV2 } from "@storyblok/js";
|
|
3
|
+
import type { RawCodeItemOptions } from "../vite-plugins/vite-plugin-storyblok-bridge";
|
|
4
|
+
import type { Rollup } from "vite";
|
|
5
|
+
import type { SpreadElement, Property } from "estree";
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Parses through the Abstract Syntax Tree (AST) code to locate the 'useStoryblok' function and its properties.
|
|
9
|
+
* This functionality is crucial for generating a virtual module that can be utilized during the initialization of the Storyblok bridge.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export function parseAstRawCode(astCode: Rollup.ProgramNode) {
|
|
13
|
+
let obj: RawCodeItemOptions = {};
|
|
14
|
+
|
|
15
|
+
function customizer(_: any, srcValue: any) {
|
|
6
16
|
if (
|
|
7
17
|
srcValue?.type === "AwaitExpression" &&
|
|
8
|
-
srcValue
|
|
18
|
+
srcValue.argument.type === "CallExpression" &&
|
|
19
|
+
srcValue.argument.callee.type === "Identifier" &&
|
|
20
|
+
srcValue.argument.callee.name === "useStoryblok"
|
|
9
21
|
) {
|
|
10
|
-
const props = srcValue
|
|
11
|
-
if (props[1]
|
|
22
|
+
const props = srcValue.argument.arguments;
|
|
23
|
+
if (props && props[1].type === "ObjectExpression") {
|
|
24
|
+
const apiOptions = getAstPropToObj(props[1].properties);
|
|
12
25
|
obj = {
|
|
13
26
|
...obj,
|
|
14
|
-
apiOptions
|
|
27
|
+
apiOptions,
|
|
15
28
|
};
|
|
16
29
|
}
|
|
17
|
-
if (props[2]
|
|
30
|
+
if (props && props[2].type === "ObjectExpression") {
|
|
31
|
+
const bridgeOptions = getAstPropToObj(props[2].properties);
|
|
18
32
|
obj = {
|
|
19
33
|
...obj,
|
|
20
|
-
bridgeOptions
|
|
34
|
+
bridgeOptions,
|
|
21
35
|
};
|
|
22
36
|
}
|
|
23
37
|
}
|
|
@@ -27,15 +41,26 @@ export function parseAstRawCode(astCode) {
|
|
|
27
41
|
return obj;
|
|
28
42
|
}
|
|
29
43
|
|
|
30
|
-
function getAstPropToObj(properties) {
|
|
31
|
-
|
|
44
|
+
function getAstPropToObj(properties: (SpreadElement | Property)[]) {
|
|
45
|
+
const option: ISbStoriesParams | StoryblokBridgeConfigV2 = {};
|
|
46
|
+
|
|
47
|
+
return properties.reduce((options, property) => {
|
|
48
|
+
if (property.type !== "Property") return options;
|
|
49
|
+
const { key, value } = property;
|
|
32
50
|
const { type } = value;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
51
|
+
if (key.type !== "Identifier") return options;
|
|
52
|
+
|
|
53
|
+
if (type === "Literal") {
|
|
54
|
+
options[key.name] = value.value;
|
|
55
|
+
} else if (type === "ArrayExpression") {
|
|
56
|
+
const arrayValues = value.elements.reduce((acc, element) => {
|
|
57
|
+
if (element.type === "Literal" && element.value) {
|
|
58
|
+
return [...acc, element.value];
|
|
59
|
+
}
|
|
60
|
+
return acc;
|
|
61
|
+
}, []);
|
|
62
|
+
options[key.name] = arrayValues;
|
|
63
|
+
}
|
|
39
64
|
return options;
|
|
40
|
-
},
|
|
65
|
+
}, option);
|
|
41
66
|
}
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from "vite";
|
|
2
|
-
import { parseAstRawCode } from "../utils/parseAstCode";
|
|
3
|
-
import { generateFinalBridgeObject } from "../utils/generateFinalBridgeObject";
|
|
4
|
-
let previousRawCode = [];
|
|
5
|
-
|
|
6
|
-
export function vitePluginStoryblokBridge(): Plugin {
|
|
7
|
-
let rawCode = [];
|
|
8
|
-
const virtualModuleId = "virtual:storyblok-bridge";
|
|
9
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
10
|
-
let _server = null;
|
|
11
|
-
let restartTimeout = null;
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
name: "vite-plugin-storyblok-bridge",
|
|
15
|
-
async resolveId(id: string) {
|
|
16
|
-
if (id === virtualModuleId) {
|
|
17
|
-
return resolvedVirtualModuleId;
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
async transform(code, id) {
|
|
21
|
-
if (id.includes("node_modules") && !id.includes("/pages/")) return;
|
|
22
|
-
if (!code.includes("useStoryblok")) return;
|
|
23
|
-
const moduleInfo = this.getModuleInfo(id);
|
|
24
|
-
if (!moduleInfo.meta?.astro) return;
|
|
25
|
-
const [, ...routeArray] = id.split("src/pages/");
|
|
26
|
-
const url = routeArray.join("/").replace(".astro", "");
|
|
27
|
-
const options = parseAstRawCode(this.parse(code));
|
|
28
|
-
if (previousRawCode.length) {
|
|
29
|
-
rawCode = previousRawCode.filter((i) => i.url !== url);
|
|
30
|
-
}
|
|
31
|
-
rawCode.push({
|
|
32
|
-
url,
|
|
33
|
-
options,
|
|
34
|
-
});
|
|
35
|
-
if (!_server) return;
|
|
36
|
-
if (restartTimeout) {
|
|
37
|
-
clearTimeout(restartTimeout);
|
|
38
|
-
}
|
|
39
|
-
restartTimeout = setTimeout(() => {
|
|
40
|
-
if (alreadyHaveThisUrl(previousRawCode, rawCode)) return;
|
|
41
|
-
if (previousRawCode.length !== 0) {
|
|
42
|
-
_server.restart();
|
|
43
|
-
console.info("Updating bridge options...");
|
|
44
|
-
}
|
|
45
|
-
previousRawCode = [...rawCode];
|
|
46
|
-
}, 1000);
|
|
47
|
-
},
|
|
48
|
-
async load(id: string) {
|
|
49
|
-
if (id === resolvedVirtualModuleId) {
|
|
50
|
-
return `export const bridgeOptions = ${JSON.stringify(generateFinalBridgeObject(rawCode))}`;
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
configureServer(server) {
|
|
54
|
-
_server = server;
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
interface ParsedCodeObj {
|
|
60
|
-
url: string;
|
|
61
|
-
options: any;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
function alreadyHaveThisUrl(a: ParsedCodeObj[] = [], b: ParsedCodeObj[] = []) {
|
|
65
|
-
return b.every(({ url, options }) => {
|
|
66
|
-
const aCopy = a.find((e) => e?.url === url);
|
|
67
|
-
return aCopy && JSON.stringify(options) === JSON.stringify(aCopy.options);
|
|
68
|
-
});
|
|
69
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Custom Vite plugin by Tony Sull (https://github.com/tony-sull)
|
|
3
|
-
*/
|
|
4
|
-
import camelcase from "camelcase";
|
|
5
|
-
import type { Plugin } from "vite";
|
|
6
|
-
|
|
7
|
-
export function vitePluginStoryblokComponents(
|
|
8
|
-
componentsDir: string,
|
|
9
|
-
components?: object,
|
|
10
|
-
enableFallbackComponent?: boolean,
|
|
11
|
-
customFallbackComponent?: string
|
|
12
|
-
): Plugin {
|
|
13
|
-
const virtualModuleId = "virtual:storyblok-components";
|
|
14
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
15
|
-
|
|
16
|
-
return {
|
|
17
|
-
name: "vite-plugin-storyblok-components",
|
|
18
|
-
async resolveId(id: string) {
|
|
19
|
-
if (id === virtualModuleId) {
|
|
20
|
-
return resolvedVirtualModuleId;
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
async load(id: string) {
|
|
24
|
-
if (id === resolvedVirtualModuleId) {
|
|
25
|
-
/**
|
|
26
|
-
* Handle registered components
|
|
27
|
-
*/
|
|
28
|
-
const imports: string[] = [];
|
|
29
|
-
const excludedKeys: string[] = [];
|
|
30
|
-
for await (const [key, value] of Object.entries(components)) {
|
|
31
|
-
const resolvedId = await this.resolve(
|
|
32
|
-
"/" + componentsDir + "/" + value + ".astro"
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* if the component cannot be resolved
|
|
37
|
-
*/
|
|
38
|
-
if (!resolvedId) {
|
|
39
|
-
if (enableFallbackComponent) {
|
|
40
|
-
/**
|
|
41
|
-
* if showFallbackComponent is enabled, the current component key needs to be excluded from the imports
|
|
42
|
-
* otherwise the attempted import would result in an error
|
|
43
|
-
*/
|
|
44
|
-
excludedKeys.push(key);
|
|
45
|
-
} else {
|
|
46
|
-
/**
|
|
47
|
-
* if it is not enabled, throw a specific error here
|
|
48
|
-
*/
|
|
49
|
-
throw new Error(
|
|
50
|
-
`Component could not be found for blok "${key}"! Does "${
|
|
51
|
-
"/" + componentsDir + "/" + value
|
|
52
|
-
}.astro" exist?`
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
} else {
|
|
56
|
-
/**
|
|
57
|
-
* if the component can be resolved, add it to the imports array
|
|
58
|
-
* important: convert blok names to camel case for valid import names
|
|
59
|
-
* StoryblokComponent.astro needs to do the same when resolving components!
|
|
60
|
-
*/
|
|
61
|
-
imports.push(`import ${camelcase(key)} from "${resolvedId.id}"`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Handle custom fallback component
|
|
67
|
-
*/
|
|
68
|
-
|
|
69
|
-
let fallbackComponentKey: string = "";
|
|
70
|
-
|
|
71
|
-
if (enableFallbackComponent) {
|
|
72
|
-
fallbackComponentKey = ",FallbackComponent";
|
|
73
|
-
if (customFallbackComponent) {
|
|
74
|
-
/**
|
|
75
|
-
* resolve custom FallbackComponent defined in astro.config.mjs
|
|
76
|
-
*/
|
|
77
|
-
const fallbackComponentResolvedId = await this.resolve(
|
|
78
|
-
"/" + componentsDir + "/" + customFallbackComponent + ".astro"
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
if (!fallbackComponentResolvedId) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
`Custom fallback component could not be found. Does "${
|
|
84
|
-
"/" + componentsDir + "/" + customFallbackComponent
|
|
85
|
-
}.astro" exist?`
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
imports.push(
|
|
90
|
-
`import FallbackComponent from "${fallbackComponentResolvedId.id}"`
|
|
91
|
-
);
|
|
92
|
-
} else {
|
|
93
|
-
/**
|
|
94
|
-
* import default FallbackComponent bundled with @storyblok/astro
|
|
95
|
-
*/
|
|
96
|
-
imports.push(
|
|
97
|
-
`import FallbackComponent from '@storyblok/astro/FallbackComponent.astro'`
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (!Object.values(components).length) {
|
|
103
|
-
/**
|
|
104
|
-
* If no components are registered in astro.config.mjs, either export just the fallback component (default or custom),
|
|
105
|
-
* or throw an error.
|
|
106
|
-
*/
|
|
107
|
-
if (enableFallbackComponent) {
|
|
108
|
-
return `${
|
|
109
|
-
imports[0]
|
|
110
|
-
}; export default {${fallbackComponentKey.replace(",", "")}}`;
|
|
111
|
-
}
|
|
112
|
-
throw new Error(
|
|
113
|
-
`Currently, no Storyblok components are registered in astro.config.mjs.\nPlease register your components or enable the fallback component.\nDetailed information can be found here: https://github.com/storyblok/storyblok-astro`
|
|
114
|
-
);
|
|
115
|
-
} else {
|
|
116
|
-
return `${imports.join(";")};export default {${Object.keys(components)
|
|
117
|
-
.filter((key) => !excludedKeys.includes(key))
|
|
118
|
-
.map((key) => camelcase(key))
|
|
119
|
-
.join(",")}${fallbackComponentKey}}`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { ISbConfig } from "../types";
|
|
2
|
-
import type { Plugin } from "vite";
|
|
3
|
-
|
|
4
|
-
export function vitePluginStoryblokInit(
|
|
5
|
-
accessToken: string,
|
|
6
|
-
useCustomApi: boolean,
|
|
7
|
-
apiOptions: ISbConfig
|
|
8
|
-
): Plugin {
|
|
9
|
-
const virtualModuleId = "virtual:storyblok-init";
|
|
10
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
11
|
-
|
|
12
|
-
return {
|
|
13
|
-
name: "vite-plugin-storyblok-init",
|
|
14
|
-
async resolveId(id: string) {
|
|
15
|
-
if (id === virtualModuleId) {
|
|
16
|
-
return resolvedVirtualModuleId;
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
async load(id: string) {
|
|
20
|
-
if (id === resolvedVirtualModuleId) {
|
|
21
|
-
return `
|
|
22
|
-
import { storyblokInit, apiPlugin } from "@storyblok/js";
|
|
23
|
-
const { storyblokApi } = storyblokInit({
|
|
24
|
-
accessToken: "${accessToken}",
|
|
25
|
-
use: ${useCustomApi ? "[]" : "[apiPlugin]"},
|
|
26
|
-
apiOptions: ${JSON.stringify(apiOptions)},
|
|
27
|
-
});
|
|
28
|
-
export const storyblokApiInstance = storyblokApi;
|
|
29
|
-
`;
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import type { Plugin } from "vite";
|
|
2
|
-
|
|
3
|
-
export function vitePluginStoryblokOptions(options: object): Plugin {
|
|
4
|
-
const virtualModuleId = `virtual:storyblok-options`;
|
|
5
|
-
const resolvedVirtualModuleId = "\0" + virtualModuleId;
|
|
6
|
-
|
|
7
|
-
return {
|
|
8
|
-
name: "vite-plugin-storyblok-options",
|
|
9
|
-
async resolveId(id: string) {
|
|
10
|
-
if (id === virtualModuleId) {
|
|
11
|
-
return resolvedVirtualModuleId;
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
async load(id: string) {
|
|
15
|
-
if (id === resolvedVirtualModuleId) {
|
|
16
|
-
return `export default ${JSON.stringify(options)}`;
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}
|