openapi-explorer 0.9.397 → 0.10.400
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 +3 -0
- package/README.md +3 -2
- package/dist/browser/openapi-explorer.min.js +6 -6
- package/dist/browser/openapi-explorer.min.js.map +1 -1
- package/dist/es/components/api-request.js +9 -8
- package/dist/es/components/api-response.js +5 -4
- package/dist/es/components/json-tree.js +3 -2
- package/dist/es/components/mime-types.js +5 -5
- package/dist/es/components/schema-table.js +1 -1
- package/dist/es/components/schema-tree.js +3 -2
- package/dist/es/languages/en.js +59 -0
- package/dist/es/languages/fr.js +59 -0
- package/dist/es/languages/index.js +20 -0
- package/dist/es/openapi-explorer.js +4 -3
- package/dist/es/styles/input-styles.js +1 -1
- package/dist/es/templates/code-samples-template.js +2 -1
- package/dist/es/templates/components-template.js +1 -1
- package/dist/es/templates/navbar-template.js +3 -2
- package/dist/es/templates/overview-template.js +2 -1
- package/dist/es/templates/security-scheme-template.js +6 -5
- package/dist/es/templates/server-template.js +4 -3
- package/dist/es/utils/common-utils.js +4 -2
- package/dist/es/utils/schema-utils.js +1 -1
- package/dist/es/utils/spec-parser.js +3 -2
- package/dist/lib/components/api-request.js +10 -8
- package/dist/lib/components/api-response.js +6 -4
- package/dist/lib/components/json-tree.js +4 -2
- package/dist/lib/components/mime-types.js +8 -9
- package/dist/lib/components/schema-table.js +1 -1
- package/dist/lib/components/schema-tree.js +4 -2
- package/dist/lib/languages/en.js +64 -0
- package/dist/lib/languages/fr.js +64 -0
- package/dist/lib/languages/index.js +32 -0
- package/dist/lib/openapi-explorer.js +5 -3
- package/dist/lib/styles/input-styles.js +1 -1
- package/dist/lib/templates/code-samples-template.js +3 -1
- package/dist/lib/templates/components-template.js +1 -1
- package/dist/lib/templates/navbar-template.js +4 -2
- package/dist/lib/templates/overview-template.js +3 -1
- package/dist/lib/templates/security-scheme-template.js +7 -5
- package/dist/lib/templates/server-template.js +5 -3
- package/dist/lib/utils/common-utils.js +4 -2
- package/dist/lib/utils/schema-utils.js +1 -1
- package/dist/lib/utils/spec-parser.js +4 -2
- package/package.json +7 -4
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
translation: {
|
|
3
|
+
'menu': {
|
|
4
|
+
'filter': 'Filter',
|
|
5
|
+
'search': 'Search',
|
|
6
|
+
'overview': 'Overview',
|
|
7
|
+
'api-servers': 'API Servers',
|
|
8
|
+
'authentication': 'Authentication',
|
|
9
|
+
'operations': 'OPERATIONS',
|
|
10
|
+
'components': 'COMPONENTS',
|
|
11
|
+
'schemas': 'Schemas'
|
|
12
|
+
},
|
|
13
|
+
'headers': {
|
|
14
|
+
'api-servers': 'API SERVER',
|
|
15
|
+
'authentication': 'AUTHENTICATION'
|
|
16
|
+
},
|
|
17
|
+
'overview': {
|
|
18
|
+
'email': 'Email',
|
|
19
|
+
'terms-of-service': 'Terms of Service'
|
|
20
|
+
},
|
|
21
|
+
'api-servers': {
|
|
22
|
+
'server-variables': 'SERVER VARIABLES',
|
|
23
|
+
'selected': 'SELECTED'
|
|
24
|
+
},
|
|
25
|
+
'authentication': {
|
|
26
|
+
'no-api-key-applied': 'No API key applied',
|
|
27
|
+
'http-basic': 'HTTP Basic',
|
|
28
|
+
'http-basic-desc': 'Send the Authorization header containing the type Basic followed by a space and a base64 encoded string of username:password',
|
|
29
|
+
'username': 'username',
|
|
30
|
+
'password': 'password',
|
|
31
|
+
'requires': 'Requires',
|
|
32
|
+
'http-basic-note': 'Base 64 encoded username:password',
|
|
33
|
+
'in-auth-header': 'in Authorization header',
|
|
34
|
+
'set': 'SET'
|
|
35
|
+
},
|
|
36
|
+
'operations': {
|
|
37
|
+
'request': 'REQUEST',
|
|
38
|
+
'request-body': 'REQUEST BODY',
|
|
39
|
+
'model': 'MODEL',
|
|
40
|
+
'body': 'BODY',
|
|
41
|
+
'request-headers': 'REQUEST HEADERS',
|
|
42
|
+
'clear': 'CLEAR',
|
|
43
|
+
'clear-response': 'CLEAR RESPONSE',
|
|
44
|
+
'execute': 'EXECUTE',
|
|
45
|
+
'response': 'RESPONSE',
|
|
46
|
+
'response-headers': 'RESPONSE HEADERS',
|
|
47
|
+
'example': 'EXAMPLE',
|
|
48
|
+
'response-status': 'Response Status',
|
|
49
|
+
'fetch-fail': 'Failed to fetch (Check the browser network tab for more information.)',
|
|
50
|
+
'copy': 'Copy',
|
|
51
|
+
'copied': 'Copied'
|
|
52
|
+
},
|
|
53
|
+
'schemas': {
|
|
54
|
+
'collapse-desc': 'Collapse',
|
|
55
|
+
'expand-desc': 'Expand',
|
|
56
|
+
'schema-missing': 'Schema not found'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
translation: {
|
|
3
|
+
'menu': {
|
|
4
|
+
'filter': 'Filtre',
|
|
5
|
+
'search': 'Chercher',
|
|
6
|
+
'overview': 'Aperçu',
|
|
7
|
+
'api-servers': 'Serveur API',
|
|
8
|
+
'authentication': 'Authentification',
|
|
9
|
+
'operations': 'OPÉRATIONS',
|
|
10
|
+
'components': 'COMPOSANTS',
|
|
11
|
+
'schemas': 'Schémas'
|
|
12
|
+
},
|
|
13
|
+
'headers': {
|
|
14
|
+
'api-servers': 'SERVEUR API',
|
|
15
|
+
'authentication': 'AUTHENTIFICATION'
|
|
16
|
+
},
|
|
17
|
+
'overview': {
|
|
18
|
+
'email': 'Courriel',
|
|
19
|
+
'terms-of-service': 'Avis'
|
|
20
|
+
},
|
|
21
|
+
'api-servers': {
|
|
22
|
+
'server-variables': 'VARIABLES SERVEUR',
|
|
23
|
+
'selected': 'CHOISI'
|
|
24
|
+
},
|
|
25
|
+
'authentication': {
|
|
26
|
+
'no-api-key-applied': "Aucune clé d'API appliquée",
|
|
27
|
+
'http-basic': 'HTTP Basique',
|
|
28
|
+
'http-basic-desc': "Envoyez l'en-tête Authorization contenant le type Basic suivi d'un espace et d'une chaîne encodée en base64 de nom d'utilisateur:mot de passe",
|
|
29
|
+
'username': "nom d'utilisateur",
|
|
30
|
+
'password': 'mot de passe',
|
|
31
|
+
'requires': 'Nécessite',
|
|
32
|
+
'http-basic-note': "un nom d'utilisateur/mot de passe encodé en base64",
|
|
33
|
+
'in-auth-header': "dans l'en-tête Authorization",
|
|
34
|
+
'set': 'DÉFINIR'
|
|
35
|
+
},
|
|
36
|
+
'operations': {
|
|
37
|
+
'request': 'REQUÊTE',
|
|
38
|
+
'request-body': 'CORPS DE LA REQUÊTE',
|
|
39
|
+
'model': 'MODÈLE',
|
|
40
|
+
'body': 'CORPS',
|
|
41
|
+
'request-headers': 'EN-TÊTES DE LA REQUÊTE',
|
|
42
|
+
'clear': 'VIDER',
|
|
43
|
+
'clear-response': 'VIDER LA RÉPONSE',
|
|
44
|
+
'execute': 'EXÉCUTER',
|
|
45
|
+
'response': 'RÉPONSE',
|
|
46
|
+
'response-headers': 'EN-TÊTES DE LA RÉPONSE',
|
|
47
|
+
'example': 'EXEMPLE',
|
|
48
|
+
'response-status': 'Statut de réponse',
|
|
49
|
+
'fetch-fail': "Échec d'obtenir (Consultez l'onglet Réseau de navigateur pour plus d'information.)",
|
|
50
|
+
'copy': 'Copier',
|
|
51
|
+
'copied': 'Copié'
|
|
52
|
+
},
|
|
53
|
+
'schemas': {
|
|
54
|
+
'collapse-desc': 'Réduire',
|
|
55
|
+
'expand-desc': 'Agrandir',
|
|
56
|
+
'schema-missing': 'Schéma introuvable'
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import i18next from 'i18next';
|
|
2
|
+
import en from './en';
|
|
3
|
+
import fr from './fr';
|
|
4
|
+
export async function initI18n() {
|
|
5
|
+
const initLang = window.navigator.language.substring(0, 2);
|
|
6
|
+
await i18next.init({
|
|
7
|
+
lng: initLang,
|
|
8
|
+
fallbackLng: 'en',
|
|
9
|
+
debug: true,
|
|
10
|
+
ns: ['translation'],
|
|
11
|
+
defaultNS: 'translation',
|
|
12
|
+
resources: {
|
|
13
|
+
en,
|
|
14
|
+
fr
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
export function getI18nText(key) {
|
|
19
|
+
return i18next.t(key);
|
|
20
|
+
}
|
|
@@ -12,7 +12,7 @@ import 'prismjs/components/prism-python';
|
|
|
12
12
|
import 'prismjs/components/prism-http';
|
|
13
13
|
import 'prismjs/components/prism-csharp'; // Styles
|
|
14
14
|
|
|
15
|
-
import FontStyles from './styles/font-styles';
|
|
15
|
+
import FontStyles from './styles/font-styles.js';
|
|
16
16
|
import InputStyles from './styles/input-styles';
|
|
17
17
|
import FlexStyles from './styles/flex-styles';
|
|
18
18
|
import TableStyles from './styles/table-styles';
|
|
@@ -23,6 +23,7 @@ import NavStyles from './styles/nav-styles';
|
|
|
23
23
|
import InfoStyles from './styles/info-styles';
|
|
24
24
|
import advancedSearchStyles from './styles/advanced-search-styles';
|
|
25
25
|
import { advancedSearch, getCurrentElement, replaceState, sleep } from './utils/common-utils';
|
|
26
|
+
import { initI18n } from './languages';
|
|
26
27
|
import ProcessSpec from './utils/spec-parser';
|
|
27
28
|
import responsiveViewMainBodyTemplate from './templates/responsiveViewMainBodyTemplate';
|
|
28
29
|
import apiRequestStyles from './styles/api-request-styles';
|
|
@@ -218,7 +219,7 @@ export default class OpenApiExplorer extends LitElement {
|
|
|
218
219
|
}
|
|
219
220
|
|
|
220
221
|
static get styles() {
|
|
221
|
-
return [FontStyles, InputStyles, FlexStyles, TableStyles, EndpointStyles, PrismStyles, TabStyles, NavStyles, InfoStyles, advancedSearchStyles, apiRequestStyles, css`:not(:defined){display:none}:host{display:flex;flex-direction:column;width:100%;height:100%;margin:0;padding:0;overflow:hidden;letter-spacing:normal;color:var(--fg);background-color:var(--bg);font-family:var(--font-regular)}.body{display:flex;height:100%;width:100%;overflow:hidden}.main-content{margin:0;padding:0;display:block;flex:1;height:100%;overflow-y:overlay;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:var(--border-color) transparent}.main-content::-webkit-scrollbar{width:8px;height:8px}.main-content::-webkit-scrollbar-track{background:0 0}.main-content::-webkit-scrollbar-thumb{background-color:var(--border-color)}.section-gap.section-tag{border-bottom:1px solid var(--border-color)}.method-section-gap{padding:24px 8px 0 4px}.section-gap{padding:24px 0 0}.section-tag-header{position:relative;cursor:n-resize;padding:12px 0}.collapsed .section-tag-header:hover{cursor:s-resize}.section-tag-header:hover{background-image:linear-gradient(to right,rgba(0,0,0,0),var(--border-color),rgba(0,0,0,0))}.collapsed .section-tag-header:hover::after{color:var(--primary-color)}.collapsed .section-tag-body{display:none}.logo{height:36px;width:36px;margin-left:5px}.only-large-screen,.only-large-screen-flex{display:none}.header-title{font-size:calc(var(--font-size-regular) + 8px);padding:0 8px}.tag.title{text-transform:uppercase}.header{background-color:var(--header-bg);color:var(--header-fg);width:100%}input.header-input{background:var(--header-color-darker);color:var(--header-fg);border:1px solid var(--header-color-border);flex:1;padding-right:24px;border-radius:3px}input.header-input::placeholder{opacity:.4}input:disabled{cursor:not-allowed}.loader{margin:16px auto 16px auto;border:4px solid var(--bg3);border-radius:50%;border-top:4px solid var(--primary-color);width:36px;height:36px;animation:spin 2s linear infinite}.expanded-endpoint-body{position:relative;padding:6px 0}.divider{border-top:2px solid var(--border-color);margin:24px 0;width:100%}.tooltip{border:1px solid var(--border-color);border-left-width:4px;margin-left:2px}.tooltip a{color:var(--fg2);text-decoration:none}.tooltip-text{color:var(--fg2);background-color:var(--bg2);visibility:hidden;overflow-wrap:break-word}.tooltip:hover{color:var(--primary-color);border-color:var(--primary-color)}.tooltip:hover a:hover{color:var(--primary-color)}.tooltip:hover .tooltip-text{visibility:visible;opacity:1}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media only screen and (max-width:767.98px){.section-padding{margin:1rem}.sub-title.tag{margin-left:1rem}.section-tag-body .description{margin-left:1rem;margin-right:1rem}}@media only screen and (min-width:768px){.nav-bar{width:260px;display:flex}.only-large-screen{display:block}.only-large-screen-flex{display:flex}.section-gap{padding:24px 24px}.section-gap--read-mode{padding:24px 8px}.section-gap--focused-mode{padding:
|
|
222
|
+
return [FontStyles, InputStyles, FlexStyles, TableStyles, EndpointStyles, PrismStyles, TabStyles, NavStyles, InfoStyles, advancedSearchStyles, apiRequestStyles, css`:not(:defined){display:none}:host{display:flex;flex-direction:column;width:100%;height:100%;margin:0;padding:0;overflow:hidden;letter-spacing:normal;color:var(--fg);background-color:var(--bg);font-family:var(--font-regular)}.body{display:flex;height:100%;width:100%;overflow:hidden}.main-content{margin:0;padding:0;display:block;flex:1;height:100%;overflow-y:overlay;overflow-x:hidden;scrollbar-width:thin;scrollbar-color:var(--border-color) transparent}.main-content::-webkit-scrollbar{width:8px;height:8px}.main-content::-webkit-scrollbar-track{background:0 0}.main-content::-webkit-scrollbar-thumb{background-color:var(--border-color)}.section-gap.section-tag{border-bottom:1px solid var(--border-color)}.method-section-gap{padding:24px 8px 0 4px}.section-gap{padding:24px 0 0}.section-tag-header{position:relative;cursor:n-resize;padding:12px 0}.collapsed .section-tag-header:hover{cursor:s-resize}.section-tag-header:hover{background-image:linear-gradient(to right,rgba(0,0,0,0),var(--border-color),rgba(0,0,0,0))}.collapsed .section-tag-header:hover::after{color:var(--primary-color)}.collapsed .section-tag-body{display:none}.logo{height:36px;width:36px;margin-left:5px}.only-large-screen,.only-large-screen-flex{display:none}.header-title{font-size:calc(var(--font-size-regular) + 8px);padding:0 8px}.tag.title{text-transform:uppercase}.header{background-color:var(--header-bg);color:var(--header-fg);width:100%}input.header-input{background:var(--header-color-darker);color:var(--header-fg);border:1px solid var(--header-color-border);flex:1;padding-right:24px;border-radius:3px}input.header-input::placeholder{opacity:.4}input:disabled{cursor:not-allowed}.loader{margin:16px auto 16px auto;border:4px solid var(--bg3);border-radius:50%;border-top:4px solid var(--primary-color);width:36px;height:36px;animation:spin 2s linear infinite}.expanded-endpoint-body{position:relative;padding:6px 0}.divider{border-top:2px solid var(--border-color);margin:24px 0;width:100%}.tooltip{border:1px solid var(--border-color);border-left-width:4px;margin-left:2px}.tooltip a{color:var(--fg2);text-decoration:none}.tooltip-text{color:var(--fg2);background-color:var(--bg2);visibility:hidden;overflow-wrap:break-word}.tooltip:hover{color:var(--primary-color);border-color:var(--primary-color)}.tooltip:hover a:hover{color:var(--primary-color)}.tooltip:hover .tooltip-text{visibility:visible;opacity:1}@keyframes spin{0%{transform:rotate(0)}100%{transform:rotate(360deg)}}@media only screen and (max-width:767.98px){.section-padding{margin:1rem}.sub-title.tag{margin-left:1rem}.section-tag-body .description{margin-left:1rem;margin-right:1rem}}@media only screen and (min-width:768px){.nav-bar{width:260px;display:flex}.only-large-screen{display:block}.only-large-screen-flex{display:flex}.section-gap{padding:24px 24px}.section-gap--read-mode{padding:24px 8px}.section-gap--focused-mode{padding:1.5rem}.endpoint-body{position:relative;padding:36px 0 48px 0}}@media only screen and (min-width:1024px){.nav-bar{width:${unsafeCSS(this.fontSize === 'default' ? '300px' : this.fontSize === 'large' ? '315px' : '330px')};display:flex}.section-gap--read-mode{padding:24px 24px 12px}.main-content-inner{padding:24px}}`];
|
|
222
223
|
} // Startup
|
|
223
224
|
|
|
224
225
|
|
|
@@ -227,6 +228,7 @@ export default class OpenApiExplorer extends LitElement {
|
|
|
227
228
|
this.handleResize = this.handleResize.bind(this);
|
|
228
229
|
window.addEventListener('resize', this.handleResize);
|
|
229
230
|
this.loading = true;
|
|
231
|
+
initI18n();
|
|
230
232
|
const parent = this.parentElement;
|
|
231
233
|
|
|
232
234
|
if (parent) {
|
|
@@ -373,7 +375,6 @@ export default class OpenApiExplorer extends LitElement {
|
|
|
373
375
|
attributeChangedCallback(name, oldVal, newVal) {
|
|
374
376
|
if (name === 'spec-url') {
|
|
375
377
|
if (oldVal !== newVal) {
|
|
376
|
-
// put it at the end of event-loop to load all the attributes
|
|
377
378
|
window.setTimeout(async () => {
|
|
378
379
|
await this.loadSpec(newVal); // If the initial location is set, then attempt to scroll there
|
|
379
380
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { css } from 'lit-element';
|
|
2
2
|
/* eslint-disable max-len */
|
|
3
3
|
|
|
4
|
-
export default css`.m-btn{border-radius:var(--border-radius);font-weight:600;display:inline-block;padding:6px 16px;font-size:var(--font-size-small);outline:0;line-height:1;text-align:center;white-space:nowrap;border:2px solid var(--primary-color);background-color:transparent;transition:background-color .2s;user-select:none;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.m-btn.primary{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.thin-border{border-width:1px}.m-btn.large{padding:8px 14px}.m-btn.small{padding:5px 12px}.m-btn.tiny{padding:5px 6px}.m-btn.circle{border-radius:50%}.m-btn:hover{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.nav{border:2px solid var(--secondary-color)}.m-btn.nav:hover{background-color:var(--secondary-color)}.m-btn:disabled{background-color:var(--bg3);color:var(--fg3);border-color:var(--fg3);cursor:progress;opacity:.4}.toolbar-copy-btn{cursor:pointer;padding:.125rem .5rem;margin:0 2px;font-size:.8rem;width:
|
|
4
|
+
export default css`.m-btn{border-radius:var(--border-radius);font-weight:600;display:inline-block;padding:6px 16px;font-size:var(--font-size-small);outline:0;line-height:1;text-align:center;white-space:nowrap;border:2px solid var(--primary-color);background-color:transparent;transition:background-color .2s;user-select:none;cursor:pointer;box-shadow:0 1px 3px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.24)}.m-btn.primary{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.thin-border{border-width:1px}.m-btn.large{padding:8px 14px}.m-btn.small{padding:5px 12px}.m-btn.tiny{padding:5px 6px}.m-btn.circle{border-radius:50%}.m-btn:hover{background-color:var(--primary-color);color:var(--primary-btn-text-color)}.m-btn.nav{border:2px solid var(--secondary-color)}.m-btn.nav:hover{background-color:var(--secondary-color)}.m-btn:disabled{background-color:var(--bg3);color:var(--fg3);border-color:var(--fg3);cursor:progress;opacity:.4}.toolbar-copy-btn{cursor:pointer;padding:.125rem .5rem;margin:0 2px;font-size:.8rem;width:60px;color:var(--primary-btn-text-color);border-radius:2px;border:none;background-color:var(--primary-color)}.tab-content .toolbar-copy-btn{position:absolute;top:8px;right:8px;margin-right:8px}.tab-content .toolbar-copy-btn+pre{white-space:pre;max-height:400px;overflow:auto;display:flex;padding-right:70px}button,input,pre,select,textarea{color:var(--fg);outline:0;background-color:var(--input-bg);border:1px solid var(--border-color);border-radius:var(--border-radius)}button{font-family:var(--font-regular)}input[type=file],input[type=password],input[type=text],pre,select,textarea{font-family:var(--font-mono);font-weight:400;font-size:var(--font-size-small);transition:border .2s;padding:6px 5px}select{font-family:var(--font-regular);padding-right:30px;background-image:url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2212%22%20height%3D%2212%22%3E%3Cpath%20d%3D%22M10.3%203.3L6%207.6%201.7%203.3A1%201%200%2000.3%204.7l5%205a1%201%200%20001.4%200l5-5a1%201%200%2010-1.4-1.4z%22%20fill%3D%22%23777777%22%2F%3E%3C%2Fsvg%3E");background-position:calc(100% - 5px) center;background-repeat:no-repeat;background-size:10px;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer}select:hover{border-color:var(--primary-color)}input[type=password]::placeholder,input[type=text]::placeholder,textarea::placeholder{color:var(--placeholder-color);opacity:1}input[type=password]:active,input[type=password]:focus,input[type=text]:active,input[type=text]:focus,select:focus,textarea:active,textarea:focus{border:1px solid var(--primary-color)}input[type=file]{font-family:var(--font-regular);padding:2px;cursor:pointer;border:1px solid var(--primary-color);min-height:calc(var(--font-size-small) + 18px)}input[type=file]::-webkit-file-upload-button{font-family:var(--font-regular);font-size:var(--font-size-small);outline:0;cursor:pointer;padding:3px 8px;border:1px solid var(--primary-color);background-color:var(--primary-color);color:var(--primary-btn-text-color);border-radius:var(--border-radius);-webkit-appearance:none}pre,textarea{scrollbar-width:thin;scrollbar-color:var(--border-color) var(--input-bg)}pre::-webkit-scrollbar,textarea::-webkit-scrollbar{width:8px;height:8px}pre::-webkit-scrollbar-track,textarea::-webkit-scrollbar-track{background:var(--input-bg)}pre::-webkit-scrollbar-thumb,textarea::-webkit-scrollbar-thumb{border-radius:2px;background-color:var(--border-color)}.link{font-size:var(--font-size-small);text-decoration:underline;color:var(--blue);font-family:var(--font-mono);margin-bottom:2px}input[type=checkbox]:focus{outline:0}input[type=checkbox]{appearance:none;display:inline-block;background-color:var(--light-bg);border-radius:9px;cursor:pointer;height:18px;position:relative;transition:border .15s,padding .25s;min-width:36px;width:36px;vertical-align:top}input[type=checkbox]:after{position:absolute;background-color:var(--bg);border-radius:8px;content:'';top:0;left:0;right:16px;display:block;height:16px;transition:left .25s .1s,right .15s .175s}input[type=checkbox]:checked{box-shadow:inset 0 0 0 13px var(--primary-color);border-color:var(--primary-color)}input[type=checkbox]:checked:after{border:1px solid var(--primary-color);left:16px;right:1px;transition:border .25s,left .15s .25s,right .25s .175s}input.oauth-client-id{flex-grow:1;max-width:300px}input.oauth-client-secret{flex-grow:1;max-width:300px}`;
|
|
@@ -2,6 +2,7 @@ import { html } from 'lit-element';
|
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
3
|
import Prism from 'prismjs';
|
|
4
4
|
import { copyToClipboard } from '../utils/common-utils';
|
|
5
|
+
import { getI18nText } from '../languages';
|
|
5
6
|
/* eslint-disable indent */
|
|
6
7
|
|
|
7
8
|
export default function codeSamplesTemplate(xCodeSamples) {
|
|
@@ -19,7 +20,7 @@ export default function codeSamplesTemplate(xCodeSamples) {
|
|
|
19
20
|
});
|
|
20
21
|
}}"> <div class="tab-buttons row" style="width:100"> ${xCodeSamples.map((v, i) => html`<button class="tab-btn ${i === 0 ? 'active' : ''}" data-tab="${v.lang}${i}"> ${v.label || v.lang} </button>`)} </div> ${xCodeSamples.map((v, i) => html` <div class="tab-content m-markdown code-sample-wrapper" style="display:${i === 0 ? 'block' : 'none'}" data-tab="${v.lang}${i}"> <button class="toolbar-copy-btn" @click="${e => {
|
|
21
22
|
copyToClipboard(v.source, e);
|
|
22
|
-
}}"
|
|
23
|
+
}}">${getI18nText('operations.copy')}</button> <pre>
|
|
23
24
|
<code>${Prism.languages[v.lang && v.lang.toLowerCase()] ? unsafeHTML(Prism.highlight(v.source, Prism.languages[v.lang && v.lang.toLowerCase()], v.lang && v.lang.toLowerCase())) : v.source}</code>
|
|
24
25
|
</pre> </div>`)} </div></section>`;
|
|
25
26
|
}
|
|
@@ -14,6 +14,6 @@ function componentBodyTemplate(sComponent) {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export default function componentsTemplate() {
|
|
17
|
-
return html` ${this.resolvedSpec.components.map(component => html` <div id="cmp--${component.name.toLowerCase()}" class="regular-font section-gap--
|
|
17
|
+
return html` ${this.resolvedSpec.components.map(component => html` <div id="cmp--${component.name.toLowerCase()}" class="regular-font section-gap--focused-mode observe-me" style="padding-bottom:0"> <div class="title tag">${component.name}</div> <div class="regular-font-size"> ${unsafeHTML(`<div class='m-markdown regular-font'>${marked(component.description ? component.description : '')}</div>`)} </div> </div> <div class="regular-font section-gap--focused-mode" style="padding-top:0"> ${component.subComponents.filter(c => c.expanded).map(sComponent => componentBodyTemplate.call(this, sComponent))} </div> `)} `;
|
|
18
18
|
}
|
|
19
19
|
/* eslint-enable indent */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { marked } from 'marked';
|
|
3
3
|
import { componentIsInSearch, pathIsInSearch } from '../utils/common-utils';
|
|
4
|
+
import { getI18nText } from '../languages';
|
|
4
5
|
|
|
5
6
|
function onExpandCollapse(tagId) {
|
|
6
7
|
const tag = this.resolvedSpec.tags.find(t => t.elementId === tagId);
|
|
@@ -39,7 +40,7 @@ export function expandCollapseAllComponents() {
|
|
|
39
40
|
export default function navbarTemplate() {
|
|
40
41
|
var _this$resolvedSpec$co;
|
|
41
42
|
|
|
42
|
-
return html` <nav class="nav-bar ${this.renderStyle}" part="section-navbar"> ${this.allowSearch === 'false' && this.allowAdvancedSearch === 'false' ? '' : html` <div style="display:flex;flex-direction:row;justify-content:center;align-items:center;padding:24px;${this.allowAdvancedSearch === 'false' ? 'border-bottom: 1px solid var(--nav-hover-bg-color)' : ''}"> ${this.allowSearch === 'false' ? '' : html` <div style="display:flex;flex:1;line-height:22px"> <input id="nav-bar-search" part="textbox textbox-nav-filter" style="width:100%;padding-right:20px;color:var(--nav-hover-text-color);border-color:var(--secondary-color);background-color:var(--nav-hover-bg-color)" type="text" placeholder="
|
|
43
|
+
return html` <nav class="nav-bar ${this.renderStyle}" part="section-navbar"> ${this.allowSearch === 'false' && this.allowAdvancedSearch === 'false' ? '' : html` <div style="display:flex;flex-direction:row;justify-content:center;align-items:center;padding:24px;${this.allowAdvancedSearch === 'false' ? 'border-bottom: 1px solid var(--nav-hover-bg-color)' : ''}"> ${this.allowSearch === 'false' ? '' : html` <div style="display:flex;flex:1;line-height:22px"> <input id="nav-bar-search" part="textbox textbox-nav-filter" style="width:100%;padding-right:20px;color:var(--nav-hover-text-color);border-color:var(--secondary-color);background-color:var(--nav-hover-bg-color)" type="text" placeholder="${getI18nText('menu.filter')}" @change="${this.onSearchChange}" spellcheck="false"> <div style="margin:6px 5px 0 -24px;font-size:var(--font-size-regular);cursor:pointer">↩</div> </div> ${this.matchPaths ? html` <div @click="${this.onClearSearch}" style="margin-left:5px;cursor:pointer;align-self:center;color:var(--nav-text-color)" class="small-font-size primary-text bold-text"> CLEAR </div>` : ''} `} ${this.allowAdvancedSearch === 'false' || this.matchPaths ? '' : html` <button class="m-btn primary" part="btn btn-fill btn-search" style="margin-left:5px" @click="${this.onShowSearchModalClicked}"> ${getI18nText('menu.search')} </button> `} </div> `} ${html`<nav class="nav-scroll" part="navbar-scroll"> ${this.showInfo === 'false' || !this.resolvedSpec.info ? '' : html`<div class="nav-bar-info" id="link-overview" data-content-id="overview" @click="${e => this.scrollToEventTarget(e, false)}"> ${this.isV1 && this.resolvedSpec.info.title || getI18nText('menu.overview')} </div>`} ${this.allowServerSelection === 'false' ? '' : html`<div class="nav-bar-info" id="link-servers" data-content-id="servers" @click="${e => this.scrollToEventTarget(e, false)}"> ${getI18nText('menu.api-servers')} </div>`} ${this.allowAuthentication === 'false' || !this.resolvedSpec.securitySchemes ? '' : html`<div class="nav-bar-info" id="link-auth" data-content-id="auth" @click="${e => this.scrollToEventTarget(e, false)}"> ${getI18nText('menu.authentication')} </div>`} <slot name="nav-section" class="custom-nav-section" data-content-id="section" @click="${e => this.scrollToCustomNavSectionTarget(e, false)}"></slot> <div class="sticky-scroll-element"> <div class="nav-bar-section" part="navbar-operations-header"> <slot name="operations-header"> <div class="nav-bar-section-title">${getI18nText('menu.operations')}</div> </slot> <div style="" part="navbar-operations-header-collapse"> ${this.resolvedSpec.tags.length > 1 && this.resolvedSpec.tags.some(tag => tag.paths.some(path => pathIsInSearch(this.matchPaths, path))) ? html` ${this.operationsCollapsed ? html`<div @click="${() => {
|
|
43
44
|
expandCollapseAll.call(this);
|
|
44
45
|
}}" style="font-size:16px;transform:rotate(0);cursor:pointer">▸</div>` : html`<div @click="${() => {
|
|
45
46
|
expandCollapseAll.call(this);
|
|
@@ -47,7 +48,7 @@ export default function navbarTemplate() {
|
|
|
47
48
|
onExpandCollapse.call(this, tag.elementId);
|
|
48
49
|
}}"> <div style="display:flex;justify-content:space-between;width:100%"> <div>${tag.name}</div> <div class="nav-bar-tag-icon expand-button-arrow">▸</div> <div class="nav-bar-tag-icon collapse-button-arrow">▾</div> </div> </div> `} <div class="tag-headers"> ${tag.headers.map(header => html` <div class="nav-bar-h${header.depth}" id="link-${tag.elementId}--${new marked.Slugger().slug(header.text)}" data-content-id="${tag.elementId}--${new marked.Slugger().slug(header.text)}" @click="${e => this.scrollToEventTarget(e, false)}"> ${header.text} </div>`)} </div> <div class="nav-bar-paths-under-tag"> ${tag.paths.filter(v => pathIsInSearch(this.matchPaths, v)).map(p => html` <div class="nav-bar-path ${this.usePathInNavBar === 'true' ? 'small-font' : ''}" data-content-id="${p.elementId}" id="link-${p.elementId}" @click="${e => {
|
|
49
50
|
this.scrollToEventTarget(e, false);
|
|
50
|
-
}}"> <span style="line-break:anywhere;${p.deprecated ? 'filter:opacity(0.5)' : ''}"> ${this.usePathInNavBar === 'true' ? html`<span class="mono-font">${p.method.toUpperCase()} ${p.path}</span>` : p.summary || p.shortSummary} ${p.isWebhook ? '(Webhook)' : ''} </span> </div>`)} </div> </div> </slot> `)} ${(_this$resolvedSpec$co = this.resolvedSpec.components) !== null && _this$resolvedSpec$co !== void 0 && _this$resolvedSpec$co.length && !this.hideComponents ? html` <div class="sticky-scroll-element"> <div id="link-components" class="nav-bar-section"> <slot name="components-header"> <div class="nav-bar-section-title"
|
|
51
|
+
}}"> <span style="line-break:anywhere;${p.deprecated ? 'filter:opacity(0.5)' : ''}"> ${this.usePathInNavBar === 'true' ? html`<span class="mono-font">${p.method.toUpperCase()} ${p.path}</span>` : p.summary || p.shortSummary} ${p.isWebhook ? '(Webhook)' : ''} </span> </div>`)} </div> </div> </slot> `)} ${(_this$resolvedSpec$co = this.resolvedSpec.components) !== null && _this$resolvedSpec$co !== void 0 && _this$resolvedSpec$co.length && !this.hideComponents ? html` <div class="sticky-scroll-element"> <div id="link-components" class="nav-bar-section"> <slot name="components-header"> <div class="nav-bar-section-title">${getI18nText('menu.components')}</div> </slot> ${this.resolvedSpec.components.some(c => c.subComponents.some(s => componentIsInSearch(this.matchPaths, s))) ? html` <div style="" part="navbar-components-header-collapse"> ${this.componentsCollapsed ? html`<div @click="${() => {
|
|
51
52
|
expandCollapseAllComponents.call(this);
|
|
52
53
|
}}" style="font-size:16px;transform:rotate(0);cursor:pointer">▸</div>` : html`<div @click="${() => {
|
|
53
54
|
expandCollapseAllComponents.call(this);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
3
|
import { marked } from 'marked';
|
|
4
|
+
import { getI18nText } from '../languages';
|
|
4
5
|
/* eslint-disable indent */
|
|
5
6
|
|
|
6
7
|
export default function overviewTemplate() {
|
|
7
|
-
return html` <section id="overview" part="section-overview" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> ${this.resolvedSpec && this.resolvedSpec.info ? html` <slot name="overview"> <div id="api-title" part="label-overview-title" style="font-size:32px" class="section-padding"> ${this.resolvedSpec.info.title} ${!this.resolvedSpec.info.version ? '' : html` <span style="font-size:var(--font-size-small);font-weight:700"> ${this.resolvedSpec.info.version} </span>`} </div> <div id="api-info" style="font-size:calc(var(--font-size-regular) - 1px);margin-top:8px" class="section-padding"> ${this.resolvedSpec.info.contact && this.resolvedSpec.info.contact.email ? html`<span>${this.resolvedSpec.info.contact.name || '
|
|
8
|
+
return html` <section id="overview" part="section-overview" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> ${this.resolvedSpec && this.resolvedSpec.info ? html` <slot name="overview"> <div id="api-title" part="label-overview-title" style="font-size:32px" class="section-padding"> ${this.resolvedSpec.info.title} ${!this.resolvedSpec.info.version ? '' : html` <span style="font-size:var(--font-size-small);font-weight:700"> ${this.resolvedSpec.info.version} </span>`} </div> <div id="api-info" style="font-size:calc(var(--font-size-regular) - 1px);margin-top:8px" class="section-padding"> ${this.resolvedSpec.info.contact && this.resolvedSpec.info.contact.email ? html`<span>${this.resolvedSpec.info.contact.name || getI18nText('overview.email')}: <a href="mailto:${this.resolvedSpec.info.contact.email}" part="anchor anchor-overview">${this.resolvedSpec.info.contact.email}</a> </span>` : ''} ${this.resolvedSpec.info.contact && this.resolvedSpec.info.contact.url ? html`<span>URL: <a href="${this.resolvedSpec.info.contact.url}" part="anchor anchor-overview">${this.resolvedSpec.info.contact.url}</a></span>` : ''} ${this.resolvedSpec.info.license ? html`<span>License: ${this.resolvedSpec.info.license.url ? html`<a href="${this.resolvedSpec.info.license.url}" part="anchor anchor-overview">${this.resolvedSpec.info.license.name}</a>` : this.resolvedSpec.info.license.name} </span>` : ''} ${this.resolvedSpec.info.termsOfService ? html`<span><a href="${this.resolvedSpec.info.termsOfService}" part="anchor anchor-overview">${getI18nText('overview.terms-of-service')}</a></span>` : ''} </div> </slot> <slot name="overview-api-description"> ${this.resolvedSpec.info.description ? html`${unsafeHTML(`<div class="m-markdown regular-font section-padding">${marked(this.resolvedSpec.info.description)}</div>`)}` : ''} </slot> ` : ''} </section> `;
|
|
8
9
|
}
|
|
9
10
|
/* eslint-enable indent */
|
|
@@ -2,6 +2,7 @@ import { html } from 'lit-element';
|
|
|
2
2
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
3
3
|
import { marked } from 'marked';
|
|
4
4
|
import base64url from 'base64url';
|
|
5
|
+
import { getI18nText } from '../languages';
|
|
5
6
|
|
|
6
7
|
function onApiKeyChange(apiKeyId, e) {
|
|
7
8
|
let apiKeyValue = '';
|
|
@@ -281,16 +282,16 @@ export default function securitySchemeTemplate() {
|
|
|
281
282
|
}
|
|
282
283
|
|
|
283
284
|
const providedApiKeys = schemes.filter(v => v.finalKeyValue);
|
|
284
|
-
return html` <section id="auth" part="section-auth" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <slot name="authentication"> <div class="section-padding"> <div class="sub-title regular-font"
|
|
285
|
+
return html` <section id="auth" part="section-auth" class="observe-me ${this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <slot name="authentication"> <div class="section-padding"> <div class="sub-title regular-font">${getI18nText('headers.authentication')}</div> <div class="small-font-size" style="display:flex;align-items:center;min-height:30px"> ${providedApiKeys.length > 0 ? html` <div class="blue-text"> ${providedApiKeys.length} API key applied </div> <div style="flex:1"></div> <button class="m-btn thin-border" part="btn btn-outline" @click="${() => {
|
|
285
286
|
onClearAllApiKeys.call(this);
|
|
286
|
-
}}">CLEAR ALL API KEYS</button>` : html`<div class="red-text"
|
|
287
|
+
}}">CLEAR ALL API KEYS</button>` : html`<div class="red-text">${getI18nText('authentication.no-api-key-applied')}</div>`} </div> ${schemes.length > 0 ? html` <table role="presentation" class="m-table" style="width:100%"> ${schemes.map(v => html` <tr> <td style="max-width:500px;overflow-wrap:break-word"> <div style="min-height:24px"> <span style="font-weight:700">${v.typeDisplay}</span> ${v.finalKeyValue ? html` <span class="blue-text"> ${v.finalKeyValue ? 'Key Applied' : ''} </span> <button class="m-btn thin-border small" part="btn btn-outline" @click="${() => {
|
|
287
288
|
v.finalKeyValue = '';
|
|
288
289
|
this.requestUpdate();
|
|
289
290
|
}}">REMOVE</button> ` : ''} </div> ${v.description ? html` <div class="m-markdown"> ${unsafeHTML(marked(v.description || ''))} </div>` : ''} </td> <td> ${v.type && (v.type.toLowerCase() === 'apikey' || v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'bearer') ? html` ${v.type.toLowerCase() === 'apikey' ? html`Send <code>${v.name}</code> in <code>${v.in}</code> with the given value:` : html`Send <code>Authorization</code> in <code>header</code> containing the word <code>Bearer</code> followed by a space and a Token String.`} <form style="display:flex"> ${v.in === 'cookie' ? html` <div style="display:block"> <input type="text" value="${getCookieValue(v.apiKeyId)}" disabled="disabled" class="api-key-input" placeholder="IygRVGf54B59e0GAkKmigGfuiVlp/uhFfk2ifA+jMMJzau2F1jPldc09gPTfnMw13BFBxqUZIFDm55DPfwkb0A==" spellcheck="false" style="resize:horizontal;width:100%"> <br> <small> <strong>Cookies</strong> are set and configured by the remote service, therefore it is not possible to configure them from the browser. </small> </div>` : html` <input type="text" value="${v.value}" class="api-key-input" placeholder="api-token" spellcheck="false"> <button type="submit" class="m-btn thin-border" style="margin-left:5px" part="btn btn-outline" @click="${e => {
|
|
290
291
|
onApiKeyChange.call(this, v.apiKeyId, e);
|
|
291
|
-
}}"> ${v.finalKeyValue ? 'UPDATE' : 'SET'} </button>`} </form>` : ''} ${v.type && v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic' ? html`
|
|
292
|
+
}}"> ${v.finalKeyValue ? 'UPDATE' : 'SET'} </button>`} </form>` : ''} ${v.type && v.type.toLowerCase() === 'http' && v.scheme && v.scheme.toLowerCase() === 'basic' ? html` ${getI18nText('authentication.http-basic-desc')} <form style="display:flex"> <input type="text" value="${v.user}" placeholder="${getI18nText('authentication.username')}" spellcheck="false" class="api-key-user" style="width:100px"> <input type="password" value="${v.password}" placeholder="${getI18nText('authentication.password')}" spellcheck="false" class="api-key-password" style="width:100px;margin:0 5px"> <button type="submit" class="m-btn thin-border" @click="${e => {
|
|
292
293
|
onApiKeyChange.call(this, v.apiKeyId, e);
|
|
293
|
-
}}" part="btn btn-outline"> ${v.finalKeyValue ? 'UPDATE' : '
|
|
294
|
+
}}" part="btn btn-outline"> ${v.finalKeyValue ? 'UPDATE' : getI18nText('authentication.set')} </button> </form>` : ''} </td> </tr> ${v.type.toLowerCase() === 'oauth2' ? html` <tr> <td colspan="2" style="border:none;padding-left:48px"> ${Object.keys(v.flows).map(f => oAuthFlowTemplate.call(this, f, v, v.flows[f]))} </td> </tr> ` : ''} `)} </table>` : ''} </div> </slot> </section> `;
|
|
294
295
|
}
|
|
295
296
|
|
|
296
297
|
function getOauthScopeTemplate(scopes) {
|
|
@@ -322,7 +323,7 @@ export function pathSecurityTemplate(pathSecurity) {
|
|
|
322
323
|
securityDefs: andSecurityKeys1
|
|
323
324
|
});
|
|
324
325
|
});
|
|
325
|
-
return html`<div class="security-info-button" data-content-id="auth" @click="${e => this.scrollToEventTarget(e, false)}"> <div style="position:relative;display:flex;min-width:350px;max-width:700px;justify-content:flex-end"> <svg width="16" height="24" style="cursor:pointer"> <g> <path style="fill:var(--fg3)" d="m13.8,8.5l0,-2.6l0,0c0,-3.2 -2.6,-5.8 -5.8,-5.8s-5.8,2.6 -5.8,5.8l0,0l0,2.6l-2.1,0l0,11.2l16,0l0,-11.2l-2.1,0l-0,0l0,0l0,0l-0,0zm-9.8,-2.6c0,0 0,0 0,0c0,-2.2 1.8,-4 4,-4c2.2,0 4,1.8 4,4c0,0 0,0 0,0l0,2.6l-8.03,0l0,-2.6l0,0l0,0z"/> </g> </svg> ${orSecurityKeys1.map((orSecurityItem1, i) => html` ${i !== 0 ? html`<div style="padding:3px 4px"> OR </div>` : ''} <div class="tooltip" style="cursor:pointer"> <div style="padding:2px 4px;white-space:nowrap;text-overflow:ellipsis;max-width:150px;overflow:hidden"> <span part="anchor anchor-operation-security"> ${orSecurityItem1.securityTypes} </span> </div> <div class="tooltip-text" style="position:absolute;color:var(--fg);top:26px;right:0;border:1px solid var(--border-color);padding:2px 4px;display:block"> ${orSecurityItem1.securityDefs.length > 1 ? html`<div>Requires <b>all</b> of the following </div>` : ''} <div style="padding-left:8px"> ${orSecurityItem1.securityDefs.map((andSecurityItem, j) => html` ${andSecurityItem.type === 'oauth2' ? html` <div> ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> ` : html`Requires`} OAuth token (${andSecurityItem.apiKeyId}) in <b>Authorization header</b> ${getOauthScopeTemplate(andSecurityItem.scopes)} </div>` : andSecurityItem.type === 'http' ? html` <div> ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> ` : html`
|
|
326
|
+
return html`<div class="security-info-button" data-content-id="auth" @click="${e => this.scrollToEventTarget(e, false)}"> <div style="position:relative;display:flex;min-width:350px;max-width:700px;justify-content:flex-end"> <svg width="16" height="24" style="cursor:pointer"> <g> <path style="fill:var(--fg3)" d="m13.8,8.5l0,-2.6l0,0c0,-3.2 -2.6,-5.8 -5.8,-5.8s-5.8,2.6 -5.8,5.8l0,0l0,2.6l-2.1,0l0,11.2l16,0l0,-11.2l-2.1,0l-0,0l0,0l0,0l-0,0zm-9.8,-2.6c0,0 0,0 0,0c0,-2.2 1.8,-4 4,-4c2.2,0 4,1.8 4,4c0,0 0,0 0,0l0,2.6l-8.03,0l0,-2.6l0,0l0,0z"/> </g> </svg> ${orSecurityKeys1.map((orSecurityItem1, i) => html` ${i !== 0 ? html`<div style="padding:3px 4px"> OR </div>` : ''} <div class="tooltip" style="cursor:pointer"> <div style="padding:2px 4px;white-space:nowrap;text-overflow:ellipsis;max-width:150px;overflow:hidden"> <span part="anchor anchor-operation-security"> ${orSecurityItem1.securityTypes} </span> </div> <div class="tooltip-text" style="position:absolute;color:var(--fg);top:26px;right:0;border:1px solid var(--border-color);padding:2px 4px;display:block"> ${orSecurityItem1.securityDefs.length > 1 ? html`<div>Requires <b>all</b> of the following </div>` : ''} <div style="padding-left:8px"> ${orSecurityItem1.securityDefs.map((andSecurityItem, j) => html` ${andSecurityItem.type === 'oauth2' ? html` <div> ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> ` : html`Requires`} OAuth token (${andSecurityItem.apiKeyId}) in <b>Authorization header</b> ${getOauthScopeTemplate(andSecurityItem.scopes)} </div>` : andSecurityItem.type === 'http' ? html` <div> ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> ` : html`${getI18nText('authentication.requires')}`} ${andSecurityItem.scheme === 'basic' ? getI18nText('authentication.http-basic-note') : 'Bearer Token'} ${getI18nText('authentication.in-auth-header')} ${getOauthScopeTemplate(andSecurityItem.scopes)} </div>` : html` <div> ${orSecurityItem1.securityDefs.length > 1 ? html`<b>${j + 1}.</b> ` : html`Requires`} Token in <b>${andSecurityItem.name} ${andSecurityItem.in}</b> ${getOauthScopeTemplate(andSecurityItem.scopes)} </div>`} `)} </div> </div> </div> `)} </div> </div>`;
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
return '';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { html } from 'lit-element';
|
|
2
2
|
import { marked } from 'marked';
|
|
3
3
|
import { unsafeHTML } from 'lit-html/directives/unsafe-html.js';
|
|
4
|
+
import { getI18nText } from '../languages';
|
|
4
5
|
|
|
5
6
|
function onApiServerChange(e, server) {
|
|
6
7
|
if (e && e.target.checked) {
|
|
@@ -23,7 +24,7 @@ function onApiServerVarChange(e, serverObj) {
|
|
|
23
24
|
|
|
24
25
|
|
|
25
26
|
function serverVarsTemplate() {
|
|
26
|
-
return this.selectedServer && this.selectedServer.variables ? html` <div class="table-title"
|
|
27
|
+
return this.selectedServer && this.selectedServer.variables ? html` <div class="table-title">${getI18nText('api-servers.server-variables')}</div> <table role="presentation" class="m-table"> ${Object.entries(this.selectedServer.variables).map(kv => html` <tr> <td style="vertical-align:middle">${kv[0]}</td> <td> ${kv[1].enum ? html` <select data-var="${kv[0]}" @input="${e => {
|
|
27
28
|
onApiServerVarChange.call(this, e, this.selectedServer);
|
|
28
29
|
}}"> ${Object.entries(kv[1].enum).map(e => kv[1].default === e[1] ? html` <option selected="selected" label="${e[1]}" value="${e[1]}">` : html` <option label="${e[1]}" value="${e[1]}">`)} </select>` : html` <input type="text" part="textbox textbox-server-var" spellcheck="false" data-var="${kv[0]}" value="${kv[1].default}" @input="${e => {
|
|
29
30
|
onApiServerVarChange.call(this, e, this.selectedServer);
|
|
@@ -35,8 +36,8 @@ export default function serverTemplate() {
|
|
|
35
36
|
return undefined;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
return html` <section id="servers" part="section-servers" style="margin-top:24px;margin-bottom:24px" class="regular-font observe-me section-padding ${this.renderStyle === 'read' ? 'section-gap--read-mode' : this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <div class="sub-title"
|
|
39
|
+
return html` <section id="servers" part="section-servers" style="margin-top:24px;margin-bottom:24px" class="regular-font observe-me section-padding ${this.renderStyle === 'read' ? 'section-gap--read-mode' : this.renderStyle === 'focused' ? 'section-gap--focused-mode' : 'section-gap'}"> <div class="sub-title">${getI18nText('headers.api-servers')}</div> <div class="mono-font" style="margin:12px 0;font-size:calc(var(--font-size-small) + 1px)"> ${!this.resolvedSpec.servers || !this.resolvedSpec.servers.length ? '' : html` ${this.resolvedSpec.servers.map((server, i) => html` <input type="radio" name="api_server" id="srvr-opt-${i}" value="${server.url}" @change="${e => {
|
|
39
40
|
onApiServerChange.call(this, e, server);
|
|
40
|
-
}}" .checked="${this.selectedServer.url === server.url}" style="margin:4px 0;cursor:pointer"> <label style="cursor:pointer" for="srvr-opt-${i}"> ${server.url} ${server.description ? html`- <span class="regular-font">${server.description} </span>` : ''} </label> <br> `)} `} <div class="table-title primary-text" part="label-selected-server">
|
|
41
|
+
}}" .checked="${this.selectedServer.url === server.url}" style="margin:4px 0;cursor:pointer"> <label style="cursor:pointer" for="srvr-opt-${i}"> ${server.url} ${server.description ? html`- <span class="regular-font">${server.description} </span>` : ''} </label> <br> `)} `} <div class="table-title primary-text" part="label-selected-server"> ${getI18nText('api-servers.selected')}: ${this.selectedServer && this.selectedServer.computedUrl || 'none'}</div> </div> <slot name="servers"></slot> ${serverVarsTemplate.call(this)} </section>`;
|
|
41
42
|
}
|
|
42
43
|
/* eslint-enable indent */
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { getI18nText } from '../languages';
|
|
1
2
|
/* For Delayed Event Handler Execution */
|
|
3
|
+
|
|
2
4
|
export function debounce(fn, delay) {
|
|
3
5
|
let timeoutID = null;
|
|
4
6
|
return (...args) => {
|
|
@@ -26,9 +28,9 @@ export function copyToClipboard(data, e) {
|
|
|
26
28
|
|
|
27
29
|
try {
|
|
28
30
|
document.execCommand('copy');
|
|
29
|
-
btnEl.innerText = '
|
|
31
|
+
btnEl.innerText = getI18nText('operations.copied');
|
|
30
32
|
setTimeout(() => {
|
|
31
|
-
btnEl.innerText = '
|
|
33
|
+
btnEl.innerText = getI18nText('operations.copy');
|
|
32
34
|
}, 5000);
|
|
33
35
|
} catch (err) {
|
|
34
36
|
console.error('Unable to copy', err); // eslint-disable-line no-console
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import cloneDeep from 'lodash.clonedeep';
|
|
2
2
|
import { expandN } from 'regex-to-strings';
|
|
3
|
-
import xmlFormatter from './xml/xml'; // When the type is not known for a property set the displayed type to be this:
|
|
3
|
+
import xmlFormatter from './xml/xml.js'; // When the type is not known for a property set the displayed type to be this:
|
|
4
4
|
|
|
5
5
|
const IS_MISSING_TYPE_INFO_TYPE = '';
|
|
6
6
|
/* Generates an schema object containing type and constraint info */
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import OpenApiResolver from 'openapi-resolver/dist/openapi-resolver.browser';
|
|
2
2
|
import { marked } from 'marked';
|
|
3
3
|
import { invalidCharsRegEx } from './common-utils';
|
|
4
|
+
import { getI18nText } from '../languages';
|
|
4
5
|
import cloneDeep from 'lodash.clonedeep';
|
|
5
6
|
export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
6
7
|
const inputSpecIsAUrl = typeof specUrlOrObject === 'string' && specUrlOrObject.match(/^http/) || typeof specUrlOrObject === 'object' && typeof specUrlOrObject.href === 'string';
|
|
@@ -53,7 +54,7 @@ export default async function ProcessSpec(specUrlOrObject, serverUrl = '') {
|
|
|
53
54
|
|
|
54
55
|
securitySchemes.forEach(v => {
|
|
55
56
|
if (v.type === 'http') {
|
|
56
|
-
v.typeDisplay = v.scheme === 'basic' ? '
|
|
57
|
+
v.typeDisplay = v.scheme === 'basic' ? getI18nText('authentication.http-basic') : 'HTTP Bearer';
|
|
57
58
|
} else if (v.type === 'apiKey') {
|
|
58
59
|
v.typeDisplay = `API Key (${v.name})`;
|
|
59
60
|
} else if (v.type === 'oauth2') {
|
|
@@ -155,7 +156,7 @@ function getComponents(openApiSpec) {
|
|
|
155
156
|
|
|
156
157
|
switch (component) {
|
|
157
158
|
case 'schemas':
|
|
158
|
-
cmpName = '
|
|
159
|
+
cmpName = getI18nText('menu.schemas');
|
|
159
160
|
cmpDescription = '';
|
|
160
161
|
break;
|
|
161
162
|
|
|
@@ -17,6 +17,8 @@ var _xmlButPrettier = _interopRequireDefault(require("xml-but-prettier"));
|
|
|
17
17
|
|
|
18
18
|
var _commonUtils = require("../utils/common-utils");
|
|
19
19
|
|
|
20
|
+
var _languages = require("../languages");
|
|
21
|
+
|
|
20
22
|
var _schemaUtils = require("../utils/schema-utils");
|
|
21
23
|
|
|
22
24
|
require("./json-tree");
|
|
@@ -173,7 +175,7 @@ class ApiRequest extends _litElement.LitElement {
|
|
|
173
175
|
}
|
|
174
176
|
|
|
175
177
|
render() {
|
|
176
|
-
return (0, _litElement.html)` <div class="api-request col regular-font request-panel ${this.renderStyle === 'focused' || this.callback === 'true' ? 'focused-mode' : 'view-mode'}"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}"> ${this.callback === 'true' ? 'CALLBACK REQUEST' : '
|
|
178
|
+
return (0, _litElement.html)` <div class="api-request col regular-font request-panel ${this.renderStyle === 'focused' || this.callback === 'true' ? 'focused-mode' : 'view-mode'}"> <div class="${this.callback === 'true' ? 'tiny-title' : 'req-res-title'}"> ${this.callback === 'true' ? 'CALLBACK REQUEST' : (0, _languages.getI18nText)('operations.request')} </div> <div> ${this.inputParametersTemplate('path')} ${this.inputParametersTemplate('query')} ${this.requestBodyTemplate()} ${this.inputParametersTemplate('header')} ${this.inputParametersTemplate('cookie')} ${this.allowTry === 'false' ? '' : (0, _litElement.html)`${this.apiCallTemplate()}`} </div> </div> `;
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
updated(changedProperties) {
|
|
@@ -376,7 +378,7 @@ class ApiRequest extends _litElement.LitElement {
|
|
|
376
378
|
if (e.target.tagName.toLowerCase() === 'button') {
|
|
377
379
|
this.activeSchemaTab = e.target.dataset.tab;
|
|
378
380
|
}
|
|
379
|
-
}}"> <button class="tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" data-tab="model"
|
|
381
|
+
}}"> <button class="tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" data-tab="model">${(0, _languages.getI18nText)('operations.model')}</button> <button class="tab-btn ${this.activeSchemaTab === 'body' ? 'active' : ''}" data-tab="body">${(0, _languages.getI18nText)('operations.body')}</button> </div> ${(0, _litElement.html)`<div class="tab-content col" style="display:${this.activeSchemaTab === 'model' ? 'block' : 'none'}"> ${reqBodySchemaHtml}</div>`} ${(0, _litElement.html)`<div class="tab-content col" style="display:${this.activeSchemaTab === 'model' ? 'none' : 'block'}"> ${reqBodyDefaultHtml}</div>`} </div>` : (0, _litElement.html)` ${reqBodyFileInputHtml} ${reqBodyFormHtml}`} </div> `;
|
|
380
382
|
}
|
|
381
383
|
|
|
382
384
|
formDataTemplate(schema, mimeType, exampleValue = '') {
|
|
@@ -422,7 +424,7 @@ class ApiRequest extends _litElement.LitElement {
|
|
|
422
424
|
if (e.target.tagName.toLowerCase() === 'button') {
|
|
423
425
|
this.activeSchemaTab = e.target.dataset.tab;
|
|
424
426
|
}
|
|
425
|
-
}}"> <button class="v-tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" data-tab="model"
|
|
427
|
+
}}"> <button class="v-tab-btn ${this.activeSchemaTab === 'model' ? 'active' : ''}" data-tab="model">${(0, _languages.getI18nText)('operations.model')}</button> <button class="v-tab-btn ${this.activeSchemaTab === 'body' ? 'active' : ''}" data-tab="body">${(0, _languages.getI18nText)('operations.request-body')}</button> </div> </div> ${(0, _litElement.html)` <div class="tab-content col" data-tab="model" style="display:${this.activeSchemaTab === 'model' ? 'block' : 'none'};padding-left:5px;width:100%"> <schema-tree .data="${formdataPartSchema}" schema-expand-level="${this.schemaExpandLevel}"> </schema-tree> </div>`} ${(0, _litElement.html)` <div class="tab-content col" data-tab="body" style="display:${this.activeSchemaTab === 'body' ? 'block' : 'none'};padding-left:5px;width:100%"> <textarea class="textarea" placeholder="${formdataPartExample[0] && formdataPartExample[0].exampleValue || paramSchema.default || ''}" part="textarea textarea-param" style="width:100%;border:none;resize:vertical" data-array="false" data-ptype="${mimeType.includes('form-urlencode') ? 'form-urlencode' : 'form-data'}" data-pname="${fieldName}" data-default="${paramSchema.default || ''}" spellcheck="false">${this.fillRequestWithDefault === 'true' ? paramSchema.default : ''}</textarea> <textarea data-pname="hidden-${fieldName}" data-ptype="${mimeType.includes('form-urlencode') ? 'hidden-form-urlencode' : 'hidden-form-data'}" class="is-hidden" style="display:none">${paramSchema.default}</textarea> </div>`} </div>` : (0, _litElement.html)` ${this.allowTry === 'true' ? (0, _litElement.html)`<input placeholder="${paramSchema.example || paramSchema.default || ''}" .value="${this.fillRequestWithDefault === 'true' ? paramSchema.default || '' : ''}" spellcheck="false" type="${fieldSchema.format === 'binary' ? 'file' : fieldSchema.format === 'password' ? 'password' : 'text'}" part="textbox textbox-param" style="width:100%" data-ptype="${mimeType.includes('form-urlencode') ? 'form-urlencode' : 'form-data'}" data-pname="${fieldName}" data-default="${paramSchema.default || ''}" data-array="false">` : ''} `}`} </td> ${fieldType === 'object' ? '' : (0, _litElement.html)` <td> ${paramSchema.default || paramSchema.constraint || paramSchema.allowedValues || paramSchema.pattern ? (0, _litElement.html)` <div class="param-constraint"> ${paramSchema.pattern ? (0, _litElement.html)`<span style="font-weight:700">Pattern: </span>${paramSchema.pattern}<br>` : ''} ${paramSchema.constraint ? (0, _litElement.html)`<span style="font-weight:700">Constraints: </span>${paramSchema.constraint}<br>` : ''} ${paramSchema.allowedValues && paramSchema.allowedValues.split('┃').map((v, i) => (0, _litElement.html)` ${i > 0 ? '|' : (0, _litElement.html)`<span style="font-weight:700">Allowed: </span>`} ${(0, _litElement.html)` <a part="anchor anchor-param-constraint" class="${this.allowTry === 'true' ? '' : 'inactive-link'}" data-type="${paramSchema.type === 'array' ? paramSchema.type : 'string'}" data-enum="${v.trim()}" @click="${e => {
|
|
426
428
|
const inputEl = e.target.closest('table').querySelector(`[data-pname="${fieldName}"]`);
|
|
427
429
|
|
|
428
430
|
if (inputEl) {
|
|
@@ -459,18 +461,18 @@ class ApiRequest extends _litElement.LitElement {
|
|
|
459
461
|
}
|
|
460
462
|
|
|
461
463
|
this.activeResponseTab = e.target.dataset.tab;
|
|
462
|
-
}}"> <button class="tab-btn ${this.activeResponseTab === 'response' ? 'active' : ''}" data-tab="response"
|
|
464
|
+
}}"> <button class="tab-btn ${this.activeResponseTab === 'response' ? 'active' : ''}" data-tab="response">${(0, _languages.getI18nText)('operations.response')}</button> <button class="tab-btn ${this.activeResponseTab === 'headers' ? 'active' : ''}" data-tab="headers">${(0, _languages.getI18nText)('operations.response-headers')}</button> <button class="tab-btn ${this.activeResponseTab === 'curl' ? 'active' : ''}" data-tab="curl">CURL</button> </div> ${this.responseIsBlob ? (0, _litElement.html)` <div class="tab-content col" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'}"> <button class="m-btn thin-border mar-top-8" style="width:135px" @click="${this.downloadResponseBlob}" part="btn btn-outline">DOWNLOAD</button> ${this.responseBlobType === 'view' ? (0, _litElement.html)`<button class="m-btn thin-border mar-top-8" style="width:135px" @click="${this.viewResponseBlob}" part="btn btn-outline">VIEW (NEW TAB)</button>` : ''} </div>` : (0, _litElement.html)` <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'response' ? 'flex' : 'none'}"> <button class="toolbar-copy-btn" @click="${e => {
|
|
463
465
|
(0, _commonUtils.copyToClipboard)(this.responseText, e);
|
|
464
|
-
}}" part="btn btn-fill"
|
|
466
|
+
}}" part="btn btn-fill">${(0, _languages.getI18nText)('operations.copy')}</button> <pre>${responseFormat ? (0, _litElement.html)`<code>${(0, _unsafeHtml.unsafeHTML)(_prismjs.default.highlight(this.responseText, _prismjs.default.languages[responseFormat], responseFormat))}</code>` : `${this.responseText}`}
|
|
465
467
|
</pre> </div>`} <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'headers' ? 'flex' : 'none'}"> <button class="toolbar-copy-btn" @click="${e => {
|
|
466
468
|
(0, _commonUtils.copyToClipboard)(this.responseHeaders, e);
|
|
467
|
-
}}" part="btn btn-fill"
|
|
469
|
+
}}" part="btn btn-fill">${(0, _languages.getI18nText)('operations.copy')}</button> <pre><code>${(0, _unsafeHtml.unsafeHTML)(_prismjs.default.highlight(this.responseHeaders, _prismjs.default.languages.css, 'css'))}</code></pre> </div> <div class="tab-content col m-markdown" style="flex:1;display:${this.activeResponseTab === 'curl' ? 'flex' : 'none'}"> <button class="toolbar-copy-btn" @click="${e => {
|
|
468
470
|
(0, _commonUtils.copyToClipboard)(this.curlSyntax.replace(/\\$/, ''), e);
|
|
469
|
-
}}" part="btn btn-fill"
|
|
471
|
+
}}" part="btn btn-fill">${(0, _languages.getI18nText)('operations.copy')}</button> <pre><code>${(0, _unsafeHtml.unsafeHTML)(_prismjs.default.highlight(this.curlSyntax.trim().replace(/\\$/, ''), _prismjs.default.languages.shell, 'shell'))}</code></pre> </div> </div>`;
|
|
470
472
|
}
|
|
471
473
|
|
|
472
474
|
apiCallTemplate() {
|
|
473
|
-
return (0, _litElement.html)` <div style="display:flex;align-items:flex-end;margin:16px 0;font-size:var(--font-size-small)"> ${this.parameters.length > 0 || this.request_body ? (0, _litElement.html)` <button class="m-btn thin-border" part="btn btn-outline" style="margin-right:5px" @click="${this.onClearRequestData}">
|
|
475
|
+
return (0, _litElement.html)` <div style="display:flex;align-items:flex-end;margin:16px 0;font-size:var(--font-size-small)"> ${this.parameters.length > 0 || this.request_body ? (0, _litElement.html)` <button class="m-btn thin-border" part="btn btn-outline" style="margin-right:5px" @click="${this.onClearRequestData}"> ${(0, _languages.getI18nText)('operations.clear')} </button>` : ''} <button class="m-btn primary btn-execute thin-border" part="btn btn-fill btn-try" @click="${this.onTryClick}">${(0, _languages.getI18nText)('operations.execute')}</button> </div> ${this.responseMessage === '' ? '' : this.apiResponseTabTemplate()} `;
|
|
474
476
|
}
|
|
475
477
|
/* eslint-enable indent */
|
|
476
478
|
|