@gitbook/react-openapi 1.5.2 → 1.5.4
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 +31 -0
- package/dist/InteractiveSection.js +2 -2
- package/dist/OpenAPICodeSample.js +8 -5
- package/dist/OpenAPICodeSampleInteractive.js +1 -5
- package/dist/OpenAPICopyButton.js +12 -7
- package/dist/OpenAPIDisclosure.js +4 -6
- package/dist/OpenAPIDisclosureGroup.js +21 -7
- package/dist/OpenAPIPath.js +12 -38
- package/dist/OpenAPIPathItem.js +22 -0
- package/dist/OpenAPIPathMultipleServers.js +43 -0
- package/dist/OpenAPIRequiredScopes.js +67 -0
- package/dist/OpenAPISchema.js +187 -79
- package/dist/OpenAPISecurities.js +17 -43
- package/dist/OpenAPISelect.js +6 -6
- package/dist/OpenAPISpec.js +1 -1
- package/dist/OpenAPITooltip.js +23 -0
- package/dist/ScalarApiButton.js +5 -2
- package/dist/code-samples.js +33 -3
- package/dist/context.d.ts +3 -0
- package/dist/formatPath.js +25 -0
- package/dist/generateSchemaExample.js +20 -3
- package/dist/getOrCreateDisclosureStoreByKey.js +31 -0
- package/dist/resolveOpenAPIOperation.js +5 -2
- package/dist/translate.js +2 -2
- package/dist/translations/de.js +2 -0
- package/dist/translations/en.d.ts +2 -0
- package/dist/translations/en.js +2 -0
- package/dist/translations/es.js +2 -0
- package/dist/translations/fr.js +2 -0
- package/dist/translations/index.d.ts +18 -0
- package/dist/translations/ja.js +2 -0
- package/dist/translations/nl.js +2 -0
- package/dist/translations/no.js +2 -0
- package/dist/translations/pt-br.js +2 -0
- package/dist/translations/zh.js +2 -0
- package/dist/types.d.ts +1 -0
- package/dist/util/tryit-prefill.js +4 -1
- package/dist/utils.js +8 -6
- package/package.json +23 -10
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { checkIsReference } from "./utils.js";
|
|
2
|
+
import { isPlainObject } from "./contentTypeChecks.js";
|
|
2
3
|
|
|
3
4
|
//#region src/generateSchemaExample.ts
|
|
4
5
|
/**
|
|
@@ -81,6 +82,10 @@ const getExampleFromSchema = (schema, options, level = 0, parentSchema, name, re
|
|
|
81
82
|
resultCache.set(schema$1, result);
|
|
82
83
|
return result;
|
|
83
84
|
}
|
|
85
|
+
function mergeAllOfIntoResponse(allOfItems, response, parent) {
|
|
86
|
+
const allOfResults = allOfItems.map((item) => getExampleFromSchema(item, options, level + 1, parent, void 0, resultCache)).filter(isPlainObject);
|
|
87
|
+
if (allOfResults.length > 0) Object.assign(response, ...allOfResults);
|
|
88
|
+
}
|
|
84
89
|
if (resultCache.has(schema)) return resultCache.get(schema);
|
|
85
90
|
if (level === MAX_LEVELS_DEEP + 1) try {
|
|
86
91
|
JSON.stringify(schema);
|
|
@@ -129,9 +134,21 @@ const getExampleFromSchema = (schema, options, level = 0, parentSchema, name, re
|
|
|
129
134
|
if (schema.additionalProperties === true || typeof schema.additionalProperties === "object" && !Object.keys(schema.additionalProperties).length) response.ANY_ADDITIONAL_PROPERTY = "anything";
|
|
130
135
|
else if (schema.additionalProperties !== false) response.ANY_ADDITIONAL_PROPERTY = getExampleFromSchema(schema.additionalProperties, options, level + 1, void 0, void 0, resultCache);
|
|
131
136
|
}
|
|
132
|
-
if (schema.anyOf !== void 0)
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
if (schema.anyOf !== void 0) {
|
|
138
|
+
const anyOfItem = schema.anyOf[0];
|
|
139
|
+
if (anyOfItem) if (anyOfItem?.allOf !== void 0 && Array.isArray(anyOfItem.allOf)) mergeAllOfIntoResponse(anyOfItem.allOf, response, anyOfItem);
|
|
140
|
+
else {
|
|
141
|
+
const anyOfResult = getExampleFromSchema(anyOfItem, options, level + 1, void 0, void 0, resultCache);
|
|
142
|
+
if (isPlainObject(anyOfResult)) Object.assign(response, anyOfResult);
|
|
143
|
+
}
|
|
144
|
+
} else if (schema.oneOf !== void 0) {
|
|
145
|
+
const oneOfItem = schema.oneOf[0];
|
|
146
|
+
if (oneOfItem) if (oneOfItem?.allOf !== void 0 && Array.isArray(oneOfItem.allOf)) mergeAllOfIntoResponse(oneOfItem.allOf, response, oneOfItem);
|
|
147
|
+
else {
|
|
148
|
+
const oneOfResult = getExampleFromSchema(oneOfItem, options, level + 1, void 0, void 0, resultCache);
|
|
149
|
+
if (isPlainObject(oneOfResult)) Object.assign(response, oneOfResult);
|
|
150
|
+
}
|
|
151
|
+
} else if (schema.allOf !== void 0) mergeAllOfIntoResponse(schema.allOf, response, schema);
|
|
135
152
|
return cache(schema, response);
|
|
136
153
|
}
|
|
137
154
|
if (schema.type === "array" || schema.items !== void 0) {
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { createStore } from "zustand";
|
|
2
|
+
|
|
3
|
+
//#region src/getOrCreateDisclosureStoreByKey.ts
|
|
4
|
+
const createDisclosureStore = (initialKeys) => {
|
|
5
|
+
return createStore()((set) => ({
|
|
6
|
+
expandedKeys: initialKeys ? new Set(initialKeys) : /* @__PURE__ */ new Set(),
|
|
7
|
+
setExpandedKeys: (keys) => {
|
|
8
|
+
set(() => ({ expandedKeys: keys }));
|
|
9
|
+
},
|
|
10
|
+
toggleKey: (key) => {
|
|
11
|
+
set((state) => {
|
|
12
|
+
const newKeys = new Set(state.expandedKeys);
|
|
13
|
+
if (newKeys.has(key)) newKeys.delete(key);
|
|
14
|
+
else newKeys.add(key);
|
|
15
|
+
return { expandedKeys: newKeys };
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
}));
|
|
19
|
+
};
|
|
20
|
+
const defaultDisclosureStores = /* @__PURE__ */ new Map();
|
|
21
|
+
const createDisclosureStoreFactory = (stores) => {
|
|
22
|
+
return (storeKey, initialKeys) => {
|
|
23
|
+
if (!stores.has(storeKey)) stores.set(storeKey, createDisclosureStore(initialKeys));
|
|
24
|
+
if (!stores.get(storeKey)) throw new Error(`Failed to get or create store for key: ${storeKey}`);
|
|
25
|
+
return stores.get(storeKey);
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
const getOrCreateDisclosureStoreByKey = createDisclosureStoreFactory(defaultDisclosureStores);
|
|
29
|
+
|
|
30
|
+
//#endregion
|
|
31
|
+
export { getOrCreateDisclosureStoreByKey };
|
|
@@ -88,8 +88,11 @@ function flattenSecurities(security) {
|
|
|
88
88
|
* Resolve the scopes for a security scheme.
|
|
89
89
|
*/
|
|
90
90
|
function resolveSecurityScopes({ securityScheme, operationScopes }) {
|
|
91
|
-
if (!
|
|
92
|
-
return
|
|
91
|
+
if (!operationScopes?.length || !securityScheme || checkIsReference(securityScheme)) return null;
|
|
92
|
+
if (isOAuthSecurityScheme(securityScheme)) return (securityScheme.flows ? Object.entries(securityScheme.flows) : []).flatMap(([_, flow]) => {
|
|
93
|
+
return Object.entries(flow.scopes ?? {}).filter(([scope]) => operationScopes.includes(scope));
|
|
94
|
+
});
|
|
95
|
+
return operationScopes.map((scope) => [scope, void 0]);
|
|
93
96
|
}
|
|
94
97
|
/**
|
|
95
98
|
* Check if a security scheme is an OAuth or OpenID Connect security scheme.
|
package/dist/translate.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { isValidElement } from "react";
|
|
2
2
|
|
|
3
3
|
//#region src/translate.tsx
|
|
4
4
|
/**
|
|
@@ -35,7 +35,7 @@ function reactToString(el) {
|
|
|
35
35
|
if (typeof el === "string" || typeof el === "number" || typeof el === "boolean") return `${el}`;
|
|
36
36
|
if (el === null || el === void 0) return "";
|
|
37
37
|
if (Array.isArray(el)) return el.map(reactToString).join("");
|
|
38
|
-
if (
|
|
38
|
+
if (isValidElement(el)) return el.props.children.map(reactToString).join("");
|
|
39
39
|
throw new Error(`Unsupported type ${typeof el}`);
|
|
40
40
|
}
|
|
41
41
|
|
package/dist/translations/de.js
CHANGED
|
@@ -38,6 +38,8 @@ const de = {
|
|
|
38
38
|
hide: "Verstecke ${1}",
|
|
39
39
|
available_items: "Verfügbare Elemente",
|
|
40
40
|
required_scopes: "Erforderliche Scopes",
|
|
41
|
+
required_scopes_description: "Dieser Endpunkt erfordert die folgenden Scopes:",
|
|
42
|
+
available_scopes: "Verfügbare Scopes:",
|
|
41
43
|
properties: "Eigenschaften",
|
|
42
44
|
or: "oder",
|
|
43
45
|
and: "und",
|
package/dist/translations/en.js
CHANGED
|
@@ -38,6 +38,8 @@ const en = {
|
|
|
38
38
|
hide: "Hide ${1}",
|
|
39
39
|
available_items: "Available items",
|
|
40
40
|
required_scopes: "Required scopes",
|
|
41
|
+
required_scopes_description: "This endpoint requires the following scopes:",
|
|
42
|
+
available_scopes: "Available scopes:",
|
|
41
43
|
possible_values: "Possible values",
|
|
42
44
|
properties: "Properties",
|
|
43
45
|
or: "or",
|
package/dist/translations/es.js
CHANGED
|
@@ -38,6 +38,8 @@ const es = {
|
|
|
38
38
|
hide: "Ocultar ${1}",
|
|
39
39
|
available_items: "Elementos disponibles",
|
|
40
40
|
required_scopes: "Scopes requeridos",
|
|
41
|
+
required_scopes_description: "Este endpoint requiere los siguientes scopes:",
|
|
42
|
+
available_scopes: "Scopes disponibles:",
|
|
41
43
|
properties: "Propiedades",
|
|
42
44
|
or: "o",
|
|
43
45
|
and: "y",
|
package/dist/translations/fr.js
CHANGED
|
@@ -38,6 +38,8 @@ const fr = {
|
|
|
38
38
|
hide: "Masquer ${1}",
|
|
39
39
|
available_items: "Éléments disponibles",
|
|
40
40
|
required_scopes: "Scopes requis",
|
|
41
|
+
required_scopes_description: "Cet endpoint nécessite les scopes suivants:",
|
|
42
|
+
available_scopes: "Scopes disponibles:",
|
|
41
43
|
properties: "Propriétés",
|
|
42
44
|
or: "ou",
|
|
43
45
|
and: "et",
|
|
@@ -41,6 +41,8 @@ declare const translations: {
|
|
|
41
41
|
hide: string;
|
|
42
42
|
available_items: string;
|
|
43
43
|
required_scopes: string;
|
|
44
|
+
required_scopes_description: string;
|
|
45
|
+
available_scopes: string;
|
|
44
46
|
possible_values: string;
|
|
45
47
|
properties: string;
|
|
46
48
|
or: string;
|
|
@@ -85,6 +87,8 @@ declare const translations: {
|
|
|
85
87
|
hide: string;
|
|
86
88
|
available_items: string;
|
|
87
89
|
required_scopes: string;
|
|
90
|
+
required_scopes_description: string;
|
|
91
|
+
available_scopes: string;
|
|
88
92
|
properties: string;
|
|
89
93
|
or: string;
|
|
90
94
|
and: string;
|
|
@@ -129,6 +133,8 @@ declare const translations: {
|
|
|
129
133
|
hide: string;
|
|
130
134
|
available_items: string;
|
|
131
135
|
required_scopes: string;
|
|
136
|
+
required_scopes_description: string;
|
|
137
|
+
available_scopes: string;
|
|
132
138
|
properties: string;
|
|
133
139
|
or: string;
|
|
134
140
|
and: string;
|
|
@@ -173,6 +179,8 @@ declare const translations: {
|
|
|
173
179
|
hide: string;
|
|
174
180
|
available_items: string;
|
|
175
181
|
required_scopes: string;
|
|
182
|
+
required_scopes_description: string;
|
|
183
|
+
available_scopes: string;
|
|
176
184
|
properties: string;
|
|
177
185
|
or: string;
|
|
178
186
|
and: string;
|
|
@@ -217,6 +225,8 @@ declare const translations: {
|
|
|
217
225
|
hide: string;
|
|
218
226
|
available_items: string;
|
|
219
227
|
required_scopes: string;
|
|
228
|
+
required_scopes_description: string;
|
|
229
|
+
available_scopes: string;
|
|
220
230
|
properties: string;
|
|
221
231
|
or: string;
|
|
222
232
|
and: string;
|
|
@@ -261,6 +271,8 @@ declare const translations: {
|
|
|
261
271
|
hide: string;
|
|
262
272
|
available_items: string;
|
|
263
273
|
required_scopes: string;
|
|
274
|
+
required_scopes_description: string;
|
|
275
|
+
available_scopes: string;
|
|
264
276
|
properties: string;
|
|
265
277
|
or: string;
|
|
266
278
|
and: string;
|
|
@@ -305,6 +317,8 @@ declare const translations: {
|
|
|
305
317
|
hide: string;
|
|
306
318
|
available_items: string;
|
|
307
319
|
required_scopes: string;
|
|
320
|
+
required_scopes_description: string;
|
|
321
|
+
available_scopes: string;
|
|
308
322
|
properties: string;
|
|
309
323
|
or: string;
|
|
310
324
|
and: string;
|
|
@@ -349,6 +363,8 @@ declare const translations: {
|
|
|
349
363
|
hide: string;
|
|
350
364
|
available_items: string;
|
|
351
365
|
required_scopes: string;
|
|
366
|
+
required_scopes_description: string;
|
|
367
|
+
available_scopes: string;
|
|
352
368
|
properties: string;
|
|
353
369
|
or: string;
|
|
354
370
|
and: string;
|
|
@@ -393,6 +409,8 @@ declare const translations: {
|
|
|
393
409
|
hide: string;
|
|
394
410
|
available_items: string;
|
|
395
411
|
required_scopes: string;
|
|
412
|
+
required_scopes_description: string;
|
|
413
|
+
available_scopes: string;
|
|
396
414
|
properties: string;
|
|
397
415
|
or: string;
|
|
398
416
|
and: string;
|
package/dist/translations/ja.js
CHANGED
package/dist/translations/nl.js
CHANGED
|
@@ -38,6 +38,8 @@ const nl = {
|
|
|
38
38
|
hide: "Verberg ${1}",
|
|
39
39
|
available_items: "Beschikbare items",
|
|
40
40
|
required_scopes: "Vereiste scopes",
|
|
41
|
+
required_scopes_description: "Dit endpoint vereist de volgende scopes:",
|
|
42
|
+
available_scopes: "Beschikbare scopes:",
|
|
41
43
|
properties: "Eigenschappen",
|
|
42
44
|
or: "of",
|
|
43
45
|
and: "en",
|
package/dist/translations/no.js
CHANGED
|
@@ -38,6 +38,8 @@ const no = {
|
|
|
38
38
|
hide: "Skjul ${1}",
|
|
39
39
|
available_items: "Tilgjengelige elementer",
|
|
40
40
|
required_scopes: "Påkrevde scopes",
|
|
41
|
+
required_scopes_description: "Dette endepunktet krever følgende scopes:",
|
|
42
|
+
available_scopes: "Tilgjengelige scopes:",
|
|
41
43
|
properties: "Egenskaper",
|
|
42
44
|
or: "eller",
|
|
43
45
|
and: "og",
|
|
@@ -38,6 +38,8 @@ const pt_br = {
|
|
|
38
38
|
hide: "Ocultar ${1}",
|
|
39
39
|
available_items: "Itens disponíveis",
|
|
40
40
|
required_scopes: "Scopes obrigatórios",
|
|
41
|
+
required_scopes_description: "Este endpoint requer os seguintes scopes:",
|
|
42
|
+
available_scopes: "Scopes disponíveis:",
|
|
41
43
|
properties: "Propriedades",
|
|
42
44
|
or: "ou",
|
|
43
45
|
and: "e",
|
package/dist/translations/zh.js
CHANGED
package/dist/types.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ type OpenAPIServerVariableWithCustomProperties = OpenAPIV3.ServerVariableObject
|
|
|
6
6
|
* OpenAPI ServerObject type extended to provide x-gitbook prefill custom properties at the variable level.
|
|
7
7
|
*/
|
|
8
8
|
type OpenAPIServerWithCustomProperties = Omit<OpenAPIV3.ServerObject, 'variables'> & {
|
|
9
|
+
name?: string;
|
|
9
10
|
variables?: {
|
|
10
11
|
[variable: string]: OpenAPIServerVariableWithCustomProperties;
|
|
11
12
|
};
|
|
@@ -95,7 +95,10 @@ function resolveTryItPrefillServersForOperationServers(args) {
|
|
|
95
95
|
function resolvePrefillCodePlaceholderFromSecurityScheme(args) {
|
|
96
96
|
const { security, defaultPlaceholderValue } = args;
|
|
97
97
|
const prefillExprParts = extractPrefillExpressionPartsFromSecurityScheme(security);
|
|
98
|
-
if (prefillExprParts.length === 0)
|
|
98
|
+
if (prefillExprParts.length === 0) {
|
|
99
|
+
if (security["x-gitbook-token-placeholder"]) return security["x-gitbook-token-placeholder"];
|
|
100
|
+
return defaultPlaceholderValue ?? "";
|
|
101
|
+
}
|
|
99
102
|
return toPrefillCodePlaceholder(templatePartsToExpression(prefillExprParts), defaultPlaceholderValue);
|
|
100
103
|
}
|
|
101
104
|
function extractPrefillExpressionPartsFromSecurityScheme(security) {
|
package/dist/utils.js
CHANGED
|
@@ -122,20 +122,22 @@ function getStatusCodeCategory(statusCode) {
|
|
|
122
122
|
if (Number.isNaN(code) || code < 100 || code >= 600) return "unknown";
|
|
123
123
|
return Math.floor(code / 100);
|
|
124
124
|
}
|
|
125
|
-
function getSchemaTitle(schema) {
|
|
125
|
+
function getSchemaTitle(schema, options) {
|
|
126
126
|
let type = "any";
|
|
127
127
|
if (schema.enum || schema["x-enumDescriptions"] || schema["x-gitbook-enum"]) type = `${schema.type} · enum`;
|
|
128
|
-
else if (schema.type === "array" && !!schema.items) type = `${getSchemaTitle(schema.items)}[]`;
|
|
128
|
+
else if (schema.type === "array" && !!schema.items) type = `${getSchemaTitle(schema.items, options)}[]`;
|
|
129
129
|
else if (Array.isArray(schema.type)) type = schema.type.join(" | ");
|
|
130
130
|
else if (schema.type || schema.properties) {
|
|
131
131
|
type = schema.type ?? "object";
|
|
132
132
|
if (schema.format) type += ` · ${schema.format}`;
|
|
133
133
|
if (type === "object" && schema.title) type += ` · ${schema.title.replaceAll(" ", "")}`;
|
|
134
134
|
}
|
|
135
|
-
if (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
if (!options?.ignoreAlternatives) {
|
|
136
|
+
if ("anyOf" in schema) type = "any of";
|
|
137
|
+
else if ("oneOf" in schema) type = "one of";
|
|
138
|
+
else if ("allOf" in schema) type = "all of";
|
|
139
|
+
else if ("not" in schema) type = "not";
|
|
140
|
+
}
|
|
139
141
|
return type;
|
|
140
142
|
}
|
|
141
143
|
/**
|
package/package.json
CHANGED
|
@@ -7,31 +7,40 @@
|
|
|
7
7
|
"default": "./dist/index.js"
|
|
8
8
|
}
|
|
9
9
|
},
|
|
10
|
-
"version": "1.5.
|
|
10
|
+
"version": "1.5.4",
|
|
11
11
|
"sideEffects": false,
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@gitbook/expr": "1.2.
|
|
14
|
-
"@gitbook/openapi-parser": "3.0.
|
|
15
|
-
"@scalar/api-client-react": "^1.3.
|
|
16
|
-
"@scalar/oas-utils": "^0.
|
|
17
|
-
"@scalar/types": "^0.
|
|
13
|
+
"@gitbook/expr": "1.2.4",
|
|
14
|
+
"@gitbook/openapi-parser": "3.0.6",
|
|
15
|
+
"@scalar/api-client-react": "^1.3.46",
|
|
16
|
+
"@scalar/oas-utils": "^0.6.3",
|
|
17
|
+
"@scalar/types": "^0.4.0",
|
|
18
18
|
"classnames": "^2.5.1",
|
|
19
19
|
"flatted": "^3.2.9",
|
|
20
20
|
"json-xml-parse": "^1.3.0",
|
|
21
21
|
"react-aria-components": "^1.13.0",
|
|
22
22
|
"react-aria": "^3.44.0",
|
|
23
|
-
"
|
|
23
|
+
"react-stately": "^3.42.0",
|
|
24
|
+
"usehooks-ts": "^3.1.1",
|
|
24
25
|
"zustand": "^5.0.3",
|
|
25
26
|
"js-yaml": "^4.1.0"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
29
|
"@types/js-yaml": "^4.0.9",
|
|
30
|
+
"@types/react": "^19.0.0",
|
|
31
|
+
"@types/react-dom": "^19.0.0",
|
|
29
32
|
"bun-types": "^1.1.20",
|
|
30
|
-
"react": "^19.0.
|
|
31
|
-
"react-dom": "^19.0.
|
|
33
|
+
"react": "^19.0.1",
|
|
34
|
+
"react-dom": "^19.0.1",
|
|
32
35
|
"tsdown": "^0.15.6",
|
|
33
36
|
"typescript": "^5.5.3"
|
|
34
37
|
},
|
|
38
|
+
"overrides": {
|
|
39
|
+
"@types/react": "catalog:",
|
|
40
|
+
"@types/react-dom": "catalog:",
|
|
41
|
+
"react": "catalog:",
|
|
42
|
+
"react-dom": "catalog:"
|
|
43
|
+
},
|
|
35
44
|
"peerDependencies": {
|
|
36
45
|
"react": "*",
|
|
37
46
|
"react-dom": "*"
|
|
@@ -41,11 +50,15 @@
|
|
|
41
50
|
"typecheck": "tsc --noEmit",
|
|
42
51
|
"unit": "bun test",
|
|
43
52
|
"dev": "bun run build -- --watch ./src",
|
|
44
|
-
"clean": "rm -rf ./dist"
|
|
53
|
+
"clean": "rm -rf ./dist",
|
|
54
|
+
"publish-to-npm": "../../scripts/publish-if-new.sh"
|
|
45
55
|
},
|
|
46
56
|
"files": ["dist", "README.md", "CHANGELOG.md"],
|
|
47
57
|
"publishConfig": {
|
|
48
58
|
"access": "public",
|
|
49
59
|
"registry": "https://registry.npmjs.org/"
|
|
60
|
+
},
|
|
61
|
+
"repository": {
|
|
62
|
+
"url": "https://github.com/GitbookIO/gitbook"
|
|
50
63
|
}
|
|
51
64
|
}
|