diff --git a/README.md b/README.md index 51c6b60..8e13b7e 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,8 @@ See [production docker compose example](https://github.com/phishingclub/phishing - **Browser impersonation** - Impersonate JA4 fingerprints in proxied requests - **Response overwriting** - Shortcut proxying with custom responses - **Forward proxying** - Use HTTP and SOCKS5 proxies to ensure requests originate from the right location +- **Visual Editor** - Use the visual editor to easily setup a proxy +- **Import compromised oauth token** - Use compromised tokens to send more phishing via. oauth enabled endpoints ### Blogs & Resources - [Covert red team phishing with Phishing Club](http://phishing.club/blog/covert-red-team-phishing-with-phishing-club/) diff --git a/frontend/src/lib/components/Modal.svelte b/frontend/src/lib/components/Modal.svelte index 341f49e..004195f 100644 --- a/frontend/src/lib/components/Modal.svelte +++ b/frontend/src/lib/components/Modal.svelte @@ -11,6 +11,7 @@ export let bindTo = null; export let resetTabFocus = () => {}; export let noAutoFocus = false; + export let fullscreen = false; let modalElement; let previousActiveElement; @@ -25,7 +26,7 @@ // only handle focus when modal visibility actually changes and not during submission if (visible && !modalInitialized) { window.addEventListener('keydown', keyHandler); - // Prevent body scrolling when modal is open + // prevent body scrolling when modal is open document.body.style.overflow = 'hidden'; if (!isSubmitting) { handleModalOpen(); @@ -34,7 +35,7 @@ wasVisible = true; } else if (!visible && modalInitialized) { window.removeEventListener('keydown', keyHandler); - // Restore body scrolling when modal is closed + // restore body scrolling when modal is closed document.body.style.overflow = 'auto'; handleModalClose(); modalInitialized = false; @@ -49,13 +50,13 @@ close(); } } else if (e.key === 'Tab') { - // Check if the focused element is a dropdown option button + // check if the focused element is a dropdown option button const focusedElement = document.activeElement; const isDropdownOption = focusedElement?.closest('[role="listbox"]') && focusedElement?.role === 'option'; if (isDropdownOption) { - // Don't intercept tab from dropdown options - let them handle it first + // don't intercept tab from dropdown options - let them handle it first return; } @@ -64,62 +65,62 @@ }; const handleTabKey = (e) => { - // Store the current focused element before updating the list + // store the current focused element before updating the list const currentlyFocused = document.activeElement; - // Update focusable elements before handling tab to account for dynamic changes + // update focusable elements before handling tab to account for dynamic changes updateFocusableElements(); if (focusableElements.length === 0) return; - // Always prevent default tab behavior to keep focus within modal + // always prevent default tab behavior to keep focus within modal e.preventDefault(); let currentIndex = focusableElements.indexOf(currentlyFocused); - // If current element is not found (-1), try to find a related element + // if current element is not found (-1), try to find a related element if (currentIndex === -1) { - // Check if the current element is inside a TextFieldSelect or similar component + // check if the current element is inside a TextFieldSelect or similar component const parentComponent = currentlyFocused?.closest('.textfield-select-container'); if (parentComponent) { - // Look for the input element within the same component + // look for the input element within the same component const inputInComponent = parentComponent.querySelector('input'); if (inputInComponent) { const inputIndex = focusableElements.indexOf(inputInComponent); if (inputIndex !== -1) { - // Use the input's position for navigation and continue tab flow + // use the input's position for navigation and continue tab flow currentIndex = inputIndex; } } } } - // If we still can't find the element, handle it gracefully + // if we still can't find the element, handle it gracefully if (currentIndex === -1) { - // Check if the current element is inside a TextFieldSelect or similar component + // check if the current element is inside a TextFieldSelect or similar component const parentComponent = currentlyFocused?.closest('.textfield-select-container'); if (parentComponent) { - // Look for the input element within the same component + // look for the input element within the same component const inputInComponent = parentComponent.querySelector('input'); if (inputInComponent) { const inputIndex = focusableElements.indexOf(inputInComponent); if (inputIndex !== -1) { - // Use the input's position for navigation + // use the input's position for navigation currentIndex = inputIndex; } } } } - // If we still can't find the element, handle it gracefully + // if we still can't find the element, handle it gracefully if (currentIndex === -1) { - // If we can't find the element or related element, try to be smarter - // Check if we should go forward or backward based on the shift key + // if we can't find the element or related element, try to be smarter + // check if we should go forward or backward based on the shift key if (e.shiftKey) { - // Shift+Tab: go to last element + // shift+Tab: go to last element lastFocusableElement?.focus(); } else { - // Tab: try to find the first input in the form, or fallback to first element + // tab: try to find the first input in the form, or fallback to first element const firstInput = focusableElements.find((el) => el.tagName === 'INPUT'); if (firstInput) { firstInput.focus(); @@ -130,23 +131,23 @@ return; } - // Now handle normal tab navigation + // now handle normal tab navigation if (e.shiftKey) { - // Shift + Tab - go to previous element + // shift + Tab - go to previous element if (currentIndex <= 0) { - // If at first element, go to last + // if at first element, go to last lastFocusableElement?.focus(); } else { - // Go to previous element + // go to previous element focusableElements[currentIndex - 1]?.focus(); } } else { - // Tab - go to next element + // tab - go to next element if (currentIndex >= focusableElements.length - 1) { - // If at last element, go to first + // if at last element, go to first firstFocusableElement?.focus(); } else { - // Go to next element + // go to next element focusableElements[currentIndex + 1]?.focus(); } } @@ -206,7 +207,7 @@ const updateFocusableElements = () => { focusableElements = getFocusableElements(); - // Reorder elements: form controls first, then navigation buttons, then close button + // reorder elements: form controls first, then navigation buttons, then close button const formElements = []; const navigationButtons = []; const closeButton = modalElement?.querySelector('[data-close-button]'); @@ -226,7 +227,7 @@ } }); - // Rebuild focusable elements in desired order: form controls, then navigation, then close + // rebuild focusable elements in desired order: form controls, then navigation, then close focusableElements = [...formElements, ...navigationButtons]; if (closeButton) { focusableElements.push(closeButton); @@ -242,37 +243,37 @@ return; } - // Store the currently focused element + // store the currently focused element previousActiveElement = document.activeElement; - // Wait for the DOM to update + // wait for the DOM to update await tick(); updateFocusableElements(); - // Focus the first focusable element (excluding close button) + // focus the first focusable element (excluding close button) if (!noAutoFocus && firstFocusableElement) { firstFocusableElement.focus(); } }; const handleModalClose = () => { - // Restore focus to the previously focused element + // restore focus to the previously focused element if (previousActiveElement && typeof previousActiveElement.focus === 'function') { previousActiveElement.focus(); } }; - // Exposed function to reset tab focus when modal content changes + // exposed function to reset tab focus when modal content changes const handleResetTabFocus = async () => { - // Check if a TextFieldSelect is currently selecting an option + // check if a TextFieldSelect is currently selecting an option const isTextFieldSelectActive = modalElement?.querySelector('[data-selecting="true"]'); await tick(); updateFocusableElements(); }; - // Call resetTabFocus when it changes + // call resetTabFocus when it changes $: if (resetTabFocus) { resetTabFocus = handleResetTabFocus; } @@ -280,9 +281,9 @@ onMount(() => { return () => { window.removeEventListener('keydown', keyHandler); - // Ensure body scrolling is restored when component is destroyed + // ensure body scrolling is restored when component is destroyed document.body.style.overflow = 'auto'; - // Restore focus if modal was open when component was destroyed + // restore focus if modal was open when component was destroyed if (visible && previousActiveElement && typeof previousActiveElement.focus === 'function') { previousActiveElement.focus(); } @@ -306,7 +307,7 @@ } visible = false; window.removeEventListener('keydown', keyHandler); - // Restore body scrolling when modal is closed + // restore body scrolling when modal is closed document.body.style.overflow = 'auto'; onClose(); }; @@ -324,11 +325,15 @@ >

{headerText}

@@ -346,7 +351,11 @@
-
+
diff --git a/frontend/src/lib/components/TextField.svelte b/frontend/src/lib/components/TextField.svelte index 65dc55a..6a79e05 100644 --- a/frontend/src/lib/components/TextField.svelte +++ b/frontend/src/lib/components/TextField.svelte @@ -23,6 +23,7 @@ export let pattern = null; export let id = null; export let onBlur = () => {}; + export let error = false; // type can only be set initially export let type = 'text'; let inputType = 'text'; @@ -97,7 +98,9 @@ {required} {placeholder} {pattern} - class="text-ellipsis row-start-1 row-span-3 justify-self-center rounded-md py-2 pl-2 text-gray-600 dark:text-gray-300 border border-transparent dark:border-gray-700/60 focus:outline-none focus:border-solid focus:border-slate-400 dark:focus:border-highlight-blue/80 focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal transition-colors duration-200" + class="text-ellipsis row-start-1 row-span-3 justify-self-center rounded-md py-2 pl-2 text-gray-600 dark:text-gray-300 border focus:outline-none focus:border-solid focus:bg-gray-100 dark:focus:bg-gray-700/60 bg-grayblue-light dark:bg-gray-900/60 font-normal transition-colors duration-200 {error + ? 'border-red-500 dark:border-red-400' + : 'border-transparent dark:border-gray-700/60 focus:border-slate-400 dark:focus:border-highlight-blue/80'}" class:w-24={width === 'small'} class:w-60={width === 'medium'} class:w-95={width === 'large'} diff --git a/frontend/src/lib/components/TextFieldSelect.svelte b/frontend/src/lib/components/TextFieldSelect.svelte index 7b5e6d3..c706dfa 100644 --- a/frontend/src/lib/components/TextFieldSelect.svelte +++ b/frontend/src/lib/components/TextFieldSelect.svelte @@ -21,6 +21,31 @@ // Ensure options is always an array $: optionsArray = Array.isArray(options) ? options : Array.from(options); + // helper to get display label for an option (supports both string and {value, label} objects) + const getOptionLabel = (opt) => { + if (opt && typeof opt === 'object' && 'label' in opt) { + return opt.label; + } + return opt; + }; + + // helper to get value for an option (supports both string and {value, label} objects) + const getOptionValue = (opt) => { + if (opt && typeof opt === 'object' && 'value' in opt) { + return opt.value; + } + return opt; + }; + + // get display label for current value + const getDisplayLabel = (val) => { + const found = optionsArray.find((opt) => getOptionValue(opt) === val); + if (found) { + return getOptionLabel(found); + } + return val; + }; + let allOptions = []; let showDropdown = false; let inputElement; @@ -33,9 +58,10 @@ if (!searchValue) { return [...optionsArray]; } - return optionsArray.filter( - (opt) => opt && opt.toLowerCase && opt.toLowerCase().includes(searchValue.toLowerCase()) - ); + return optionsArray.filter((opt) => { + const label = getOptionLabel(opt); + return label && label.toLowerCase && label.toLowerCase().includes(searchValue.toLowerCase()); + }); }; // Track if user has typed (for filtering) vs just focused (show all) @@ -68,11 +94,11 @@ // Select an option const selectOption = (option) => { - value = option; + value = getOptionValue(option); showDropdown = false; hasTyped = false; // Reset typing flag after selection justSelected = true; // Set flag to prevent dropdown reopening - onSelect(option); + onSelect(value); // Focus the input field after selection without reopening dropdown setTimeout(() => { if (inputElement) { @@ -244,6 +270,7 @@ const labelId = `${comboboxId}-label`; // Reactive statements for accessibility + $: displayValue = getDisplayLabel(value); $: hasValue = value && value !== ''; $: ariaExpanded = showDropdown; @@ -292,7 +319,7 @@ aria-controls={listboxId} aria-autocomplete="list" aria-haspopup="listbox" - bind:value + value={showDropdown ? value : displayValue} on:focus={handleFocus} on:blur={handleBlur} on:input={handleInput} @@ -358,7 +385,7 @@ {/each} diff --git a/frontend/src/lib/components/proxy/ProxyConfigBuilder.svelte b/frontend/src/lib/components/proxy/ProxyConfigBuilder.svelte new file mode 100644 index 0000000..2968194 --- /dev/null +++ b/frontend/src/lib/components/proxy/ProxyConfigBuilder.svelte @@ -0,0 +1,3707 @@ + + +
+
+ +
+ + + +
+ + +
+ {#if activeTab === 'basic'} + +
+ +
+
+

General

+
+ + + +
+
+
+
+ +
+
+ +
+
+ + Domain must match a phishing domain in the Hosts tab +
+
+
+ +
+

Proxy Settings

+
+
+ + Forward Proxy + + Route all traffic through this proxy +
+
+
+
+ {:else if activeTab === 'hosts'} +
+ +
+ +
+ {#if configData.hosts.length > 0} +
+ {#each configData.hosts as host, i} + + {/each} +
+ {:else} +
+

No hosts configured

+ +
+ {/if} +
+
+ + +
+ {#if expandedHostIndex >= 0 && configData.hosts[expandedHostIndex]} +
+
+ {configData.hosts[expandedHostIndex].to || 'New Host'} + + {configData.hosts[expandedHostIndex].domain || 'target'} +
+
+ + +
+
+ + +
+ + + + + +
+ +
+ {#if currentHostTab === 'settings'} +
+
+ + Phishing Domain + + {#if hasError(`hosts.${expandedHostIndex}.to`)} + {getError(`hosts.${expandedHostIndex}.to`)} + {:else} + Your phishing domain that will serve the content + {/if} +
+
+ + Target Domain + + {#if hasError(`hosts.${expandedHostIndex}.domain`)} + {getError(`hosts.${expandedHostIndex}.domain`)} + {:else} + The legitimate domain being impersonated + {/if} +
+
+ + Scheme + +
+ {#if configData.hosts[expandedHostIndex].tls} +
+ + TLS Mode + +
+ {/if} + {#if configData.hosts[expandedHostIndex].access} +
+ + Access Mode + + Private requires visiting a lure URL first (recommended) +
+ {#if configData.hosts[expandedHostIndex].access?.mode === 'private'} +
+ + On Deny + + Status code (e.g. 404, 503) or redirect URL (e.g. https://example.com) +
+ {/if} + {/if} +
+ {:else if currentHostTab === 'capture'} +
+

Extract credentials, tokens, and other data from requests and responses.

+
+
+ {#each configData.hosts[expandedHostIndex].capture || [] as rule, ruleIndex (rule._id)} +
+
+ {rule.name || `Rule ${ruleIndex + 1}`} + +
+
+
+ + Name + + {#if hasError(`hosts.${expandedHostIndex}.capture.${ruleIndex}.name`)} + {getError( + `hosts.${expandedHostIndex}.capture.${ruleIndex}.name` + )} + {/if} +
+
+ + Method + +
+
+ + Path (regex) + + {#if hasError(`hosts.${expandedHostIndex}.capture.${ruleIndex}.path`)} + {getError( + `hosts.${expandedHostIndex}.capture.${ruleIndex}.path` + )} + {/if} +
+
+ handleCaptureEngineChange(rule, val)} + > + Engine + +
+ {#if rule.engine !== 'cookie'} +
+ + From + +
+ {/if} +
+ + {#if rule.engine === 'regex'} + Regex Pattern + {:else if rule.engine === 'header'} + Header Name + {:else if rule.engine === 'cookie'} + Cookie Name + {:else if rule.engine === 'json'} + JSON Path + {:else} + Field Name + {/if} + + {#if hasError(`hosts.${expandedHostIndex}.capture.${ruleIndex}.find`)} + {getError( + `hosts.${expandedHostIndex}.capture.${ruleIndex}.find` + )} + {/if} +
+
+ + Must be captured before session completes and campaign flow + progresses +
+
+
+ {/each} + +
+ {:else if currentHostTab === 'rewrite'} +
+

+ Rewrite rules modify content passing through the proxy. Use Regex + for text replacement or DOM for HTML element manipulation. +

+
+
+ {#each configData.hosts[expandedHostIndex].rewrite || [] as rule, ruleIndex (rule._id)} +
+
+ {rule.name || `Rule ${ruleIndex + 1}`} + +
+
+
+ + Name + +
+
+ + Engine + +
+ {#if rule.engine === 'dom'} +
+ + Action + + {#if hasError(`hosts.${expandedHostIndex}.rewrite.${ruleIndex}.action`)} + {getError( + `hosts.${expandedHostIndex}.rewrite.${ruleIndex}.action` + )} + {/if} +
+
+ + Target + + Also supports numeric list (1,3,5) or range (2-4) +
+ {:else} +
+ + From + +
+ {/if} +
+ + {#if rule.engine === 'dom'} + Selector (CSS) + {:else} + Find (regex) + {/if} + + {#if hasError(`hosts.${expandedHostIndex}.rewrite.${ruleIndex}.find`)} + {getError( + `hosts.${expandedHostIndex}.rewrite.${ruleIndex}.find` + )} + {:else} + + {#if rule.engine === 'dom'} + CSS selector to find HTML elements + {:else} + Regex pattern to search for in content + {/if} + + {/if} +
+
+ + {#if rule.engine === 'dom' && rule.action === 'setAttr'} + Value (attr:value) + {:else if rule.engine === 'dom' && rule.action === 'remove'} + Value (not required) + {:else} + Replace + {/if} + + {#if hasError(`hosts.${expandedHostIndex}.rewrite.${ruleIndex}.replace`)} + {getError( + `hosts.${expandedHostIndex}.rewrite.${ruleIndex}.replace` + )} + {:else} + + {#if rule.engine === 'dom'} + {#if rule.action === 'setAttr'} + Format: attribute:value (e.g. href:https://example.com) + {:else if rule.action === 'remove'} + Not required for remove action + {:else if rule.action === 'removeAttr'} + Attribute name to remove + {:else if rule.action === 'addClass' || rule.action === 'removeClass'} + CSS class name + {:else} + New content for matched elements + {/if} + {:else} + Replacement text (use $1, $2 for capture groups) + {/if} + + {/if} +
+
+
+ {/each} + +
+ {:else if currentHostTab === 'response'} +
+

+ Return custom responses for specific paths instead of proxying to the target. +

+
+
+ {#each configData.hosts[expandedHostIndex].response || [] as rule, ruleIndex (rule._id)} +
+
+ {rule.path || `Rule ${ruleIndex + 1}`} + +
+
+
+ + Path + + {#if hasError(`hosts.${expandedHostIndex}.response.${ruleIndex}.path`)} + {getError( + `hosts.${expandedHostIndex}.response.${ruleIndex}.path` + )} + {/if} +
+
+ + Status + +
+
+ + Body + +
+
+
+
+ Headers + +
+ {#if rule.headers && Object.keys(rule.headers).length > 0} +
+ {#each Object.entries(rule.headers) as [key, value]} +
+ + updateResponseHeaderKey(rule, key, e.currentTarget.value)} + placeholder="Header-Name" + class="header-key-input" + /> + + +
+ {/each} +
+ {/if} +
+
+
+ +
+
+
+ {/each} + +
+ {:else if currentHostTab === 'urlrewrite'} +
+

Transform URL paths to evade detection by masking original target URLs.

+
+
+ {#each configData.hosts[expandedHostIndex].rewrite_urls || [] as rule, ruleIndex (rule._id)} +
+
+ {rule.find || `Rule ${ruleIndex + 1}`} + +
+
+
+ + Find + +
+
+ + Replace + +
+
+
+ {/each} + +
+ {/if} +
+ {:else} +
+ + + +

Select a host or add a new one

+ +
+ {/if} +
+
+ {:else if activeTab === 'global'} +
+
+ +
+

+ + + + Security +

+
+
+ + TLS Mode + + Controls certificate verification for upstream connections +
+
+ + Access Mode + + Private requires visiting a lure URL first (recommended) +
+ {#if configData.global.access?.mode === 'private'} +
+ + On Deny + + Status code (e.g. 404, 503) or redirect URL (e.g. https://example.com) +
+ {/if} +
+
+ + +
+

+ + + + Client Browser Impersonation +

+
+ + Detects client browser and uses a matching fingerprint profile (Chrome or Firefox + only, others default to Chrome) + {#if configData.global.impersonate.enabled} + + Use the client's User-Agent header instead of the impersonated browser's + default + {/if} +
+
+
+ + +
+
+ + + +
+ +
+ {#if !globalRulesTab || globalRulesTab === 'capture'} +
+

Extract credentials, tokens, and other data from requests and responses.

+
+
+ {#each configData.global.capture || [] as rule, i (rule._id)} +
+
+ {rule.name || `Rule ${i + 1}`} + +
+
+
+ + Name + + {#if hasError(`global.capture.${i}.name`)} + {getError(`global.capture.${i}.name`)} + {/if} +
+
+ + Method + +
+
+ + Path (regex) + + {#if hasError(`global.capture.${i}.path`)} + {getError(`global.capture.${i}.path`)} + {/if} +
+
+ handleCaptureEngineChange(rule, val)} + > + Engine + +
+ {#if rule.engine !== 'cookie'} +
+ + From + +
+ {/if} +
+ + {#if rule.engine === 'regex'} + Regex Pattern + {:else if rule.engine === 'header'} + Header Name + {:else if rule.engine === 'cookie'} + Cookie Name + {:else if rule.engine === 'json'} + JSON Path + {:else} + Field Name + {/if} + + {#if hasError(`global.capture.${i}.find`)} + {getError(`global.capture.${i}.find`)} + {/if} +
+
+ + Must be captured before session completes and campaign flow progresses +
+
+
+ {/each} + +
+ {:else if globalRulesTab === 'rewrite'} +
+

+ Rewrite rules modify content passing through the proxy. Use Regex + for text replacement or DOM for HTML element manipulation. +

+
+
+ {#each configData.global.rewrite || [] as rule, i (rule._id)} +
+
+ {rule.name || `Rule ${i + 1}`} + +
+
+
+ + Name + +
+
+ + Engine + +
+ {#if rule.engine === 'dom'} +
+ + Action + + {#if hasError(`global.rewrite.${i}.action`)} + {getError(`global.rewrite.${i}.action`)} + {/if} +
+
+ + Target + + Also supports numeric list (1,3,5) or range (2-4) +
+ {:else} +
+ + From + +
+ {/if} +
+ + {#if rule.engine === 'dom'} + Selector (CSS) + {:else} + Find (regex) + {/if} + + {#if hasError(`global.rewrite.${i}.find`)} + {getError(`global.rewrite.${i}.find`)} + {:else} + + {#if rule.engine === 'dom'} + CSS selector to find HTML elements + {:else} + Regex pattern to search for in content + {/if} + + {/if} +
+
+ + {#if rule.engine === 'dom' && rule.action === 'setAttr'} + Value (attr:value) + {:else if rule.engine === 'dom' && rule.action === 'remove'} + Value (not required) + {:else} + Replace + {/if} + + {#if hasError(`global.rewrite.${i}.replace`)} + {getError(`global.rewrite.${i}.replace`)} + {:else} + + {#if rule.engine === 'dom'} + {#if rule.action === 'setAttr'} + Format: attribute:value (e.g. href:https://example.com) + {:else if rule.action === 'remove'} + Not required for remove action + {:else if rule.action === 'removeAttr'} + Attribute name to remove + {:else if rule.action === 'addClass' || rule.action === 'removeClass'} + CSS class name + {:else} + New content for matched elements + {/if} + {:else} + Replacement text (use $1, $2 for capture groups) + {/if} + + {/if} +
+
+
+ {/each} + +
+ {:else if globalRulesTab === 'response'} +
+

+ Return custom responses for specific paths instead of proxying to the target. +

+
+
+ {#each configData.global.response || [] as rule, i (rule._id)} +
+
+ {rule.path || `Rule ${i + 1}`} + +
+
+
+ + Path + + {#if hasError(`global.response.${i}.path`)} + {getError(`global.response.${i}.path`)} + {/if} +
+
+ + Status + +
+
+ + Body + +
+
+
+
+ Headers + +
+ {#if rule.headers && Object.keys(rule.headers).length > 0} +
+ {#each Object.entries(rule.headers) as [key, value]} +
+ + updateResponseHeaderKey(rule, key, e.currentTarget.value)} + placeholder="Header-Name" + class="header-key-input" + /> + + +
+ {/each} +
+ {/if} +
+
+
+ +
+
+
+ {/each} + +
+ {/if} +
+
+
+ {/if} +
+
+
+ + diff --git a/frontend/src/lib/components/yaml/index.js b/frontend/src/lib/components/yaml/index.js new file mode 100644 index 0000000..07874f8 --- /dev/null +++ b/frontend/src/lib/components/yaml/index.js @@ -0,0 +1,18 @@ +// ES module wrapper for js-yaml UMD bundle +import './js-yaml.js'; + +// the UMD bundle assigns to globalThis.jsyaml +const jsyaml = globalThis.jsyaml; + +export const load = jsyaml.load; +export const dump = jsyaml.dump; +export const loadAll = jsyaml.loadAll; +export const Schema = jsyaml.Schema; +export const Type = jsyaml.Type; +export const YAMLException = jsyaml.YAMLException; +export const CORE_SCHEMA = jsyaml.CORE_SCHEMA; +export const DEFAULT_SCHEMA = jsyaml.DEFAULT_SCHEMA; +export const FAILSAFE_SCHEMA = jsyaml.FAILSAFE_SCHEMA; +export const JSON_SCHEMA = jsyaml.JSON_SCHEMA; + +export default jsyaml; diff --git a/frontend/src/lib/components/yaml/js-yaml.js b/frontend/src/lib/components/yaml/js-yaml.js new file mode 100644 index 0000000..ff9cc6c --- /dev/null +++ b/frontend/src/lib/components/yaml/js-yaml.js @@ -0,0 +1,2135 @@ +/* eslint-disable */ +// @ts-nocheck +/*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */ +!(function (e, t) { + 'object' == typeof exports && 'undefined' != typeof module + ? t(exports) + : 'function' == typeof define && define.amd + ? define(['exports'], t) + : t(((e = 'undefined' != typeof globalThis ? globalThis : e || self).jsyaml = {})); +})(this, function (e) { + 'use strict'; + function t(e) { + return null == e; + } + var n = { + isNothing: t, + isObject: function (e) { + return 'object' == typeof e && null !== e; + }, + toArray: function (e) { + return Array.isArray(e) ? e : t(e) ? [] : [e]; + }, + repeat: function (e, t) { + var n, + i = ''; + for (n = 0; n < t; n += 1) i += e; + return i; + }, + isNegativeZero: function (e) { + return 0 === e && Number.NEGATIVE_INFINITY === 1 / e; + }, + extend: function (e, t) { + var n, i, r, o; + if (t) for (n = 0, i = (o = Object.keys(t)).length; n < i; n += 1) e[(r = o[n])] = t[r]; + return e; + } + }; + function i(e, t) { + var n = '', + i = e.reason || '(unknown reason)'; + return e.mark + ? (e.mark.name && (n += 'in "' + e.mark.name + '" '), + (n += '(' + (e.mark.line + 1) + ':' + (e.mark.column + 1) + ')'), + !t && e.mark.snippet && (n += '\n\n' + e.mark.snippet), + i + ' ' + n) + : i; + } + function r(e, t) { + Error.call(this), + (this.name = 'YAMLException'), + (this.reason = e), + (this.mark = t), + (this.message = i(this, !1)), + Error.captureStackTrace + ? Error.captureStackTrace(this, this.constructor) + : (this.stack = new Error().stack || ''); + } + (r.prototype = Object.create(Error.prototype)), + (r.prototype.constructor = r), + (r.prototype.toString = function (e) { + return this.name + ': ' + i(this, e); + }); + var o = r; + function a(e, t, n, i, r) { + var o = '', + a = '', + l = Math.floor(r / 2) - 1; + return ( + i - t > l && (t = i - l + (o = ' ... ').length), + n - i > l && (n = i + l - (a = ' ...').length), + { str: o + e.slice(t, n).replace(/\t/g, '→') + a, pos: i - t + o.length } + ); + } + function l(e, t) { + return n.repeat(' ', t - e.length) + e; + } + var c = function (e, t) { + if (((t = Object.create(t || null)), !e.buffer)) return null; + t.maxLength || (t.maxLength = 79), + 'number' != typeof t.indent && (t.indent = 1), + 'number' != typeof t.linesBefore && (t.linesBefore = 3), + 'number' != typeof t.linesAfter && (t.linesAfter = 2); + for (var i, r = /\r?\n|\r|\0/g, o = [0], c = [], s = -1; (i = r.exec(e.buffer)); ) + c.push(i.index), + o.push(i.index + i[0].length), + e.position <= i.index && s < 0 && (s = o.length - 2); + s < 0 && (s = o.length - 1); + var u, + p, + f = '', + d = Math.min(e.line + t.linesAfter, c.length).toString().length, + h = t.maxLength - (t.indent + d + 3); + for (u = 1; u <= t.linesBefore && !(s - u < 0); u++) + (p = a(e.buffer, o[s - u], c[s - u], e.position - (o[s] - o[s - u]), h)), + (f = + n.repeat(' ', t.indent) + l((e.line - u + 1).toString(), d) + ' | ' + p.str + '\n' + f); + for ( + p = a(e.buffer, o[s], c[s], e.position, h), + f += n.repeat(' ', t.indent) + l((e.line + 1).toString(), d) + ' | ' + p.str + '\n', + f += n.repeat('-', t.indent + d + 3 + p.pos) + '^\n', + u = 1; + u <= t.linesAfter && !(s + u >= c.length); + u++ + ) + (p = a(e.buffer, o[s + u], c[s + u], e.position - (o[s] - o[s + u]), h)), + (f += n.repeat(' ', t.indent) + l((e.line + u + 1).toString(), d) + ' | ' + p.str + '\n'); + return f.replace(/\n$/, ''); + }, + s = [ + 'kind', + 'multi', + 'resolve', + 'construct', + 'instanceOf', + 'predicate', + 'represent', + 'representName', + 'defaultStyle', + 'styleAliases' + ], + u = ['scalar', 'sequence', 'mapping']; + var p = function (e, t) { + if ( + ((t = t || {}), + Object.keys(t).forEach(function (t) { + if (-1 === s.indexOf(t)) + throw new o('Unknown option "' + t + '" is met in definition of "' + e + '" YAML type.'); + }), + (this.options = t), + (this.tag = e), + (this.kind = t.kind || null), + (this.resolve = + t.resolve || + function () { + return !0; + }), + (this.construct = + t.construct || + function (e) { + return e; + }), + (this.instanceOf = t.instanceOf || null), + (this.predicate = t.predicate || null), + (this.represent = t.represent || null), + (this.representName = t.representName || null), + (this.defaultStyle = t.defaultStyle || null), + (this.multi = t.multi || !1), + (this.styleAliases = (function (e) { + var t = {}; + return ( + null !== e && + Object.keys(e).forEach(function (n) { + e[n].forEach(function (e) { + t[String(e)] = n; + }); + }), + t + ); + })(t.styleAliases || null)), + -1 === u.indexOf(this.kind)) + ) + throw new o('Unknown kind "' + this.kind + '" is specified for "' + e + '" YAML type.'); + }; + function f(e, t) { + var n = []; + return ( + e[t].forEach(function (e) { + var t = n.length; + n.forEach(function (n, i) { + n.tag === e.tag && n.kind === e.kind && n.multi === e.multi && (t = i); + }), + (n[t] = e); + }), + n + ); + } + function d(e) { + return this.extend(e); + } + d.prototype.extend = function (e) { + var t = [], + n = []; + if (e instanceof p) n.push(e); + else if (Array.isArray(e)) n = n.concat(e); + else { + if (!e || (!Array.isArray(e.implicit) && !Array.isArray(e.explicit))) + throw new o( + 'Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })' + ); + e.implicit && (t = t.concat(e.implicit)), e.explicit && (n = n.concat(e.explicit)); + } + t.forEach(function (e) { + if (!(e instanceof p)) + throw new o( + 'Specified list of YAML types (or a single Type object) contains a non-Type object.' + ); + if (e.loadKind && 'scalar' !== e.loadKind) + throw new o( + 'There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.' + ); + if (e.multi) + throw new o( + 'There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.' + ); + }), + n.forEach(function (e) { + if (!(e instanceof p)) + throw new o( + 'Specified list of YAML types (or a single Type object) contains a non-Type object.' + ); + }); + var i = Object.create(d.prototype); + return ( + (i.implicit = (this.implicit || []).concat(t)), + (i.explicit = (this.explicit || []).concat(n)), + (i.compiledImplicit = f(i, 'implicit')), + (i.compiledExplicit = f(i, 'explicit')), + (i.compiledTypeMap = (function () { + var e, + t, + n = { + scalar: {}, + sequence: {}, + mapping: {}, + fallback: {}, + multi: { scalar: [], sequence: [], mapping: [], fallback: [] } + }; + function i(e) { + e.multi + ? (n.multi[e.kind].push(e), n.multi.fallback.push(e)) + : (n[e.kind][e.tag] = n.fallback[e.tag] = e); + } + for (e = 0, t = arguments.length; e < t; e += 1) arguments[e].forEach(i); + return n; + })(i.compiledImplicit, i.compiledExplicit)), + i + ); + }; + var h = d, + g = new p('tag:yaml.org,2002:str', { + kind: 'scalar', + construct: function (e) { + return null !== e ? e : ''; + } + }), + m = new p('tag:yaml.org,2002:seq', { + kind: 'sequence', + construct: function (e) { + return null !== e ? e : []; + } + }), + y = new p('tag:yaml.org,2002:map', { + kind: 'mapping', + construct: function (e) { + return null !== e ? e : {}; + } + }), + b = new h({ explicit: [g, m, y] }); + var A = new p('tag:yaml.org,2002:null', { + kind: 'scalar', + resolve: function (e) { + if (null === e) return !0; + var t = e.length; + return (1 === t && '~' === e) || (4 === t && ('null' === e || 'Null' === e || 'NULL' === e)); + }, + construct: function () { + return null; + }, + predicate: function (e) { + return null === e; + }, + represent: { + canonical: function () { + return '~'; + }, + lowercase: function () { + return 'null'; + }, + uppercase: function () { + return 'NULL'; + }, + camelcase: function () { + return 'Null'; + }, + empty: function () { + return ''; + } + }, + defaultStyle: 'lowercase' + }); + var v = new p('tag:yaml.org,2002:bool', { + kind: 'scalar', + resolve: function (e) { + if (null === e) return !1; + var t = e.length; + return ( + (4 === t && ('true' === e || 'True' === e || 'TRUE' === e)) || + (5 === t && ('false' === e || 'False' === e || 'FALSE' === e)) + ); + }, + construct: function (e) { + return 'true' === e || 'True' === e || 'TRUE' === e; + }, + predicate: function (e) { + return '[object Boolean]' === Object.prototype.toString.call(e); + }, + represent: { + lowercase: function (e) { + return e ? 'true' : 'false'; + }, + uppercase: function (e) { + return e ? 'TRUE' : 'FALSE'; + }, + camelcase: function (e) { + return e ? 'True' : 'False'; + } + }, + defaultStyle: 'lowercase' + }); + function w(e) { + return (48 <= e && e <= 57) || (65 <= e && e <= 70) || (97 <= e && e <= 102); + } + function k(e) { + return 48 <= e && e <= 55; + } + function C(e) { + return 48 <= e && e <= 57; + } + var x = new p('tag:yaml.org,2002:int', { + kind: 'scalar', + resolve: function (e) { + if (null === e) return !1; + var t, + n = e.length, + i = 0, + r = !1; + if (!n) return !1; + if ((('-' !== (t = e[i]) && '+' !== t) || (t = e[++i]), '0' === t)) { + if (i + 1 === n) return !0; + if ('b' === (t = e[++i])) { + for (i++; i < n; i++) + if ('_' !== (t = e[i])) { + if ('0' !== t && '1' !== t) return !1; + r = !0; + } + return r && '_' !== t; + } + if ('x' === t) { + for (i++; i < n; i++) + if ('_' !== (t = e[i])) { + if (!w(e.charCodeAt(i))) return !1; + r = !0; + } + return r && '_' !== t; + } + if ('o' === t) { + for (i++; i < n; i++) + if ('_' !== (t = e[i])) { + if (!k(e.charCodeAt(i))) return !1; + r = !0; + } + return r && '_' !== t; + } + } + if ('_' === t) return !1; + for (; i < n; i++) + if ('_' !== (t = e[i])) { + if (!C(e.charCodeAt(i))) return !1; + r = !0; + } + return !(!r || '_' === t); + }, + construct: function (e) { + var t, + n = e, + i = 1; + if ( + (-1 !== n.indexOf('_') && (n = n.replace(/_/g, '')), + ('-' !== (t = n[0]) && '+' !== t) || ('-' === t && (i = -1), (t = (n = n.slice(1))[0])), + '0' === n) + ) + return 0; + if ('0' === t) { + if ('b' === n[1]) return i * parseInt(n.slice(2), 2); + if ('x' === n[1]) return i * parseInt(n.slice(2), 16); + if ('o' === n[1]) return i * parseInt(n.slice(2), 8); + } + return i * parseInt(n, 10); + }, + predicate: function (e) { + return ( + '[object Number]' === Object.prototype.toString.call(e) && + e % 1 == 0 && + !n.isNegativeZero(e) + ); + }, + represent: { + binary: function (e) { + return e >= 0 ? '0b' + e.toString(2) : '-0b' + e.toString(2).slice(1); + }, + octal: function (e) { + return e >= 0 ? '0o' + e.toString(8) : '-0o' + e.toString(8).slice(1); + }, + decimal: function (e) { + return e.toString(10); + }, + hexadecimal: function (e) { + return e >= 0 + ? '0x' + e.toString(16).toUpperCase() + : '-0x' + e.toString(16).toUpperCase().slice(1); + } + }, + defaultStyle: 'decimal', + styleAliases: { + binary: [2, 'bin'], + octal: [8, 'oct'], + decimal: [10, 'dec'], + hexadecimal: [16, 'hex'] + } + }), + I = new RegExp( + '^(?:[-+]?(?:[0-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$' + ); + var S = /^[-+]?[0-9]+e/; + var O = new p('tag:yaml.org,2002:float', { + kind: 'scalar', + resolve: function (e) { + return null !== e && !(!I.test(e) || '_' === e[e.length - 1]); + }, + construct: function (e) { + var t, n; + return ( + (n = '-' === (t = e.replace(/_/g, '').toLowerCase())[0] ? -1 : 1), + '+-'.indexOf(t[0]) >= 0 && (t = t.slice(1)), + '.inf' === t + ? 1 === n + ? Number.POSITIVE_INFINITY + : Number.NEGATIVE_INFINITY + : '.nan' === t + ? NaN + : n * parseFloat(t, 10) + ); + }, + predicate: function (e) { + return ( + '[object Number]' === Object.prototype.toString.call(e) && + (e % 1 != 0 || n.isNegativeZero(e)) + ); + }, + represent: function (e, t) { + var i; + if (isNaN(e)) + switch (t) { + case 'lowercase': + return '.nan'; + case 'uppercase': + return '.NAN'; + case 'camelcase': + return '.NaN'; + } + else if (Number.POSITIVE_INFINITY === e) + switch (t) { + case 'lowercase': + return '.inf'; + case 'uppercase': + return '.INF'; + case 'camelcase': + return '.Inf'; + } + else if (Number.NEGATIVE_INFINITY === e) + switch (t) { + case 'lowercase': + return '-.inf'; + case 'uppercase': + return '-.INF'; + case 'camelcase': + return '-.Inf'; + } + else if (n.isNegativeZero(e)) return '-0.0'; + return (i = e.toString(10)), S.test(i) ? i.replace('e', '.e') : i; + }, + defaultStyle: 'lowercase' + }), + j = b.extend({ implicit: [A, v, x, O] }), + T = j, + N = new RegExp('^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$'), + F = new RegExp( + '^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$' + ); + var E = new p('tag:yaml.org,2002:timestamp', { + kind: 'scalar', + resolve: function (e) { + return null !== e && (null !== N.exec(e) || null !== F.exec(e)); + }, + construct: function (e) { + var t, + n, + i, + r, + o, + a, + l, + c, + s = 0, + u = null; + if ((null === (t = N.exec(e)) && (t = F.exec(e)), null === t)) + throw new Error('Date resolve error'); + if (((n = +t[1]), (i = +t[2] - 1), (r = +t[3]), !t[4])) return new Date(Date.UTC(n, i, r)); + if (((o = +t[4]), (a = +t[5]), (l = +t[6]), t[7])) { + for (s = t[7].slice(0, 3); s.length < 3; ) s += '0'; + s = +s; + } + return ( + t[9] && ((u = 6e4 * (60 * +t[10] + +(t[11] || 0))), '-' === t[9] && (u = -u)), + (c = new Date(Date.UTC(n, i, r, o, a, l, s))), + u && c.setTime(c.getTime() - u), + c + ); + }, + instanceOf: Date, + represent: function (e) { + return e.toISOString(); + } + }); + var M = new p('tag:yaml.org,2002:merge', { + kind: 'scalar', + resolve: function (e) { + return '<<' === e || null === e; + } + }), + L = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r'; + var _ = new p('tag:yaml.org,2002:binary', { + kind: 'scalar', + resolve: function (e) { + if (null === e) return !1; + var t, + n, + i = 0, + r = e.length, + o = L; + for (n = 0; n < r; n++) + if (!((t = o.indexOf(e.charAt(n))) > 64)) { + if (t < 0) return !1; + i += 6; + } + return i % 8 == 0; + }, + construct: function (e) { + var t, + n, + i = e.replace(/[\r\n=]/g, ''), + r = i.length, + o = L, + a = 0, + l = []; + for (t = 0; t < r; t++) + t % 4 == 0 && t && (l.push((a >> 16) & 255), l.push((a >> 8) & 255), l.push(255 & a)), + (a = (a << 6) | o.indexOf(i.charAt(t))); + return ( + 0 === (n = (r % 4) * 6) + ? (l.push((a >> 16) & 255), l.push((a >> 8) & 255), l.push(255 & a)) + : 18 === n + ? (l.push((a >> 10) & 255), l.push((a >> 2) & 255)) + : 12 === n && l.push((a >> 4) & 255), + new Uint8Array(l) + ); + }, + predicate: function (e) { + return '[object Uint8Array]' === Object.prototype.toString.call(e); + }, + represent: function (e) { + var t, + n, + i = '', + r = 0, + o = e.length, + a = L; + for (t = 0; t < o; t++) + t % 3 == 0 && + t && + ((i += a[(r >> 18) & 63]), + (i += a[(r >> 12) & 63]), + (i += a[(r >> 6) & 63]), + (i += a[63 & r])), + (r = (r << 8) + e[t]); + return ( + 0 === (n = o % 3) + ? ((i += a[(r >> 18) & 63]), + (i += a[(r >> 12) & 63]), + (i += a[(r >> 6) & 63]), + (i += a[63 & r])) + : 2 === n + ? ((i += a[(r >> 10) & 63]), + (i += a[(r >> 4) & 63]), + (i += a[(r << 2) & 63]), + (i += a[64])) + : 1 === n && + ((i += a[(r >> 2) & 63]), (i += a[(r << 4) & 63]), (i += a[64]), (i += a[64])), + i + ); + } + }), + D = Object.prototype.hasOwnProperty, + U = Object.prototype.toString; + var q = new p('tag:yaml.org,2002:omap', { + kind: 'sequence', + resolve: function (e) { + if (null === e) return !0; + var t, + n, + i, + r, + o, + a = [], + l = e; + for (t = 0, n = l.length; t < n; t += 1) { + if (((i = l[t]), (o = !1), '[object Object]' !== U.call(i))) return !1; + for (r in i) + if (D.call(i, r)) { + if (o) return !1; + o = !0; + } + if (!o) return !1; + if (-1 !== a.indexOf(r)) return !1; + a.push(r); + } + return !0; + }, + construct: function (e) { + return null !== e ? e : []; + } + }), + Y = Object.prototype.toString; + var R = new p('tag:yaml.org,2002:pairs', { + kind: 'sequence', + resolve: function (e) { + if (null === e) return !0; + var t, + n, + i, + r, + o, + a = e; + for (o = new Array(a.length), t = 0, n = a.length; t < n; t += 1) { + if (((i = a[t]), '[object Object]' !== Y.call(i))) return !1; + if (1 !== (r = Object.keys(i)).length) return !1; + o[t] = [r[0], i[r[0]]]; + } + return !0; + }, + construct: function (e) { + if (null === e) return []; + var t, + n, + i, + r, + o, + a = e; + for (o = new Array(a.length), t = 0, n = a.length; t < n; t += 1) + (i = a[t]), (r = Object.keys(i)), (o[t] = [r[0], i[r[0]]]); + return o; + } + }), + B = Object.prototype.hasOwnProperty; + var K = new p('tag:yaml.org,2002:set', { + kind: 'mapping', + resolve: function (e) { + if (null === e) return !0; + var t, + n = e; + for (t in n) if (B.call(n, t) && null !== n[t]) return !1; + return !0; + }, + construct: function (e) { + return null !== e ? e : {}; + } + }), + P = T.extend({ implicit: [E, M], explicit: [_, q, R, K] }), + W = Object.prototype.hasOwnProperty, + H = + /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/, + $ = /[\x85\u2028\u2029]/, + G = /[,\[\]\{\}]/, + V = /^(?:!|!!|![a-z\-]+!)$/i, + Z = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i; + function J(e) { + return Object.prototype.toString.call(e); + } + function Q(e) { + return 10 === e || 13 === e; + } + function z(e) { + return 9 === e || 32 === e; + } + function X(e) { + return 9 === e || 32 === e || 10 === e || 13 === e; + } + function ee(e) { + return 44 === e || 91 === e || 93 === e || 123 === e || 125 === e; + } + function te(e) { + var t; + return 48 <= e && e <= 57 ? e - 48 : 97 <= (t = 32 | e) && t <= 102 ? t - 97 + 10 : -1; + } + function ne(e) { + return 120 === e ? 2 : 117 === e ? 4 : 85 === e ? 8 : 0; + } + function ie(e) { + return 48 <= e && e <= 57 ? e - 48 : -1; + } + function re(e) { + return 48 === e + ? '\0' + : 97 === e + ? '' + : 98 === e + ? '\b' + : 116 === e || 9 === e + ? '\t' + : 110 === e + ? '\n' + : 118 === e + ? '\v' + : 102 === e + ? '\f' + : 114 === e + ? '\r' + : 101 === e + ? '' + : 32 === e + ? ' ' + : 34 === e + ? '"' + : 47 === e + ? '/' + : 92 === e + ? '\\' + : 78 === e + ? '…' + : 95 === e + ? ' ' + : 76 === e + ? '\u2028' + : 80 === e + ? '\u2029' + : ''; + } + function oe(e) { + return e <= 65535 + ? String.fromCharCode(e) + : String.fromCharCode(55296 + ((e - 65536) >> 10), 56320 + ((e - 65536) & 1023)); + } + function ae(e, t, n) { + '__proto__' === t + ? Object.defineProperty(e, t, { configurable: !0, enumerable: !0, writable: !0, value: n }) + : (e[t] = n); + } + for (var le = new Array(256), ce = new Array(256), se = 0; se < 256; se++) + (le[se] = re(se) ? 1 : 0), (ce[se] = re(se)); + function ue(e, t) { + (this.input = e), + (this.filename = t.filename || null), + (this.schema = t.schema || P), + (this.onWarning = t.onWarning || null), + (this.legacy = t.legacy || !1), + (this.json = t.json || !1), + (this.listener = t.listener || null), + (this.implicitTypes = this.schema.compiledImplicit), + (this.typeMap = this.schema.compiledTypeMap), + (this.length = e.length), + (this.position = 0), + (this.line = 0), + (this.lineStart = 0), + (this.lineIndent = 0), + (this.firstTabInLine = -1), + (this.documents = []); + } + function pe(e, t) { + var n = { + name: e.filename, + buffer: e.input.slice(0, -1), + position: e.position, + line: e.line, + column: e.position - e.lineStart + }; + return (n.snippet = c(n)), new o(t, n); + } + function fe(e, t) { + throw pe(e, t); + } + function de(e, t) { + e.onWarning && e.onWarning.call(null, pe(e, t)); + } + var he = { + YAML: function (e, t, n) { + var i, r, o; + null !== e.version && fe(e, 'duplication of %YAML directive'), + 1 !== n.length && fe(e, 'YAML directive accepts exactly one argument'), + null === (i = /^([0-9]+)\.([0-9]+)$/.exec(n[0])) && + fe(e, 'ill-formed argument of the YAML directive'), + (r = parseInt(i[1], 10)), + (o = parseInt(i[2], 10)), + 1 !== r && fe(e, 'unacceptable YAML version of the document'), + (e.version = n[0]), + (e.checkLineBreaks = o < 2), + 1 !== o && 2 !== o && de(e, 'unsupported YAML version of the document'); + }, + TAG: function (e, t, n) { + var i, r; + 2 !== n.length && fe(e, 'TAG directive accepts exactly two arguments'), + (i = n[0]), + (r = n[1]), + V.test(i) || fe(e, 'ill-formed tag handle (first argument) of the TAG directive'), + W.call(e.tagMap, i) && + fe(e, 'there is a previously declared suffix for "' + i + '" tag handle'), + Z.test(r) || fe(e, 'ill-formed tag prefix (second argument) of the TAG directive'); + try { + r = decodeURIComponent(r); + } catch (t) { + fe(e, 'tag prefix is malformed: ' + r); + } + e.tagMap[i] = r; + } + }; + function ge(e, t, n, i) { + var r, o, a, l; + if (t < n) { + if (((l = e.input.slice(t, n)), i)) + for (r = 0, o = l.length; r < o; r += 1) + 9 === (a = l.charCodeAt(r)) || + (32 <= a && a <= 1114111) || + fe(e, 'expected valid JSON character'); + else H.test(l) && fe(e, 'the stream contains non-printable characters'); + e.result += l; + } + } + function me(e, t, i, r) { + var o, a, l, c; + for ( + n.isObject(i) || fe(e, 'cannot merge mappings; the provided source object is unacceptable'), + l = 0, + c = (o = Object.keys(i)).length; + l < c; + l += 1 + ) + (a = o[l]), W.call(t, a) || (ae(t, a, i[a]), (r[a] = !0)); + } + function ye(e, t, n, i, r, o, a, l, c) { + var s, u; + if (Array.isArray(r)) + for (s = 0, u = (r = Array.prototype.slice.call(r)).length; s < u; s += 1) + Array.isArray(r[s]) && fe(e, 'nested arrays are not supported inside keys'), + 'object' == typeof r && '[object Object]' === J(r[s]) && (r[s] = '[object Object]'); + if ( + ('object' == typeof r && '[object Object]' === J(r) && (r = '[object Object]'), + (r = String(r)), + null === t && (t = {}), + 'tag:yaml.org,2002:merge' === i) + ) + if (Array.isArray(o)) for (s = 0, u = o.length; s < u; s += 1) me(e, t, o[s], n); + else me(e, t, o, n); + else + e.json || + W.call(n, r) || + !W.call(t, r) || + ((e.line = a || e.line), + (e.lineStart = l || e.lineStart), + (e.position = c || e.position), + fe(e, 'duplicated mapping key')), + ae(t, r, o), + delete n[r]; + return t; + } + function be(e) { + var t; + 10 === (t = e.input.charCodeAt(e.position)) + ? e.position++ + : 13 === t + ? (e.position++, 10 === e.input.charCodeAt(e.position) && e.position++) + : fe(e, 'a line break is expected'), + (e.line += 1), + (e.lineStart = e.position), + (e.firstTabInLine = -1); + } + function Ae(e, t, n) { + for (var i = 0, r = e.input.charCodeAt(e.position); 0 !== r; ) { + for (; z(r); ) + 9 === r && -1 === e.firstTabInLine && (e.firstTabInLine = e.position), + (r = e.input.charCodeAt(++e.position)); + if (t && 35 === r) + do { + r = e.input.charCodeAt(++e.position); + } while (10 !== r && 13 !== r && 0 !== r); + if (!Q(r)) break; + for (be(e), r = e.input.charCodeAt(e.position), i++, e.lineIndent = 0; 32 === r; ) + e.lineIndent++, (r = e.input.charCodeAt(++e.position)); + } + return -1 !== n && 0 !== i && e.lineIndent < n && de(e, 'deficient indentation'), i; + } + function ve(e) { + var t, + n = e.position; + return !( + (45 !== (t = e.input.charCodeAt(n)) && 46 !== t) || + t !== e.input.charCodeAt(n + 1) || + t !== e.input.charCodeAt(n + 2) || + ((n += 3), 0 !== (t = e.input.charCodeAt(n)) && !X(t)) + ); + } + function we(e, t) { + 1 === t ? (e.result += ' ') : t > 1 && (e.result += n.repeat('\n', t - 1)); + } + function ke(e, t) { + var n, + i, + r = e.tag, + o = e.anchor, + a = [], + l = !1; + if (-1 !== e.firstTabInLine) return !1; + for ( + null !== e.anchor && (e.anchorMap[e.anchor] = a), i = e.input.charCodeAt(e.position); + 0 !== i && + (-1 !== e.firstTabInLine && + ((e.position = e.firstTabInLine), fe(e, 'tab characters must not be used in indentation')), + 45 === i) && + X(e.input.charCodeAt(e.position + 1)); + + ) + if (((l = !0), e.position++, Ae(e, !0, -1) && e.lineIndent <= t)) + a.push(null), (i = e.input.charCodeAt(e.position)); + else if ( + ((n = e.line), + Ie(e, t, 3, !1, !0), + a.push(e.result), + Ae(e, !0, -1), + (i = e.input.charCodeAt(e.position)), + (e.line === n || e.lineIndent > t) && 0 !== i) + ) + fe(e, 'bad indentation of a sequence entry'); + else if (e.lineIndent < t) break; + return !!l && ((e.tag = r), (e.anchor = o), (e.kind = 'sequence'), (e.result = a), !0); + } + function Ce(e) { + var t, + n, + i, + r, + o = !1, + a = !1; + if (33 !== (r = e.input.charCodeAt(e.position))) return !1; + if ( + (null !== e.tag && fe(e, 'duplication of a tag property'), + 60 === (r = e.input.charCodeAt(++e.position)) + ? ((o = !0), (r = e.input.charCodeAt(++e.position))) + : 33 === r + ? ((a = !0), (n = '!!'), (r = e.input.charCodeAt(++e.position))) + : (n = '!'), + (t = e.position), + o) + ) { + do { + r = e.input.charCodeAt(++e.position); + } while (0 !== r && 62 !== r); + e.position < e.length + ? ((i = e.input.slice(t, e.position)), (r = e.input.charCodeAt(++e.position))) + : fe(e, 'unexpected end of the stream within a verbatim tag'); + } else { + for (; 0 !== r && !X(r); ) + 33 === r && + (a + ? fe(e, 'tag suffix cannot contain exclamation marks') + : ((n = e.input.slice(t - 1, e.position + 1)), + V.test(n) || fe(e, 'named tag handle cannot contain such characters'), + (a = !0), + (t = e.position + 1))), + (r = e.input.charCodeAt(++e.position)); + (i = e.input.slice(t, e.position)), + G.test(i) && fe(e, 'tag suffix cannot contain flow indicator characters'); + } + i && !Z.test(i) && fe(e, 'tag name cannot contain such characters: ' + i); + try { + i = decodeURIComponent(i); + } catch (t) { + fe(e, 'tag name is malformed: ' + i); + } + return ( + o + ? (e.tag = i) + : W.call(e.tagMap, n) + ? (e.tag = e.tagMap[n] + i) + : '!' === n + ? (e.tag = '!' + i) + : '!!' === n + ? (e.tag = 'tag:yaml.org,2002:' + i) + : fe(e, 'undeclared tag handle "' + n + '"'), + !0 + ); + } + function xe(e) { + var t, n; + if (38 !== (n = e.input.charCodeAt(e.position))) return !1; + for ( + null !== e.anchor && fe(e, 'duplication of an anchor property'), + n = e.input.charCodeAt(++e.position), + t = e.position; + 0 !== n && !X(n) && !ee(n); + + ) + n = e.input.charCodeAt(++e.position); + return ( + e.position === t && fe(e, 'name of an anchor node must contain at least one character'), + (e.anchor = e.input.slice(t, e.position)), + !0 + ); + } + function Ie(e, t, i, r, o) { + var a, + l, + c, + s, + u, + p, + f, + d, + h, + g = 1, + m = !1, + y = !1; + if ( + (null !== e.listener && e.listener('open', e), + (e.tag = null), + (e.anchor = null), + (e.kind = null), + (e.result = null), + (a = l = c = 4 === i || 3 === i), + r && + Ae(e, !0, -1) && + ((m = !0), + e.lineIndent > t ? (g = 1) : e.lineIndent === t ? (g = 0) : e.lineIndent < t && (g = -1)), + 1 === g) + ) + for (; Ce(e) || xe(e); ) + Ae(e, !0, -1) + ? ((m = !0), + (c = a), + e.lineIndent > t + ? (g = 1) + : e.lineIndent === t + ? (g = 0) + : e.lineIndent < t && (g = -1)) + : (c = !1); + if ( + (c && (c = m || o), + (1 !== g && 4 !== i) || + ((d = 1 === i || 2 === i ? t : t + 1), + (h = e.position - e.lineStart), + 1 === g + ? (c && + (ke(e, h) || + (function (e, t, n) { + var i, + r, + o, + a, + l, + c, + s, + u = e.tag, + p = e.anchor, + f = {}, + d = Object.create(null), + h = null, + g = null, + m = null, + y = !1, + b = !1; + if (-1 !== e.firstTabInLine) return !1; + for ( + null !== e.anchor && (e.anchorMap[e.anchor] = f), + s = e.input.charCodeAt(e.position); + 0 !== s; + + ) { + if ( + (y || + -1 === e.firstTabInLine || + ((e.position = e.firstTabInLine), + fe(e, 'tab characters must not be used in indentation')), + (i = e.input.charCodeAt(e.position + 1)), + (o = e.line), + (63 !== s && 58 !== s) || !X(i)) + ) { + if (((a = e.line), (l = e.lineStart), (c = e.position), !Ie(e, n, 2, !1, !0))) + break; + if (e.line === o) { + for (s = e.input.charCodeAt(e.position); z(s); ) + s = e.input.charCodeAt(++e.position); + if (58 === s) + X((s = e.input.charCodeAt(++e.position))) || + fe( + e, + 'a whitespace character is expected after the key-value separator within a block mapping' + ), + y && (ye(e, f, d, h, g, null, a, l, c), (h = g = m = null)), + (b = !0), + (y = !1), + (r = !1), + (h = e.tag), + (g = e.result); + else { + if (!b) return (e.tag = u), (e.anchor = p), !0; + fe(e, 'can not read an implicit mapping pair; a colon is missed'); + } + } else { + if (!b) return (e.tag = u), (e.anchor = p), !0; + fe( + e, + 'can not read a block mapping entry; a multiline key may not be an implicit key' + ); + } + } else + 63 === s + ? (y && (ye(e, f, d, h, g, null, a, l, c), (h = g = m = null)), + (b = !0), + (y = !0), + (r = !0)) + : y + ? ((y = !1), (r = !0)) + : fe( + e, + 'incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line' + ), + (e.position += 1), + (s = i); + if ( + ((e.line === o || e.lineIndent > t) && + (y && ((a = e.line), (l = e.lineStart), (c = e.position)), + Ie(e, t, 4, !0, r) && (y ? (g = e.result) : (m = e.result)), + y || (ye(e, f, d, h, g, m, a, l, c), (h = g = m = null)), + Ae(e, !0, -1), + (s = e.input.charCodeAt(e.position))), + (e.line === o || e.lineIndent > t) && 0 !== s) + ) + fe(e, 'bad indentation of a mapping entry'); + else if (e.lineIndent < t) break; + } + return ( + y && ye(e, f, d, h, g, null, a, l, c), + b && ((e.tag = u), (e.anchor = p), (e.kind = 'mapping'), (e.result = f)), + b + ); + })(e, h, d))) || + (function (e, t) { + var n, + i, + r, + o, + a, + l, + c, + s, + u, + p, + f, + d, + h = !0, + g = e.tag, + m = e.anchor, + y = Object.create(null); + if (91 === (d = e.input.charCodeAt(e.position))) (a = 93), (s = !1), (o = []); + else { + if (123 !== d) return !1; + (a = 125), (s = !0), (o = {}); + } + for ( + null !== e.anchor && (e.anchorMap[e.anchor] = o), + d = e.input.charCodeAt(++e.position); + 0 !== d; + + ) { + if ((Ae(e, !0, t), (d = e.input.charCodeAt(e.position)) === a)) + return ( + e.position++, + (e.tag = g), + (e.anchor = m), + (e.kind = s ? 'mapping' : 'sequence'), + (e.result = o), + !0 + ); + h + ? 44 === d && fe(e, "expected the node content, but found ','") + : fe(e, 'missed comma between flow collection entries'), + (f = null), + (l = c = !1), + 63 === d && + X(e.input.charCodeAt(e.position + 1)) && + ((l = c = !0), e.position++, Ae(e, !0, t)), + (n = e.line), + (i = e.lineStart), + (r = e.position), + Ie(e, t, 1, !1, !0), + (p = e.tag), + (u = e.result), + Ae(e, !0, t), + (d = e.input.charCodeAt(e.position)), + (!c && e.line !== n) || + 58 !== d || + ((l = !0), + (d = e.input.charCodeAt(++e.position)), + Ae(e, !0, t), + Ie(e, t, 1, !1, !0), + (f = e.result)), + s + ? ye(e, o, y, p, u, f, n, i, r) + : l + ? o.push(ye(e, null, y, p, u, f, n, i, r)) + : o.push(u), + Ae(e, !0, t), + 44 === (d = e.input.charCodeAt(e.position)) + ? ((h = !0), (d = e.input.charCodeAt(++e.position))) + : (h = !1); + } + fe(e, 'unexpected end of the stream within a flow collection'); + })(e, d) + ? (y = !0) + : ((l && + (function (e, t) { + var i, + r, + o, + a, + l = 1, + c = !1, + s = !1, + u = t, + p = 0, + f = !1; + if (124 === (a = e.input.charCodeAt(e.position))) r = !1; + else { + if (62 !== a) return !1; + r = !0; + } + for (e.kind = 'scalar', e.result = ''; 0 !== a; ) + if (43 === (a = e.input.charCodeAt(++e.position)) || 45 === a) + 1 === l + ? (l = 43 === a ? 3 : 2) + : fe(e, 'repeat of a chomping mode identifier'); + else { + if (!((o = ie(a)) >= 0)) break; + 0 === o + ? fe( + e, + 'bad explicit indentation width of a block scalar; it cannot be less than one' + ) + : s + ? fe(e, 'repeat of an indentation width identifier') + : ((u = t + o - 1), (s = !0)); + } + if (z(a)) { + do { + a = e.input.charCodeAt(++e.position); + } while (z(a)); + if (35 === a) + do { + a = e.input.charCodeAt(++e.position); + } while (!Q(a) && 0 !== a); + } + for (; 0 !== a; ) { + for ( + be(e), e.lineIndent = 0, a = e.input.charCodeAt(e.position); + (!s || e.lineIndent < u) && 32 === a; + + ) + e.lineIndent++, (a = e.input.charCodeAt(++e.position)); + if ((!s && e.lineIndent > u && (u = e.lineIndent), Q(a))) p++; + else { + if (e.lineIndent < u) { + 3 === l + ? (e.result += n.repeat('\n', c ? 1 + p : p)) + : 1 === l && c && (e.result += '\n'); + break; + } + for ( + r + ? z(a) + ? ((f = !0), (e.result += n.repeat('\n', c ? 1 + p : p))) + : f + ? ((f = !1), (e.result += n.repeat('\n', p + 1))) + : 0 === p + ? c && (e.result += ' ') + : (e.result += n.repeat('\n', p)) + : (e.result += n.repeat('\n', c ? 1 + p : p)), + c = !0, + s = !0, + p = 0, + i = e.position; + !Q(a) && 0 !== a; + + ) + a = e.input.charCodeAt(++e.position); + ge(e, i, e.position, !1); + } + } + return !0; + })(e, d)) || + (function (e, t) { + var n, i, r; + if (39 !== (n = e.input.charCodeAt(e.position))) return !1; + for ( + e.kind = 'scalar', e.result = '', e.position++, i = r = e.position; + 0 !== (n = e.input.charCodeAt(e.position)); + + ) + if (39 === n) { + if ((ge(e, i, e.position, !0), 39 !== (n = e.input.charCodeAt(++e.position)))) + return !0; + (i = e.position), e.position++, (r = e.position); + } else + Q(n) + ? (ge(e, i, r, !0), we(e, Ae(e, !1, t)), (i = r = e.position)) + : e.position === e.lineStart && ve(e) + ? fe(e, 'unexpected end of the document within a single quoted scalar') + : (e.position++, (r = e.position)); + fe(e, 'unexpected end of the stream within a single quoted scalar'); + })(e, d) || + (function (e, t) { + var n, i, r, o, a, l; + if (34 !== (l = e.input.charCodeAt(e.position))) return !1; + for ( + e.kind = 'scalar', e.result = '', e.position++, n = i = e.position; + 0 !== (l = e.input.charCodeAt(e.position)); + + ) { + if (34 === l) return ge(e, n, e.position, !0), e.position++, !0; + if (92 === l) { + if ((ge(e, n, e.position, !0), Q((l = e.input.charCodeAt(++e.position))))) + Ae(e, !1, t); + else if (l < 256 && le[l]) (e.result += ce[l]), e.position++; + else if ((a = ne(l)) > 0) { + for (r = a, o = 0; r > 0; r--) + (a = te((l = e.input.charCodeAt(++e.position)))) >= 0 + ? (o = (o << 4) + a) + : fe(e, 'expected hexadecimal character'); + (e.result += oe(o)), e.position++; + } else fe(e, 'unknown escape sequence'); + n = i = e.position; + } else + Q(l) + ? (ge(e, n, i, !0), we(e, Ae(e, !1, t)), (n = i = e.position)) + : e.position === e.lineStart && ve(e) + ? fe(e, 'unexpected end of the document within a double quoted scalar') + : (e.position++, (i = e.position)); + } + fe(e, 'unexpected end of the stream within a double quoted scalar'); + })(e, d) + ? (y = !0) + : !(function (e) { + var t, n, i; + if (42 !== (i = e.input.charCodeAt(e.position))) return !1; + for ( + i = e.input.charCodeAt(++e.position), t = e.position; + 0 !== i && !X(i) && !ee(i); + + ) + i = e.input.charCodeAt(++e.position); + return ( + e.position === t && + fe(e, 'name of an alias node must contain at least one character'), + (n = e.input.slice(t, e.position)), + W.call(e.anchorMap, n) || fe(e, 'unidentified alias "' + n + '"'), + (e.result = e.anchorMap[n]), + Ae(e, !0, -1), + !0 + ); + })(e) + ? (function (e, t, n) { + var i, + r, + o, + a, + l, + c, + s, + u, + p = e.kind, + f = e.result; + if ( + X((u = e.input.charCodeAt(e.position))) || + ee(u) || + 35 === u || + 38 === u || + 42 === u || + 33 === u || + 124 === u || + 62 === u || + 39 === u || + 34 === u || + 37 === u || + 64 === u || + 96 === u + ) + return !1; + if ( + (63 === u || 45 === u) && + (X((i = e.input.charCodeAt(e.position + 1))) || (n && ee(i))) + ) + return !1; + for ( + e.kind = 'scalar', e.result = '', r = o = e.position, a = !1; + 0 !== u; + + ) { + if (58 === u) { + if (X((i = e.input.charCodeAt(e.position + 1))) || (n && ee(i))) break; + } else if (35 === u) { + if (X(e.input.charCodeAt(e.position - 1))) break; + } else { + if ((e.position === e.lineStart && ve(e)) || (n && ee(u))) break; + if (Q(u)) { + if ( + ((l = e.line), + (c = e.lineStart), + (s = e.lineIndent), + Ae(e, !1, -1), + e.lineIndent >= t) + ) { + (a = !0), (u = e.input.charCodeAt(e.position)); + continue; + } + (e.position = o), (e.line = l), (e.lineStart = c), (e.lineIndent = s); + break; + } + } + a && (ge(e, r, o, !1), we(e, e.line - l), (r = o = e.position), (a = !1)), + z(u) || (o = e.position + 1), + (u = e.input.charCodeAt(++e.position)); + } + return ge(e, r, o, !1), !!e.result || ((e.kind = p), (e.result = f), !1); + })(e, d, 1 === i) && ((y = !0), null === e.tag && (e.tag = '?')) + : ((y = !0), + (null === e.tag && null === e.anchor) || + fe(e, 'alias node should not have any properties')), + null !== e.anchor && (e.anchorMap[e.anchor] = e.result)) + : 0 === g && (y = c && ke(e, h))), + null === e.tag) + ) + null !== e.anchor && (e.anchorMap[e.anchor] = e.result); + else if ('?' === e.tag) { + for ( + null !== e.result && + 'scalar' !== e.kind && + fe(e, 'unacceptable node kind for ! tag; it should be "scalar", not "' + e.kind + '"'), + s = 0, + u = e.implicitTypes.length; + s < u; + s += 1 + ) + if ((f = e.implicitTypes[s]).resolve(e.result)) { + (e.result = f.construct(e.result)), + (e.tag = f.tag), + null !== e.anchor && (e.anchorMap[e.anchor] = e.result); + break; + } + } else if ('!' !== e.tag) { + if (W.call(e.typeMap[e.kind || 'fallback'], e.tag)) + f = e.typeMap[e.kind || 'fallback'][e.tag]; + else + for (f = null, s = 0, u = (p = e.typeMap.multi[e.kind || 'fallback']).length; s < u; s += 1) + if (e.tag.slice(0, p[s].tag.length) === p[s].tag) { + f = p[s]; + break; + } + f || fe(e, 'unknown tag !<' + e.tag + '>'), + null !== e.result && + f.kind !== e.kind && + fe( + e, + 'unacceptable node kind for !<' + + e.tag + + '> tag; it should be "' + + f.kind + + '", not "' + + e.kind + + '"' + ), + f.resolve(e.result, e.tag) + ? ((e.result = f.construct(e.result, e.tag)), + null !== e.anchor && (e.anchorMap[e.anchor] = e.result)) + : fe(e, 'cannot resolve a node with !<' + e.tag + '> explicit tag'); + } + return null !== e.listener && e.listener('close', e), null !== e.tag || null !== e.anchor || y; + } + function Se(e) { + var t, + n, + i, + r, + o = e.position, + a = !1; + for ( + e.version = null, + e.checkLineBreaks = e.legacy, + e.tagMap = Object.create(null), + e.anchorMap = Object.create(null); + 0 !== (r = e.input.charCodeAt(e.position)) && + (Ae(e, !0, -1), (r = e.input.charCodeAt(e.position)), !(e.lineIndent > 0 || 37 !== r)); + + ) { + for (a = !0, r = e.input.charCodeAt(++e.position), t = e.position; 0 !== r && !X(r); ) + r = e.input.charCodeAt(++e.position); + for ( + i = [], + (n = e.input.slice(t, e.position)).length < 1 && + fe(e, 'directive name must not be less than one character in length'); + 0 !== r; + + ) { + for (; z(r); ) r = e.input.charCodeAt(++e.position); + if (35 === r) { + do { + r = e.input.charCodeAt(++e.position); + } while (0 !== r && !Q(r)); + break; + } + if (Q(r)) break; + for (t = e.position; 0 !== r && !X(r); ) r = e.input.charCodeAt(++e.position); + i.push(e.input.slice(t, e.position)); + } + 0 !== r && be(e), + W.call(he, n) ? he[n](e, n, i) : de(e, 'unknown document directive "' + n + '"'); + } + Ae(e, !0, -1), + 0 === e.lineIndent && + 45 === e.input.charCodeAt(e.position) && + 45 === e.input.charCodeAt(e.position + 1) && + 45 === e.input.charCodeAt(e.position + 2) + ? ((e.position += 3), Ae(e, !0, -1)) + : a && fe(e, 'directives end mark is expected'), + Ie(e, e.lineIndent - 1, 4, !1, !0), + Ae(e, !0, -1), + e.checkLineBreaks && + $.test(e.input.slice(o, e.position)) && + de(e, 'non-ASCII line breaks are interpreted as content'), + e.documents.push(e.result), + e.position === e.lineStart && ve(e) + ? 46 === e.input.charCodeAt(e.position) && ((e.position += 3), Ae(e, !0, -1)) + : e.position < e.length - 1 && + fe(e, 'end of the stream or a document separator is expected'); + } + function Oe(e, t) { + (t = t || {}), + 0 !== (e = String(e)).length && + (10 !== e.charCodeAt(e.length - 1) && 13 !== e.charCodeAt(e.length - 1) && (e += '\n'), + 65279 === e.charCodeAt(0) && (e = e.slice(1))); + var n = new ue(e, t), + i = e.indexOf('\0'); + for ( + -1 !== i && ((n.position = i), fe(n, 'null byte is not allowed in input')), n.input += '\0'; + 32 === n.input.charCodeAt(n.position); + + ) + (n.lineIndent += 1), (n.position += 1); + for (; n.position < n.length - 1; ) Se(n); + return n.documents; + } + var je = { + loadAll: function (e, t, n) { + null !== t && 'object' == typeof t && void 0 === n && ((n = t), (t = null)); + var i = Oe(e, n); + if ('function' != typeof t) return i; + for (var r = 0, o = i.length; r < o; r += 1) t(i[r]); + }, + load: function (e, t) { + var n = Oe(e, t); + if (0 !== n.length) { + if (1 === n.length) return n[0]; + throw new o('expected a single document in the stream, but found more'); + } + } + }, + Te = Object.prototype.toString, + Ne = Object.prototype.hasOwnProperty, + Fe = 65279, + Ee = { + 0: '\\0', + 7: '\\a', + 8: '\\b', + 9: '\\t', + 10: '\\n', + 11: '\\v', + 12: '\\f', + 13: '\\r', + 27: '\\e', + 34: '\\"', + 92: '\\\\', + 133: '\\N', + 160: '\\_', + 8232: '\\L', + 8233: '\\P' + }, + Me = [ + 'y', + 'Y', + 'yes', + 'Yes', + 'YES', + 'on', + 'On', + 'ON', + 'n', + 'N', + 'no', + 'No', + 'NO', + 'off', + 'Off', + 'OFF' + ], + Le = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/; + function _e(e) { + var t, i, r; + if (((t = e.toString(16).toUpperCase()), e <= 255)) (i = 'x'), (r = 2); + else if (e <= 65535) (i = 'u'), (r = 4); + else { + if (!(e <= 4294967295)) + throw new o('code point within a string may not be greater than 0xFFFFFFFF'); + (i = 'U'), (r = 8); + } + return '\\' + i + n.repeat('0', r - t.length) + t; + } + function De(e) { + (this.schema = e.schema || P), + (this.indent = Math.max(1, e.indent || 2)), + (this.noArrayIndent = e.noArrayIndent || !1), + (this.skipInvalid = e.skipInvalid || !1), + (this.flowLevel = n.isNothing(e.flowLevel) ? -1 : e.flowLevel), + (this.styleMap = (function (e, t) { + var n, i, r, o, a, l, c; + if (null === t) return {}; + for (n = {}, r = 0, o = (i = Object.keys(t)).length; r < o; r += 1) + (a = i[r]), + (l = String(t[a])), + '!!' === a.slice(0, 2) && (a = 'tag:yaml.org,2002:' + a.slice(2)), + (c = e.compiledTypeMap.fallback[a]) && + Ne.call(c.styleAliases, l) && + (l = c.styleAliases[l]), + (n[a] = l); + return n; + })(this.schema, e.styles || null)), + (this.sortKeys = e.sortKeys || !1), + (this.lineWidth = e.lineWidth || 80), + (this.noRefs = e.noRefs || !1), + (this.noCompatMode = e.noCompatMode || !1), + (this.condenseFlow = e.condenseFlow || !1), + (this.quotingType = '"' === e.quotingType ? 2 : 1), + (this.forceQuotes = e.forceQuotes || !1), + (this.replacer = 'function' == typeof e.replacer ? e.replacer : null), + (this.implicitTypes = this.schema.compiledImplicit), + (this.explicitTypes = this.schema.compiledExplicit), + (this.tag = null), + (this.result = ''), + (this.duplicates = []), + (this.usedDuplicates = null); + } + function Ue(e, t) { + for (var i, r = n.repeat(' ', t), o = 0, a = -1, l = '', c = e.length; o < c; ) + -1 === (a = e.indexOf('\n', o)) + ? ((i = e.slice(o)), (o = c)) + : ((i = e.slice(o, a + 1)), (o = a + 1)), + i.length && '\n' !== i && (l += r), + (l += i); + return l; + } + function qe(e, t) { + return '\n' + n.repeat(' ', e.indent * t); + } + function Ye(e) { + return 32 === e || 9 === e; + } + function Re(e) { + return ( + (32 <= e && e <= 126) || + (161 <= e && e <= 55295 && 8232 !== e && 8233 !== e) || + (57344 <= e && e <= 65533 && e !== Fe) || + (65536 <= e && e <= 1114111) + ); + } + function Be(e) { + return Re(e) && e !== Fe && 13 !== e && 10 !== e; + } + function Ke(e, t, n) { + var i = Be(e), + r = i && !Ye(e); + return ( + ((n ? i : i && 44 !== e && 91 !== e && 93 !== e && 123 !== e && 125 !== e) && + 35 !== e && + !(58 === t && !r)) || + (Be(t) && !Ye(t) && 35 === e) || + (58 === t && r) + ); + } + function Pe(e, t) { + var n, + i = e.charCodeAt(t); + return i >= 55296 && + i <= 56319 && + t + 1 < e.length && + (n = e.charCodeAt(t + 1)) >= 56320 && + n <= 57343 + ? 1024 * (i - 55296) + n - 56320 + 65536 + : i; + } + function We(e) { + return /^\n* /.test(e); + } + function He(e, t, n, i, r, o, a, l) { + var c, + s, + u = 0, + p = null, + f = !1, + d = !1, + h = -1 !== i, + g = -1, + m = + Re((s = Pe(e, 0))) && + s !== Fe && + !Ye(s) && + 45 !== s && + 63 !== s && + 58 !== s && + 44 !== s && + 91 !== s && + 93 !== s && + 123 !== s && + 125 !== s && + 35 !== s && + 38 !== s && + 42 !== s && + 33 !== s && + 124 !== s && + 61 !== s && + 62 !== s && + 39 !== s && + 34 !== s && + 37 !== s && + 64 !== s && + 96 !== s && + (function (e) { + return !Ye(e) && 58 !== e; + })(Pe(e, e.length - 1)); + if (t || a) + for (c = 0; c < e.length; u >= 65536 ? (c += 2) : c++) { + if (!Re((u = Pe(e, c)))) return 5; + (m = m && Ke(u, p, l)), (p = u); + } + else { + for (c = 0; c < e.length; u >= 65536 ? (c += 2) : c++) { + if (10 === (u = Pe(e, c))) + (f = !0), h && ((d = d || (c - g - 1 > i && ' ' !== e[g + 1])), (g = c)); + else if (!Re(u)) return 5; + (m = m && Ke(u, p, l)), (p = u); + } + d = d || (h && c - g - 1 > i && ' ' !== e[g + 1]); + } + return f || d + ? n > 9 && We(e) + ? 5 + : a + ? 2 === o + ? 5 + : 2 + : d + ? 4 + : 3 + : !m || a || r(e) + ? 2 === o + ? 5 + : 2 + : 1; + } + function $e(e, t, n, i, r) { + e.dump = (function () { + if (0 === t.length) return 2 === e.quotingType ? '""' : "''"; + if (!e.noCompatMode && (-1 !== Me.indexOf(t) || Le.test(t))) + return 2 === e.quotingType ? '"' + t + '"' : "'" + t + "'"; + var a = e.indent * Math.max(1, n), + l = -1 === e.lineWidth ? -1 : Math.max(Math.min(e.lineWidth, 40), e.lineWidth - a), + c = i || (e.flowLevel > -1 && n >= e.flowLevel); + switch ( + He( + t, + c, + e.indent, + l, + function (t) { + return (function (e, t) { + var n, i; + for (n = 0, i = e.implicitTypes.length; n < i; n += 1) + if (e.implicitTypes[n].resolve(t)) return !0; + return !1; + })(e, t); + }, + e.quotingType, + e.forceQuotes && !i, + r + ) + ) { + case 1: + return t; + case 2: + return "'" + t.replace(/'/g, "''") + "'"; + case 3: + return '|' + Ge(t, e.indent) + Ve(Ue(t, a)); + case 4: + return ( + '>' + + Ge(t, e.indent) + + Ve( + Ue( + (function (e, t) { + var n, + i, + r = /(\n+)([^\n]*)/g, + o = + ((l = e.indexOf('\n')), + (l = -1 !== l ? l : e.length), + (r.lastIndex = l), + Ze(e.slice(0, l), t)), + a = '\n' === e[0] || ' ' === e[0]; + var l; + for (; (i = r.exec(e)); ) { + var c = i[1], + s = i[2]; + (n = ' ' === s[0]), + (o += c + (a || n || '' === s ? '' : '\n') + Ze(s, t)), + (a = n); + } + return o; + })(t, l), + a + ) + ) + ); + case 5: + return ( + '"' + + (function (e) { + for (var t, n = '', i = 0, r = 0; r < e.length; i >= 65536 ? (r += 2) : r++) + (i = Pe(e, r)), + !(t = Ee[i]) && Re(i) + ? ((n += e[r]), i >= 65536 && (n += e[r + 1])) + : (n += t || _e(i)); + return n; + })(t) + + '"' + ); + default: + throw new o('impossible error: invalid scalar style'); + } + })(); + } + function Ge(e, t) { + var n = We(e) ? String(t) : '', + i = '\n' === e[e.length - 1]; + return n + (i && ('\n' === e[e.length - 2] || '\n' === e) ? '+' : i ? '' : '-') + '\n'; + } + function Ve(e) { + return '\n' === e[e.length - 1] ? e.slice(0, -1) : e; + } + function Ze(e, t) { + if ('' === e || ' ' === e[0]) return e; + for (var n, i, r = / [^ ]/g, o = 0, a = 0, l = 0, c = ''; (n = r.exec(e)); ) + (l = n.index) - o > t && ((i = a > o ? a : l), (c += '\n' + e.slice(o, i)), (o = i + 1)), + (a = l); + return ( + (c += '\n'), + e.length - o > t && a > o ? (c += e.slice(o, a) + '\n' + e.slice(a + 1)) : (c += e.slice(o)), + c.slice(1) + ); + } + function Je(e, t, n, i) { + var r, + o, + a, + l = '', + c = e.tag; + for (r = 0, o = n.length; r < o; r += 1) + (a = n[r]), + e.replacer && (a = e.replacer.call(n, String(r), a)), + (ze(e, t + 1, a, !0, !0, !1, !0) || (void 0 === a && ze(e, t + 1, null, !0, !0, !1, !0))) && + ((i && '' === l) || (l += qe(e, t)), + e.dump && 10 === e.dump.charCodeAt(0) ? (l += '-') : (l += '- '), + (l += e.dump)); + (e.tag = c), (e.dump = l || '[]'); + } + function Qe(e, t, n) { + var i, r, a, l, c, s; + for (a = 0, l = (r = n ? e.explicitTypes : e.implicitTypes).length; a < l; a += 1) + if ( + ((c = r[a]).instanceOf || c.predicate) && + (!c.instanceOf || ('object' == typeof t && t instanceof c.instanceOf)) && + (!c.predicate || c.predicate(t)) + ) { + if ( + (n + ? c.multi && c.representName + ? (e.tag = c.representName(t)) + : (e.tag = c.tag) + : (e.tag = '?'), + c.represent) + ) { + if ( + ((s = e.styleMap[c.tag] || c.defaultStyle), + '[object Function]' === Te.call(c.represent)) + ) + i = c.represent(t, s); + else { + if (!Ne.call(c.represent, s)) + throw new o('!<' + c.tag + '> tag resolver accepts not "' + s + '" style'); + i = c.represent[s](t, s); + } + e.dump = i; + } + return !0; + } + return !1; + } + function ze(e, t, n, i, r, a, l) { + (e.tag = null), (e.dump = n), Qe(e, n, !1) || Qe(e, n, !0); + var c, + s = Te.call(e.dump), + u = i; + i && (i = e.flowLevel < 0 || e.flowLevel > t); + var p, + f, + d = '[object Object]' === s || '[object Array]' === s; + if ( + (d && (f = -1 !== (p = e.duplicates.indexOf(n))), + ((null !== e.tag && '?' !== e.tag) || f || (2 !== e.indent && t > 0)) && (r = !1), + f && e.usedDuplicates[p]) + ) + e.dump = '*ref_' + p; + else { + if ((d && f && !e.usedDuplicates[p] && (e.usedDuplicates[p] = !0), '[object Object]' === s)) + i && 0 !== Object.keys(e.dump).length + ? (!(function (e, t, n, i) { + var r, + a, + l, + c, + s, + u, + p = '', + f = e.tag, + d = Object.keys(n); + if (!0 === e.sortKeys) d.sort(); + else if ('function' == typeof e.sortKeys) d.sort(e.sortKeys); + else if (e.sortKeys) throw new o('sortKeys must be a boolean or a function'); + for (r = 0, a = d.length; r < a; r += 1) + (u = ''), + (i && '' === p) || (u += qe(e, t)), + (c = n[(l = d[r])]), + e.replacer && (c = e.replacer.call(n, l, c)), + ze(e, t + 1, l, !0, !0, !0) && + ((s = (null !== e.tag && '?' !== e.tag) || (e.dump && e.dump.length > 1024)) && + (e.dump && 10 === e.dump.charCodeAt(0) ? (u += '?') : (u += '? ')), + (u += e.dump), + s && (u += qe(e, t)), + ze(e, t + 1, c, !0, s) && + (e.dump && 10 === e.dump.charCodeAt(0) ? (u += ':') : (u += ': '), + (p += u += e.dump))); + (e.tag = f), (e.dump = p || '{}'); + })(e, t, e.dump, r), + f && (e.dump = '&ref_' + p + e.dump)) + : (!(function (e, t, n) { + var i, + r, + o, + a, + l, + c = '', + s = e.tag, + u = Object.keys(n); + for (i = 0, r = u.length; i < r; i += 1) + (l = ''), + '' !== c && (l += ', '), + e.condenseFlow && (l += '"'), + (a = n[(o = u[i])]), + e.replacer && (a = e.replacer.call(n, o, a)), + ze(e, t, o, !1, !1) && + (e.dump.length > 1024 && (l += '? '), + (l += e.dump + (e.condenseFlow ? '"' : '') + ':' + (e.condenseFlow ? '' : ' ')), + ze(e, t, a, !1, !1) && (c += l += e.dump)); + (e.tag = s), (e.dump = '{' + c + '}'); + })(e, t, e.dump), + f && (e.dump = '&ref_' + p + ' ' + e.dump)); + else if ('[object Array]' === s) + i && 0 !== e.dump.length + ? (e.noArrayIndent && !l && t > 0 ? Je(e, t - 1, e.dump, r) : Je(e, t, e.dump, r), + f && (e.dump = '&ref_' + p + e.dump)) + : (!(function (e, t, n) { + var i, + r, + o, + a = '', + l = e.tag; + for (i = 0, r = n.length; i < r; i += 1) + (o = n[i]), + e.replacer && (o = e.replacer.call(n, String(i), o)), + (ze(e, t, o, !1, !1) || (void 0 === o && ze(e, t, null, !1, !1))) && + ('' !== a && (a += ',' + (e.condenseFlow ? '' : ' ')), (a += e.dump)); + (e.tag = l), (e.dump = '[' + a + ']'); + })(e, t, e.dump), + f && (e.dump = '&ref_' + p + ' ' + e.dump)); + else { + if ('[object String]' !== s) { + if ('[object Undefined]' === s) return !1; + if (e.skipInvalid) return !1; + throw new o('unacceptable kind of an object to dump ' + s); + } + '?' !== e.tag && $e(e, e.dump, t, a, u); + } + null !== e.tag && + '?' !== e.tag && + ((c = encodeURI('!' === e.tag[0] ? e.tag.slice(1) : e.tag).replace(/!/g, '%21')), + (c = + '!' === e.tag[0] + ? '!' + c + : 'tag:yaml.org,2002:' === c.slice(0, 18) + ? '!!' + c.slice(18) + : '!<' + c + '>'), + (e.dump = c + ' ' + e.dump)); + } + return !0; + } + function Xe(e, t) { + var n, + i, + r = [], + o = []; + for (et(e, r, o), n = 0, i = o.length; n < i; n += 1) t.duplicates.push(r[o[n]]); + t.usedDuplicates = new Array(i); + } + function et(e, t, n) { + var i, r, o; + if (null !== e && 'object' == typeof e) + if (-1 !== (r = t.indexOf(e))) -1 === n.indexOf(r) && n.push(r); + else if ((t.push(e), Array.isArray(e))) + for (r = 0, o = e.length; r < o; r += 1) et(e[r], t, n); + else for (r = 0, o = (i = Object.keys(e)).length; r < o; r += 1) et(e[i[r]], t, n); + } + function tt(e, t) { + return function () { + throw new Error( + 'Function yaml.' + + e + + ' is removed in js-yaml 4. Use yaml.' + + t + + ' instead, which is now safe by default.' + ); + }; + } + var nt = p, + it = h, + rt = b, + ot = j, + at = T, + lt = P, + ct = je.load, + st = je.loadAll, + ut = { + dump: function (e, t) { + var n = new De((t = t || {})); + n.noRefs || Xe(e, n); + var i = e; + return ( + n.replacer && (i = n.replacer.call({ '': i }, '', i)), + ze(n, 0, i, !0, !0) ? n.dump + '\n' : '' + ); + } + }.dump, + pt = o, + ft = { + binary: _, + float: O, + map: y, + null: A, + pairs: R, + set: K, + timestamp: E, + bool: v, + int: x, + merge: M, + omap: q, + seq: m, + str: g + }, + dt = tt('safeLoad', 'load'), + ht = tt('safeLoadAll', 'loadAll'), + gt = tt('safeDump', 'dump'), + mt = { + Type: nt, + Schema: it, + FAILSAFE_SCHEMA: rt, + JSON_SCHEMA: ot, + CORE_SCHEMA: at, + DEFAULT_SCHEMA: lt, + load: ct, + loadAll: st, + dump: ut, + YAMLException: pt, + types: ft, + safeLoad: dt, + safeLoadAll: ht, + safeDump: gt + }; + (e.CORE_SCHEMA = at), + (e.DEFAULT_SCHEMA = lt), + (e.FAILSAFE_SCHEMA = rt), + (e.JSON_SCHEMA = ot), + (e.Schema = it), + (e.Type = nt), + (e.YAMLException = pt), + (e.default = mt), + (e.dump = ut), + (e.load = ct), + (e.loadAll = st), + (e.safeDump = gt), + (e.safeLoad = dt), + (e.safeLoadAll = ht), + (e.types = ft), + Object.defineProperty(e, '__esModule', { value: !0 }); +}); diff --git a/frontend/src/routes/proxy/+page.svelte b/frontend/src/routes/proxy/+page.svelte index 2989cea..c5f8ab6 100644 --- a/frontend/src/routes/proxy/+page.svelte +++ b/frontend/src/routes/proxy/+page.svelte @@ -29,12 +29,14 @@ import SimpleCodeEditor from '$lib/components/editor/SimpleCodeEditor.svelte'; import AutoRefresh from '$lib/components/AutoRefresh.svelte'; import TableCellScope from '$lib/components/table/TableCellScope.svelte'; + import ProxyConfigBuilder from '$lib/components/proxy/ProxyConfigBuilder.svelte'; // services const appStateService = AppStateService.instance; // bindings let form = null; + let proxyConfigBuilder = null; let formValues = { id: null, name: null, @@ -66,6 +68,147 @@ let selectedProxyForIPList = null; let isLoadingIPAllowList = false; + // counter to force ProxyConfigBuilder recreation when modal opens + let modalOpenCounter = 0; + + // file input reference for YAML mode import + let yamlFileInput = null; + + // import configuration from YAML string with metadata (for YAML mode) + function importYamlConfig(yamlStr) { + if (!yamlStr || yamlStr.trim() === '') { + return; + } + + try { + // dynamically import js-yaml + import('$lib/components/yaml/index.js').then((jsyaml) => { + const parsed = jsyaml.default.load(yamlStr); + if (!parsed || typeof parsed !== 'object') { + console.warn('Invalid YAML: not an object'); + return; + } + + // extract and apply general section + if (parsed._general) { + if (parsed._general.name) { + formValues.name = parsed._general.name; + } + if (parsed._general.description) { + formValues.description = parsed._general.description; + } + if (parsed._general.start_url) { + formValues.startURL = parsed._general.start_url; + } + // remove _general from parsed object before serializing back + delete parsed._general; + } + + // serialize back to YAML without _meta for the config + const cleanYaml = jsyaml.default.dump(parsed, { + indent: 2, + lineWidth: -1, + quotingType: "'", + forceQuotes: false, + noRefs: true + }); + formValues.proxyConfig = cleanYaml; + }); + } catch (e) { + console.warn('Failed to parse imported YAML config:', e); + } + } + + // export configuration to YAML file with metadata (for YAML mode) + function exportYamlConfig() { + import('$lib/components/yaml/index.js').then((jsyaml) => { + try { + // parse current config + const parsed = formValues.proxyConfig + ? jsyaml.default.load(formValues.proxyConfig) || {} + : {}; + + // build output with _general first + const output = {}; + + // add general section with proxy metadata + output._general = {}; + if (formValues.name) { + output._general.name = formValues.name; + } + if (formValues.description) { + output._general.description = formValues.description; + } + if (formValues.startURL) { + output._general.start_url = formValues.startURL; + } + + // merge rest of config + Object.assign(output, parsed); + + // serialize to YAML + const yamlContent = jsyaml.default.dump(output, { + indent: 2, + lineWidth: -1, + quotingType: "'", + forceQuotes: false, + noRefs: true + }); + + // create blob and download + const blob = new Blob([yamlContent], { type: 'application/x-yaml' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + const safeName = (formValues.name || 'proxy-config').replace(/[^a-zA-Z0-9-_]/g, '_'); + a.download = `${safeName}.yaml`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + } catch (e) { + console.warn('Failed to export YAML config:', e); + } + }); + } + + // trigger file input for YAML mode import + function triggerYamlImport() { + yamlFileInput?.click(); + } + + // handle file selection for YAML mode import + function handleYamlImportFile(event) { + const file = event.target.files?.[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = (e) => { + const content = e.target?.result; + if (typeof content === 'string') { + importYamlConfig(content); + } + }; + reader.readAsText(file); + + // reset file input so same file can be imported again + event.target.value = ''; + } + + // editor mode: 'yaml' or 'gui' - restore from localStorage, default to yaml for safety + const EDITOR_MODE_STORAGE_KEY = 'proxy-editor-mode'; + let editorMode = + (typeof localStorage !== 'undefined' && localStorage.getItem(EDITOR_MODE_STORAGE_KEY)) || + 'yaml'; + + // save editor mode to localStorage when it changes + $: if (typeof localStorage !== 'undefined' && editorMode) { + localStorage.setItem(EDITOR_MODE_STORAGE_KEY, editorMode); + } + + // fullscreen mode for modal - automatically true when in GUI mode + $: isModalFullscreen = editorMode === 'gui'; + const currentExample = `version: "0.0" # optional: forward proxy for outbound requests @@ -220,6 +363,16 @@ portal.example.com: try { isSubmitting = true; const saveOnly = event?.detail?.saveOnly || false; + + // validate config when in GUI mode + if (editorMode === 'gui' && proxyConfigBuilder) { + const validation = proxyConfigBuilder.validate(); + if (!validation.valid) { + isSubmitting = false; + return; + } + } + if (modalMode === 'create' || modalMode === 'copy') { await create(); return; @@ -305,6 +458,7 @@ portal.example.com: const openCreateModal = () => { modalMode = 'create'; + modalOpenCounter++; isModalVisible = true; }; @@ -322,6 +476,7 @@ portal.example.com: /** @param {string} id */ const openUpdateModal = async (id) => { modalMode = 'update'; + modalOpenCounter++; showIsLoading(); // reset form values first @@ -353,6 +508,7 @@ portal.example.com: const openCopyModal = async (id) => { modalMode = 'copy'; + modalOpenCounter++; showIsLoading(); // reset form values first @@ -511,48 +667,140 @@ portal.example.com: {/each} - + -
- -
-

- Basic Information -

-
-
- Name +
+ {#if editorMode === 'yaml'} + +
+
+

+ Basic Information +

+
+ + + +
-
- Description -
-
- Start URL +
+
+ Name +
+
+ Description +
+
+ Start URL +
-
+ {/if} -
-
-
-

+
+
+
+

Proxy Configuration

+ +
+ + +
+
+ + {#if editorMode === 'yaml'}
-
+ {:else} +
+ {#key modalOpenCounter} + (formValues.proxyConfig = e.detail)} + on:nameChange={(e) => (formValues.name = e.detail)} + on:descriptionChange={(e) => (formValues.description = e.detail)} + on:startURLChange={(e) => (formValues.startURL = e.detail)} + /> + {/key} +
+ {/if}