@storyblok/astro 7.4.0-alpha.0 → 8.0.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/dist/index.d.ts +2 -4
- package/dist/lib/client.d.ts +0 -1
- package/dist/lib/client.ts +0 -2
- package/dist/lib/helpers.d.ts +0 -46
- package/dist/lib/richTextToHTML.d.ts +5 -5
- package/dist/live-preview/middleware.ts +7 -6
- package/dist/public.d.ts +1 -42
- package/dist/storyblok-astro.es.js +35401 -1092
- package/dist/storyblok-astro.umd.js +85 -16
- package/dist/types.d.ts +1 -1
- package/package.json +4 -6
- package/dist/components/StoryblokServerData.astro +0 -29
- package/dist/lib/richTextToHTML.ts +0 -103
- package/dist/lib/sanitizeJSON.d.ts +0 -30
- package/dist/utils/isEditorRequest.d.ts +0 -41
package/dist/types.d.ts
CHANGED
|
@@ -8,4 +8,4 @@ ISbStoriesParams, // previously StoriesParams
|
|
|
8
8
|
ISbStory, // previously Story
|
|
9
9
|
ISbStoryData, // previously StoryData
|
|
10
10
|
ISbStoryParams, // previously StoryParams
|
|
11
|
-
MarkTypes, SbBlokData, SbBlokKeyDataTypes, SbPluginFactory, SbSDKOptions, StoryblokBridgeConfigV2, StoryblokBridgeV2, StoryblokClient, StoryblokComponentType, StoryblokRichTextDocumentNode, StoryblokRichTextImageOptimizationOptions, StoryblokRichTextNode,
|
|
11
|
+
MarkTypes, SbBlokData, SbBlokKeyDataTypes, SbPluginFactory, SbSDKOptions, StoryblokBridgeConfigV2, StoryblokBridgeV2, StoryblokClient, StoryblokComponentType, StoryblokRichTextDocumentNode, StoryblokRichTextImageOptimizationOptions, StoryblokRichTextNode, StoryblokRichTextNodeTypes, StoryblokRichTextOptions, TextTypes, } from '@storyblok/js';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyblok/astro",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "8.0.0",
|
|
5
5
|
"private": false,
|
|
6
6
|
"description": "Official Astro integration for the Storyblok Headless CMS",
|
|
7
7
|
"author": "Storyblok",
|
|
@@ -39,8 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"./client": "./dist/lib/client.ts",
|
|
41
41
|
"./FallbackComponent.astro": "./dist/components/FallbackComponent.astro",
|
|
42
|
-
"./StoryblokComponent.astro": "./dist/components/StoryblokComponent.astro"
|
|
43
|
-
"./StoryblokServerData.astro": "./dist/components/StoryblokServerData.astro"
|
|
42
|
+
"./StoryblokComponent.astro": "./dist/components/StoryblokComponent.astro"
|
|
44
43
|
},
|
|
45
44
|
"main": "./dist/storyblok-astro.es.js",
|
|
46
45
|
"module": "./dist/storyblok-astro.js",
|
|
@@ -54,8 +53,7 @@
|
|
|
54
53
|
},
|
|
55
54
|
"dependencies": {
|
|
56
55
|
"camelcase": "^8.0.0",
|
|
57
|
-
"
|
|
58
|
-
"@storyblok/js": "4.4.4"
|
|
56
|
+
"@storyblok/js": "5.0.0"
|
|
59
57
|
},
|
|
60
58
|
"devDependencies": {
|
|
61
59
|
"@cypress/vite-dev-server": "^6.0.3",
|
|
@@ -76,7 +74,7 @@
|
|
|
76
74
|
"vite-plugin-dts": "^4.5.3",
|
|
77
75
|
"vite-plugin-static-copy": "^2.2.0",
|
|
78
76
|
"vitest": "^3.1.3",
|
|
79
|
-
"@storyblok/eslint-config": "0.4.
|
|
77
|
+
"@storyblok/eslint-config": "0.4.2"
|
|
80
78
|
},
|
|
81
79
|
"eslintConfig": {
|
|
82
80
|
"env": {
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
/**
|
|
3
|
-
* StoryblokServerData Component
|
|
4
|
-
*
|
|
5
|
-
* Pass server-side data to the client that persists across live preview updates.
|
|
6
|
-
* All props passed to this component will be serialized as JSON and available
|
|
7
|
-
* to the client via the extraData parameter in getLiveStory().
|
|
8
|
-
*
|
|
9
|
-
* Data is automatically sanitized to prevent XSS attacks and script injection.
|
|
10
|
-
*
|
|
11
|
-
* @example
|
|
12
|
-
* ```astro
|
|
13
|
-
* ---
|
|
14
|
-
* import { StoryblokServerData } from '@storyblok/astro';
|
|
15
|
-
* const users = await getUsers();
|
|
16
|
-
* const config = { apiUrl: 'https://api.example.com' };
|
|
17
|
-
* ---
|
|
18
|
-
*
|
|
19
|
-
* <StoryblokServerData users={users} config={config} />
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { sanitizeJSON } from '@storyblok/astro';
|
|
24
|
-
|
|
25
|
-
const props = Astro.props;
|
|
26
|
-
const safeJson = sanitizeJSON(props);
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
<script is:inline id="__STORYBLOK_SERVERDATA__" type="application/json" set:html={safeJson} />
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
richTextResolver,
|
|
3
|
-
type StoryblokRichTextNode,
|
|
4
|
-
type StoryblokRichTextResolvers,
|
|
5
|
-
} from '@storyblok/js';
|
|
6
|
-
import { experimental_AstroContainer } from 'astro/container';
|
|
7
|
-
import StoryblokComponent from '@storyblok/astro/StoryblokComponent.astro';
|
|
8
|
-
|
|
9
|
-
// Lazily initialized Astro container (for rendering blok components)
|
|
10
|
-
let container: null | experimental_AstroContainer = null;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @experimental Converts a Storyblok RichText field into an HTML string.
|
|
14
|
-
*
|
|
15
|
-
* This API is still under development and may change in future releases.
|
|
16
|
-
* It also relies on Astro’s experimental
|
|
17
|
-
* [experimental_AstroContainer](https://docs.astro.build/en/reference/container-reference/) feature.
|
|
18
|
-
*
|
|
19
|
-
* @async
|
|
20
|
-
* @param {StoryblokRichTextNode} richTextField - The root RichText node to convert.
|
|
21
|
-
* @param {StoryblokRichTextResolvers} [customResolvers] - Optional custom resolvers
|
|
22
|
-
* for customizing how specific nodes or marks are transformed into HTML.
|
|
23
|
-
* @returns {Promise<string>} A promise that resolves to the HTML string representation
|
|
24
|
-
* of the provided RichText content.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```astro
|
|
28
|
-
* ---
|
|
29
|
-
* import { richTextToHTML } from '@storyblok/astro/client';
|
|
30
|
-
* const { blok } = Astro.props;
|
|
31
|
-
* const renderedRichText = await richTextToHTML(blok.text);
|
|
32
|
-
* ---
|
|
33
|
-
*
|
|
34
|
-
* <div set:html={renderedRichText} />
|
|
35
|
-
* ```
|
|
36
|
-
*/
|
|
37
|
-
export const richTextToHTML = async (
|
|
38
|
-
richTextField: StoryblokRichTextNode,
|
|
39
|
-
customResolvers?: StoryblokRichTextResolvers,
|
|
40
|
-
): Promise<string> => {
|
|
41
|
-
// Create Astro container only once
|
|
42
|
-
if (!container) {
|
|
43
|
-
container = await experimental_AstroContainer.create();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Collect async render results keyed by placeholder ID
|
|
47
|
-
const asyncReplacements: Promise<{ id: string; result: string }>[] = [];
|
|
48
|
-
// Build the resolvers object
|
|
49
|
-
const resolvers: StoryblokRichTextResolvers = {
|
|
50
|
-
// Handle async components
|
|
51
|
-
blok: (node) => {
|
|
52
|
-
const componentBody = node.attrs?.body;
|
|
53
|
-
if (!Array.isArray(componentBody)) {
|
|
54
|
-
return '';
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return componentBody
|
|
58
|
-
.map((blok) => {
|
|
59
|
-
if (!blok || typeof blok !== 'object' || !container) {
|
|
60
|
-
return '';
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Generate unique placeholder ID
|
|
64
|
-
const id = crypto.randomUUID();
|
|
65
|
-
const placeholder = `<!--ASYNC-${id}-->`;
|
|
66
|
-
|
|
67
|
-
// Queue async render
|
|
68
|
-
const promise = container
|
|
69
|
-
.renderToString(StoryblokComponent, {
|
|
70
|
-
props: { blok },
|
|
71
|
-
})
|
|
72
|
-
.then(result => ({ id, result }))
|
|
73
|
-
.catch((err) => {
|
|
74
|
-
console.error('Component rendering failed:', err);
|
|
75
|
-
return { id, result: '<!-- Component render error -->' };
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
asyncReplacements.push(promise);
|
|
79
|
-
return placeholder;
|
|
80
|
-
})
|
|
81
|
-
.join('\n');
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
// Add custom resolvers if provided
|
|
85
|
-
...customResolvers,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const resolver = richTextResolver({ resolvers });
|
|
89
|
-
|
|
90
|
-
let html = resolver.render(richTextField);
|
|
91
|
-
// Wait for all async renders
|
|
92
|
-
const results = await Promise.all(asyncReplacements);
|
|
93
|
-
const replacements = new Map(
|
|
94
|
-
results.map(({ id, result }) => [id, result ?? '']),
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
// Single-pass replacement using regex
|
|
98
|
-
html = html.replace(/<!--ASYNC-([\w-]+)-->/g, (_, id: string) => {
|
|
99
|
-
return replacements.get(id) ?? '';
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
return html;
|
|
103
|
-
};
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Safely serializes data to JSON and escapes characters that could break out of a script tag
|
|
3
|
-
* or execute malicious code when embedded in HTML.
|
|
4
|
-
*
|
|
5
|
-
* This prevents XSS attacks by escaping:
|
|
6
|
-
* - `</script>` tags that could close the script tag early
|
|
7
|
-
* - `<!--` and `-->` HTML comment sequences
|
|
8
|
-
* - Line separator (U+2028) and paragraph separator (U+2029) which are valid JSON but can break JS
|
|
9
|
-
* - Other potentially dangerous Unicode characters
|
|
10
|
-
*
|
|
11
|
-
* @param data - The data to serialize
|
|
12
|
-
* @returns A safe JSON string that can be embedded in HTML
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```ts
|
|
16
|
-
* const safeJSON = sanitizeJSON({
|
|
17
|
-
* message: '</script><script>alert("XSS")</script>'
|
|
18
|
-
* });
|
|
19
|
-
* // Returns escaped version that won't execute
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
export declare function sanitizeJSON(data: unknown): string;
|
|
23
|
-
/**
|
|
24
|
-
* Parses JSON that was sanitized with sanitizeJSON()
|
|
25
|
-
* This is just JSON.parse but provided for symmetry and clarity
|
|
26
|
-
*
|
|
27
|
-
* @param json - The sanitized JSON string
|
|
28
|
-
* @returns The parsed data
|
|
29
|
-
*/
|
|
30
|
-
export declare function parseSanitizedJSON<T = unknown>(json: string): T;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Options for validating Storyblok Visual Editor requests.
|
|
3
|
-
*/
|
|
4
|
-
interface StoryblokValidationOptions {
|
|
5
|
-
/**
|
|
6
|
-
* Optional space ID to validate against the request.
|
|
7
|
-
* If provided, the request must match this space ID to be considered valid.
|
|
8
|
-
*/
|
|
9
|
-
spaceId?: string;
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Validates whether a given URL is a legitimate request from the Storyblok Visual Editor.
|
|
13
|
-
*
|
|
14
|
-
* This function performs a multi-layered validation to ensure the request originates from
|
|
15
|
-
* the Storyblok Visual Editor by checking for required query parameters and optionally
|
|
16
|
-
* validating the space ID.
|
|
17
|
-
*
|
|
18
|
-
* @param url - The URL object to validate.
|
|
19
|
-
* @param options - Optional validation configuration.
|
|
20
|
-
* @param options.spaceId - If provided, validates that the request's space ID matches this value.
|
|
21
|
-
*
|
|
22
|
-
* @returns `true` if the URL contains all required Storyblok Visual Editor parameters
|
|
23
|
-
* and passes optional space ID validation; `false` otherwise.
|
|
24
|
-
*
|
|
25
|
-
* @example
|
|
26
|
-
* ```typescript
|
|
27
|
-
* const url = new URL('https://example.com/?_storyblok=123&_storyblok_c=456&_storyblok_tk[space_id]=789');
|
|
28
|
-
*
|
|
29
|
-
* // Basic validation
|
|
30
|
-
* if (isEditorRequest(url)) {
|
|
31
|
-
* console.log('Valid Storyblok editor request');
|
|
32
|
-
* }
|
|
33
|
-
*
|
|
34
|
-
* // Validation with space ID check
|
|
35
|
-
* if (isEditorRequest(url, { spaceId: '789' })) {
|
|
36
|
-
* console.log('Valid request for specific space');
|
|
37
|
-
* }
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
export declare function isEditorRequest(url: URL, options?: StoryblokValidationOptions): boolean;
|
|
41
|
-
export {};
|