@storyblok/astro 5.1.0-next.1 → 5.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/LICENSE +21 -0
- package/README.md +6 -13
- package/{components → dist/components}/FallbackComponent.astro +1 -1
- package/dist/components/FallbackComponent.d.ts +6 -0
- package/{components → dist/components}/StoryblokComponent.astro +3 -3
- package/dist/components/StoryblokComponent.d.ts +6 -0
- package/dist/dev-toolbar/toolbarApp.d.ts +3 -0
- package/{dev-toolbar → dist/dev-toolbar}/toolbarApp.ts +146 -151
- package/dist/{types/index.d.ts → index.d.ts} +11 -14
- package/dist/{types/live-preview → live-preview}/handleStoryblokMessage.d.ts +1 -1
- package/dist/live-preview/middleware.d.ts +1 -0
- package/dist/live-preview/middleware.ts +25 -0
- package/dist/storyblok-astro.es.js +1324 -0
- package/dist/storyblok-astro.umd.js +69 -0
- package/dist/types.d.ts +12 -0
- package/dist/utils/generateFinalBridgeObject.d.ts +3 -0
- package/dist/{types/utils → utils}/parseAstCode.d.ts +2 -2
- package/dist/utils/toCamelCase.d.ts +1 -0
- package/dist/{types/vite-plugins → vite-plugins}/vite-plugin-storyblok-bridge.d.ts +2 -2
- package/dist/vite-plugins/vite-plugin-storyblok-components.d.ts +2 -0
- package/dist/vite-plugins/vite-plugin-storyblok-init.d.ts +3 -0
- package/dist/{types/vite-plugins → vite-plugins}/vite-plugin-storyblok-options.d.ts +1 -1
- package/package.json +123 -62
- package/components/FallbackComponent.ts +0 -2
- package/components/StoryblokComponent.ts +0 -2
- package/dist/storyblok-astro.js +0 -68
- package/dist/storyblok-astro.mjs +0 -1314
- package/dist/types/components/FallbackComponent.d.ts +0 -2
- package/dist/types/components/StoryblokComponent.d.ts +0 -2
- package/dist/types/cypress/e2e/index.cy.d.ts +0 -0
- package/dist/types/cypress/plugins/index.d.ts +0 -2
- package/dist/types/cypress/support/commands.d.ts +0 -0
- package/dist/types/cypress/support/e2e.d.ts +0 -1
- package/dist/types/cypress.config.d.ts +0 -2
- package/dist/types/dev-toolbar/toolbarApp.d.ts +0 -7
- package/dist/types/live-preview/middleware.d.ts +0 -1
- package/dist/types/node_modules/camelcase/index.d.ts +0 -102
- package/dist/types/types.d.ts +0 -12
- package/dist/types/utils/generateFinalBridgeObject.d.ts +0 -3
- package/dist/types/vite-plugins/vite-plugin-storyblok-components.d.ts +0 -2
- package/dist/types/vite-plugins/vite-plugin-storyblok-init.d.ts +0 -3
- package/live-preview/handleStoryblokMessage.ts +0 -76
- package/live-preview/middleware.ts +0 -24
- package/utils/generateFinalBridgeObject.ts +0 -33
- package/utils/parseAstCode.ts +0 -66
|
File without changes
|
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
declare const _default: {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
icon: "<svg width=\"45px\" height=\"53px\" viewBox=\"0 0 45 53\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <g id=\"storyblok-logo-kit\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <g id=\"storyblok-partner-logo\" transform=\"translate(-59.000000, -169.000000)\" fill-rule=\"nonzero\">\n <g id=\"storyblok-symbol\" transform=\"translate(59.000000, 169.000000)\">\n <path d=\"M2.32662261,0 C1.03405449,0 0,1.0331384 0,2.27290448 L0,42.8752437 C0,44.1150097 1.03405449,44.8898635 2.27491989,44.8898635 L8.27243596,44.8898635 L8.27243596,53 L15.7176283,44.9415205 L42.9132615,44.9415205 C44.1541269,44.9415205 44.9296678,44.1666667 44.9296678,42.8752437 L44.9296678,2.3245614 C44.9296678,1.08479532 44.2058296,0 42.9132615,0 L2.32662261,0 Z\" id=\"Shape-path-Copy\" fill=\"#0AB3AF\"></path>\n <path d=\"M29.1016723,8.11483254 C30.1351059,8.11483254 31.0135245,8.32132604 31.8402713,8.78593643 C32.6153465,9.19892344 33.33875,9.76678059 33.9071385,10.4378845 C35.0647615,11.8482391 35.6869248,13.6215753 35.6639755,15.445352 C35.6639755,16.7875598 35.3022738,18.0781442 34.630542,19.3171053 C33.9341248,20.5632996 32.8438147,21.5436614 31.5302412,22.1047676 C33.183735,22.569378 34.4755269,23.395352 35.4572888,24.5826897 C36.387379,25.8216507 36.8524241,27.4219754 36.8524241,29.4352871 C36.8524241,30.7258715 36.6168825,31.8756998 36.1290206,32.7391832 C35.6123039,33.668404 34.8372287,34.4427546 33.9071385,35.0106118 C32.9253766,35.6300923 31.8402713,36.1979494 30.600151,36.4560663 C29.3600307,36.7658066 28.0165671,37.0239234 26.6214318,37.0239234 L8.32965751,37.0239234 L8.32965751,8.11483254 L29.1016723,8.11483254 Z M26.1340815,24.271851 L15.77813,24.271851 L15.77813,29.1552028 L25.8851404,29.1552028 C26.4825991,29.1552028 27.0302696,28.9110352 27.4783637,28.5203671 C27.8766695,28.1296989 28.1256107,27.5436967 28.1256107,26.811194 C28.140051,26.1827412 27.948041,25.5663945 27.5779401,25.0531873 C27.1796343,24.5648522 26.7315403,24.271851 26.1340815,24.271851 Z M25.2876816,14.5051475 L15.77813,14.5051475 L15.77813,18.9001641 L25.0885287,18.9001641 C25.586411,18.9001641 26.0842933,18.6559965 26.4825991,18.3629954 C26.9306932,18.0699943 27.1298461,17.4351586 27.1298461,16.6049888 C27.1298461,15.872486 26.9306932,15.3353173 26.5821756,14.9934827 C26.233658,14.7004816 25.7855639,14.5051475 25.2876816,14.5051475 Z\" id=\"Combined-Shape-Copy-3\" fill=\"#FFFFFF\"></path>\n </g>\n </g>\n </g>\n</svg>";
|
|
5
|
-
init(canvas: ShadowRoot): void;
|
|
6
|
-
};
|
|
7
|
-
export default _default;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const onRequest: import("astro").MiddlewareHandler;
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
export type Options = {
|
|
2
|
-
/**
|
|
3
|
-
Uppercase the first character: `foo-bar` → `FooBar`.
|
|
4
|
-
|
|
5
|
-
@default false
|
|
6
|
-
*/
|
|
7
|
-
readonly pascalCase?: boolean;
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
Preserve consecutive uppercase characters: `foo-BAR` → `FooBAR`.
|
|
11
|
-
|
|
12
|
-
@default false
|
|
13
|
-
*/
|
|
14
|
-
readonly preserveConsecutiveUppercase?: boolean;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
The locale parameter indicates the locale to be used to convert to upper/lower case according to any locale-specific case mappings. If multiple locales are given in an array, the best available locale is used.
|
|
18
|
-
|
|
19
|
-
Setting `locale: false` ignores the platform locale and uses the [Unicode Default Case Conversion](https://unicode-org.github.io/icu/userguide/transforms/casemappings.html#simple-single-character-case-mapping) algorithm.
|
|
20
|
-
|
|
21
|
-
Default: The host environment’s current locale.
|
|
22
|
-
|
|
23
|
-
@example
|
|
24
|
-
```
|
|
25
|
-
import camelCase from 'camelcase';
|
|
26
|
-
|
|
27
|
-
camelCase('lorem-ipsum', {locale: 'en-US'});
|
|
28
|
-
//=> 'loremIpsum'
|
|
29
|
-
|
|
30
|
-
camelCase('lorem-ipsum', {locale: 'tr-TR'});
|
|
31
|
-
//=> 'loremİpsum'
|
|
32
|
-
|
|
33
|
-
camelCase('lorem-ipsum', {locale: ['en-US', 'en-GB']});
|
|
34
|
-
//=> 'loremIpsum'
|
|
35
|
-
|
|
36
|
-
camelCase('lorem-ipsum', {locale: ['tr', 'TR', 'tr-TR']});
|
|
37
|
-
//=> 'loremİpsum'
|
|
38
|
-
```
|
|
39
|
-
*/
|
|
40
|
-
readonly locale?: false | string | readonly string[];
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
Convert a dash/dot/underscore/space separated string to camelCase or PascalCase: `foo-bar` → `fooBar`.
|
|
45
|
-
|
|
46
|
-
Correctly handles Unicode strings.
|
|
47
|
-
|
|
48
|
-
@param input - The string to convert to camel case.
|
|
49
|
-
|
|
50
|
-
@example
|
|
51
|
-
```
|
|
52
|
-
import camelCase from 'camelcase';
|
|
53
|
-
|
|
54
|
-
camelCase('foo-bar');
|
|
55
|
-
//=> 'fooBar'
|
|
56
|
-
|
|
57
|
-
camelCase('foo_bar');
|
|
58
|
-
//=> 'fooBar'
|
|
59
|
-
|
|
60
|
-
camelCase('Foo-Bar');
|
|
61
|
-
//=> 'fooBar'
|
|
62
|
-
|
|
63
|
-
camelCase('розовый_пушистый_единорог');
|
|
64
|
-
//=> 'розовыйПушистыйЕдинорог'
|
|
65
|
-
|
|
66
|
-
camelCase('Foo-Bar', {pascalCase: true});
|
|
67
|
-
//=> 'FooBar'
|
|
68
|
-
|
|
69
|
-
camelCase('--foo.bar', {pascalCase: false});
|
|
70
|
-
//=> 'fooBar'
|
|
71
|
-
|
|
72
|
-
camelCase('Foo-BAR', {preserveConsecutiveUppercase: true});
|
|
73
|
-
//=> 'fooBAR'
|
|
74
|
-
|
|
75
|
-
camelCase('fooBAR', {pascalCase: true, preserveConsecutiveUppercase: true});
|
|
76
|
-
//=> 'FooBAR'
|
|
77
|
-
|
|
78
|
-
camelCase('foo bar');
|
|
79
|
-
//=> 'fooBar'
|
|
80
|
-
|
|
81
|
-
console.log(process.argv[3]);
|
|
82
|
-
//=> '--foo-bar'
|
|
83
|
-
camelCase(process.argv[3]);
|
|
84
|
-
//=> 'fooBar'
|
|
85
|
-
|
|
86
|
-
camelCase(['foo', 'bar']);
|
|
87
|
-
//=> 'fooBar'
|
|
88
|
-
|
|
89
|
-
camelCase(['__foo__', '--bar'], {pascalCase: true});
|
|
90
|
-
//=> 'FooBar'
|
|
91
|
-
|
|
92
|
-
camelCase(['foo', 'BAR'], {pascalCase: true, preserveConsecutiveUppercase: true})
|
|
93
|
-
//=> 'FooBAR'
|
|
94
|
-
|
|
95
|
-
camelCase('lorem-ipsum', {locale: 'en-US'});
|
|
96
|
-
//=> 'loremIpsum'
|
|
97
|
-
```
|
|
98
|
-
*/
|
|
99
|
-
export default function camelcase(
|
|
100
|
-
input: string | readonly string[],
|
|
101
|
-
options?: Options
|
|
102
|
-
): string;
|
package/dist/types/types.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type { SbPluginFactory, SbBlokKeyDataTypes, SbBlokData, SbRichTextOptions, SbSDKOptions, StoryblokClient, StoryblokBridgeV2, StoryblokBridgeConfigV2, ISbConfig, // previously StoryblokConfig
|
|
2
|
-
ISbCache, // previously StoryblokCache
|
|
3
|
-
ISbResult, // previously StoryblokResult
|
|
4
|
-
ISbResponse, ISbError, ISbNode, ISbSchema, ThrottleFn, AsyncFn, ArrayFn, ISbContentMangmntAPI, ISbManagmentApiResult, // previously StoryblokManagmentApiResult
|
|
5
|
-
ISbStories, // previously Stories
|
|
6
|
-
ISbStory, // previously Story
|
|
7
|
-
ISbDimensions, StoryblokComponentType, ISbStoryData, // previously StoryData
|
|
8
|
-
ISbAlternateObject, // previously AlternateObject
|
|
9
|
-
ISbStoriesParams, // previously StoriesParams
|
|
10
|
-
ISbStoryParams, // previously StoryParams
|
|
11
|
-
ISbRichtext, // previously Richtext
|
|
12
|
-
ISbEventPayload, } from "@storyblok/js";
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import type { ISbStoryData } from "@storyblok/js";
|
|
2
|
-
|
|
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
|
-
}) {
|
|
14
|
-
const { action, story } = event || {};
|
|
15
|
-
|
|
16
|
-
if (action === "input" && story) {
|
|
17
|
-
// Debounce the getNewHTMLBody function
|
|
18
|
-
const debouncedGetNewHTMLBody = async () => {
|
|
19
|
-
const newBody = await getNewHTMLBody(story);
|
|
20
|
-
const currentBody = document.body;
|
|
21
|
-
if (newBody.outerHTML === currentBody.outerHTML) return;
|
|
22
|
-
// Get current focused element in Storyblok
|
|
23
|
-
const focusedElem = document.querySelector('[data-blok-focused="true"]');
|
|
24
|
-
updateDOMWithNewBody(currentBody, newBody, focusedElem);
|
|
25
|
-
};
|
|
26
|
-
const debounceDelay = 500; // Adjust the delay as needed
|
|
27
|
-
clearTimeout(timeout);
|
|
28
|
-
timeout = setTimeout(debouncedGetNewHTMLBody, debounceDelay);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
if (["published", "change"].includes(event?.action)) {
|
|
32
|
-
location.reload();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function updateDOMWithNewBody(
|
|
37
|
-
currentBody: HTMLElement,
|
|
38
|
-
newBody: HTMLElement,
|
|
39
|
-
focusedElem: Element | null
|
|
40
|
-
) {
|
|
41
|
-
if (focusedElem) {
|
|
42
|
-
//Get the [data-blok-uid] of the focused element in storyblok
|
|
43
|
-
const focusedElementID = focusedElem.getAttribute("data-blok-uid");
|
|
44
|
-
//Now find the same element by above [data-blok-uid] in our new virtual HTML page
|
|
45
|
-
const newDomFocusElem = newBody.querySelector(
|
|
46
|
-
`[data-blok-uid="${focusedElementID}"]`
|
|
47
|
-
);
|
|
48
|
-
if (newDomFocusElem) {
|
|
49
|
-
// Add the [data-blok-focused] attribute to the above element
|
|
50
|
-
newDomFocusElem.setAttribute("data-blok-focused", "true");
|
|
51
|
-
// console.log("Doing partial replace");
|
|
52
|
-
focusedElem.replaceWith(newDomFocusElem);
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
// console.log("Doing full replace");
|
|
56
|
-
currentBody.replaceWith(newBody);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function getNewHTMLBody(story: ISbStoryData) {
|
|
61
|
-
//TODO How to handel (50x, 405, etc.)
|
|
62
|
-
const result = await fetch(location.href, {
|
|
63
|
-
method: "POST",
|
|
64
|
-
body: JSON.stringify({
|
|
65
|
-
...story,
|
|
66
|
-
is_storyblok_preview: true,
|
|
67
|
-
}),
|
|
68
|
-
headers: {
|
|
69
|
-
"Content-Type": "application/json",
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
const html = await result.text();
|
|
73
|
-
const parser = new DOMParser();
|
|
74
|
-
const doc = parser.parseFromString(html, "text/html");
|
|
75
|
-
return doc.body;
|
|
76
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { defineMiddleware } from "astro/middleware";
|
|
2
|
-
|
|
3
|
-
export const onRequest = defineMiddleware(async ({ locals, request }, next) => {
|
|
4
|
-
if (request["method"] === "POST") {
|
|
5
|
-
const url = new URL(request.url);
|
|
6
|
-
//First do a basic check if its coming from within storyblok
|
|
7
|
-
const isStoryblokRequest =
|
|
8
|
-
url.searchParams.has("_storyblok") &&
|
|
9
|
-
url.searchParams.has("_storyblok_c");
|
|
10
|
-
|
|
11
|
-
if (isStoryblokRequest) {
|
|
12
|
-
try {
|
|
13
|
-
//Create a copy of the request
|
|
14
|
-
const requestBody = await request.clone().json();
|
|
15
|
-
if (requestBody && requestBody["is_storyblok_preview"]) {
|
|
16
|
-
locals["_storyblok_preview_data"] = requestBody;
|
|
17
|
-
}
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.error("Error reading request body:", error);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return next();
|
|
24
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
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 = {
|
|
6
|
-
resolveRelations: [],
|
|
7
|
-
};
|
|
8
|
-
|
|
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
|
-
);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
for (const item of rawCode) {
|
|
20
|
-
if (item.options) {
|
|
21
|
-
const { apiOptions, bridgeOptions } = item.options;
|
|
22
|
-
addToResolveRelations(apiOptions?.resolve_relations);
|
|
23
|
-
if (bridgeOptions) {
|
|
24
|
-
const { resolveRelations, ...rest } = bridgeOptions;
|
|
25
|
-
addToResolveRelations(resolveRelations);
|
|
26
|
-
Object.assign(mergedOptions, rest);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
mergedOptions.resolveRelations = [...new Set(mergedOptions.resolveRelations)];
|
|
31
|
-
|
|
32
|
-
return mergedOptions;
|
|
33
|
-
}
|
package/utils/parseAstCode.ts
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
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";
|
|
6
|
-
|
|
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) {
|
|
16
|
-
if (
|
|
17
|
-
srcValue?.type === "AwaitExpression" &&
|
|
18
|
-
srcValue.argument.type === "CallExpression" &&
|
|
19
|
-
srcValue.argument.callee.type === "Identifier" &&
|
|
20
|
-
srcValue.argument.callee.name === "useStoryblok"
|
|
21
|
-
) {
|
|
22
|
-
const props = srcValue.argument.arguments;
|
|
23
|
-
if (props && props[1].type === "ObjectExpression") {
|
|
24
|
-
const apiOptions = getAstPropToObj(props[1].properties);
|
|
25
|
-
obj = {
|
|
26
|
-
...obj,
|
|
27
|
-
apiOptions,
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
if (props && props[2].type === "ObjectExpression") {
|
|
31
|
-
const bridgeOptions = getAstPropToObj(props[2].properties);
|
|
32
|
-
obj = {
|
|
33
|
-
...obj,
|
|
34
|
-
bridgeOptions,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
mergeWith({}, astCode, customizer);
|
|
41
|
-
return obj;
|
|
42
|
-
}
|
|
43
|
-
|
|
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;
|
|
50
|
-
const { type } = value;
|
|
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
|
-
}
|
|
64
|
-
return options;
|
|
65
|
-
}, option);
|
|
66
|
-
}
|