openapi-explorer 2.1.656 → 2.1.658
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/browser/openapi-explorer.min.js +2 -2
- package/dist/es/components/api-request.js +58 -140
- package/dist/es/components/api-response.js +9 -34
- package/dist/es/components/json-tree.js +4 -18
- package/dist/es/components/request-form-table.js +13 -36
- package/dist/es/components/schema-table.js +28 -42
- package/dist/es/components/schema-tree.js +31 -61
- package/dist/es/components/syntax-highlighter.js +7 -26
- package/dist/es/components/tag-input.js +2 -14
- package/dist/es/openapi-explorer-oauth-handler.js +0 -2
- package/dist/es/openapi-explorer.js +62 -174
- package/dist/es/react.js +4 -4
- package/dist/es/styles/input-styles.js +1 -1
- package/dist/es/styles/schema-styles.js +1 -1
- package/dist/es/templates/advance-search-template.js +1 -5
- package/dist/es/templates/callback-template.js +2 -2
- package/dist/es/templates/code-samples-template.js +1 -3
- package/dist/es/templates/components-template.js +41 -4
- package/dist/es/templates/endpoint-template.js +6 -17
- package/dist/es/templates/expanded-endpoint-template.js +4 -7
- package/dist/es/templates/focused-endpoint-template.js +0 -10
- package/dist/es/templates/mainBodyTemplate.js +3 -2
- package/dist/es/templates/navbar-template.js +9 -12
- package/dist/es/templates/overview-template.js +1 -1
- package/dist/es/templates/security-scheme-template.js +12 -73
- package/dist/es/templates/server-template.js +1 -8
- package/dist/es/utils/color-utils.js +2 -21
- package/dist/es/utils/common-utils.js +3 -20
- package/dist/es/utils/schema-utils.js +35 -132
- package/dist/es/utils/spec-parser.js +35 -120
- package/dist/es/utils/theme.js +3 -6
- package/dist/es/utils/xml/xml.js +1 -40
- package/dist/lib/components/api-request.js +58 -157
- package/dist/lib/components/api-response.js +9 -54
- package/dist/lib/components/json-tree.js +4 -27
- package/dist/lib/components/request-form-table.js +14 -42
- package/dist/lib/components/schema-table.js +28 -52
- package/dist/lib/components/schema-tree.js +31 -72
- package/dist/lib/components/syntax-highlighter.js +6 -49
- package/dist/lib/components/tag-input.js +2 -18
- package/dist/lib/languages/en.js +2 -3
- package/dist/lib/languages/fr.js +2 -3
- package/dist/lib/languages/index.js +0 -6
- package/dist/lib/openapi-explorer-oauth-handler.js +0 -6
- package/dist/lib/openapi-explorer.js +61 -197
- package/dist/lib/react.js +4 -5
- package/dist/lib/styles/advanced-search-styles.js +1 -5
- package/dist/lib/styles/api-request-styles.js +1 -5
- package/dist/lib/styles/border-styles.js +1 -5
- package/dist/lib/styles/endpoint-styles.js +1 -5
- package/dist/lib/styles/flex-styles.js +1 -5
- package/dist/lib/styles/font-styles.js +1 -5
- package/dist/lib/styles/info-styles.js +1 -5
- package/dist/lib/styles/input-styles.js +1 -5
- package/dist/lib/styles/key-frame-styles.js +1 -5
- package/dist/lib/styles/nav-styles.js +1 -5
- package/dist/lib/styles/prism-styles.js +1 -5
- package/dist/lib/styles/schema-styles.js +1 -5
- package/dist/lib/styles/tab-styles.js +1 -5
- package/dist/lib/styles/table-styles.js +1 -5
- package/dist/lib/styles/tag-input-styles.js +1 -5
- package/dist/lib/templates/advance-search-template.js +0 -6
- package/dist/lib/templates/callback-template.js +1 -3
- package/dist/lib/templates/code-samples-template.js +0 -4
- package/dist/lib/templates/components-template.js +43 -9
- package/dist/lib/templates/endpoint-template.js +6 -29
- package/dist/lib/templates/expanded-endpoint-template.js +3 -17
- package/dist/lib/templates/focused-endpoint-template.js +0 -19
- package/dist/lib/templates/mainBodyTemplate.js +2 -13
- package/dist/lib/templates/navbar-template.js +9 -20
- package/dist/lib/templates/overview-template.js +0 -5
- package/dist/lib/templates/security-scheme-template.js +12 -79
- package/dist/lib/templates/server-template.js +1 -12
- package/dist/lib/utils/color-utils.js +4 -25
- package/dist/lib/utils/common-utils.js +3 -33
- package/dist/lib/utils/schema-utils.js +33 -141
- package/dist/lib/utils/spec-parser.js +35 -128
- package/dist/lib/utils/theme.js +3 -16
- package/dist/lib/utils/xml/xml.js +1 -42
- package/package.json +2 -2
@@ -1,14 +1,11 @@
|
|
1
1
|
import OpenApiResolver from 'openapi-resolver/dist/openapi-resolver.browser.js';
|
2
2
|
import { marked } from 'marked';
|
3
3
|
import { invalidCharsRegEx } from './common-utils.js';
|
4
|
-
import { getI18nText } from '../languages/index.js';
|
5
4
|
import cloneDeep from 'lodash.clonedeep';
|
6
5
|
export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
7
6
|
var _jsonParsedSpec$info, _jsonParsedSpec$compo;
|
8
|
-
|
9
7
|
const inputSpecIsAUrl = typeof specUrlOrObject === 'string' && specUrlOrObject.match(/^http/) || typeof specUrlOrObject === 'object' && typeof specUrlOrObject.href === 'string';
|
10
8
|
let jsonParsedSpec;
|
11
|
-
|
12
9
|
try {
|
13
10
|
jsonParsedSpec = await OpenApiResolver(specUrlOrObject);
|
14
11
|
} catch (error) {
|
@@ -16,20 +13,21 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
16
13
|
console.error('Error parsing specification', error);
|
17
14
|
throw Error('SpecificationNotFound');
|
18
15
|
}
|
19
|
-
|
20
16
|
if (!jsonParsedSpec) {
|
21
17
|
throw Error('SpecificationNotFound');
|
22
|
-
}
|
23
|
-
|
18
|
+
}
|
24
19
|
|
25
|
-
|
20
|
+
// Tags with Paths and WebHooks
|
21
|
+
const tags = groupByTags(jsonParsedSpec);
|
26
22
|
|
27
|
-
|
23
|
+
// Components
|
24
|
+
const components = getComponents(jsonParsedSpec);
|
28
25
|
|
29
|
-
|
26
|
+
// Info Description Headers
|
27
|
+
const infoDescriptionHeaders = (_jsonParsedSpec$info = jsonParsedSpec.info) !== null && _jsonParsedSpec$info !== void 0 && _jsonParsedSpec$info.description ? getHeadersFromMarkdown(jsonParsedSpec.info.description) : [];
|
30
28
|
|
29
|
+
// Security Scheme
|
31
30
|
const securitySchemes = [];
|
32
|
-
|
33
31
|
if ((_jsonParsedSpec$compo = jsonParsedSpec.components) !== null && _jsonParsedSpec$compo !== void 0 && _jsonParsedSpec$compo.securitySchemes) {
|
34
32
|
Object.entries(jsonParsedSpec.components.securitySchemes).forEach(kv => {
|
35
33
|
const securityObj = {
|
@@ -38,7 +36,6 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
38
36
|
};
|
39
37
|
securityObj.value = '';
|
40
38
|
securityObj.finalKeyValue = '';
|
41
|
-
|
42
39
|
if (kv[1].type === 'apiKey' || kv[1].type === 'http') {
|
43
40
|
securityObj.name = kv[1].name || 'Authorization';
|
44
41
|
securityObj.user = '';
|
@@ -48,26 +45,22 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
48
45
|
securityObj.clientId = '';
|
49
46
|
securityObj.clientSecret = '';
|
50
47
|
}
|
51
|
-
|
52
48
|
securitySchemes.push(securityObj);
|
53
49
|
});
|
54
|
-
}
|
55
|
-
|
50
|
+
}
|
56
51
|
|
52
|
+
// Servers
|
57
53
|
let servers = [];
|
58
|
-
|
59
54
|
if (Array.isArray(jsonParsedSpec.servers) && jsonParsedSpec.servers.length) {
|
60
55
|
jsonParsedSpec.servers.filter(s => s).forEach(v => {
|
61
56
|
let computedUrl = v.url.trim();
|
62
|
-
|
63
57
|
if (!(computedUrl.startsWith('http') || computedUrl.startsWith('//') || computedUrl.startsWith('{'))) {
|
64
58
|
if (window.location.origin.startsWith('http')) {
|
65
59
|
v.url = window.location.origin + v.url;
|
66
60
|
computedUrl = v.url;
|
67
61
|
}
|
68
|
-
}
|
69
|
-
|
70
|
-
|
62
|
+
}
|
63
|
+
// Apply server-variables to generate final computed-url
|
71
64
|
if (v.variables) {
|
72
65
|
Object.entries(v.variables).forEach(kv => {
|
73
66
|
const regex = new RegExp(`{${kv[0]}}`, 'g');
|
@@ -75,7 +68,6 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
75
68
|
kv[1].value = kv[1].default || '';
|
76
69
|
});
|
77
70
|
}
|
78
|
-
|
79
71
|
v.computedUrl = computedUrl;
|
80
72
|
});
|
81
73
|
const explicitServers = serverUrl && !jsonParsedSpec.servers.some(s => s.url === serverUrl || s.computedUrl === serverUrl) ? [{
|
@@ -104,7 +96,6 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
104
96
|
computedUrl: 'http://localhost'
|
105
97
|
}];
|
106
98
|
}
|
107
|
-
|
108
99
|
const parsedSpec = {
|
109
100
|
info: jsonParsedSpec.info,
|
110
101
|
infoDescriptionHeaders,
|
@@ -117,96 +108,36 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
117
108
|
};
|
118
109
|
return parsedSpec;
|
119
110
|
}
|
120
|
-
|
121
111
|
function getHeadersFromMarkdown(markdownContent) {
|
122
112
|
const tokens = marked.lexer(markdownContent);
|
123
113
|
const headers = tokens.filter(v => v.type === 'heading' && v.depth <= 2);
|
124
114
|
return headers || [];
|
125
115
|
}
|
126
|
-
|
127
116
|
function getComponents(openApiSpec) {
|
128
117
|
if (!openApiSpec.components) {
|
129
118
|
return [];
|
130
119
|
}
|
131
|
-
|
132
120
|
const components = [];
|
133
|
-
|
134
|
-
|
135
|
-
const subComponents = Object.keys(openApiSpec.components[component]).map(sComponent => ({
|
121
|
+
for (const componentKeyId in openApiSpec.components) {
|
122
|
+
const subComponents = Object.keys(openApiSpec.components[componentKeyId]).map(sComponent => ({
|
136
123
|
expanded: true,
|
137
|
-
id: `${
|
124
|
+
id: `${componentKeyId.toLowerCase()}-${sComponent.toLowerCase()}`.replace(invalidCharsRegEx, '-'),
|
138
125
|
name: sComponent,
|
139
|
-
component: openApiSpec.components[
|
126
|
+
component: openApiSpec.components[componentKeyId][sComponent]
|
140
127
|
})).sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
switch (component) {
|
145
|
-
case 'schemas':
|
146
|
-
cmpName = getI18nText('menu.schemas');
|
147
|
-
cmpDescription = '';
|
148
|
-
break;
|
149
|
-
|
150
|
-
case 'responses':
|
151
|
-
cmpName = 'Responses';
|
152
|
-
cmpDescription = 'Describes responses from an API Operation, including design-time, static links to operations based on the response.';
|
153
|
-
break;
|
154
|
-
|
155
|
-
case 'parameters':
|
156
|
-
cmpName = 'Parameters';
|
157
|
-
cmpDescription = 'Describes operation parameters. A unique parameter is defined by a combination of a name and location.';
|
158
|
-
break;
|
159
|
-
|
160
|
-
case 'examples':
|
161
|
-
cmpName = 'Examples';
|
162
|
-
cmpDescription = 'List of Examples for operations, can be requests, responses and objects examples.';
|
163
|
-
break;
|
164
|
-
|
165
|
-
case 'requestBodies':
|
166
|
-
break;
|
167
|
-
|
168
|
-
case 'headers':
|
169
|
-
cmpName = 'Headers';
|
170
|
-
cmpDescription = 'Headers follows the structure of the Parameters but they are explicitly in "header"';
|
171
|
-
break;
|
172
|
-
|
173
|
-
case 'securitySchemes':
|
174
|
-
case 'securitySchemas':
|
175
|
-
break;
|
176
|
-
|
177
|
-
case 'links':
|
178
|
-
cmpName = 'Links';
|
179
|
-
cmpDescription = 'Links represent a possible design-time link for a response. The presence of a link does not guarantee the caller\'s ability to successfully invoke it, rather it provides a known relationship and traversal mechanism between responses and other operations.';
|
180
|
-
break;
|
181
|
-
|
182
|
-
case 'callbacks':
|
183
|
-
cmpName = 'Callbacks'; // eslint-disable-next-line max-len
|
184
|
-
|
185
|
-
cmpDescription = 'A map of possible out-of band callbacks related to the parent operation. Each value in the map is a Path Item Object that describes a set of requests that may be initiated by the API provider and the expected responses. The key value used to identify the path item object is an expression, evaluated at runtime, that identifies a URL to use for the callback operation.';
|
186
|
-
break;
|
187
|
-
|
188
|
-
default:
|
189
|
-
cmpName = component;
|
190
|
-
cmpDescription = component;
|
191
|
-
break;
|
192
|
-
}
|
193
|
-
|
194
|
-
if (cmpName) {
|
195
|
-
components.push({
|
196
|
-
expanded: true,
|
197
|
-
name: cmpName,
|
198
|
-
description: cmpDescription,
|
199
|
-
subComponents
|
200
|
-
});
|
128
|
+
if (componentKeyId === 'requestBodies' || componentKeyId === 'securitySchemes' || componentKeyId === 'securitySchemas') {
|
129
|
+
continue;
|
201
130
|
}
|
131
|
+
components.push({
|
132
|
+
expanded: true,
|
133
|
+
componentKeyId,
|
134
|
+
subComponents
|
135
|
+
});
|
202
136
|
}
|
203
|
-
|
204
137
|
return components;
|
205
138
|
}
|
206
|
-
|
207
139
|
function groupByTags(openApiSpec) {
|
208
140
|
const supportedMethods = ['get', 'query', 'put', 'post', 'patch', 'delete', 'head', 'options']; // this is also used for ordering endpoints by methods
|
209
|
-
|
210
141
|
const tags = openApiSpec.tags && Array.isArray(openApiSpec.tags) ? openApiSpec.tags.map(t => {
|
211
142
|
const name = typeof t === 'string' ? t : t.name;
|
212
143
|
return {
|
@@ -219,42 +150,32 @@ function groupByTags(openApiSpec) {
|
|
219
150
|
};
|
220
151
|
}) : [];
|
221
152
|
const pathsAndWebhooks = openApiSpec.paths || {};
|
222
|
-
|
223
153
|
if (openApiSpec.webhooks) {
|
224
154
|
for (const [key, value] of Object.entries(openApiSpec.webhooks)) {
|
225
155
|
value._type = 'webhook'; // eslint-disable-line no-underscore-dangle
|
226
|
-
|
227
156
|
pathsAndWebhooks[key] = value;
|
228
157
|
}
|
229
|
-
}
|
230
|
-
|
231
|
-
|
158
|
+
}
|
159
|
+
// For each path find the tag and push it into the corresponding tag
|
232
160
|
for (const pathOrHookName in pathsAndWebhooks) {
|
233
161
|
const commonPathPropServers = pathsAndWebhooks[pathOrHookName].servers || [];
|
234
162
|
const isWebhook = pathsAndWebhooks[pathOrHookName]._type === 'webhook'; // eslint-disable-line no-underscore-dangle
|
235
|
-
|
236
163
|
supportedMethods.forEach(methodName => {
|
237
164
|
const commonParams = cloneDeep(pathsAndWebhooks[pathOrHookName].parameters);
|
238
|
-
|
239
165
|
if (pathsAndWebhooks[pathOrHookName][methodName]) {
|
240
|
-
const pathOrHookObj = openApiSpec.paths[pathOrHookName][methodName];
|
241
|
-
|
166
|
+
const pathOrHookObj = openApiSpec.paths[pathOrHookName][methodName];
|
167
|
+
// If path.methods are tagged, else generate it from path
|
242
168
|
const pathTags = Array.isArray(pathOrHookObj.tags) ? pathOrHookObj.tags : pathOrHookObj.tags && [pathOrHookObj.tags] || [];
|
243
|
-
|
244
169
|
if (pathTags.length === 0) {
|
245
170
|
pathTags.push('General ⦂');
|
246
171
|
}
|
247
|
-
|
248
172
|
pathTags.forEach(tag => {
|
249
173
|
let tagObj;
|
250
174
|
let specTagsItem;
|
251
|
-
|
252
175
|
if (openApiSpec.tags) {
|
253
176
|
specTagsItem = tags.find(v => v.name.toLowerCase() === tag.toLowerCase());
|
254
177
|
}
|
255
|
-
|
256
178
|
tagObj = tags.find(v => v.name === tag);
|
257
|
-
|
258
179
|
if (!tagObj) {
|
259
180
|
tagObj = {
|
260
181
|
elementId: `tag--${tag.replace(invalidCharsRegEx, '-')}`,
|
@@ -265,25 +186,21 @@ function groupByTags(openApiSpec) {
|
|
265
186
|
expanded: true
|
266
187
|
};
|
267
188
|
tags.push(tagObj);
|
268
|
-
}
|
269
|
-
|
189
|
+
}
|
270
190
|
|
191
|
+
// Generate a short summary which is broken
|
271
192
|
let shortSummary = (pathOrHookObj.summary || pathOrHookObj.description || `${methodName.toUpperCase()} ${pathOrHookName}`).trim();
|
272
|
-
|
273
193
|
if (shortSummary.length > 100) {
|
274
194
|
shortSummary = shortSummary.split(/[.|!|?]\s|[\r?\n]/)[0]; // take the first line (period or carriage return)
|
275
|
-
}
|
276
|
-
|
277
|
-
|
195
|
+
}
|
196
|
+
// Merge Common Parameters with This methods parameters
|
278
197
|
let finalParameters = [];
|
279
|
-
|
280
198
|
if (commonParams) {
|
281
199
|
if (pathOrHookObj.parameters) {
|
282
200
|
finalParameters = commonParams.filter(commonParam => {
|
283
201
|
if (!pathOrHookObj.parameters.some(param => commonParam.name === param.name && commonParam.in === param.in)) {
|
284
202
|
return commonParam;
|
285
203
|
}
|
286
|
-
|
287
204
|
return undefined;
|
288
205
|
}).concat(pathOrHookObj.parameters);
|
289
206
|
} else {
|
@@ -291,22 +208,21 @@ function groupByTags(openApiSpec) {
|
|
291
208
|
}
|
292
209
|
} else {
|
293
210
|
finalParameters = pathOrHookObj.parameters ? pathOrHookObj.parameters.slice(0) : [];
|
294
|
-
}
|
295
|
-
|
211
|
+
}
|
296
212
|
|
213
|
+
// Remove bad callbacks
|
297
214
|
if (pathOrHookObj.callbacks) {
|
298
215
|
for (const [callbackName, callbackConfig] of Object.entries(pathOrHookObj.callbacks)) {
|
299
216
|
const originalCallbackEntries = Object.entries(callbackConfig);
|
300
217
|
const filteredCallbacks = originalCallbackEntries.filter(entry => typeof entry[1] === 'object') || [];
|
301
218
|
pathOrHookObj.callbacks[callbackName] = Object.fromEntries(filteredCallbacks);
|
302
|
-
|
303
219
|
if (filteredCallbacks.length !== originalCallbackEntries.length) {
|
304
220
|
console.warn(`OpenAPI Explorer: Invalid Callback found in ${callbackName}`); // eslint-disable-line no-console
|
305
221
|
}
|
306
222
|
}
|
307
|
-
}
|
308
|
-
|
223
|
+
}
|
309
224
|
|
225
|
+
// Update Responses
|
310
226
|
const pathObject = {
|
311
227
|
expanded: false,
|
312
228
|
isWebhook,
|
@@ -338,6 +254,5 @@ function groupByTags(openApiSpec) {
|
|
338
254
|
}
|
339
255
|
}); // End of Methods
|
340
256
|
}
|
341
|
-
|
342
257
|
return tags;
|
343
258
|
}
|
package/dist/es/utils/theme.js
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
import { html } from 'lit';
|
2
2
|
import color from 'color';
|
3
3
|
import ColorUtils from './color-utils.js';
|
4
|
+
|
4
5
|
/* Generates an schema object containing type and constraint info */
|
5
|
-
// TODO: possible drive theme from:
|
6
6
|
|
7
|
+
// TODO: possible drive theme from:
|
7
8
|
/*
|
8
9
|
if (!this.theme || !'light, dark,'.includes(`${this.theme},`)) {
|
9
10
|
this.theme = (window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches) ? 'light' : 'dark';
|
@@ -14,16 +15,11 @@ export default function setTheme(theme = {}) {
|
|
14
15
|
const bg1 = theme.bg1 ? theme.bg1 : '#ffffff';
|
15
16
|
const fg1 = theme.fg1 ? theme.fg1 : '#444444';
|
16
17
|
const bg2 = theme.bg2 ? theme.bg2 : ColorUtils.color.brightness(bg1, -5); // or '#fafafa'
|
17
|
-
|
18
18
|
const bg3 = theme.bg3 ? theme.bg3 : ColorUtils.color.brightness(bg1, -15); // or '#f6f6f6'
|
19
|
-
|
20
19
|
const lightBg = theme.bg3 ? theme.bg3 : ColorUtils.color.brightness(bg1, -45);
|
21
20
|
const fg2 = theme.fg2 ? theme.fg2 : ColorUtils.color.brightness(fg1, 17); // or '#555'
|
22
|
-
|
23
21
|
const fg3 = theme.fg3 ? theme.fg3 : ColorUtils.color.brightness(fg1, 30); // or #666
|
24
|
-
|
25
22
|
const lightFg = theme.fg3 ? theme.fg3 : ColorUtils.color.brightness(fg1, 70); // or #999
|
26
|
-
|
27
23
|
const inlineCodeFg = theme.inlineCodeFg ? theme.inlineCodeFg : 'brown';
|
28
24
|
const selectionBg = '#444';
|
29
25
|
const selectionFg = '#eee';
|
@@ -66,6 +62,7 @@ export default function setTheme(theme = {}) {
|
|
66
62
|
// #dedede
|
67
63
|
hoverColor: theme.hoverColor || ColorUtils.color.brightness(bg1, -5),
|
68
64
|
// # f1f1f1
|
65
|
+
|
69
66
|
codeFg: theme.codeFg || '#666',
|
70
67
|
codePropertyColor: theme.codePropertyColor || '#905',
|
71
68
|
codeKeywordColor: theme.codeKeywordColor || '#07a',
|
package/dist/es/utils/xml/xml.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
/* eslint-disable no-underscore-dangle */
|
2
|
+
|
2
3
|
const XML_CHARACTER_MAP = {
|
3
4
|
'&': '&',
|
4
5
|
'"': '"',
|
@@ -6,47 +7,38 @@ const XML_CHARACTER_MAP = {
|
|
6
7
|
'<': '<',
|
7
8
|
'>': '>'
|
8
9
|
};
|
9
|
-
|
10
10
|
function escapeForXML(string) {
|
11
11
|
return string && string.replace ? string.replace(/([&"<>'])/g, function (str, item) {
|
12
12
|
return XML_CHARACTER_MAP[item];
|
13
13
|
}) : string;
|
14
14
|
}
|
15
|
-
|
16
15
|
const DEFAULT_INDENT = ' ';
|
17
16
|
export default function xml(input, rawOptions) {
|
18
17
|
let options = rawOptions;
|
19
|
-
|
20
18
|
if (typeof options !== 'object') {
|
21
19
|
options = {
|
22
20
|
indent: options
|
23
21
|
};
|
24
22
|
}
|
25
|
-
|
26
23
|
let output = '';
|
27
24
|
const indent = !options.indent ? '' : options.indent === true ? DEFAULT_INDENT : options.indent;
|
28
|
-
|
29
25
|
function append(_, out) {
|
30
26
|
if (out !== undefined) {
|
31
27
|
output += out;
|
32
28
|
}
|
33
29
|
}
|
34
|
-
|
35
30
|
function add(value, last) {
|
36
31
|
format(append, resolve(value, indent, indent ? 1 : 0), last);
|
37
32
|
}
|
38
|
-
|
39
33
|
function addXmlDeclaration(declaration) {
|
40
34
|
const encoding = declaration.encoding || 'UTF-8';
|
41
35
|
const attr = {
|
42
36
|
version: '1.0',
|
43
37
|
encoding: encoding
|
44
38
|
};
|
45
|
-
|
46
39
|
if (declaration.standalone) {
|
47
40
|
attr.standalone = declaration.standalone;
|
48
41
|
}
|
49
|
-
|
50
42
|
add({
|
51
43
|
'?xml': {
|
52
44
|
_attr: attr
|
@@ -54,11 +46,9 @@ export default function xml(input, rawOptions) {
|
|
54
46
|
});
|
55
47
|
output = output.replace('/>', '?>');
|
56
48
|
}
|
57
|
-
|
58
49
|
if (options.declaration) {
|
59
50
|
addXmlDeclaration(options.declaration);
|
60
51
|
}
|
61
|
-
|
62
52
|
if (input && input.forEach) {
|
63
53
|
input.forEach(function (value, i) {
|
64
54
|
add(value, i + 1 === input.length);
|
@@ -66,26 +56,21 @@ export default function xml(input, rawOptions) {
|
|
66
56
|
} else {
|
67
57
|
add(input, true);
|
68
58
|
}
|
69
|
-
|
70
59
|
return output;
|
71
60
|
}
|
72
|
-
|
73
61
|
function create_indent(character, count) {
|
74
62
|
return new Array(count || 0).join(character || '');
|
75
63
|
}
|
76
|
-
|
77
64
|
function resolve(data, indent, indent_count_raw) {
|
78
65
|
const indent_count = indent_count_raw || 0;
|
79
66
|
const indent_spaces = create_indent(indent, indent_count);
|
80
67
|
let name;
|
81
68
|
let values = data;
|
82
69
|
const interrupt = false;
|
83
|
-
|
84
70
|
if (typeof data === 'object') {
|
85
71
|
const keys = Object.keys(data);
|
86
72
|
name = keys[0];
|
87
73
|
values = data[name];
|
88
|
-
|
89
74
|
if (values && values._elem) {
|
90
75
|
values._elem.name = name;
|
91
76
|
values._elem.icount = indent_count;
|
@@ -95,39 +80,32 @@ function resolve(data, indent, indent_count_raw) {
|
|
95
80
|
return values._elem;
|
96
81
|
}
|
97
82
|
}
|
98
|
-
|
99
83
|
const attributes = [];
|
100
84
|
const content = [];
|
101
85
|
let isStringContent;
|
102
|
-
|
103
86
|
function get_attributes(obj) {
|
104
87
|
const keys = Object.keys(obj);
|
105
88
|
keys.forEach(function (key) {
|
106
89
|
attributes.push(attribute(key, obj[key]));
|
107
90
|
});
|
108
91
|
}
|
109
|
-
|
110
92
|
switch (typeof values) {
|
111
93
|
case 'object':
|
112
94
|
if (values === null) {
|
113
95
|
break;
|
114
96
|
}
|
115
|
-
|
116
97
|
if (values._attr) {
|
117
98
|
get_attributes(values._attr);
|
118
99
|
}
|
119
|
-
|
120
100
|
if (values._cdata) {
|
121
101
|
content.push(`${`<![CDATA[${values._cdata}`.replace(/\]\]>/g, ']]]]><![CDATA[>')}]]>`);
|
122
102
|
}
|
123
|
-
|
124
103
|
if (values.forEach) {
|
125
104
|
isStringContent = false;
|
126
105
|
content.push('');
|
127
106
|
values.forEach(function (value) {
|
128
107
|
if (typeof value === 'object') {
|
129
108
|
const _name = Object.keys(value)[0];
|
130
|
-
|
131
109
|
if (_name === '_attr') {
|
132
110
|
get_attributes(value._attr);
|
133
111
|
} else {
|
@@ -140,19 +118,15 @@ function resolve(data, indent, indent_count_raw) {
|
|
140
118
|
content.push(escapeForXML(value));
|
141
119
|
}
|
142
120
|
});
|
143
|
-
|
144
121
|
if (!isStringContent) {
|
145
122
|
content.push('');
|
146
123
|
}
|
147
124
|
}
|
148
|
-
|
149
125
|
break;
|
150
|
-
|
151
126
|
default:
|
152
127
|
// string
|
153
128
|
content.push(escapeForXML(values));
|
154
129
|
}
|
155
|
-
|
156
130
|
return {
|
157
131
|
name: name,
|
158
132
|
interrupt: interrupt,
|
@@ -163,33 +137,25 @@ function resolve(data, indent, indent_count_raw) {
|
|
163
137
|
indent: indent
|
164
138
|
};
|
165
139
|
}
|
166
|
-
|
167
140
|
function format(append, elem, end) {
|
168
141
|
if (typeof elem !== 'object') {
|
169
142
|
append(false, elem);
|
170
143
|
return;
|
171
144
|
}
|
172
|
-
|
173
145
|
const len = elem.interrupt ? 1 : elem.content.length;
|
174
|
-
|
175
146
|
function proceed() {
|
176
147
|
while (elem.content.length) {
|
177
148
|
const value = elem.content.shift();
|
178
|
-
|
179
149
|
if (value === undefined) {
|
180
150
|
continue;
|
181
151
|
}
|
182
|
-
|
183
152
|
if (interrupt(value)) {
|
184
153
|
return;
|
185
154
|
}
|
186
|
-
|
187
155
|
format(append, value);
|
188
156
|
}
|
189
|
-
|
190
157
|
append(false, (len > 1 ? elem.indents : '') + (elem.name ? `</${elem.name}>` : '') + (elem.indent && !end ? '\n' : ''));
|
191
158
|
}
|
192
|
-
|
193
159
|
function interrupt(value) {
|
194
160
|
if (value.interrupt) {
|
195
161
|
value.interrupt.append = append;
|
@@ -198,22 +164,17 @@ function format(append, elem, end) {
|
|
198
164
|
append(true);
|
199
165
|
return true;
|
200
166
|
}
|
201
|
-
|
202
167
|
return false;
|
203
168
|
}
|
204
|
-
|
205
169
|
append(false, elem.indents + (elem.name ? `<${elem.name}` : '') + (elem.attributes.length ? ` ${elem.attributes.join(' ')}` : '') + (len ? elem.name ? '>' : '' : elem.name ? '/>' : '') + (elem.indent && len > 1 ? '\n' : ''));
|
206
|
-
|
207
170
|
if (!len) {
|
208
171
|
append(false, elem.indent ? '\n' : '');
|
209
172
|
return;
|
210
173
|
}
|
211
|
-
|
212
174
|
if (!interrupt(elem)) {
|
213
175
|
proceed();
|
214
176
|
}
|
215
177
|
}
|
216
|
-
|
217
178
|
function attribute(key, value) {
|
218
179
|
return `${key}=` + `"${escapeForXML(value)}"`;
|
219
180
|
}
|