From 7b11e7dd801b6bb9b0f67a0f3a1b42ec044d36cf Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Tue, 22 Jul 2025 16:12:28 +1000
Subject: [PATCH 01/13] MVP of parametric SVG system - vibe coded
---
src/css/property-validation.css | 129 +++++++++++
src/index.html | 12 +-
src/js/Keyboard.js | 2 +-
src/js/Panel.js | 9 +-
src/js/Parameters.js | 196 +++++++++++++++++
src/js/PropertyValidation.js | 365 ++++++++++++++++++++++++++++++++
src/js/dao.js | 9 +
src/js/editor.js | 186 ++++++++++++++++
src/js/lib/jquery-draginput.js | 9 +
src/js/modals.js | 307 +++++++++++++++++++++++++++
src/js/start.js | 11 +-
src/js/state.js | 1 +
src/js/svgcanvas.js | 2 +
13 files changed, 1231 insertions(+), 7 deletions(-)
create mode 100644 src/css/property-validation.css
create mode 100644 src/js/Parameters.js
create mode 100644 src/js/PropertyValidation.js
diff --git a/src/css/property-validation.css b/src/css/property-validation.css
new file mode 100644
index 00000000..0e7f1295
--- /dev/null
+++ b/src/css/property-validation.css
@@ -0,0 +1,129 @@
+/* Property Input Validation Styles */
+
+/* Valid parameter reference (e.g., @width) */
+.draginput .param-reference {
+ background-color: #e7f3ff !important;
+ border-color: #007cba !important;
+ color: #005a8b !important;
+ font-weight: 500;
+ font-size: 10px !important;
+ /* Maintain proper draginput layout - preserve original padding */
+ padding: 30px 0 16px !important;
+ text-align: center !important;
+ /* Ensure text doesn't overflow into label area */
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ /* Preserve draginput positioning */
+ position: relative !important;
+ z-index: 2 !important;
+ width: 100% !important;
+ height: 24px !important;
+}
+
+/* Make labels visible on parameter reference fields - use class-based approach */
+.draginput.has-parameter span,
+.draginput.has-parameter span.icon_label,
+.draginput .param-reference + span,
+.draginput .param-reference + span.icon_label,
+.draginput .param-reference ~ span,
+.draginput .param-reference ~ span.icon_label {
+ color: #333 !important;
+ font-weight: 600 !important;
+ /* Ensure label stays in correct position */
+ position: absolute !important;
+ top: 5px !important;
+ left: 5px !important;
+ z-index: 10 !important;
+ white-space: nowrap !important;
+ display: block !important;
+ visibility: visible !important;
+ opacity: 1 !important;
+ font-size: 12px !important;
+ background: none !important;
+ border: none !important;
+ pointer-events: none !important;
+}
+
+/* Valid value (number or valid parameter reference) */
+.draginput .param-valid {
+ border-color: #28a745 !important;
+}
+
+/* Invalid value */
+.draginput .param-invalid {
+ background-color: #fff5f5 !important;
+ border-color: #dc3545 !important;
+ color: #dc3545 !important;
+ font-size: 11px !important;
+ /* Maintain proper draginput layout */
+ padding: 30px 0 16px !important;
+ text-align: center !important;
+ position: relative !important;
+ z-index: 2 !important;
+ width: 100% !important;
+ height: 24px !important;
+}
+
+/* Make labels visible on invalid fields too */
+.draginput .param-invalid + span,
+.draginput .param-invalid + span.icon_label,
+.draginput .param-invalid ~ span,
+.draginput .param-invalid ~ span.icon_label {
+ color: #333 !important;
+ font-weight: 600 !important;
+ /* Ensure label stays in correct position */
+ position: absolute !important;
+ top: 5px !important;
+ left: 5px !important;
+ z-index: 10 !important;
+ white-space: nowrap !important;
+ display: block !important;
+ visibility: visible !important;
+ opacity: 1 !important;
+ font-size: 12px !important;
+ background: none !important;
+ border: none !important;
+ pointer-events: none !important;
+}
+
+/* Parameter autocomplete suggestions */
+datalist option {
+ background: #f8f9fa;
+ color: #007cba;
+ font-family: monospace;
+}
+
+/* Focus states for parameter inputs */
+input.param-reference:focus {
+ box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.25);
+}
+
+input.param-invalid:focus {
+ box-shadow: 0 0 0 2px rgba(220, 53, 69, 0.25);
+}
+
+/* Placeholder styling for parameter hints */
+input[data-attr]::placeholder {
+ color: #666;
+ font-style: italic;
+}
+
+/* Tooltip for invalid parameter references */
+input.param-invalid {
+ position: relative;
+}
+
+input.param-invalid:hover::after {
+ content: "Invalid parameter reference or number format";
+ position: absolute;
+ top: 100%;
+ left: 0;
+ background: #dc3545;
+ color: white;
+ padding: 4px 8px;
+ border-radius: 3px;
+ font-size: 12px;
+ white-space: nowrap;
+ z-index: 1000;
+ margin-top: 2px;
+}
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
index d71ea870..57da29ac 100644
--- a/src/index.html
+++ b/src/index.html
@@ -35,7 +35,8 @@
-
+
+
@@ -87,6 +88,7 @@
+
@@ -96,6 +98,8 @@
+
+
@@ -152,12 +156,12 @@ Canvas
-
+
Width
-
+
Height
@@ -802,6 +806,8 @@ Stroke
+
+
diff --git a/src/js/Keyboard.js b/src/js/Keyboard.js
index d1075d2b..7f75ef0b 100644
--- a/src/js/Keyboard.js
+++ b/src/js/Keyboard.js
@@ -85,7 +85,7 @@ MD.Keyboard = function(){
document.addEventListener("keyup", function(e){
if ($("#color_picker").is(":visible")) return e;
const canvasMode = state.get("canvasMode");
- const key = e.key.toLowerCase();
+ const key = e.key ? e.key.toLowerCase() : '';
const keys = {
"alt": ()=> $("#workarea").removeClass("out"),
" ": ()=> editor.pan.stopPan(),
diff --git a/src/js/Panel.js b/src/js/Panel.js
index 38c247df..b4efbaa3 100644
--- a/src/js/Panel.js
+++ b/src/js/Panel.js
@@ -350,7 +350,7 @@ MD.Panel = function(){
if (!elem && !multiselected) {
menu_items.disableContextMenuItems('#delete,#cut,#copy,#ungroup,#move_front,#move_up,#move_down,#move_back');
- $('.menu_item', '#edit_menu').addClass('disabled');
+ $('.menu_item.action_selected', '#edit_menu').addClass('disabled');
}
$('.menu_item', '#object_menu').toggleClass('disabled', !elem && !multiselected);
@@ -371,6 +371,13 @@ MD.Panel = function(){
// Enable regular menu options
$("#cmenu_canvas").enableContextMenuItems('#delete,#cut,#copy,#move_front,#move_up,#move_down,#move_back');
}
+
+ // Restore parameter references for the selected element, or clear validation if none selected
+ if (editor.propertyValidation) {
+ setTimeout(() => {
+ editor.propertyValidation.restoreParameterReferences();
+ }, 10);
+ }
}
$('#cur_context_panel').delegate('a', 'click', function() {
diff --git a/src/js/Parameters.js b/src/js/Parameters.js
new file mode 100644
index 00000000..d48fb966
--- /dev/null
+++ b/src/js/Parameters.js
@@ -0,0 +1,196 @@
+MD.Parameters = function(){
+ const _self = this;
+
+ // Parameter name validation regex: must start with letter or underscore,
+ // followed by letters, numbers, or underscores
+ const PARAM_NAME_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
+
+ // Parameter types supported
+ const PARAM_TYPES = {
+ number: { label: 'Number', defaultValue: 0 },
+ text: { label: 'Text', defaultValue: '' },
+ color: { label: 'Color', defaultValue: '#000000' },
+ boolean: { label: 'Boolean', defaultValue: false }
+ };
+
+ // Get current parameters from state
+ function getParameters() {
+ return state.get('canvasParameters') || {};
+ }
+
+ // Save parameters to state
+ function saveParameters(params) {
+ state.set('canvasParameters', params);
+ }
+
+ // Validate parameter name
+ function isValidParameterName(name) {
+ if (!name || typeof name !== 'string') return false;
+ return PARAM_NAME_REGEX.test(name);
+ }
+
+ // Check if parameter name already exists
+ function parameterExists(name, excludeId = null) {
+ const params = getParameters();
+ return Object.keys(params).some(id =>
+ id !== excludeId && params[id].name === name
+ );
+ }
+
+ // Generate unique parameter ID
+ function generateParameterId() {
+ return 'param_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
+ }
+
+ // Add new parameter
+ function addParameter(name, type, defaultValue, description = '') {
+ if (!isValidParameterName(name)) {
+ throw new Error('Invalid parameter name. Must start with letter or underscore, followed by letters, numbers, or underscores.');
+ }
+
+ if (parameterExists(name)) {
+ throw new Error('Parameter name already exists.');
+ }
+
+ if (!PARAM_TYPES[type]) {
+ throw new Error('Invalid parameter type.');
+ }
+
+ const params = getParameters();
+ const id = generateParameterId();
+
+ params[id] = {
+ name: name,
+ type: type,
+ defaultValue: defaultValue,
+ description: description
+ };
+
+ saveParameters(params);
+ return id;
+ }
+
+ // Update existing parameter
+ function updateParameter(id, name, type, defaultValue, description = '') {
+ if (!isValidParameterName(name)) {
+ throw new Error('Invalid parameter name. Must start with letter or underscore, followed by letters, numbers, or underscores.');
+ }
+
+ if (parameterExists(name, id)) {
+ throw new Error('Parameter name already exists.');
+ }
+
+ if (!PARAM_TYPES[type]) {
+ throw new Error('Invalid parameter type.');
+ }
+
+ const params = getParameters();
+ if (!params[id]) {
+ throw new Error('Parameter not found.');
+ }
+
+ params[id] = {
+ name: name,
+ type: type,
+ defaultValue: defaultValue,
+ description: description
+ };
+
+ saveParameters(params);
+ }
+
+ // Delete parameter
+ function deleteParameter(id) {
+ const params = getParameters();
+ if (!params[id]) {
+ throw new Error('Parameter not found.');
+ }
+
+ delete params[id];
+ saveParameters(params);
+ }
+
+ // Get parameter by ID
+ function getParameter(id) {
+ const params = getParameters();
+ return params[id] || null;
+ }
+
+ // Get parameter by name
+ function getParameterByName(name) {
+ const params = getParameters();
+ const id = Object.keys(params).find(id => params[id].name === name);
+ return id ? params[id] : null;
+ }
+
+ // Get all parameter names (for autocomplete)
+ function getParameterNames() {
+ const params = getParameters();
+ return Object.values(params).map(param => param.name);
+ }
+
+ // Resolve parameter reference (e.g., "@width" -> actual value)
+ function resolveParameterValue(value) {
+ if (typeof value !== 'string' || !value.startsWith('@')) {
+ return value;
+ }
+
+ const paramName = value.substring(1);
+ const param = getParameterByName(paramName);
+
+ if (!param) {
+ console.warn(`Parameter @${paramName} not found, using original value`);
+ return value;
+ }
+
+ // Ensure proper type conversion
+ const resolvedValue = param.defaultValue;
+ if (param.type === 'number') {
+ const num = parseFloat(resolvedValue);
+ return isNaN(num) ? 0 : num;
+ }
+
+ return resolvedValue;
+ }
+
+ // Check if a value is a parameter reference
+ function isParameterReference(value) {
+ return typeof value === 'string' && value.startsWith('@') && value.length > 1;
+ }
+
+ // Validate parameter value for its type
+ function validateParameterValue(value, type) {
+ switch (type) {
+ case 'number':
+ const num = parseFloat(value);
+ return !isNaN(num) ? num : PARAM_TYPES.number.defaultValue;
+ case 'text':
+ return String(value);
+ case 'color':
+ // Basic color validation - should be hex color
+ if (typeof value === 'string' && /^#[0-9A-F]{6}$/i.test(value)) {
+ return value;
+ }
+ return PARAM_TYPES.color.defaultValue;
+ case 'boolean':
+ return Boolean(value);
+ default:
+ return value;
+ }
+ }
+
+ // Public API
+ this.getParameters = getParameters;
+ this.addParameter = addParameter;
+ this.updateParameter = updateParameter;
+ this.deleteParameter = deleteParameter;
+ this.getParameter = getParameter;
+ this.getParameterByName = getParameterByName;
+ this.getParameterNames = getParameterNames;
+ this.resolveParameterValue = resolveParameterValue;
+ this.isParameterReference = isParameterReference;
+ this.validateParameterValue = validateParameterValue;
+ this.isValidParameterName = isValidParameterName;
+ this.parameterExists = parameterExists;
+ this.PARAM_TYPES = PARAM_TYPES;
+};
\ No newline at end of file
diff --git a/src/js/PropertyValidation.js b/src/js/PropertyValidation.js
new file mode 100644
index 00000000..1b9e09fd
--- /dev/null
+++ b/src/js/PropertyValidation.js
@@ -0,0 +1,365 @@
+MD.PropertyValidation = function() {
+ const _self = this;
+
+ // Pattern to match parameter references (@paramName)
+ const PARAM_REFERENCE_PATTERN = /^@[a-zA-Z_][a-zA-Z0-9_]*$/;
+
+ // Pattern to match numeric values (including decimals and negatives)
+ const NUMERIC_PATTERN = /^-?[0-9]+(\.[0-9]+)?$/;
+
+ // Validate if a value is either a number or a valid parameter reference
+ function isValidPropertyValue(value) {
+ if (typeof value !== 'string') return false;
+
+ value = value.trim();
+ if (value === '') return false;
+
+ // Check if it's a number
+ if (NUMERIC_PATTERN.test(value)) return true;
+
+ // Check if it's a valid parameter reference
+ if (PARAM_REFERENCE_PATTERN.test(value)) {
+ const paramName = value.substring(1);
+ return editor.parametersManager.getParameterByName(paramName) !== null;
+ }
+
+ return false;
+ }
+
+ // Clear all validation classes from an input
+ function clearInputValidation(input) {
+ input.classList.remove('param-valid', 'param-invalid', 'param-reference');
+ input.removeAttribute('data-original-param');
+
+ // Remove has-parameter class from parent draginput
+ const draginputParent = input.closest('.draginput');
+ if (draginputParent) {
+ draginputParent.classList.remove('has-parameter');
+ }
+ }
+
+ // Add visual feedback to input field based on validation
+ function updateInputValidation(input) {
+ let value = input.value.trim();
+
+ // Handle parameter display format: "@width (200)" - extract just the parameter reference
+ const paramMatch = value.match(/^(@[a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)$/);
+ if (paramMatch) {
+ value = paramMatch[1]; // Get just the parameter reference part
+ }
+
+ const isValid = value === '' || isValidPropertyValue(value);
+
+ // Remove existing validation classes
+ input.classList.remove('param-valid', 'param-invalid', 'param-reference');
+
+ if (value === '') {
+ // Empty is neutral - make sure no parameter data remains
+ input.removeAttribute('data-original-param');
+ return;
+ }
+
+ if (isValid) {
+ input.classList.add('param-valid');
+
+ // Add special styling for parameter references
+ if (PARAM_REFERENCE_PATTERN.test(value)) {
+ input.classList.add('param-reference');
+ }
+ } else {
+ input.classList.add('param-invalid');
+ }
+ }
+
+ // Enhanced change handler for dragInput callbacks
+ function createEnhancedCallback(originalCallback) {
+ return function(attr, value, completed) {
+ // Validate the value before processing
+ if (typeof value === 'string' && value.trim() !== '') {
+ if (!isValidPropertyValue(value)) {
+ console.warn(`Invalid property value: ${value}. Expected number or @paramName.`);
+ return; // Don't apply invalid values
+ }
+ }
+
+ // Call the original callback
+ return originalCallback.call(this, attr, value, completed);
+ };
+ }
+
+ // Initialize validation for all property inputs
+ function initializeValidation() {
+ // Find all property input fields
+ const propertyInputs = document.querySelectorAll('.attr_changer, input[data-attr]');
+
+ propertyInputs.forEach(input => {
+ // Update pattern to accept parameter references
+ if (input.hasAttribute('pattern')) {
+ input.pattern = '([0-9]+(\.[0-9]+)?|@[a-zA-Z_][a-zA-Z0-9_]*)';
+ } else {
+ input.setAttribute('pattern', '([0-9]+(\.[0-9]+)?|@[a-zA-Z_][a-zA-Z0-9_]*)');
+ }
+
+ // Add real-time validation
+ input.addEventListener('input', () => updateInputValidation(input));
+ input.addEventListener('blur', () => updateInputValidation(input));
+ input.addEventListener('change', () => updateInputValidation(input));
+
+ // Handle parameter references on blur/change/enter
+ input.addEventListener('blur', function() {
+ handleParameterInput(this);
+ });
+ input.addEventListener('change', function() {
+ handleParameterInput(this);
+ });
+
+ // Handle Enter key for parameter references
+ input.addEventListener('keydown', function(e) {
+ if (e.key === 'Enter' && isValidParameterReference(this.value)) {
+ e.preventDefault();
+ handleParameterInput(this);
+ this.blur();
+ }
+ });
+
+ // Initial validation
+ updateInputValidation(input);
+ });
+
+ // Add autocomplete support for parameter names
+ addParameterAutocomplete();
+ }
+
+ // Check if a value is a valid parameter reference
+ function isValidParameterReference(value) {
+ // Handle parameter display format: "@width (200)" - extract just the parameter reference
+ const paramMatch = value.match(/^(@[a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)$/);
+ if (paramMatch) {
+ value = paramMatch[1]; // Get just the parameter reference part
+ }
+
+ if (!PARAM_REFERENCE_PATTERN.test(value)) return false;
+ const paramName = value.substring(1);
+ return editor.parametersManager.getParameterByName(paramName) !== null;
+ }
+
+ // Handle parameter input changes
+ function handleParameterInput(input) {
+ let value = input.value.trim();
+
+ // Handle parameter display format: "@width (200)" - extract just the parameter reference
+ const paramMatch = value.match(/^(@[a-zA-Z_][a-zA-Z0-9_]*)\s*\([^)]*\)$/);
+ if (paramMatch) {
+ value = paramMatch[1]; // Get just the parameter reference part
+ }
+
+ // If this is not a parameter reference, make sure we clear any parameter data
+ if (!PARAM_REFERENCE_PATTERN.test(value)) {
+ const attr = input.getAttribute('data-attr');
+ if (attr) {
+ // Clear parameter data from selected elements
+ const selectedElements = svgCanvas.getSelectedElems();
+ selectedElements.forEach(elem => {
+ if (elem) {
+ elem.removeAttribute(`data-param-${attr}`);
+ }
+ });
+ }
+ // Clear parameter display data
+ input.removeAttribute('data-original-param');
+ return;
+ }
+
+ // Validate the parameter exists
+ if (!isValidParameterReference(value)) return;
+
+ // Get the attribute name and resolve the parameter
+ const attr = input.getAttribute('data-attr');
+ if (!attr) return;
+
+ const resolvedValue = editor.parametersManager.resolveParameterValue(value);
+
+ // Store parameter reference on selected elements for persistence
+ storeParameterReference(attr, value);
+
+ // Update input display to show parameter and resolved value
+ updateParameterDisplay(input, value, resolvedValue);
+
+ // Call the appropriate change handler directly with resolved value
+ if (typeof editor.changeAttribute === 'function') {
+ editor.changeAttribute(attr, resolvedValue, true);
+ }
+ }
+
+ // Store parameter reference on SVG elements for persistence
+ function storeParameterReference(attr, paramRef) {
+ const selectedElements = svgCanvas.getSelectedElems();
+ selectedElements.forEach(elem => {
+ if (elem) {
+ elem.setAttribute(`data-param-${attr}`, paramRef);
+ }
+ });
+ }
+
+ // Update input display to show both parameter and resolved value
+ function updateParameterDisplay(input, paramRef, resolvedValue) {
+ const displayValue = `${paramRef} (${resolvedValue})`;
+ input.value = displayValue;
+
+ // Store original parameter reference for later use
+ input.setAttribute('data-original-param', paramRef);
+
+ // Add class to parent draginput to help with label styling
+ const draginputParent = input.closest('.draginput');
+ if (draginputParent) {
+ draginputParent.classList.add('has-parameter');
+ }
+ }
+
+ // Clear all parameter validation from inputs
+ function clearAllInputValidation() {
+ const propertyInputs = document.querySelectorAll('.attr_changer, input[data-attr]');
+ propertyInputs.forEach(input => {
+ clearInputValidation(input);
+ });
+ }
+
+ // Restore parameter references when elements are selected
+ function restoreParameterReferences() {
+ const selectedElements = svgCanvas.getSelectedElems();
+ if (!selectedElements.length || !selectedElements[0]) {
+ // No element selected, clear all validation styling
+ clearAllInputValidation();
+ return;
+ }
+
+ const elem = selectedElements[0];
+
+ // Find all property inputs and check for stored parameter references
+ const propertyInputs = document.querySelectorAll('.attr_changer, input[data-attr]');
+ propertyInputs.forEach(input => {
+ const attr = input.getAttribute('data-attr');
+ if (!attr) return;
+
+ // Clear any existing validation first
+ clearInputValidation(input);
+
+ const paramRef = elem.getAttribute(`data-param-${attr}`);
+ if (paramRef && PARAM_REFERENCE_PATTERN.test(paramRef)) {
+ const resolvedValue = editor.parametersManager.resolveParameterValue(paramRef);
+ updateParameterDisplay(input, paramRef, resolvedValue);
+ updateInputValidation(input);
+ }
+ });
+ }
+
+ // Add autocomplete functionality for parameter names
+ function addParameterAutocomplete() {
+ // Create a datalist element for parameter suggestions
+ let datalist = document.getElementById('parameter-suggestions');
+ if (!datalist) {
+ datalist = document.createElement('datalist');
+ datalist.id = 'parameter-suggestions';
+ document.body.appendChild(datalist);
+ }
+
+ // Update the datalist with current parameters
+ function updateParameterSuggestions() {
+ if (!editor.parametersManager) return;
+ const paramNames = editor.parametersManager.getParameterNames();
+ datalist.innerHTML = paramNames.map(name => `@${name} `).join('');
+ }
+
+ // Add autocomplete to property inputs
+ const propertyInputs = document.querySelectorAll('.attr_changer, input[data-attr]');
+ propertyInputs.forEach(input => {
+ input.setAttribute('list', 'parameter-suggestions');
+
+ // Update suggestions when input gets focus
+ input.addEventListener('focus', updateParameterSuggestions);
+
+ // Also trigger on input for @ character
+ input.addEventListener('input', function(e) {
+ if (e.target.value.includes('@')) {
+ updateParameterSuggestions();
+ }
+ });
+ });
+
+ // Update suggestions when parameters change
+ updateParameterSuggestions();
+ }
+
+ // Flag to prevent infinite loops during parameter reset
+ let isResettingParameters = false;
+
+ // Reset elements with parameters back to their parameter values after manual changes
+ function resetParameterizedAttributes(elements) {
+ if (isResettingParameters) {
+ return; // Prevent infinite loops
+ }
+
+ if (!Array.isArray(elements)) {
+ elements = [elements];
+ }
+
+ isResettingParameters = true;
+
+ try {
+ elements.forEach(elem => {
+ if (!elem) return;
+
+ // Find all parameter attributes on this element
+ const attributes = elem.attributes;
+ for (let i = 0; i < attributes.length; i++) {
+ const attr = attributes[i];
+ if (attr.name.startsWith('data-param-')) {
+ const attrName = attr.name.substring('data-param-'.length);
+ const paramRef = attr.value;
+
+ if (PARAM_REFERENCE_PATTERN.test(paramRef)) {
+ const resolvedValue = editor.parametersManager.resolveParameterValue(paramRef);
+
+ // Apply the parameter value to the actual SVG attribute
+ elem.setAttribute(attrName, resolvedValue);
+
+ // Update the corresponding input field if it exists
+ const input = document.querySelector(`input[data-attr="${attrName}"]`);
+ if (input) {
+ updateParameterDisplay(input, paramRef, resolvedValue);
+ updateInputValidation(input);
+ }
+ }
+ }
+ }
+ });
+ } finally {
+ isResettingParameters = false;
+ }
+ }
+
+ // Check if element has any parameter references
+ function hasParameterReferences(elem) {
+ if (!elem || !elem.attributes) return false;
+
+ for (let i = 0; i < elem.attributes.length; i++) {
+ if (elem.attributes[i].name.startsWith('data-param-')) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Public API
+ this.isValidPropertyValue = isValidPropertyValue;
+ this.updateInputValidation = updateInputValidation;
+ this.createEnhancedCallback = createEnhancedCallback;
+ this.initializeValidation = initializeValidation;
+ this.addParameterAutocomplete = addParameterAutocomplete;
+ this.restoreParameterReferences = restoreParameterReferences;
+ this.clearAllInputValidation = clearAllInputValidation;
+ this.resetParameterizedAttributes = resetParameterizedAttributes;
+ this.hasParameterReferences = hasParameterReferences;
+ this.PARAM_REFERENCE_PATTERN = PARAM_REFERENCE_PATTERN;
+ this.NUMERIC_PATTERN = NUMERIC_PATTERN;
+};
\ No newline at end of file
diff --git a/src/js/dao.js b/src/js/dao.js
index bfdb2f98..80b1a468 100644
--- a/src/js/dao.js
+++ b/src/js/dao.js
@@ -146,6 +146,15 @@ const dao = [
private: true,
save: true,
},
+ // parametric SVG parameters
+ {
+ name: "canvasParameters",
+ label: "Canvas Parameters",
+ type: "object",
+ default: {},
+ private: true,
+ save: true,
+ },
];
diff --git a/src/js/editor.js b/src/js/editor.js
index 7af66550..de0ba979 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -196,6 +196,18 @@ MD.Editor = function(){
elems: elems
});
+ // Reset any parametrized attributes back to their parameter values after element changes
+ if (editor.propertyValidation && elems && elems.length > 0) {
+ // Use setTimeout to ensure DOM updates are complete
+ setTimeout(() => {
+ const elementsWithParams = elems.filter(elem =>
+ elem && editor.propertyValidation.hasParameterReferences(elem)
+ );
+ if (elementsWithParams.length > 0) {
+ editor.propertyValidation.resetParameterizedAttributes(elementsWithParams);
+ }
+ }, 50);
+ }
if (!svgCanvas.getContext()) {
saveCanvas();
@@ -203,6 +215,7 @@ MD.Editor = function(){
}
function changeAttribute(attr, value, completed) {
+ // Parameter resolution handled by PropertyValidation
if (attr === "opacity") value *= 0.01;
if (completed) {
svgCanvas.changeSelectedAttribute(attr, value);
@@ -300,6 +313,169 @@ MD.Editor = function(){
}});
};
+ function exportJS() {
+ try {
+ console.log('Starting JavaScript export...');
+
+ // Get the SVG content
+ const svgString = svgCanvas.getSvgString();
+ console.log('Got SVG string:', svgString.length, 'characters');
+
+ // Create the JavaScript function
+ const jsFunction = generateParametricJS(svgString);
+ console.log('Generated JS function:', jsFunction.length, 'characters');
+
+ // Create and download the JS file
+ const title = state.get("canvasTitle") || "parametric-svg";
+ const filename = title.replace(/[^a-z0-9]/gi, '_').toLowerCase();
+ const blob = new Blob([jsFunction], { type: "application/javascript;charset=utf-8" });
+
+ console.log('Downloading file:', `${filename}.js`);
+
+ // Use the saveAs function from filesaver.js
+ if (typeof saveAs !== 'undefined') {
+ saveAs(blob, `${filename}.js`);
+ } else {
+ // Fallback download method
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `${filename}.js`;
+ document.body.appendChild(a);
+ a.click();
+ setTimeout(() => {
+ document.body.removeChild(a);
+ URL.revokeObjectURL(url);
+ }, 0);
+ }
+
+ console.log('JavaScript export completed successfully');
+ } catch (error) {
+ console.error('Error during JavaScript export:', error);
+ alert('Error exporting JavaScript file: ' + error.message);
+ }
+ }
+
+ function generateParametricJS(svgString) {
+ // Parse the SVG to find parametric elements
+ const parser = new DOMParser();
+ const svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
+
+ // Collect all parameters and their default values
+ const parametersObj = editor.parametersManager.getParameters() || {};
+ console.log('Parameters object:', parametersObj);
+ const paramMap = {};
+
+ // Convert parameters object to map by parameter name
+ Object.values(parametersObj).forEach(param => {
+ if (param && param.name) {
+ paramMap[param.name] = param;
+ }
+ });
+ console.log('Parameter map:', paramMap);
+
+ // Find all elements with data-param-* attributes and replace their values
+ const parameterizedElements = svgDoc.querySelectorAll('[class*="data-param-"], [data-param-width], [data-param-height], [data-param-x], [data-param-y], [data-param-cx], [data-param-cy], [data-param-rx], [data-param-ry], [data-param-r]');
+
+ // Actually, let's find ALL elements and check their attributes
+ const allElements = svgDoc.querySelectorAll('*');
+ allElements.forEach(elem => {
+ for (let i = 0; i < elem.attributes.length; i++) {
+ const attr = elem.attributes[i];
+ if (attr.name.startsWith('data-param-')) {
+ const attrName = attr.name.substring('data-param-'.length);
+ const paramRef = attr.value;
+ const paramName = paramRef.substring(1); // Remove the @ symbol
+
+ if (paramMap[paramName]) {
+ // Replace the actual attribute value with template literal
+ elem.setAttribute(attrName, `\${${paramName}}`);
+ }
+ }
+ }
+ });
+
+ // Clean up data-param-* attributes from the final output
+ allElements.forEach(elem => {
+ const attributesToRemove = [];
+ for (let i = 0; i < elem.attributes.length; i++) {
+ const attr = elem.attributes[i];
+ if (attr.name.startsWith('data-param-')) {
+ attributesToRemove.push(attr.name);
+ }
+ }
+ attributesToRemove.forEach(attrName => {
+ elem.removeAttribute(attrName);
+ });
+ });
+
+ // Get the modified SVG string
+ const serializer = new XMLSerializer();
+ let modifiedSvgString = serializer.serializeToString(svgDoc.documentElement);
+
+ // Generate parameter list and default values
+ const paramNames = Object.keys(paramMap);
+ const paramDefaults = paramNames.map(name => {
+ const param = paramMap[name];
+ let defaultValue = param.defaultValue;
+
+ // Format default value based on type
+ if (param.type === 'text' || param.type === 'color') {
+ defaultValue = `"${defaultValue}"`;
+ } else if (param.type === 'boolean') {
+ defaultValue = defaultValue === 'true' || defaultValue === true ? 'true' : 'false';
+ }
+
+ return defaultValue;
+ });
+
+ // Escape the SVG string for template literal
+ const escapedSvg = modifiedSvgString
+ .replace(/\\/g, '\\\\') // Escape backslashes first
+ .replace(/`/g, '\\`') // Escape backticks
+ .replace(/\$(?!{)/g, '\\$'); // Escape $ that aren't part of ${...}
+
+ // Generate the function
+ const hasParams = paramNames.length > 0;
+ const paramComment = hasParams
+ ? paramNames.map(name => ` * @param {${paramMap[name].type}} ${name} - Default: ${paramMap[name].defaultValue}`).join('\n')
+ : ' * No parameters defined';
+
+ const functionParams = hasParams ? `{${paramNames.join(', ')}} = {}` : '';
+ const defaultAssignments = hasParams
+ ? paramNames.map((name, i) => ` const ${name}_val = ${name} !== undefined ? ${name} : ${paramDefaults[i]};`).join('\n')
+ : '';
+ const variableDeclaration = hasParams
+ ? ` const ${paramNames.join(', ')} = ${paramNames.map(name => `${name}_val`).join(', ')};`
+ : '';
+
+ const functionBody = `/**
+ * Parametric SVG Generator
+ * Generated by Method Draw
+ *
+ * Parameters:
+${paramComment}
+ */
+function generateSVG(${functionParams}) {
+${defaultAssignments}
+${variableDeclaration}
+
+ return \`${escapedSvg}\`;
+}
+
+// Export for different module systems
+if (typeof module !== 'undefined' && module.exports) {
+ module.exports = generateSVG;
+} else if (typeof define === 'function' && define.amd) {
+ define([], function() { return generateSVG; });
+} else if (typeof window !== 'undefined') {
+ window.generateSVG = generateSVG;
+}
+`;
+
+ return functionBody;
+ }
+
function saveCanvas(){
state.set("canvasContent", svgCanvas.getSvgString());
}
@@ -350,6 +526,14 @@ MD.Editor = function(){
editor.modal.source.open();
}
+ function parameters(){
+ // Refresh the parameters list before opening
+ if (editor.modal.parameters.renderParametersList) {
+ editor.modal.parameters.renderParametersList();
+ }
+ editor.modal.parameters.open();
+ }
+
function loadFromUrl(url, cb){
if(!cb) cb = function(){/*noop*/};
$.ajax({
@@ -406,6 +590,8 @@ MD.Editor = function(){
this.shortcuts = shortcuts;
this.donate = donate;
this.source = source;
+ this.parameters = parameters;
+ this.exportJS = exportJS;
this.saveCanvas = saveCanvas;
this.loadFromUrl = loadFromUrl;
diff --git a/src/js/lib/jquery-draginput.js b/src/js/lib/jquery-draginput.js
index 4921bf5a..c6b05d2d 100644
--- a/src/js/lib/jquery-draginput.js
+++ b/src/js/lib/jquery-draginput.js
@@ -46,6 +46,13 @@ $.fn.dragInput = function(cfg){
this.adjustValue = function(i, completed = false){
var v;
i = parseFloat(i);
+
+ // Check for parameter references - PropertyValidation handles this more reliably
+ if (typeof this.value === 'string' && this.value.trim().startsWith('@')) {
+ // Let PropertyValidation handle parameter resolution
+ return;
+ }
+
if(isNaN(this.value)) {
v = this.dragCfg.reset;
} else if($.isFunction(this.dragCfg.stepfunc)) {
@@ -138,6 +145,8 @@ $.fn.dragInput = function(cfg){
})
+
+
.bind("dblclick taphold", function(e) {
this.removeAttribute("readonly", "readonly");
this.focus();
diff --git a/src/js/modals.js b/src/js/modals.js
index a066d3aa..55671059 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -81,5 +81,312 @@ editor.modal = {
js: function(el){
el.children[0].classList.add("modal-item-wide");
}
+ }),
+ parameters: new MD.Modal({
+ html: `
+ Parameters
+
+
+
+ No parameters defined yet. Click "Add Parameter" to create your first parameter.
+
+
+
+
+ Name
+ Type
+ Default Value
+ Actions
+
+
+
+
+
+
+
+ Cancel
+ Add Parameter
+
+
+
+
+ `,
+ js: function(el){
+ el.children[0].classList.add("modal-item-wide");
+
+ const modal = this;
+ const parametersContainer = el.querySelector('#parameters-container');
+ const parameterForm = el.querySelector('#parameter-form');
+ const parametersTable = el.querySelector('#parameters-table');
+ const parametersEmpty = el.querySelector('#parameters-empty');
+ const parametersTBody = el.querySelector('#parameters-tbody');
+ const addParameterBtn = el.querySelector('#add-parameter-btn');
+ const parametersCancelBtn = el.querySelector('#parameters-cancel-btn');
+ const parameterFormTitle = el.querySelector('#parameter-form-title');
+ const parameterFormElement = el.querySelector('#parameter-form-element');
+ const parameterFormCancel = el.querySelector('#parameter-form-cancel');
+
+ const paramNameInput = el.querySelector('#param-name');
+ const paramTypeSelect = el.querySelector('#param-type');
+ const paramDefaultInput = el.querySelector('#param-default');
+ const paramDescriptionInput = el.querySelector('#param-description');
+
+ let editingParameterId = null;
+
+ // Update default value input based on parameter type
+ function updateDefaultValueInput() {
+ const type = paramTypeSelect.value;
+ let currentElement = el.querySelector('#param-default');
+
+ const baseStyle = 'width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; position: relative; z-index: 1001; pointer-events: auto;';
+
+ if (type === 'boolean') {
+ // Replace input with select for boolean
+ if (currentElement.tagName === 'INPUT') {
+ const select = document.createElement('select');
+ select.id = 'param-default';
+ select.style.cssText = baseStyle;
+ select.innerHTML = 'False True ';
+ currentElement.parentNode.replaceChild(select, currentElement);
+ }
+ } else {
+ // Replace select with input for non-boolean types, or just update if already input
+ if (currentElement.tagName === 'SELECT') {
+ const input = document.createElement('input');
+ input.id = 'param-default';
+ input.style.cssText = baseStyle;
+ currentElement.parentNode.replaceChild(input, currentElement);
+ currentElement = input;
+ }
+
+ // Set input properties based on type
+ switch (type) {
+ case 'number':
+ currentElement.type = 'number';
+ currentElement.placeholder = 'e.g., 100';
+ break;
+ case 'text':
+ currentElement.type = 'text';
+ currentElement.placeholder = 'e.g., Hello World';
+ break;
+ case 'color':
+ currentElement.type = 'color';
+ currentElement.placeholder = '';
+ break;
+ default:
+ currentElement.type = 'text';
+ }
+ }
+
+ // Re-apply click handling after updating the input
+ ensureDefaultInputClickable();
+ }
+
+ // Render parameters list
+ function renderParametersList() {
+ const parameters = editor.parametersManager.getParameters();
+ const paramIds = Object.keys(parameters);
+
+ if (paramIds.length === 0) {
+ parametersTable.style.display = 'none';
+ parametersEmpty.style.display = 'block';
+ } else {
+ parametersTable.style.display = 'table';
+ parametersEmpty.style.display = 'none';
+
+ parametersTBody.innerHTML = '';
+ paramIds.forEach(id => {
+ const param = parameters[id];
+ const row = document.createElement('tr');
+ row.style.borderBottom = '1px solid #eee';
+
+ row.innerHTML =
+ '@' + param.name + ' ' +
+ '' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
+ '' + param.defaultValue + ' ' +
+ '' +
+ 'Edit ' +
+ 'Delete ' +
+ ' ';
+
+ parametersTBody.appendChild(row);
+ });
+
+ // Add event listeners for edit/delete buttons
+ el.querySelectorAll('.edit-param-btn').forEach(btn => {
+ btn.addEventListener('click', function() {
+ editParameter(this.dataset.id);
+ });
+ });
+
+ el.querySelectorAll('.delete-param-btn').forEach(btn => {
+ btn.addEventListener('click', function() {
+ deleteParameter(this.dataset.id);
+ });
+ });
+ }
+ }
+
+ // Store the render function on the modal object so it can be called later
+ modal.renderParametersList = renderParametersList;
+
+ // Show parameter form
+ function showParameterForm(isEdit = false, parameterId = null) {
+ parametersContainer.style.display = 'none';
+ parameterForm.style.display = 'block';
+ parameterFormTitle.textContent = isEdit ? 'Edit Parameter' : 'Add Parameter';
+ editingParameterId = parameterId;
+
+ if (isEdit && parameterId) {
+ const param = editor.parametersManager.getParameter(parameterId);
+ if (param) {
+ paramNameInput.value = param.name;
+ paramTypeSelect.value = param.type;
+ updateDefaultValueInput();
+
+ // Set default value after updating input type
+ setTimeout(() => {
+ const defaultInput = el.querySelector('#param-default');
+ defaultInput.value = param.defaultValue;
+ }, 0);
+
+ paramDescriptionInput.value = param.description || '';
+ }
+ } else {
+ parameterFormElement.reset();
+ updateDefaultValueInput();
+ }
+
+ paramNameInput.focus();
+ }
+
+ // Hide parameter form
+ function hideParameterForm() {
+ parametersContainer.style.display = 'block';
+ parameterForm.style.display = 'none';
+ editingParameterId = null;
+ parameterFormElement.reset();
+ }
+
+ // Edit parameter
+ function editParameter(id) {
+ showParameterForm(true, id);
+ }
+
+ // Delete parameter
+ function deleteParameter(id) {
+ const param = editor.parametersManager.getParameter(id);
+ if (param && confirm("Are you sure you want to delete parameter \"@" + param.name + "\"?")) {
+ try {
+ editor.parametersManager.deleteParameter(id);
+ renderParametersList();
+
+ // Update property validation autocomplete
+ if (editor.propertyValidation) {
+ editor.propertyValidation.addParameterAutocomplete();
+ }
+ } catch (error) {
+ alert('Error deleting parameter: ' + error.message);
+ }
+ }
+ }
+
+ // Event listeners
+ addParameterBtn.addEventListener('click', () => showParameterForm());
+ parametersCancelBtn.addEventListener('click', () => editor.modal.parameters.close());
+ parameterFormCancel.addEventListener('click', hideParameterForm);
+ paramTypeSelect.addEventListener('change', updateDefaultValueInput);
+
+ // Ensure input fields are clickable
+ paramNameInput.addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+
+ // Handle dynamic default input field
+ function ensureDefaultInputClickable() {
+ const defaultInput = el.querySelector('#param-default');
+ if (defaultInput) {
+ defaultInput.addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+ }
+ }
+ ensureDefaultInputClickable();
+
+ parameterFormElement.addEventListener('submit', function(e) {
+ e.preventDefault();
+
+ const name = paramNameInput.value.trim();
+ const type = paramTypeSelect.value;
+ const defaultValue = el.querySelector('#param-default').value;
+ const description = paramDescriptionInput.value.trim();
+
+ if (!name) {
+ alert('Parameter name is required.');
+ return;
+ }
+
+ try {
+ if (editingParameterId) {
+ editor.parametersManager.updateParameter(editingParameterId, name, type, defaultValue, description);
+ } else {
+ editor.parametersManager.addParameter(name, type, defaultValue, description);
+ }
+
+ hideParameterForm();
+ renderParametersList();
+
+ // Update property validation autocomplete
+ if (editor.propertyValidation) {
+ editor.propertyValidation.addParameterAutocomplete();
+ }
+ } catch (error) {
+ alert('Error saving parameter: ' + error.message);
+ }
+ });
+ }
})
};
\ No newline at end of file
diff --git a/src/js/start.js b/src/js/start.js
index 73949893..23794b3b 100644
--- a/src/js/start.js
+++ b/src/js/start.js
@@ -18,7 +18,9 @@ editor.import = new MD.Import();
editor.contextMenu = new MD.ContextMenu();
editor.darkmode = new MD.Darkmode();
editor.title = new MD.Title();
-
+editor.parametersManager = new MD.Parameters();
+editor.propertyValidation = new MD.PropertyValidation();
+
// bind the selected event to our function that handles updates to the UI
svgCanvas.bind("selected", editor.selectedChanged);
svgCanvas.bind("transition", editor.elementTransition);
@@ -61,4 +63,9 @@ state.set("canvasTitle", svgCanvas.getDocumentTitle());
//editor.paintBox.canvas.setPaint(state.get("canvasBackground"));
document.body.classList.remove("loading");
-document.getElementById("svgcanvas").removeAttribute("title");
\ No newline at end of file
+document.getElementById("svgcanvas").removeAttribute("title");
+
+// Initialize property validation for parameter references
+setTimeout(() => {
+ editor.propertyValidation.initializeValidation();
+}, 100);
\ No newline at end of file
diff --git a/src/js/state.js b/src/js/state.js
index e4cfd82a..2b99ab84 100644
--- a/src/js/state.js
+++ b/src/js/state.js
@@ -32,6 +32,7 @@ function State(){
this.canvasFill = (paint) => { /* noop */ }
this.canvasStroke = (paint) => { /* noop */ }
this.canvasBackground = (paint) => { /* noop */ }
+ this.canvasParameters = (params) => { /* noop */ }
this.darkmode = (isDark) => { editor.darkmode.set(isDark) }
this.clean = (warn = true) => {
diff --git a/src/js/svgcanvas.js b/src/js/svgcanvas.js
index 3513703c..c4d166a8 100644
--- a/src/js/svgcanvas.js
+++ b/src/js/svgcanvas.js
@@ -3099,6 +3099,8 @@ var getMouseTarget = this.getMouseTarget = function(evt) {
selectorManager.requestSelector(selectedElements[i]).resize();
}
}
+
+
}
// no change in position/size, so maybe we should move to pathedit
From 8b95845e2db7b265aa9d78b35b2dbcc6f8e85974 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Wed, 23 Jul 2025 12:55:11 +1000
Subject: [PATCH 02/13] Fix syntax error
---
src/js/method-draw.js | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/js/method-draw.js b/src/js/method-draw.js
index 9e3b63a9..3038bcd0 100644
--- a/src/js/method-draw.js
+++ b/src/js/method-draw.js
@@ -1,4 +1,4 @@
-window.methodDraw = function() {
+window.methodDraw = (function($) {
var Editor = {};
var is_ready = false;
var curConfig = {
@@ -2070,7 +2070,6 @@ window.methodDraw = function() {
}
};
- };
var callbacks = [];
@@ -2151,7 +2150,7 @@ window.methodDraw = function() {
};
return Editor;
-}(jQuery);
+})(jQuery);
// Run init once DOM is loaded
$(methodDraw.init);
\ No newline at end of file
From 724cd56ac4efc39b5077efe2efc3f9ac8e022a49 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Wed, 23 Jul 2025 14:49:45 +1000
Subject: [PATCH 03/13] Add Parametric Clone Grids, for repeating elements
---
src/index.html | 2 +
src/js/ContextMenu.js | 155 ++++++++++++++++++----------
src/js/Menu.js | 3 +
src/js/Panel.js | 20 ++++
src/js/Parameters.js | 6 +-
src/js/editor.js | 169 +++++++++++++++++++++++++++++-
src/js/method-draw.js | 55 +---------
src/js/modals.js | 232 ++++++++++++++++++++++++++++++++++++++++--
src/js/svgcanvas.js | 207 +++++++++++++++++++++++++++++++++++++
9 files changed, 728 insertions(+), 121 deletions(-)
diff --git a/src/index.html b/src/index.html
index 57da29ac..0d2c6e77 100644
--- a/src/index.html
+++ b/src/index.html
@@ -118,6 +118,7 @@
+
@@ -740,6 +741,7 @@ Stroke
Delete⌫
Group⌘G
Ungroup⌘⇧G
+ Define Parametric Clone...
Bring to Front⌘⇧↑
Bring Forward⌘↑
Send Backward⌘↓
diff --git a/src/js/ContextMenu.js b/src/js/ContextMenu.js
index 332eb196..26fa50e4 100644
--- a/src/js/ContextMenu.js
+++ b/src/js/ContextMenu.js
@@ -1,56 +1,105 @@
MD.ContextMenu = function(){
+ // Set up the context menu
$("#workarea").contextMenu({
- menu: 'cmenu_canvas',
- inSpeed: 0
- },
- function(action, el, pos) {
- switch ( action ) {
- case 'delete':
- editor.deleteSelected();
+ menu: 'cmenu_canvas',
+ inSpeed: 0
+ },
+ function(action, el, pos) {
+ switch ( action ) {
+ case 'delete':
+ svgCanvas.deleteSelectedElements();
+ break;
+ case 'cut':
+ // Flash edit menu and call cut
+ var edit_menu_title = $('#edit_menu').prev();
+ edit_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => edit_menu_title.removeAttr('style'), 200);
+ svgCanvas.cutSelectedElements();
+ break;
+ case 'copy':
+ // Flash edit menu and call copy
+ var edit_menu_title = $('#edit_menu').prev();
+ edit_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => edit_menu_title.removeAttr('style'), 200);
+ svgCanvas.copySelectedElements();
+ break;
+ case 'paste':
+ // Flash edit menu and call paste with proper positioning
+ var edit_menu_title = $('#edit_menu').prev();
+ edit_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => edit_menu_title.removeAttr('style'), 200);
+ var zoom = svgCanvas.getZoom();
+ var workarea = $("#workarea");
+ var x = (workarea[0].scrollLeft + workarea.width()/2)/zoom - svgCanvas.contentW;
+ var y = (workarea[0].scrollTop + workarea.height()/2)/zoom - svgCanvas.contentH;
+ svgCanvas.pasteElements('point', x, y);
+ break;
+ case 'paste_in_place':
+ // Flash edit menu and call paste in place
+ var edit_menu_title = $('#edit_menu').prev();
+ edit_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => edit_menu_title.removeAttr('style'), 200);
+ svgCanvas.pasteElements('in_place');
+ break;
+ case 'group':
+ svgCanvas.groupSelectedElements();
+ break;
+ case 'ungroup':
+ svgCanvas.ungroupSelectedElement();
+ break;
+ case 'move_front':
+ // Flash object menu and call move front
+ var object_menu_title = $('#object_menu').prev();
+ object_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => object_menu_title.removeAttr('style'), 200);
+ svgCanvas.moveToTopSelectedElement();
+ break;
+ case 'move_up':
+ // Flash object menu and call move up
+ var object_menu_title = $('#object_menu').prev();
+ object_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => object_menu_title.removeAttr('style'), 200);
+ svgCanvas.moveUpDownSelected('Up');
+ break;
+ case 'move_down':
+ // Flash object menu and call move down
+ var object_menu_title = $('#object_menu').prev();
+ object_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => object_menu_title.removeAttr('style'), 200);
+ svgCanvas.moveUpDownSelected('Down');
+ break;
+ case 'move_back':
+ // Flash object menu and call move back
+ var object_menu_title = $('#object_menu').prev();
+ object_menu_title.css({'background': 'white', 'color': 'black'});
+ setTimeout(() => object_menu_title.removeAttr('style'), 200);
+ svgCanvas.moveToBottomSelectedElement();
+ break;
+ case 'parametric_clone':
+ // Check if we're editing an existing parametric clone
+ var selectedElements = svgCanvas.getSelectedElems();
+ var isParametricClone = selectedElements[0] && selectedElements[0].getAttribute('data-parametric-clone') === 'true';
+
+ if (isParametricClone) {
+ editor.editParametricClone(selectedElements[0]);
+ } else {
+ editor.modal.parametricClone.open();
+ }
+ break;
+ default:
+ if(svgedit.contextmenu && svgedit.contextmenu.hasCustomHandler(action)){
+ svgedit.contextmenu.getCustomHandler(action).call();
+ }
break;
- case 'cut':
- editor.cutSelected();
- break;
- case 'copy':
- editor.copySelected();
- break;
- case 'paste':
- editor.pasteSelected();
- break;
- case 'paste_in_place':
- svgCanvas.pasteElements('in_place');
- break;
- case 'group':
- editor.groupSelected();
- break;
- case 'ungroup':
- editor.ungroupSelected();
- break;
- case 'move_front':
- editor.moveToTopSelected();
- break;
- case 'move_up':
- editor.moveUpSelected();
- break;
- case 'move_down':
- editor.moveDownSelected();
- break;
- case 'move_back':
- editor.moveToBottomSelected();
- break;
- default:
- if(svgedit.contextmenu && svgedit.contextmenu.hasCustomHandler(action)){
- svgedit.contextmenu.getCustomHandler(action).call();
- }
- break;
- }
-
- });
-
- $('.contextMenu li').mousedown(function(ev) {
- ev.preventDefault();
- })
-
- $('#cmenu_canvas li').disableContextMenu();
- $("#cmenu_canvas").enableContextMenuItems('#delete,#cut,#copy');
-}
\ No newline at end of file
+ }
+
+ });
+
+ $('.contextMenu li').mousedown(function(ev) {
+ ev.preventDefault();
+ })
+
+ $('#cmenu_canvas li').disableContextMenu();
+ var canv_menu = $("#cmenu_canvas");
+ canv_menu.enableContextMenuItems('#delete,#cut,#copy');
+};
\ No newline at end of file
diff --git a/src/js/Menu.js b/src/js/Menu.js
index 7104cb39..4c494a59 100644
--- a/src/js/Menu.js
+++ b/src/js/Menu.js
@@ -8,6 +8,9 @@ MD.Menu = function(){
$('#tool_topath').on("click", editor.convertToPath);
$('#tool_group').on("click", editor.groupSelected);
$('#tool_ungroup').on("click", editor.ungroupSelected);
+ $('#tool_parametric_clone').on("click", function() {
+ editor.modal.parametricClone.open();
+ });
if (window.location.host === "editor.method.ac") {
$('#modal_donate').show();
$('#sponsors').show();
diff --git a/src/js/Panel.js b/src/js/Panel.js
index b4efbaa3..6ac5a6c2 100644
--- a/src/js/Panel.js
+++ b/src/js/Panel.js
@@ -348,6 +348,23 @@ MD.Panel = function(){
.disableContextMenuItems('#ungroup');
}
+ // Handle parametric clone menu items
+ const isParametricClone = elem && elem.getAttribute('data-parametric-clone') === 'true';
+
+ if (isParametricClone) {
+ // Change menu text to "Edit Parametric Clone..." for parametric clones
+ $('#cmenu_canvas a[href="#parametric_clone"]').text('Edit Parametric Clone...');
+ menu_items.enableContextMenuItems('#parametric_clone');
+ } else if (elem && !multiselected) {
+ // Show "Define Parametric Clone..." for non-parametric elements
+ $('#cmenu_canvas a[href="#parametric_clone"]').text('Define Parametric Clone...');
+ menu_items.enableContextMenuItems('#parametric_clone');
+ } else {
+ // Disable for no selection or multiselection
+ $('#cmenu_canvas a[href="#parametric_clone"]').text('Define Parametric Clone...');
+ menu_items.disableContextMenuItems('#parametric_clone');
+ }
+
if (!elem && !multiselected) {
menu_items.disableContextMenuItems('#delete,#cut,#copy,#ungroup,#move_front,#move_up,#move_down,#move_back');
$('.menu_item.action_selected', '#edit_menu').addClass('disabled');
@@ -355,6 +372,9 @@ MD.Panel = function(){
$('.menu_item', '#object_menu').toggleClass('disabled', !elem && !multiselected);
+ // Also ensure Object menu parametric clone item follows the same logic
+ $('#tool_parametric_clone').toggleClass('disabled', !elem || multiselected);
+
// update history buttons
setTimeout(function(){
$('#tool_paste').toggleClass( 'disabled', !svgCanvas.clipBoard.length > 0);
diff --git a/src/js/Parameters.js b/src/js/Parameters.js
index d48fb966..cf271c3d 100644
--- a/src/js/Parameters.js
+++ b/src/js/Parameters.js
@@ -10,7 +10,11 @@ MD.Parameters = function(){
number: { label: 'Number', defaultValue: 0 },
text: { label: 'Text', defaultValue: '' },
color: { label: 'Color', defaultValue: '#000000' },
- boolean: { label: 'Boolean', defaultValue: false }
+ boolean: { label: 'Boolean', defaultValue: false },
+ grid_cols: { label: 'Grid Columns', defaultValue: 3 },
+ grid_rows: { label: 'Grid Rows', defaultValue: 2 },
+ grid_spacing_x: { label: 'Horizontal Spacing', defaultValue: 50 },
+ grid_spacing_y: { label: 'Vertical Spacing', defaultValue: 50 }
};
// Get current parameters from state
diff --git a/src/js/editor.js b/src/js/editor.js
index de0ba979..d451e939 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -395,12 +395,75 @@ MD.Editor = function(){
}
});
- // Clean up data-param-* attributes from the final output
+ // Handle parametric clone groups
+ const cloneGroups = svgDoc.querySelectorAll('[data-parametric-clone="true"]');
+ const cloneHelperFunctions = [];
+
+ cloneGroups.forEach((cloneGroup, index) => {
+ const colsParam = cloneGroup.getAttribute('data-cols-param');
+ const rowsParam = cloneGroup.getAttribute('data-rows-param');
+ const spacingXParam = cloneGroup.getAttribute('data-spacing-x-param');
+ const spacingYParam = cloneGroup.getAttribute('data-spacing-y-param');
+
+ // Find template group
+ const templateGroup = cloneGroup.querySelector('[data-template="true"]');
+ if (templateGroup) {
+ // Get template elements as string
+ const templateElements = Array.from(templateGroup.children).map(child => {
+ return new XMLSerializer().serializeToString(child);
+ }).join('');
+
+ // Generate helper function name
+ const funcName = `generateCloneGrid_${index}`;
+
+ // Create helper function
+ const helperFunction = `
+ function ${funcName}() {
+ const cols = ${colsParam};
+ const rows = ${rowsParam};
+ const spacingX = ${spacingXParam};
+ const spacingY = ${spacingYParam};
+
+ let elements = '';
+ for (let row = 0; row < rows; row++) {
+ for (let col = 0; col < cols; col++) {
+ const offsetX = col * spacingX;
+ const offsetY = row * spacingY;
+
+ if (offsetX === 0 && offsetY === 0) {
+ // Original position - just add template elements
+ elements += \`${templateElements.replace(/`/g, '\\`')}\`;
+ } else {
+ // Clone position - wrap in transform group
+ elements += \`${templateElements.replace(/`/g, '\\`')} \`;
+ }
+ }
+ }
+ return elements;
+ }`;
+
+ cloneHelperFunctions.push(helperFunction);
+
+ // Replace the clone group with a placeholder that calls the helper function
+ const placeholder = svgDoc.createElement('g');
+ placeholder.setAttribute('id', cloneGroup.id);
+ placeholder.innerHTML = `\${${funcName}()}`;
+ cloneGroup.parentNode.replaceChild(placeholder, cloneGroup);
+ }
+ });
+
+ // Clean up data-param-* attributes and parametric clone attributes from the final output
allElements.forEach(elem => {
const attributesToRemove = [];
for (let i = 0; i < elem.attributes.length; i++) {
const attr = elem.attributes[i];
- if (attr.name.startsWith('data-param-')) {
+ if (attr.name.startsWith('data-param-') ||
+ attr.name.startsWith('data-parametric-') ||
+ attr.name.startsWith('data-cols-') ||
+ attr.name.startsWith('data-rows-') ||
+ attr.name.startsWith('data-spacing-') ||
+ attr.name === 'data-template' ||
+ attr.name === 'data-clone-instance') {
attributesToRemove.push(attr.name);
}
}
@@ -446,7 +509,7 @@ MD.Editor = function(){
? paramNames.map((name, i) => ` const ${name}_val = ${name} !== undefined ? ${name} : ${paramDefaults[i]};`).join('\n')
: '';
const variableDeclaration = hasParams
- ? ` const ${paramNames.join(', ')} = ${paramNames.map(name => `${name}_val`).join(', ')};`
+ ? paramNames.map(name => ` const ${name} = ${name}_val;`).join('\n')
: '';
const functionBody = `/**
@@ -459,6 +522,7 @@ ${paramComment}
function generateSVG(${functionParams}) {
${defaultAssignments}
${variableDeclaration}
+${cloneHelperFunctions.join('')}
return \`${escapedSvg}\`;
}
@@ -503,6 +567,103 @@ if (typeof module !== 'undefined' && module.exports) {
}
}
+ function createParametricClone(cols, rows, spacingX, spacingY) {
+ // Check if we have selected elements
+ const selectedElements = svgCanvas.getSelectedElems();
+ if (!selectedElements || selectedElements.length === 0 || !selectedElements[0]) {
+ alert('Please select one or more elements to create a parametric clone.');
+ return;
+ }
+
+ // Generate unique parameter names based on timestamp
+ const timestamp = Date.now();
+ const colsParamName = `clone_cols_${timestamp}`;
+ const rowsParamName = `clone_rows_${timestamp}`;
+ const spacingXParamName = `clone_spacing_x_${timestamp}`;
+ const spacingYParamName = `clone_spacing_y_${timestamp}`;
+
+ try {
+ // Add the grid parameters to the parameter system
+ editor.parametersManager.addParameter(colsParamName, 'grid_cols', cols, 'Number of columns in the grid');
+ editor.parametersManager.addParameter(rowsParamName, 'grid_rows', rows, 'Number of rows in the grid');
+ editor.parametersManager.addParameter(spacingXParamName, 'grid_spacing_x', spacingX, 'Horizontal spacing between elements');
+ editor.parametersManager.addParameter(spacingYParamName, 'grid_spacing_y', spacingY, 'Vertical spacing between elements');
+
+ // Create the parametric clone group using SVG canvas
+ const cloneGroupId = svgCanvas.createParametricCloneGroup(
+ selectedElements,
+ colsParamName,
+ rowsParamName,
+ spacingXParamName,
+ spacingYParamName
+ );
+
+ if (cloneGroupId) {
+ // Select the new group
+ const cloneGroup = svgedit.utilities.getElem(cloneGroupId);
+ if (cloneGroup) {
+ svgCanvas.clearSelection();
+ svgCanvas.addToSelection([cloneGroup]);
+ }
+
+ saveCanvas();
+ alert(`Parametric clone created with ${cols}×${rows} grid pattern.`);
+ }
+ } catch (error) {
+ alert('Error creating parametric clone: ' + error.message);
+ }
+ }
+
+ function editParametricClone(cloneGroup) {
+ if (!cloneGroup || cloneGroup.getAttribute('data-parametric-clone') !== 'true') {
+ alert('Selected element is not a parametric clone.');
+ return;
+ }
+
+ // Get parameter names from the clone group
+ const colsParam = cloneGroup.getAttribute('data-cols-param');
+ const rowsParam = cloneGroup.getAttribute('data-rows-param');
+ const spacingXParam = cloneGroup.getAttribute('data-spacing-x-param');
+ const spacingYParam = cloneGroup.getAttribute('data-spacing-y-param');
+
+ if (!colsParam || !rowsParam || !spacingXParam || !spacingYParam) {
+ alert('Parametric clone data is corrupted.');
+ return;
+ }
+
+ // Get current parameter values
+ const colsParamObj = editor.parametersManager.getParameterByName(colsParam);
+ const rowsParamObj = editor.parametersManager.getParameterByName(rowsParam);
+ const spacingXParamObj = editor.parametersManager.getParameterByName(spacingXParam);
+ const spacingYParamObj = editor.parametersManager.getParameterByName(spacingYParam);
+
+ if (!colsParamObj || !rowsParamObj || !spacingXParamObj || !spacingYParamObj) {
+ alert('Could not find associated parameters for this parametric clone.');
+ return;
+ }
+
+ // Set up the modal with current values
+ const modal = editor.modal.parametricClone;
+ modal.open();
+
+ // Pre-populate the form with current values
+ setTimeout(() => {
+ const modalEl = modal.el;
+ modalEl.querySelector('#clone-cols').value = colsParamObj.defaultValue;
+ modalEl.querySelector('#clone-rows').value = rowsParamObj.defaultValue;
+ modalEl.querySelector('#clone-spacing-x').value = spacingXParamObj.defaultValue;
+ modalEl.querySelector('#clone-spacing-y').value = spacingYParamObj.defaultValue;
+
+ // Store the parameter names for updating
+ modalEl.setAttribute('data-editing-clone', 'true');
+ modalEl.setAttribute('data-cols-param', colsParam);
+ modalEl.setAttribute('data-rows-param', rowsParam);
+ modalEl.setAttribute('data-spacing-x-param', spacingXParam);
+ modalEl.setAttribute('data-spacing-y-param', spacingYParam);
+ modalEl.setAttribute('data-clone-group-id', cloneGroup.id);
+ }, 50);
+ }
+
function about(){
editor.modal.about.open();
}
@@ -559,6 +720,8 @@ if (typeof module !== 'undefined' && module.exports) {
this.changeAttribute = changeAttribute;
this.contextChanged = contextChanged;
this.elementTransition = elementTransition;
+ this.createParametricClone = createParametricClone;
+ this.editParametricClone = editParametricClone;
this.switchPaint = switchPaint;
this.focusPaint = focusPaint;
this.save = save;
diff --git a/src/js/method-draw.js b/src/js/method-draw.js
index 3038bcd0..36ab2634 100644
--- a/src/js/method-draw.js
+++ b/src/js/method-draw.js
@@ -1722,60 +1722,7 @@ window.methodDraw = (function($) {
// Set default zoom
$('#zoom').val(svgCanvas.getZoom() * 100);
- $("#workarea").contextMenu({
- menu: 'cmenu_canvas',
- inSpeed: 0
- },
- function(action, el, pos) {
- switch ( action ) {
- case 'delete':
- deleteSelected();
- break;
- case 'cut':
- cutSelected();
- break;
- case 'copy':
- copySelected();
- break;
- case 'paste':
- svgCanvas.pasteElements();
- break;
- case 'paste_in_place':
- svgCanvas.pasteElements('in_place');
- break;
- case 'group':
- svgCanvas.groupSelectedElements();
- break;
- case 'ungroup':
- svgCanvas.ungroupSelectedElement();
- break;
- case 'move_front':
- moveToTopSelected();
- break;
- case 'move_up':
- moveUpDownSelected('Up');
- break;
- case 'move_down':
- moveUpDownSelected('Down');
- break;
- case 'move_back':
- moveToBottomSelected();
- break;
- default:
- if(svgedit.contextmenu && svgedit.contextmenu.hasCustomHandler(action)){
- svgedit.contextmenu.getCustomHandler(action).call();
- }
- break;
- }
-
- });
-
- $('.contextMenu li').mousedown(function(ev) {
- ev.preventDefault();
- })
-
- $('#cmenu_canvas li').disableContextMenu();
- canv_menu.enableContextMenuItems('#delete,#cut,#copy');
+
Editor.openPrep = function(func) {
$('#main_menu').hide();
diff --git a/src/js/modals.js b/src/js/modals.js
index 55671059..b16bddae 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -234,25 +234,99 @@ editor.modal = {
parametersEmpty.style.display = 'none';
parametersTBody.innerHTML = '';
+
+ // Group parameters by parametric clone groups
+ const cloneGroups = {};
+ const regularParams = [];
+
paramIds.forEach(id => {
const param = parameters[id];
+ // Check if this is a parametric clone parameter by looking for the timestamp pattern
+ const timestampMatch = param.name.match(/^clone_(cols|rows|spacing_x|spacing_y)_(\d+)$/);
+ if (timestampMatch) {
+ const timestamp = timestampMatch[2];
+ if (!cloneGroups[timestamp]) {
+ cloneGroups[timestamp] = {
+ cols: null,
+ rows: null,
+ spacing_x: null,
+ spacing_y: null
+ };
+ }
+ cloneGroups[timestamp][timestampMatch[1]] = { id, param };
+ } else {
+ regularParams.push({ id, param });
+ }
+ });
+
+ // Render regular parameters first
+ regularParams.forEach(({ id, param }) => {
const row = document.createElement('tr');
row.style.borderBottom = '1px solid #eee';
- row.innerHTML =
- '@' + param.name + ' ' +
- '' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
- '' + param.defaultValue + ' ' +
- '' +
- 'Edit ' +
- 'Delete ' +
- ' ';
+ row.innerHTML =
+ '@' + param.name + ' ' +
+ '' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
+ '' + param.defaultValue + ' ' +
+ '' +
+ 'Edit ' +
+ 'Delete ' +
+ ' ';
parametersTBody.appendChild(row);
});
+ // Add separator if we have both regular params and clone groups
+ if (regularParams.length > 0 && Object.keys(cloneGroups).length > 0) {
+ const separatorRow = document.createElement('tr');
+ separatorRow.innerHTML = 'Parametric Clone Groups ';
+ parametersTBody.appendChild(separatorRow);
+ }
+
+ // Render parametric clone groups
+ Object.keys(cloneGroups).forEach(timestamp => {
+ const group = cloneGroups[timestamp];
+
+ // Create group header
+ const headerRow = document.createElement('tr');
+ headerRow.style.background = '#f5f5f5';
+ headerRow.innerHTML = 'Clone Group ' + timestamp + ' ';
+ parametersTBody.appendChild(headerRow);
+
+ // Render group parameters in order: cols, rows, spacing_x, spacing_y
+ ['cols', 'rows', 'spacing_x', 'spacing_y'].forEach(type => {
+ if (group[type]) {
+ const { id, param } = group[type];
+ const row = document.createElement('tr');
+ row.style.borderBottom = '1px solid #eee';
+ row.style.paddingLeft = '16px';
+
+ // Friendly names for grid parameters
+ const friendlyNames = {
+ cols: 'Columns',
+ rows: 'Rows',
+ spacing_x: 'Horizontal Spacing',
+ spacing_y: 'Vertical Spacing'
+ };
+
+ row.innerHTML =
+ '└ ' + friendlyNames[type] + ' ' +
+ '' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
+ '' + param.defaultValue + ' ' +
+ '' +
+ 'Edit ' +
+ 'Delete ' +
+ ' ';
+
+ parametersTBody.appendChild(row);
+ }
+ });
+ });
+
// Add event listeners for edit/delete buttons
el.querySelectorAll('.edit-param-btn').forEach(btn => {
btn.addEventListener('click', function() {
@@ -388,5 +462,143 @@ editor.modal = {
}
});
}
+ }),
+
+ parametricClone: new MD.Modal({
+ html: `
+ Define Parametric Clone
+
+ Create a parametric grid of cloned elements with configurable spacing and dimensions.
+
+
+
+ `,
+
+ js: function(el) {
+ // Handle cancel button
+ el.querySelector('#parametric-clone-cancel').addEventListener('click', function() {
+ editor.modal.parametricClone.close();
+ });
+
+ // Handle create button
+ el.querySelector('#parametric-clone-create').addEventListener('click', function() {
+ const cols = parseInt(el.querySelector('#clone-cols').value) || 3;
+ const rows = parseInt(el.querySelector('#clone-rows').value) || 2;
+ const spacingX = parseInt(el.querySelector('#clone-spacing-x').value) || 50;
+ const spacingY = parseInt(el.querySelector('#clone-spacing-y').value) || 50;
+
+ const isEditing = el.getAttribute('data-editing-clone') === 'true';
+
+ if (isEditing) {
+ // Update existing parametric clone
+ const colsParam = el.getAttribute('data-cols-param');
+ const rowsParam = el.getAttribute('data-rows-param');
+ const spacingXParam = el.getAttribute('data-spacing-x-param');
+ const spacingYParam = el.getAttribute('data-spacing-y-param');
+ const cloneGroupId = el.getAttribute('data-clone-group-id');
+
+ try {
+ // Update parameter values
+ const parametersManager = editor.parametersManager;
+ const colsParamObj = parametersManager.getParameterByName(colsParam);
+ const rowsParamObj = parametersManager.getParameterByName(rowsParam);
+ const spacingXParamObj = parametersManager.getParameterByName(spacingXParam);
+ const spacingYParamObj = parametersManager.getParameterByName(spacingYParam);
+
+ if (colsParamObj && rowsParamObj && spacingXParamObj && spacingYParamObj) {
+ // Get parameter IDs from the parameters object
+ const parameters = parametersManager.getParameters();
+ let colsId, rowsId, spacingXId, spacingYId;
+
+ Object.keys(parameters).forEach(id => {
+ const param = parameters[id];
+ if (param.name === colsParam) colsId = id;
+ if (param.name === rowsParam) rowsId = id;
+ if (param.name === spacingXParam) spacingXId = id;
+ if (param.name === spacingYParam) spacingYId = id;
+ });
+
+ if (colsId) parametersManager.updateParameter(colsId, colsParam, 'grid_cols', cols, colsParamObj.description);
+ if (rowsId) parametersManager.updateParameter(rowsId, rowsParam, 'grid_rows', rows, rowsParamObj.description);
+ if (spacingXId) parametersManager.updateParameter(spacingXId, spacingXParam, 'grid_spacing_x', spacingX, spacingXParamObj.description);
+ if (spacingYId) parametersManager.updateParameter(spacingYId, spacingYParam, 'grid_spacing_y', spacingY, spacingYParamObj.description);
+
+ // Regenerate the clone group
+ if (typeof svgCanvas.updateParametricCloneGroup === 'function') {
+ svgCanvas.updateParametricCloneGroup(cloneGroupId);
+ }
+
+ alert('Parametric clone updated successfully.');
+ }
+ } catch (error) {
+ alert('Error updating parametric clone: ' + error.message);
+ }
+
+ // Clear editing state
+ el.removeAttribute('data-editing-clone');
+ el.removeAttribute('data-cols-param');
+ el.removeAttribute('data-rows-param');
+ el.removeAttribute('data-spacing-x-param');
+ el.removeAttribute('data-spacing-y-param');
+ el.removeAttribute('data-clone-group-id');
+ } else {
+ // Create new parametric clone
+ if (typeof editor.createParametricClone === 'function') {
+ editor.createParametricClone(cols, rows, spacingX, spacingY);
+ }
+ }
+
+ editor.modal.parametricClone.close();
+ });
+
+ // Ensure input fields are clickable (fix for modal z-index issues)
+ el.querySelector('#clone-cols').addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+ el.querySelector('#clone-rows').addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+ el.querySelector('#clone-spacing-x').addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+ el.querySelector('#clone-spacing-y').addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+ }
})
};
\ No newline at end of file
diff --git a/src/js/svgcanvas.js b/src/js/svgcanvas.js
index c4d166a8..1f49dcd5 100644
--- a/src/js/svgcanvas.js
+++ b/src/js/svgcanvas.js
@@ -8124,6 +8124,213 @@ this.groupSelectedElements = function(type) {
selectOnly([g], true);
};
+// Function: createParametricCloneGroup
+// Creates a parametric clone group with grid layout
+this.createParametricCloneGroup = function(templateElements, colsParamName, rowsParamName, spacingXParamName, spacingYParamName) {
+ if (!templateElements || templateElements.length === 0) {
+ return null;
+ }
+
+ // Get the parameter values
+ const cols = editor.parametersManager.resolveParameterValue('@' + colsParamName);
+ const rows = editor.parametersManager.resolveParameterValue('@' + rowsParamName);
+ const spacingX = editor.parametersManager.resolveParameterValue('@' + spacingXParamName);
+ const spacingY = editor.parametersManager.resolveParameterValue('@' + spacingYParamName);
+
+ const batchCmd = new BatchCommand("Create Parametric Clone");
+
+ // Create the main parametric clone group
+ const cloneGroupId = getNextId();
+ const cloneGroup = addSvgElementFromJson({
+ "element": "g",
+ "attr": {
+ "id": cloneGroupId,
+ "data-parametric-clone": "true",
+ "data-cols-param": colsParamName,
+ "data-rows-param": rowsParamName,
+ "data-spacing-x-param": spacingXParamName,
+ "data-spacing-y-param": spacingYParamName
+ }
+ });
+
+ // Create template group to hold the original elements
+ const templateGroupId = getNextId();
+ const templateGroup = addSvgElementFromJson({
+ "element": "g",
+ "attr": {
+ "id": templateGroupId,
+ "data-template": "true"
+ }
+ });
+
+ cloneGroup.appendChild(templateGroup);
+
+ // Move template elements to template group and get their bounding box
+ let templateBBox = null;
+ templateElements.forEach(elem => {
+ if (elem) {
+ const oldParent = elem.parentNode;
+ const oldNextSibling = elem.nextSibling;
+ templateGroup.appendChild(elem);
+ batchCmd.addSubCommand(new MoveElementCommand(elem, oldNextSibling, oldParent));
+
+ // Calculate bounding box of template elements
+ try {
+ const elemBBox = getStrokedBBox([elem]);
+ if (elemBBox) {
+ if (!templateBBox) {
+ templateBBox = {
+ x: elemBBox.x,
+ y: elemBBox.y,
+ width: elemBBox.width,
+ height: elemBBox.height
+ };
+ } else {
+ const x2 = Math.max(templateBBox.x + templateBBox.width, elemBBox.x + elemBBox.width);
+ const y2 = Math.max(templateBBox.y + templateBBox.height, elemBBox.y + elemBBox.height);
+ templateBBox.x = Math.min(templateBBox.x, elemBBox.x);
+ templateBBox.y = Math.min(templateBBox.y, elemBBox.y);
+ templateBBox.width = x2 - templateBBox.x;
+ templateBBox.height = y2 - templateBBox.y;
+ }
+ }
+ } catch (e) {
+ console.warn('Could not get bounding box for element:', elem);
+ }
+ }
+ });
+
+ // If we couldn't get a bounding box, use a default offset
+ if (!templateBBox) {
+ templateBBox = { x: 0, y: 0, width: 50, height: 50 };
+ }
+
+ // Generate grid of clones
+ for (let row = 0; row < rows; row++) {
+ for (let col = 0; col < cols; col++) {
+ // Skip the first position (0,0) since that's where the template is
+ if (row === 0 && col === 0) continue;
+
+ const cloneInstanceGroup = addSvgElementFromJson({
+ "element": "g",
+ "attr": {
+ "id": getNextId(),
+ "data-clone-instance": "true",
+ "data-row": row,
+ "data-col": col
+ }
+ });
+
+ // Calculate position offset
+ const offsetX = col * spacingX;
+ const offsetY = row * spacingY;
+
+ // Set transform for positioning
+ if (offsetX !== 0 || offsetY !== 0) {
+ cloneInstanceGroup.setAttribute("transform", `translate(${offsetX},${offsetY})`);
+ }
+
+ // Clone all template elements
+ templateElements.forEach(elem => {
+ if (elem) {
+ const clone = copyElem(elem);
+ cloneInstanceGroup.appendChild(clone);
+ }
+ });
+
+ cloneGroup.appendChild(cloneInstanceGroup);
+ }
+ }
+
+ batchCmd.addSubCommand(new InsertElementCommand(cloneGroup));
+ addCommandToHistory(batchCmd);
+
+ call("changed", [cloneGroup]);
+ return cloneGroupId;
+};
+
+// Function: updateParametricCloneGroup
+// Updates an existing parametric clone group with new parameter values
+this.updateParametricCloneGroup = function(cloneGroupId) {
+ const cloneGroup = getElem(cloneGroupId);
+ if (!cloneGroup || cloneGroup.getAttribute('data-parametric-clone') !== 'true') {
+ return false;
+ }
+
+ // Get parameter names
+ const colsParamName = cloneGroup.getAttribute('data-cols-param');
+ const rowsParamName = cloneGroup.getAttribute('data-rows-param');
+ const spacingXParamName = cloneGroup.getAttribute('data-spacing-x-param');
+ const spacingYParamName = cloneGroup.getAttribute('data-spacing-y-param');
+
+ // Get updated parameter values
+ const cols = editor.parametersManager.resolveParameterValue('@' + colsParamName);
+ const rows = editor.parametersManager.resolveParameterValue('@' + rowsParamName);
+ const spacingX = editor.parametersManager.resolveParameterValue('@' + spacingXParamName);
+ const spacingY = editor.parametersManager.resolveParameterValue('@' + spacingYParamName);
+
+ const batchCmd = new BatchCommand("Update Parametric Clone");
+
+ // Find template group
+ const templateGroup = cloneGroup.querySelector('[data-template="true"]');
+ if (!templateGroup) {
+ console.error('Template group not found in parametric clone');
+ return false;
+ }
+
+ // Get template elements
+ const templateElements = Array.from(templateGroup.children);
+
+ // Remove all existing clone instances
+ const cloneInstances = cloneGroup.querySelectorAll('[data-clone-instance="true"]');
+ cloneInstances.forEach(instance => {
+ batchCmd.addSubCommand(new RemoveElementCommand(instance, instance.nextSibling, instance.parentNode));
+ instance.parentNode.removeChild(instance);
+ });
+
+ // Generate new grid of clones
+ for (let row = 0; row < rows; row++) {
+ for (let col = 0; col < cols; col++) {
+ // Skip the first position (0,0) since that's where the template is
+ if (row === 0 && col === 0) continue;
+
+ const cloneInstanceGroup = addSvgElementFromJson({
+ "element": "g",
+ "attr": {
+ "id": getNextId(),
+ "data-clone-instance": "true",
+ "data-row": row,
+ "data-col": col
+ }
+ });
+
+ // Calculate position offset
+ const offsetX = col * spacingX;
+ const offsetY = row * spacingY;
+
+ // Set transform for positioning
+ if (offsetX !== 0 || offsetY !== 0) {
+ cloneInstanceGroup.setAttribute("transform", `translate(${offsetX},${offsetY})`);
+ }
+
+ // Clone all template elements
+ templateElements.forEach(elem => {
+ if (elem) {
+ const clone = copyElem(elem);
+ cloneInstanceGroup.appendChild(clone);
+ }
+ });
+
+ cloneGroup.appendChild(cloneInstanceGroup);
+ batchCmd.addSubCommand(new InsertElementCommand(cloneInstanceGroup));
+ }
+ }
+
+ addCommandToHistory(batchCmd);
+ call("changed", [cloneGroup]);
+ return true;
+};
+
// Function: pushGroupProperties
// Pushes all appropriate parent group properties down to its children, then
From 3458d210d2083707356b6941ebff6360e1007164 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Wed, 23 Jul 2025 15:24:37 +1000
Subject: [PATCH 04/13] Add equation parameter type
---
src/js/Parameters.js | 115 +++++++++++++++++++++++++++++++++--
src/js/PropertyValidation.js | 15 ++++-
src/js/editor.js | 57 +++++++++++++----
src/js/modals.js | 5 ++
4 files changed, 174 insertions(+), 18 deletions(-)
diff --git a/src/js/Parameters.js b/src/js/Parameters.js
index cf271c3d..df05103e 100644
--- a/src/js/Parameters.js
+++ b/src/js/Parameters.js
@@ -11,6 +11,7 @@ MD.Parameters = function(){
text: { label: 'Text', defaultValue: '' },
color: { label: 'Color', defaultValue: '#000000' },
boolean: { label: 'Boolean', defaultValue: false },
+ equation: { label: 'Equation', defaultValue: '0' },
grid_cols: { label: 'Grid Columns', defaultValue: 3 },
grid_rows: { label: 'Grid Rows', defaultValue: 2 },
grid_spacing_x: { label: 'Horizontal Spacing', defaultValue: 50 },
@@ -133,6 +134,79 @@ MD.Parameters = function(){
return Object.values(params).map(param => param.name);
}
+ // Evaluate equation with parameter references
+ function evaluateEquation(equation, visited = new Set()) {
+ if (typeof equation !== 'string') {
+ return equation;
+ }
+
+ // Replace parameter references with their values
+ let processedEquation = equation;
+ const paramReferenceRegex = /@([a-zA-Z_][a-zA-Z0-9_]*)/g;
+ let match;
+
+ while ((match = paramReferenceRegex.exec(equation)) !== null) {
+ const paramName = match[1];
+ const fullMatch = match[0]; // e.g., "@width"
+
+ // Check for circular dependencies
+ if (visited.has(paramName)) {
+ console.error(`Circular dependency detected involving parameter: ${paramName}`);
+ return 0;
+ }
+
+ const param = getParameterByName(paramName);
+ if (!param) {
+ console.warn(`Parameter @${paramName} not found in equation, treating as 0`);
+ processedEquation = processedEquation.replace(fullMatch, '0');
+ continue;
+ }
+
+ let resolvedValue;
+ if (param.type === 'equation') {
+ // Recursively resolve equation parameters
+ const newVisited = new Set(visited);
+ newVisited.add(paramName);
+ resolvedValue = evaluateEquation(param.defaultValue, newVisited);
+ } else {
+ resolvedValue = resolveParameterValueDirect(param);
+ }
+
+ // Replace the parameter reference with its resolved value
+ processedEquation = processedEquation.replace(fullMatch, resolvedValue);
+ }
+
+ // Evaluate the mathematical expression
+ try {
+ // Basic safety check - only allow numbers, operators, parentheses, and whitespace
+ if (!/^[0-9+\-*/.() \t]+$/.test(processedEquation)) {
+ throw new Error('Invalid characters in equation');
+ }
+
+ // Use Function constructor for safe evaluation (better than eval)
+ const result = new Function('return ' + processedEquation)();
+
+ if (typeof result !== 'number' || isNaN(result)) {
+ throw new Error('Equation did not evaluate to a number');
+ }
+
+ return result;
+ } catch (error) {
+ console.error(`Error evaluating equation "${equation}": ${error.message}`);
+ return 0;
+ }
+ }
+
+ // Helper function to resolve parameter value directly (without equation evaluation)
+ function resolveParameterValueDirect(param) {
+ const resolvedValue = param.defaultValue;
+ if (param.type === 'number') {
+ const num = parseFloat(resolvedValue);
+ return isNaN(num) ? 0 : num;
+ }
+ return resolvedValue;
+ }
+
// Resolve parameter reference (e.g., "@width" -> actual value)
function resolveParameterValue(value) {
if (typeof value !== 'string' || !value.startsWith('@')) {
@@ -147,14 +221,13 @@ MD.Parameters = function(){
return value;
}
- // Ensure proper type conversion
- const resolvedValue = param.defaultValue;
- if (param.type === 'number') {
- const num = parseFloat(resolvedValue);
- return isNaN(num) ? 0 : num;
+ // Handle equation type parameters
+ if (param.type === 'equation') {
+ return evaluateEquation(param.defaultValue);
}
- return resolvedValue;
+ // Ensure proper type conversion for other types
+ return resolveParameterValueDirect(param);
}
// Check if a value is a parameter reference
@@ -162,6 +235,29 @@ MD.Parameters = function(){
return typeof value === 'string' && value.startsWith('@') && value.length > 1;
}
+ // Validate equation syntax
+ function validateEquationSyntax(equation) {
+ if (typeof equation !== 'string') {
+ return false;
+ }
+
+ // Basic syntax validation - check for valid characters only
+ if (!/^[0-9+\-*/.()@ \t_a-zA-Z]+$/.test(equation)) {
+ return false;
+ }
+
+ // Check for valid parameter references
+ const paramReferenceRegex = /@([a-zA-Z_][a-zA-Z0-9_]*)/g;
+ let match;
+ while ((match = paramReferenceRegex.exec(equation)) !== null) {
+ const paramName = match[1];
+ // Allow parameter references even if they don't exist yet (for forward references)
+ // The actual resolution will handle missing parameters gracefully
+ }
+
+ return true;
+ }
+
// Validate parameter value for its type
function validateParameterValue(value, type) {
switch (type) {
@@ -178,6 +274,11 @@ MD.Parameters = function(){
return PARAM_TYPES.color.defaultValue;
case 'boolean':
return Boolean(value);
+ case 'equation':
+ if (validateEquationSyntax(value)) {
+ return String(value);
+ }
+ return PARAM_TYPES.equation.defaultValue;
default:
return value;
}
@@ -194,6 +295,8 @@ MD.Parameters = function(){
this.resolveParameterValue = resolveParameterValue;
this.isParameterReference = isParameterReference;
this.validateParameterValue = validateParameterValue;
+ this.validateEquationSyntax = validateEquationSyntax;
+ this.evaluateEquation = evaluateEquation;
this.isValidParameterName = isValidParameterName;
this.parameterExists = parameterExists;
this.PARAM_TYPES = PARAM_TYPES;
diff --git a/src/js/PropertyValidation.js b/src/js/PropertyValidation.js
index 1b9e09fd..66eb670e 100644
--- a/src/js/PropertyValidation.js
+++ b/src/js/PropertyValidation.js
@@ -20,7 +20,20 @@ MD.PropertyValidation = function() {
// Check if it's a valid parameter reference
if (PARAM_REFERENCE_PATTERN.test(value)) {
const paramName = value.substring(1);
- return editor.parametersManager.getParameterByName(paramName) !== null;
+ const param = editor.parametersManager.getParameterByName(paramName);
+ if (!param) return false;
+
+ // For equation parameters, validate that they can be resolved to a number
+ if (param.type === 'equation') {
+ try {
+ const resolvedValue = editor.parametersManager.resolveParameterValue(value);
+ return typeof resolvedValue === 'number' && !isNaN(resolvedValue);
+ } catch (error) {
+ return false;
+ }
+ }
+
+ return true;
}
return false;
diff --git a/src/js/editor.js b/src/js/editor.js
index d451e939..00b2fb15 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -476,9 +476,21 @@ MD.Editor = function(){
const serializer = new XMLSerializer();
let modifiedSvgString = serializer.serializeToString(svgDoc.documentElement);
- // Generate parameter list and default values
- const paramNames = Object.keys(paramMap);
- const paramDefaults = paramNames.map(name => {
+ // Separate input parameters from equation parameters
+ const inputParams = [];
+ const equationParams = [];
+
+ Object.keys(paramMap).forEach(name => {
+ const param = paramMap[name];
+ if (param.type === 'equation') {
+ equationParams.push(name);
+ } else {
+ inputParams.push(name);
+ }
+ });
+
+ // Generate parameter list and default values for input parameters only
+ const paramDefaults = inputParams.map(name => {
const param = paramMap[name];
let defaultValue = param.defaultValue;
@@ -498,18 +510,40 @@ MD.Editor = function(){
.replace(/`/g, '\\`') // Escape backticks
.replace(/\$(?!{)/g, '\\$'); // Escape $ that aren't part of ${...}
+ // Generate equation calculation code
+ const equationCalculations = equationParams.map(name => {
+ const param = paramMap[name];
+ const equation = param.defaultValue;
+
+ // Replace parameter references in equation with variable names
+ let processedEquation = equation;
+ const paramReferenceRegex = /@([a-zA-Z_][a-zA-Z0-9_]*)/g;
+ processedEquation = processedEquation.replace(paramReferenceRegex, '$1');
+
+ return ` const ${name} = (${processedEquation});`;
+ }).join('\n');
+
// Generate the function
- const hasParams = paramNames.length > 0;
- const paramComment = hasParams
- ? paramNames.map(name => ` * @param {${paramMap[name].type}} ${name} - Default: ${paramMap[name].defaultValue}`).join('\n')
+ const hasInputParams = inputParams.length > 0;
+ const hasEquationParams = equationParams.length > 0;
+ const hasAnyParams = hasInputParams || hasEquationParams;
+
+ const inputParamComment = hasInputParams
+ ? inputParams.map(name => ` * @param {${paramMap[name].type}} ${name} - Default: ${paramMap[name].defaultValue}`).join('\n')
+ : '';
+ const equationParamComment = hasEquationParams
+ ? equationParams.map(name => ` * @calculated {number} ${name} - Equation: ${paramMap[name].defaultValue}`).join('\n')
+ : '';
+ const paramComment = hasAnyParams
+ ? [inputParamComment, equationParamComment].filter(c => c).join('\n')
: ' * No parameters defined';
- const functionParams = hasParams ? `{${paramNames.join(', ')}} = {}` : '';
- const defaultAssignments = hasParams
- ? paramNames.map((name, i) => ` const ${name}_val = ${name} !== undefined ? ${name} : ${paramDefaults[i]};`).join('\n')
+ const functionParams = hasInputParams ? `{${inputParams.join(', ')}} = {}` : '';
+ const defaultAssignments = hasInputParams
+ ? inputParams.map((name, i) => ` const ${name}_val = ${name} !== undefined ? ${name} : ${paramDefaults[i]};`).join('\n')
: '';
- const variableDeclaration = hasParams
- ? paramNames.map(name => ` const ${name} = ${name}_val;`).join('\n')
+ const variableDeclaration = hasInputParams
+ ? inputParams.map(name => ` const ${name} = ${name}_val;`).join('\n')
: '';
const functionBody = `/**
@@ -522,6 +556,7 @@ ${paramComment}
function generateSVG(${functionParams}) {
${defaultAssignments}
${variableDeclaration}
+${equationCalculations ? '\n' + equationCalculations : ''}
${cloneHelperFunctions.join('')}
return \`${escapedSvg}\`;
diff --git a/src/js/modals.js b/src/js/modals.js
index b16bddae..cbecda6d 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -127,6 +127,7 @@ editor.modal = {
Text
Color
Boolean
+ Equation
@@ -212,6 +213,10 @@ editor.modal = {
currentElement.type = 'color';
currentElement.placeholder = '';
break;
+ case 'equation':
+ currentElement.type = 'text';
+ currentElement.placeholder = 'e.g., 2 * @width + 10';
+ break;
default:
currentElement.type = 'text';
}
From e63f58f9b83bbffaa8aaba8d9354b990e1d40104 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Wed, 23 Jul 2025 16:31:03 +1000
Subject: [PATCH 05/13] Make the output compatible with our existing custom
diagram widget!
---
src/js/editor.js | 52 +++++++++++++++++++++++++++++++++++++-----------
1 file changed, 40 insertions(+), 12 deletions(-)
diff --git a/src/js/editor.js b/src/js/editor.js
index 00b2fb15..b6992c93 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -445,7 +445,7 @@ MD.Editor = function(){
cloneHelperFunctions.push(helperFunction);
// Replace the clone group with a placeholder that calls the helper function
- const placeholder = svgDoc.createElement('g');
+ const placeholder = svgDoc.createElementNS('http://www.w3.org/2000/svg', 'g');
placeholder.setAttribute('id', cloneGroup.id);
placeholder.innerHTML = `\${${funcName}()}`;
cloneGroup.parentNode.replaceChild(placeholder, cloneGroup);
@@ -538,14 +538,40 @@ MD.Editor = function(){
? [inputParamComment, equationParamComment].filter(c => c).join('\n')
: ' * No parameters defined';
- const functionParams = hasInputParams ? `{${inputParams.join(', ')}} = {}` : '';
- const defaultAssignments = hasInputParams
- ? inputParams.map((name, i) => ` const ${name}_val = ${name} !== undefined ? ${name} : ${paramDefaults[i]};`).join('\n')
+ const functionParams = 'params = {}';
+ const parameterAssignments = hasInputParams
+ ? inputParams.map((name, i) => ` const ${name} = params.${name} ?? ${paramDefaults[i]};`).join('\n')
: '';
- const variableDeclaration = hasInputParams
- ? inputParams.map(name => ` const ${name} = ${name}_val;`).join('\n')
+
+ // Generate parameter types array for export
+ const typeMapping = {
+ 'number': 'Number',
+ 'text': 'String',
+ 'color': 'String',
+ 'boolean': 'Boolean',
+ 'equation': 'Number',
+ 'grid_cols': 'Number',
+ 'grid_rows': 'Number',
+ 'grid_spacing_x': 'Number',
+ 'grid_spacing_y': 'Number'
+ };
+
+ const paramsTypesArray = hasInputParams
+ ? inputParams.map(name => {
+ const param = paramMap[name];
+ const jsType = typeMapping[param.type] || 'String';
+ return ` { key: "${name}", type: "${jsType}" }`;
+ }).join(',\n')
: '';
+ const paramsTypesExport = hasInputParams
+ ? `function params() {
+ return [\n${paramsTypesArray}\n];
+}`
+ : `function params() {
+ return [];
+}`;
+
const functionBody = `/**
* Parametric SVG Generator
* Generated by Method Draw
@@ -553,22 +579,24 @@ MD.Editor = function(){
* Parameters:
${paramComment}
*/
-function generateSVG(${functionParams}) {
-${defaultAssignments}
-${variableDeclaration}
+function render(${functionParams}) {
+${parameterAssignments}
${equationCalculations ? '\n' + equationCalculations : ''}
${cloneHelperFunctions.join('')}
return \`${escapedSvg}\`;
}
+${paramsTypesExport}
+
// Export for different module systems
if (typeof module !== 'undefined' && module.exports) {
- module.exports = generateSVG;
+ module.exports = render, params;
} else if (typeof define === 'function' && define.amd) {
- define([], function() { return generateSVG; });
+ define([], function() { return render, params; });
} else if (typeof window !== 'undefined') {
- window.generateSVG = generateSVG;
+ window.render = render;
+ window.params = params;
}
`;
From cadbc55f8624f7afde1946bb4ae1f4f95eee2173 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Wed, 23 Jul 2025 16:34:02 +1000
Subject: [PATCH 06/13] Update package-lock.json
---
package-lock.json | 3502 ++++++++++++++++++++++++++++-----------------
1 file changed, 2155 insertions(+), 1347 deletions(-)
diff --git a/package-lock.json b/package-lock.json
index 43ce7b16..a4c134c2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,268 +1,354 @@
{
"name": "method-draw",
"version": "0.0.1",
- "lockfileVersion": 1,
+ "lockfileVersion": 3,
"requires": true,
- "dependencies": {
- "@types/expect": {
+ "packages": {
+ "": {
+ "name": "method-draw",
+ "version": "0.0.1",
+ "license": "MIT",
+ "devDependencies": {
+ "gulp": "^4.0.2",
+ "gulp-cache-bust": "^1.4.1",
+ "gulp-concat": "^2.6.1",
+ "gulp-minify": "^3.1.0",
+ "gulp-replace": "^1.1.3",
+ "gulp-useref": "^4.0.1"
+ }
+ },
+ "node_modules/@types/expect": {
"version": "1.20.4",
"resolved": "https://registry.npmjs.org/@types/expect/-/expect-1.20.4.tgz",
"integrity": "sha512-Q5Vn3yjTDyCMV50TB6VRIbQNxSE4OmZR86VSbGaNpfUolm0iePBB4KdEEHmxoY5sT2+2DIvXW0rvMDP2nHZ4Mg==",
"dev": true
},
- "@types/node": {
+ "node_modules/@types/node": {
"version": "14.14.45",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.45.tgz",
"integrity": "sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw==",
"dev": true
},
- "@types/vinyl": {
+ "node_modules/@types/vinyl": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/vinyl/-/vinyl-2.0.4.tgz",
"integrity": "sha512-2o6a2ixaVI2EbwBPg1QYLGQoHK56p/8X/sGfKbFC8N6sY9lfjsMf/GprtkQkSya0D4uRiutRZ2BWj7k3JvLsAQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"@types/expect": "^1.20.4",
"@types/node": "*"
}
},
- "ansi-colors": {
+ "node_modules/ansi-colors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
"integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-wrap": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "ansi-cyan": {
+ "node_modules/ansi-cyan": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz",
"integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-wrap": "0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "ansi-gray": {
+ "node_modules/ansi-gray": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
"integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-wrap": "0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "ansi-red": {
+ "node_modules/ansi-red": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz",
"integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-wrap": "0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "ansi-regex": {
+ "node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "ansi-wrap": {
+ "node_modules/ansi-wrap": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
"integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "anymatch": {
+ "node_modules/anymatch": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
"integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
"dev": true,
- "requires": {
+ "dependencies": {
"micromatch": "^3.1.4",
"normalize-path": "^2.1.1"
- },
+ }
+ },
+ "node_modules/anymatch/node_modules/normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
"dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
+ "remove-trailing-separator": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "append-buffer": {
+ "node_modules/append-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz",
"integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=",
"dev": true,
- "requires": {
+ "dependencies": {
"buffer-equal": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "archy": {
+ "node_modules/archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
"integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=",
"dev": true
},
- "arr-diff": {
+ "node_modules/arr-diff": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
"integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "arr-filter": {
+ "node_modules/arr-filter": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz",
"integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=",
"dev": true,
- "requires": {
+ "dependencies": {
"make-iterator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "arr-flatten": {
+ "node_modules/arr-flatten": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
"integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "arr-map": {
+ "node_modules/arr-map": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz",
"integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=",
"dev": true,
- "requires": {
+ "dependencies": {
"make-iterator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "arr-union": {
+ "node_modules/arr-union": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
"integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "array-each": {
+ "node_modules/array-each": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz",
"integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "array-initial": {
+ "node_modules/array-initial": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz",
"integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=",
"dev": true,
- "requires": {
+ "dependencies": {
"array-slice": "^1.0.0",
"is-number": "^4.0.0"
},
- "dependencies": {
- "is-number": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
- "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
- "dev": true
- }
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-initial/node_modules/is-number": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
+ "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "array-last": {
+ "node_modules/array-last": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz",
"integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-number": "^4.0.0"
},
- "dependencies": {
- "is-number": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
- "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
- "dev": true
- }
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-last/node_modules/is-number": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
+ "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "array-slice": {
+ "node_modules/array-slice": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz",
"integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "array-sort": {
+ "node_modules/array-sort": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz",
"integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==",
"dev": true,
- "requires": {
+ "dependencies": {
"default-compare": "^1.0.0",
"get-value": "^2.0.6",
"kind-of": "^5.0.2"
},
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-sort/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "array-unique": {
+ "node_modules/array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
"integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "assign-symbols": {
+ "node_modules/assign-symbols": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
"integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "async-done": {
+ "node_modules/async-done": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.2.tgz",
"integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==",
"dev": true,
- "requires": {
+ "dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.2",
"process-nextick-args": "^2.0.0",
"stream-exhaust": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "async-each": {
+ "node_modules/async-each": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
"integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
"dev": true
},
- "async-settle": {
+ "node_modules/async-settle": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz",
"integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=",
"dev": true,
- "requires": {
+ "dependencies": {
"async-done": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "atob": {
+ "node_modules/atob": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
- "dev": true
+ "dev": true,
+ "bin": {
+ "atob": "bin/atob.js"
+ },
+ "engines": {
+ "node": ">= 4.5.0"
+ }
},
- "bach": {
+ "node_modules/bach": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz",
"integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-filter": "^1.1.1",
"arr-flatten": "^1.0.1",
"arr-map": "^2.0.0",
@@ -272,20 +358,23 @@
"async-done": "^1.2.2",
"async-settle": "^1.0.0",
"now-and-later": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "balanced-match": {
+ "node_modules/balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
"dev": true
},
- "base": {
+ "node_modules/base": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
"integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
"dev": true,
- "requires": {
+ "dependencies": {
"cache-base": "^1.0.1",
"class-utils": "^0.3.5",
"component-emitter": "^1.2.1",
@@ -294,91 +383,115 @@
"mixin-deep": "^1.2.0",
"pascalcase": "^0.1.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/base/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "binary-extensions": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/binary-extensions": {
"version": "1.13.1",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
"integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "binaryextensions": {
+ "node_modules/binaryextensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binaryextensions/-/binaryextensions-2.3.0.tgz",
"integrity": "sha512-nAihlQsYGyc5Bwq6+EsubvANYGExeJKHDO3RjnvwU042fawQTQfM3Kxn7IHUXQOz4bzfwsGYYHGSvXyW4zOGLg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
},
- "bindings": {
+ "node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dev": true,
"optional": true,
- "requires": {
+ "dependencies": {
"file-uri-to-path": "1.0.0"
}
},
- "boolbase": {
+ "node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
"dev": true
},
- "brace-expansion": {
+ "node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
- "requires": {
+ "dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
- "braces": {
+ "node_modules/braces": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
"integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-flatten": "^1.1.0",
"array-unique": "^0.3.2",
"extend-shallow": "^2.0.1",
@@ -390,36 +503,43 @@
"split-string": "^3.0.2",
"to-regex": "^3.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/braces/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
"dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "buffer-equal": {
+ "node_modules/buffer-equal": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz",
"integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.4.0"
+ }
},
- "buffer-from": {
+ "node_modules/buffer-from": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true
},
- "cache-base": {
+ "node_modules/cache-base": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
"integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"collection-visit": "^1.0.0",
"component-emitter": "^1.2.1",
"get-value": "^2.0.6",
@@ -429,36 +549,48 @@
"to-object-path": "^0.3.0",
"union-value": "^1.0.0",
"unset-value": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "cachebust": {
+ "node_modules/cachebust": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/cachebust/-/cachebust-2.4.1.tgz",
"integrity": "sha512-Y2O58hqbFeeD09qyC3o9nPp9qHPC4KvRnZkiXI+Eaxs15IIA/3mqGrTrE8AWcThgADrwtQ+97yKbc2c/CypaAQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"cheerio": "^0.22.0",
"md5": "^2.0.0"
+ },
+ "bin": {
+ "cachebust": "cli.js"
}
},
- "camelcase": {
+ "node_modules/camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "charenc": {
+ "node_modules/charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
},
- "cheerio": {
+ "node_modules/cheerio": {
"version": "0.22.0",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
"integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
"dev": true,
- "requires": {
+ "dependencies": {
"css-select": "~1.2.0",
"dom-serializer": "~0.1.0",
"entities": "~1.1.1",
@@ -475,18 +607,20 @@
"lodash.reduce": "^4.4.0",
"lodash.reject": "^4.4.0",
"lodash.some": "^4.4.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
}
},
- "chokidar": {
+ "node_modules/chokidar": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
"integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
"dev": true,
- "requires": {
+ "dependencies": {
"anymatch": "^2.0.0",
"async-each": "^1.0.1",
"braces": "^2.3.2",
- "fsevents": "^1.2.7",
"glob-parent": "^3.1.0",
"inherits": "^2.0.3",
"is-binary-path": "^1.0.0",
@@ -495,459 +629,531 @@
"path-is-absolute": "^1.0.0",
"readdirp": "^2.2.1",
"upath": "^1.1.1"
+ },
+ "optionalDependencies": {
+ "fsevents": "^1.2.7"
}
},
- "class-utils": {
+ "node_modules/class-utils": {
"version": "0.3.6",
"resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
"integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-union": "^3.1.0",
"define-property": "^0.2.5",
"isobject": "^3.0.0",
"static-extend": "^0.1.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/class-utils/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "cliui": {
+ "node_modules/cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"dev": true,
- "requires": {
+ "dependencies": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wrap-ansi": "^2.0.0"
}
},
- "clone": {
+ "node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
},
- "clone-buffer": {
+ "node_modules/clone-buffer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz",
"integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "clone-stats": {
+ "node_modules/clone-stats": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz",
"integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=",
"dev": true
},
- "cloneable-readable": {
+ "node_modules/cloneable-readable": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.3.tgz",
"integrity": "sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"inherits": "^2.0.1",
"process-nextick-args": "^2.0.0",
"readable-stream": "^2.3.5"
}
},
- "code-point-at": {
+ "node_modules/code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "collection-map": {
+ "node_modules/collection-map": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz",
"integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-map": "^2.0.2",
"for-own": "^1.0.0",
"make-iterator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "collection-visit": {
+ "node_modules/collection-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
"integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=",
"dev": true,
- "requires": {
+ "dependencies": {
"map-visit": "^1.0.0",
"object-visit": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "color-support": {
+ "node_modules/color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "dev": true
+ "dev": true,
+ "bin": {
+ "color-support": "bin.js"
+ }
},
- "commander": {
+ "node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
- "component-emitter": {
+ "node_modules/component-emitter": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
"integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
"dev": true
},
- "concat-map": {
+ "node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
- "concat-stream": {
+ "node_modules/concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"dev": true,
- "requires": {
+ "engines": [
+ "node >= 0.8"
+ ],
+ "dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
- "concat-with-sourcemaps": {
+ "node_modules/concat-with-sourcemaps": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz",
"integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==",
"dev": true,
- "requires": {
- "source-map": "^0.6.1"
- },
"dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
+ "source-map": "^0.6.1"
+ }
+ },
+ "node_modules/concat-with-sourcemaps/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "convert-source-map": {
+ "node_modules/convert-source-map": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz",
"integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==",
"dev": true,
- "requires": {
+ "dependencies": {
"safe-buffer": "~5.1.1"
}
},
- "copy-descriptor": {
+ "node_modules/copy-descriptor": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
"integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "copy-props": {
+ "node_modules/copy-props": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz",
"integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==",
"dev": true,
- "requires": {
+ "dependencies": {
"each-props": "^1.3.0",
"is-plain-object": "^2.0.1"
}
},
- "core-util-is": {
+ "node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
- "crypt": {
+ "node_modules/crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
},
- "css-select": {
+ "node_modules/css-select": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
"dev": true,
- "requires": {
+ "dependencies": {
"boolbase": "~1.0.0",
"css-what": "2.1",
"domutils": "1.5.1",
"nth-check": "~1.0.1"
}
},
- "css-what": {
+ "node_modules/css-what": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
},
- "d": {
+ "node_modules/d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"dev": true,
- "requires": {
+ "dependencies": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
- "debug": {
+ "node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
- "requires": {
+ "dependencies": {
"ms": "2.0.0"
}
},
- "decamelize": {
+ "node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "decode-uri-component": {
+ "node_modules/decode-uri-component": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
},
- "default-compare": {
+ "node_modules/default-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz",
"integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^5.0.2"
},
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/default-compare/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "default-resolution": {
+ "node_modules/default-resolution": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz",
"integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "define-properties": {
+ "node_modules/define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"object-keys": "^1.0.12"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
- "define-property": {
+ "node_modules/define-property": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
"integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-descriptor": "^1.0.2",
"isobject": "^3.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-property/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-property/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/define-property/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
"dependencies": {
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "detect-file": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/detect-file": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz",
"integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "dom-serializer": {
+ "node_modules/dom-serializer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz",
"integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==",
"dev": true,
- "requires": {
+ "dependencies": {
"domelementtype": "^1.3.0",
"entities": "^1.1.1"
}
},
- "domelementtype": {
+ "node_modules/domelementtype": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
"dev": true
},
- "domhandler": {
+ "node_modules/domhandler": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
"dev": true,
- "requires": {
+ "dependencies": {
"domelementtype": "1"
}
},
- "domutils": {
+ "node_modules/domutils": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
"dev": true,
- "requires": {
+ "dependencies": {
"dom-serializer": "0",
"domelementtype": "1"
}
},
- "duplexer": {
+ "node_modules/duplexer": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz",
"integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=",
"dev": true
},
- "duplexify": {
+ "node_modules/duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
"integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
"dev": true,
- "requires": {
+ "dependencies": {
"end-of-stream": "^1.0.0",
"inherits": "^2.0.1",
"readable-stream": "^2.0.0",
"stream-shift": "^1.0.0"
}
},
- "each-props": {
+ "node_modules/each-props": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz",
"integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-plain-object": "^2.0.1",
"object.defaults": "^1.1.0"
}
},
- "end-of-stream": {
+ "node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dev": true,
- "requires": {
+ "dependencies": {
"once": "^1.4.0"
}
},
- "entities": {
+ "node_modules/entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
"dev": true
},
- "error-ex": {
+ "node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-arrayish": "^0.2.1"
}
},
- "es5-ext": {
+ "node_modules/es5-ext": {
"version": "0.10.53",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
"integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
"dev": true,
- "requires": {
+ "dependencies": {
"es6-iterator": "~2.0.3",
"es6-symbol": "~3.1.3",
"next-tick": "~1.0.0"
}
},
- "es6-iterator": {
+ "node_modules/es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
"dev": true,
- "requires": {
+ "dependencies": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
- "es6-symbol": {
+ "node_modules/es6-symbol": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"dev": true,
- "requires": {
+ "dependencies": {
"d": "^1.0.1",
"ext": "^1.1.2"
}
},
- "es6-weak-map": {
+ "node_modules/es6-weak-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
"integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
"dev": true,
- "requires": {
+ "dependencies": {
"d": "1",
"es5-ext": "^0.10.46",
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.1"
}
},
- "escape-string-regexp": {
+ "node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
},
- "event-stream": {
+ "node_modules/event-stream": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz",
"integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==",
"dev": true,
- "requires": {
+ "dependencies": {
"duplexer": "^0.1.1",
"from": "^0.1.7",
"map-stream": "0.0.7",
@@ -957,12 +1163,12 @@
"through": "^2.3.8"
}
},
- "expand-brackets": {
+ "node_modules/expand-brackets": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
"integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=",
"dev": true,
- "requires": {
+ "dependencies": {
"debug": "^2.3.3",
"define-property": "^0.2.5",
"extend-shallow": "^2.0.1",
@@ -971,86 +1177,98 @@
"snapdragon": "^0.8.1",
"to-regex": "^3.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-brackets/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "expand-tilde": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expand-tilde": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz",
"integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=",
"dev": true,
- "requires": {
+ "dependencies": {
"homedir-polyfill": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "ext": {
+ "node_modules/ext": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
"integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
"dev": true,
- "requires": {
- "type": "^2.0.0"
- },
"dependencies": {
- "type": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz",
- "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==",
- "dev": true
- }
+ "type": "^2.0.0"
}
},
- "extend": {
+ "node_modules/ext/node_modules/type": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.1.0.tgz",
+ "integrity": "sha512-G9absDWvhAWCV2gmF1zKud3OyC61nZDwWvBL2DApaVFogI07CprggiQAOOjvp2NRjYWFzPyu7vwtDrQFq8jeSA==",
+ "dev": true
+ },
+ "node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
"dev": true
},
- "extend-shallow": {
+ "node_modules/extend-shallow": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
"integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=",
"dev": true,
- "requires": {
+ "dependencies": {
"assign-symbols": "^1.0.0",
"is-extendable": "^1.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extend-shallow/node_modules/is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
"dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
+ "is-plain-object": "^2.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "extglob": {
+ "node_modules/extglob": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
"integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
"dev": true,
- "requires": {
+ "dependencies": {
"array-unique": "^0.3.2",
"define-property": "^1.0.0",
"expand-brackets": "^2.1.4",
@@ -1060,277 +1278,345 @@
"snapdragon": "^0.8.1",
"to-regex": "^3.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
+ "dependencies": {
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/extglob/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "fancy-log": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fancy-log": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
"integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-gray": "^0.1.1",
"color-support": "^1.1.3",
"parse-node-version": "^1.0.0",
"time-stamp": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "fast-levenshtein": {
+ "node_modules/fast-levenshtein": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.1.4.tgz",
"integrity": "sha1-5qdUzI8V5YmHqpy9J69m/W9OWvk=",
"dev": true
},
- "file-uri-to-path": {
+ "node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
"dev": true,
"optional": true
},
- "fill-range": {
+ "node_modules/fill-range": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
"integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=",
"dev": true,
- "requires": {
+ "dependencies": {
"extend-shallow": "^2.0.1",
"is-number": "^3.0.0",
"repeat-string": "^1.6.1",
"to-regex-range": "^2.1.0"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/fill-range/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
"dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "find-up": {
+ "node_modules/find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=",
"dev": true,
- "requires": {
+ "dependencies": {
"path-exists": "^2.0.0",
"pinkie-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "findup-sync": {
+ "node_modules/findup-sync": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-3.0.0.tgz",
"integrity": "sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==",
"dev": true,
- "requires": {
+ "dependencies": {
"detect-file": "^1.0.0",
"is-glob": "^4.0.0",
"micromatch": "^3.0.4",
"resolve-dir": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "fined": {
+ "node_modules/fined": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fined/-/fined-1.2.0.tgz",
"integrity": "sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng==",
"dev": true,
- "requires": {
+ "dependencies": {
"expand-tilde": "^2.0.2",
"is-plain-object": "^2.0.3",
"object.defaults": "^1.1.0",
"object.pick": "^1.2.0",
"parse-filepath": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "flagged-respawn": {
+ "node_modules/flagged-respawn": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.1.tgz",
"integrity": "sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "flush-write-stream": {
+ "node_modules/flush-write-stream": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
"integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
"dev": true,
- "requires": {
+ "dependencies": {
"inherits": "^2.0.3",
"readable-stream": "^2.3.6"
}
},
- "for-in": {
+ "node_modules/for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "for-own": {
+ "node_modules/for-own": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz",
"integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=",
"dev": true,
- "requires": {
+ "dependencies": {
"for-in": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "fork-stream": {
+ "node_modules/fork-stream": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz",
"integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=",
"dev": true
},
- "fragment-cache": {
+ "node_modules/fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
"integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=",
"dev": true,
- "requires": {
+ "dependencies": {
"map-cache": "^0.2.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "from": {
+ "node_modules/from": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz",
"integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=",
"dev": true
},
- "fs-mkdirp-stream": {
+ "node_modules/fs-mkdirp-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz",
"integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=",
"dev": true,
- "requires": {
+ "dependencies": {
"graceful-fs": "^4.1.11",
"through2": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "fs.realpath": {
+ "node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
- "fsevents": {
+ "node_modules/fsevents": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
+ "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues",
"dev": true,
+ "hasInstallScript": true,
"optional": true,
- "requires": {
+ "os": [
+ "darwin"
+ ],
+ "dependencies": {
"bindings": "^1.5.0",
"nan": "^2.12.1"
+ },
+ "engines": {
+ "node": ">= 4.0"
}
},
- "function-bind": {
+ "node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
"dev": true
},
- "get-caller-file": {
+ "node_modules/get-caller-file": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
"dev": true
},
- "get-value": {
+ "node_modules/get-value": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
"integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "glob": {
+ "node_modules/glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
- "requires": {
+ "dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
- "glob-parent": {
+ "node_modules/glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
"integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=",
"dev": true,
- "requires": {
+ "dependencies": {
"is-glob": "^3.1.0",
"path-dirname": "^1.0.0"
- },
+ }
+ },
+ "node_modules/glob-parent/node_modules/is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
"dependencies": {
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
+ "is-extglob": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "glob-stream": {
+ "node_modules/glob-stream": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz",
"integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=",
"dev": true,
- "requires": {
+ "dependencies": {
"extend": "^3.0.0",
"glob": "^7.1.1",
"glob-parent": "^3.1.0",
@@ -1341,14 +1627,17 @@
"remove-trailing-separator": "^1.0.1",
"to-absolute-glob": "^2.0.0",
"unique-stream": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "glob-watcher": {
+ "node_modules/glob-watcher": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.5.tgz",
"integrity": "sha512-zOZgGGEHPklZNjZQaZ9f41i7F2YwE+tS5ZHrDhbBCk3stwahn5vQxnFmBJZHoYdusR6R1bLSXeGUy/BhctwKzw==",
"dev": true,
- "requires": {
+ "dependencies": {
"anymatch": "^2.0.0",
"async-done": "^1.2.0",
"chokidar": "^2.0.0",
@@ -1356,93 +1645,83 @@
"just-debounce": "^1.0.0",
"normalize-path": "^3.0.0",
"object.defaults": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "global-modules": {
+ "node_modules/global-modules": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz",
"integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==",
"dev": true,
- "requires": {
+ "dependencies": {
"global-prefix": "^1.0.1",
"is-windows": "^1.0.1",
"resolve-dir": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "global-prefix": {
+ "node_modules/global-prefix": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz",
"integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=",
"dev": true,
- "requires": {
+ "dependencies": {
"expand-tilde": "^2.0.2",
"homedir-polyfill": "^1.0.1",
"ini": "^1.3.4",
"is-windows": "^1.0.1",
"which": "^1.2.14"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "glogg": {
+ "node_modules/glogg": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz",
"integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==",
"dev": true,
- "requires": {
+ "dependencies": {
"sparkles": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "graceful-fs": {
+ "node_modules/graceful-fs": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz",
"integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==",
"dev": true
},
- "gulp": {
+ "node_modules/gulp": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.2.tgz",
"integrity": "sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA==",
"dev": true,
- "requires": {
+ "dependencies": {
"glob-watcher": "^5.0.3",
"gulp-cli": "^2.2.0",
"undertaker": "^1.2.1",
"vinyl-fs": "^3.0.0"
},
- "dependencies": {
- "gulp-cli": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz",
- "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==",
- "dev": true,
- "requires": {
- "ansi-colors": "^1.0.1",
- "archy": "^1.0.0",
- "array-sort": "^1.0.0",
- "color-support": "^1.1.3",
- "concat-stream": "^1.6.0",
- "copy-props": "^2.0.1",
- "fancy-log": "^1.3.2",
- "gulplog": "^1.0.0",
- "interpret": "^1.4.0",
- "isobject": "^3.0.1",
- "liftoff": "^3.1.0",
- "matchdep": "^2.0.0",
- "mute-stdout": "^1.0.0",
- "pretty-hrtime": "^1.0.0",
- "replace-homedir": "^1.0.0",
- "semver-greatest-satisfied-range": "^1.1.0",
- "v8flags": "^3.2.0",
- "yargs": "^7.1.0"
- }
- }
- }
- },
- "gulp-cache-bust": {
+ "bin": {
+ "gulp": "bin/gulp.js"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/gulp-cache-bust": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/gulp-cache-bust/-/gulp-cache-bust-1.4.1.tgz",
"integrity": "sha512-ksYCu06p2hpUDilgtv/jMB9lxBLg/v9F0xEAYbndgS/xWqamHpIpGRPAKj76VRXJpDTHgEqVPcd2rCofj4TERg==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-colors": "^1.0.1",
"cachebust": "2.4.1",
"fancy-log": "^1.3.2",
@@ -1453,229 +1732,269 @@
"through2": "2.0.1",
"vinyl": "^2.1.0"
},
+ "engines": {
+ "node": ">=4.4.5",
+ "npm": ">=2.15.1"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/arr-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
+ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
+ "dev": true,
"dependencies": {
- "arr-diff": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
- "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.0.1",
- "array-slice": "^0.2.3"
- }
- },
- "arr-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
- "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
- "dev": true
- },
- "array-slice": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
- "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
- "dev": true
- },
- "extend-shallow": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
- "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
- "dev": true,
- "requires": {
- "kind-of": "^1.1.0"
- }
- },
- "kind-of": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
- "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
- "dev": true
- },
- "map-stream": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
- "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
- "dev": true
- },
- "plugin-error": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
- "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
- "dev": true,
- "requires": {
- "ansi-cyan": "^0.1.1",
- "ansi-red": "^0.1.1",
- "arr-diff": "^1.0.1",
- "arr-union": "^2.0.1",
- "extend-shallow": "^1.1.2"
- }
- },
- "process-nextick-args": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
- "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
- "dev": true
- },
- "readable-stream": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
- "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
- "dev": true,
- "requires": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.1",
- "isarray": "~1.0.0",
- "process-nextick-args": "~1.0.6",
- "string_decoder": "~0.10.x",
- "util-deprecate": "~1.0.1"
- }
- },
- "string_decoder": {
- "version": "0.10.31",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
- "dev": true
- },
- "through2": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz",
- "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=",
- "dev": true,
- "requires": {
- "readable-stream": "~2.0.0",
- "xtend": "~4.0.0"
- }
- }
- }
- },
- "gulp-concat": {
+ "arr-flatten": "^1.0.1",
+ "array-slice": "^0.2.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/arr-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
+ "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/extend-shallow": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
+ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/kind-of": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
+ "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/map-stream": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz",
+ "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=",
+ "dev": true
+ },
+ "node_modules/gulp-cache-bust/node_modules/plugin-error": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
+ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
+ "dev": true,
+ "dependencies": {
+ "ansi-cyan": "^0.1.1",
+ "ansi-red": "^0.1.1",
+ "arr-diff": "^1.0.1",
+ "arr-union": "^2.0.1",
+ "extend-shallow": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/process-nextick-args": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
+ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+ "dev": true
+ },
+ "node_modules/gulp-cache-bust/node_modules/readable-stream": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz",
+ "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~1.0.6",
+ "string_decoder": "~0.10.x",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/gulp-cache-bust/node_modules/string_decoder": {
+ "version": "0.10.31",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
+ "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=",
+ "dev": true
+ },
+ "node_modules/gulp-cache-bust/node_modules/through2": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz",
+ "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=",
+ "dev": true,
+ "dependencies": {
+ "readable-stream": "~2.0.0",
+ "xtend": "~4.0.0"
+ }
+ },
+ "node_modules/gulp-concat": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz",
"integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=",
"dev": true,
- "requires": {
+ "dependencies": {
"concat-with-sourcemaps": "^1.0.0",
"through2": "^2.0.0",
"vinyl": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "gulp-if": {
+ "node_modules/gulp-if": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-3.0.0.tgz",
"integrity": "sha512-fCUEngzNiEZEK2YuPm+sdMpO6ukb8+/qzbGfJBXyNOXz85bCG7yBI+pPSl+N90d7gnLvMsarthsAImx0qy7BAw==",
"dev": true,
- "requires": {
+ "dependencies": {
"gulp-match": "^1.1.0",
"ternary-stream": "^3.0.0",
"through2": "^3.0.1"
- },
+ }
+ },
+ "node_modules/gulp-if/node_modules/through2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
+ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+ "dev": true,
"dependencies": {
- "through2": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
- "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.4",
- "readable-stream": "2 || 3"
- }
- }
+ "inherits": "^2.0.4",
+ "readable-stream": "2 || 3"
}
},
- "gulp-match": {
+ "node_modules/gulp-match": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.1.0.tgz",
"integrity": "sha512-DlyVxa1Gj24DitY2OjEsS+X6tDpretuxD6wTfhXE/Rw2hweqc1f6D/XtsJmoiCwLWfXgR87W9ozEityPCVzGtQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"minimatch": "^3.0.3"
}
},
- "gulp-minify": {
+ "node_modules/gulp-minify": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/gulp-minify/-/gulp-minify-3.1.0.tgz",
"integrity": "sha512-ixF41aYg+NQikI8hpoHdEclYcQkbGdXQu1CBdHaU7Epg8H6e8d2jWXw1+rBPgYwl/XpKgjHj7NI6gkhoSNSSAg==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-colors": "^1.0.1",
"minimatch": "^3.0.2",
"plugin-error": "^0.1.2",
"terser": "^3.7.6",
"through2": "^2.0.3",
"vinyl": "^2.1.0"
+ }
+ },
+ "node_modules/gulp-minify/node_modules/arr-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
+ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
+ "dev": true,
+ "dependencies": {
+ "arr-flatten": "^1.0.1",
+ "array-slice": "^0.2.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-minify/node_modules/arr-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
+ "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-minify/node_modules/array-slice": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
+ "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-minify/node_modules/extend-shallow": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
+ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^1.1.0"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-minify/node_modules/kind-of": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
+ "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-minify/node_modules/plugin-error": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
+ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
+ "dev": true,
"dependencies": {
- "arr-diff": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz",
- "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=",
- "dev": true,
- "requires": {
- "arr-flatten": "^1.0.1",
- "array-slice": "^0.2.3"
- }
- },
- "arr-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz",
- "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=",
- "dev": true
- },
- "array-slice": {
- "version": "0.2.3",
- "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz",
- "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=",
- "dev": true
- },
- "extend-shallow": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz",
- "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=",
- "dev": true,
- "requires": {
- "kind-of": "^1.1.0"
- }
- },
- "kind-of": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz",
- "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=",
- "dev": true
- },
- "plugin-error": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz",
- "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=",
- "dev": true,
- "requires": {
- "ansi-cyan": "^0.1.1",
- "ansi-red": "^0.1.1",
- "arr-diff": "^1.0.1",
- "arr-union": "^2.0.1",
- "extend-shallow": "^1.1.2"
- }
- }
- }
- },
- "gulp-replace": {
+ "ansi-cyan": "^0.1.1",
+ "ansi-red": "^0.1.1",
+ "arr-diff": "^1.0.1",
+ "arr-union": "^2.0.1",
+ "extend-shallow": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-replace": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/gulp-replace/-/gulp-replace-1.1.3.tgz",
"integrity": "sha512-HcPHpWY4XdF8zxYkDODHnG2+7a3nD/Y8Mfu3aBgMiCFDW3X2GiOKXllsAmILcxe3KZT2BXoN18WrpEFm48KfLQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"@types/node": "^14.14.41",
"@types/vinyl": "^2.0.4",
"istextorbinary": "^3.0.0",
"replacestream": "^4.0.3",
"yargs-parser": ">=5.0.0-security.0"
+ },
+ "engines": {
+ "node": ">=10"
}
},
- "gulp-useref": {
+ "node_modules/gulp-useref": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/gulp-useref/-/gulp-useref-4.0.1.tgz",
"integrity": "sha512-+FjOGvvlCiUTbIjDQ0CAz8sQC3zkq3n1FqG6HR3njvcKQ9rNPIsHhcE5nUah4IHthKOHMPsnUBtE71nZp+dHAg==",
"dev": true,
- "requires": {
+ "dependencies": {
"event-stream": "^4.0.1",
"extend": "^3.0.2",
"glob": "^7.1.6",
@@ -1686,440 +2005,584 @@
"useref": "^1.4.3",
"vinyl-fs": "^3.0.3"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/gulp-useref/node_modules/through2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
+ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+ "dev": true,
"dependencies": {
- "through2": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
- "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.4",
- "readable-stream": "2 || 3"
- }
- }
+ "inherits": "^2.0.4",
+ "readable-stream": "2 || 3"
}
},
- "gulplog": {
+ "node_modules/gulp/node_modules/gulp-cli": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.3.0.tgz",
+ "integrity": "sha512-zzGBl5fHo0EKSXsHzjspp3y5CONegCm8ErO5Qh0UzFzk2y4tMvzLWhoDokADbarfZRL2pGpRp7yt6gfJX4ph7A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-colors": "^1.0.1",
+ "archy": "^1.0.0",
+ "array-sort": "^1.0.0",
+ "color-support": "^1.1.3",
+ "concat-stream": "^1.6.0",
+ "copy-props": "^2.0.1",
+ "fancy-log": "^1.3.2",
+ "gulplog": "^1.0.0",
+ "interpret": "^1.4.0",
+ "isobject": "^3.0.1",
+ "liftoff": "^3.1.0",
+ "matchdep": "^2.0.0",
+ "mute-stdout": "^1.0.0",
+ "pretty-hrtime": "^1.0.0",
+ "replace-homedir": "^1.0.0",
+ "semver-greatest-satisfied-range": "^1.1.0",
+ "v8flags": "^3.2.0",
+ "yargs": "^7.1.0"
+ },
+ "bin": {
+ "gulp": "bin/gulp.js"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/gulplog": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
"integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=",
"dev": true,
- "requires": {
+ "dependencies": {
"glogg": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "has": {
+ "node_modules/has": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"dev": true,
- "requires": {
+ "dependencies": {
"function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
}
},
- "has-symbols": {
+ "node_modules/has-symbols": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
},
- "has-value": {
+ "node_modules/has-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
"integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=",
"dev": true,
- "requires": {
+ "dependencies": {
"get-value": "^2.0.6",
"has-values": "^1.0.0",
"isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "has-values": {
+ "node_modules/has-values": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
"integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=",
"dev": true,
- "requires": {
+ "dependencies": {
"is-number": "^3.0.0",
"kind-of": "^4.0.0"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/has-values/node_modules/kind-of": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
+ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
+ "dev": true,
"dependencies": {
- "kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "homedir-polyfill": {
+ "node_modules/homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
"integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==",
"dev": true,
- "requires": {
+ "dependencies": {
"parse-passwd": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "hosted-git-info": {
+ "node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
- "htmlparser2": {
+ "node_modules/htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
"integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"domelementtype": "^1.3.1",
"domhandler": "^2.3.0",
"domutils": "^1.5.1",
"entities": "^1.1.1",
"inherits": "^2.0.1",
"readable-stream": "^3.1.1"
- },
+ }
+ },
+ "node_modules/htmlparser2/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
"dependencies": {
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- }
- }
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
- "inflight": {
+ "node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dev": true,
- "requires": {
+ "dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
- "inherits": {
+ "node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
- "ini": {
+ "node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true
},
- "interpret": {
+ "node_modules/interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "invert-kv": {
+ "node_modules/invert-kv": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "is-absolute": {
+ "node_modules/is-absolute": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
"integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-relative": "^1.0.0",
"is-windows": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-accessor-descriptor": {
+ "node_modules/is-accessor-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
"integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=",
+ "deprecated": "Please upgrade to v0.1.7",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^3.0.2"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-accessor-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
"dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-arrayish": {
+ "node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=",
"dev": true
},
- "is-binary-path": {
+ "node_modules/is-binary-path": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
"integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=",
"dev": true,
- "requires": {
+ "dependencies": {
"binary-extensions": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-buffer": {
+ "node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
},
- "is-core-module": {
+ "node_modules/is-core-module": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.2.0.tgz",
"integrity": "sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "is-data-descriptor": {
+ "node_modules/is-data-descriptor": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
"integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=",
+ "deprecated": "Please upgrade to v0.1.5",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^3.0.2"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-data-descriptor/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
"dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-descriptor": {
+ "node_modules/is-descriptor": {
"version": "0.1.6",
"resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
"integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-accessor-descriptor": "^0.1.6",
"is-data-descriptor": "^0.1.4",
"kind-of": "^5.0.0"
},
- "dependencies": {
- "kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true
- }
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-descriptor/node_modules/kind-of": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
+ "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-extendable": {
+ "node_modules/is-extendable": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "is-extglob": {
+ "node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "is-fullwidth-code-point": {
+ "node_modules/is-fullwidth-code-point": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
"dev": true,
- "requires": {
+ "dependencies": {
"number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-glob": {
+ "node_modules/is-glob": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
"integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-negated-glob": {
+ "node_modules/is-negated-glob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz",
"integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "is-number": {
+ "node_modules/is-number": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^3.0.2"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
"dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-plain-object": {
+ "node_modules/is-plain-object": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"dev": true,
- "requires": {
+ "dependencies": {
"isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-relative": {
+ "node_modules/is-relative": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
"integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-unc-path": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-unc-path": {
+ "node_modules/is-unc-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
"integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"unc-path-regex": "^0.1.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "is-utf8": {
+ "node_modules/is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=",
"dev": true
},
- "is-valid-glob": {
+ "node_modules/is-valid-glob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz",
"integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "is-windows": {
+ "node_modules/is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "isarray": {
+ "node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
"dev": true
},
- "isexe": {
+ "node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
- "isobject": {
+ "node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
"integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "istextorbinary": {
+ "node_modules/istextorbinary": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/istextorbinary/-/istextorbinary-3.3.0.tgz",
"integrity": "sha512-Tvq1W6NAcZeJ8op+Hq7tdZ434rqnMx4CCZ7H0ff83uEloDvVbqAwaMTZcafKGJT0VHkYzuXUiCY4hlXQg6WfoQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"binaryextensions": "^2.2.0",
"textextensions": "^3.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
}
},
- "json-stable-stringify-without-jsonify": {
+ "node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
"dev": true
},
- "just-debounce": {
+ "node_modules/just-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz",
"integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=",
"dev": true
},
- "kind-of": {
+ "node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "last-run": {
+ "node_modules/last-run": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz",
"integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=",
"dev": true,
- "requires": {
+ "dependencies": {
"default-resolution": "^2.0.0",
"es6-weak-map": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "lazystream": {
+ "node_modules/lazystream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
"integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=",
"dev": true,
- "requires": {
+ "dependencies": {
"readable-stream": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.6.3"
}
},
- "lcid": {
+ "node_modules/lcid": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz",
"integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=",
"dev": true,
- "requires": {
+ "dependencies": {
"invert-kv": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "lead": {
+ "node_modules/lead": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz",
"integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=",
"dev": true,
- "requires": {
+ "dependencies": {
"flush-write-stream": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "liftoff": {
+ "node_modules/liftoff": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/liftoff/-/liftoff-3.1.0.tgz",
"integrity": "sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog==",
"dev": true,
- "requires": {
+ "dependencies": {
"extend": "^3.0.0",
"findup-sync": "^3.0.0",
"fined": "^1.0.1",
@@ -2128,181 +2591,204 @@
"object.map": "^1.0.0",
"rechoir": "^0.6.2",
"resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">= 0.8"
}
},
- "load-json-file": {
+ "node_modules/load-json-file": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=",
"dev": true,
- "requires": {
+ "dependencies": {
"graceful-fs": "^4.1.2",
"parse-json": "^2.2.0",
"pify": "^2.0.0",
"pinkie-promise": "^2.0.0",
"strip-bom": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "lodash.assignin": {
+ "node_modules/lodash.assignin": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
"integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=",
"dev": true
},
- "lodash.bind": {
+ "node_modules/lodash.bind": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
"integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=",
"dev": true
},
- "lodash.defaults": {
+ "node_modules/lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=",
"dev": true
},
- "lodash.filter": {
+ "node_modules/lodash.filter": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
"integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=",
"dev": true
},
- "lodash.flatten": {
+ "node_modules/lodash.flatten": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=",
"dev": true
},
- "lodash.foreach": {
+ "node_modules/lodash.foreach": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
"integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=",
"dev": true
},
- "lodash.map": {
+ "node_modules/lodash.map": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
"integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=",
"dev": true
},
- "lodash.merge": {
+ "node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
- "lodash.pick": {
+ "node_modules/lodash.pick": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
"integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=",
+ "deprecated": "This package is deprecated. Use destructuring assignment syntax instead.",
"dev": true
},
- "lodash.reduce": {
+ "node_modules/lodash.reduce": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
"integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=",
"dev": true
},
- "lodash.reject": {
+ "node_modules/lodash.reject": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
"integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=",
"dev": true
},
- "lodash.some": {
+ "node_modules/lodash.some": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
"integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=",
"dev": true
},
- "make-iterator": {
+ "node_modules/make-iterator": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz",
"integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "map-cache": {
+ "node_modules/map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
"integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "map-stream": {
+ "node_modules/map-stream": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz",
"integrity": "sha1-ih8HiW2CsQkmvTdEokIACfiJdKg=",
"dev": true
},
- "map-visit": {
+ "node_modules/map-visit": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
"integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=",
"dev": true,
- "requires": {
+ "dependencies": {
"object-visit": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "matchdep": {
+ "node_modules/matchdep": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz",
"integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=",
"dev": true,
- "requires": {
+ "dependencies": {
"findup-sync": "^2.0.0",
"micromatch": "^3.0.4",
"resolve": "^1.4.0",
"stack-trace": "0.0.10"
},
+ "engines": {
+ "node": ">= 0.10.0"
+ }
+ },
+ "node_modules/matchdep/node_modules/findup-sync": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
+ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
+ "dev": true,
+ "dependencies": {
+ "detect-file": "^1.0.0",
+ "is-glob": "^3.1.0",
+ "micromatch": "^3.0.4",
+ "resolve-dir": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/matchdep/node_modules/is-glob": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
+ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
+ "dev": true,
"dependencies": {
- "findup-sync": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz",
- "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=",
- "dev": true,
- "requires": {
- "detect-file": "^1.0.0",
- "is-glob": "^3.1.0",
- "micromatch": "^3.0.4",
- "resolve-dir": "^1.0.1"
- }
- },
- "is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=",
- "dev": true,
- "requires": {
- "is-extglob": "^2.1.0"
- }
- }
- }
- },
- "md5": {
+ "is-extglob": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/md5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.2.1.tgz",
"integrity": "sha1-U6s41f48iJG6RlMp6iP6wFQBJvk=",
"dev": true,
- "requires": {
+ "dependencies": {
"charenc": "~0.0.1",
"crypt": "~0.0.1",
"is-buffer": "~1.1.1"
}
},
- "merge-stream": {
+ "node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
"dev": true
},
- "micromatch": {
+ "node_modules/micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
"integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
"braces": "^2.3.1",
@@ -2316,78 +2802,94 @@
"regex-not": "^1.0.0",
"snapdragon": "^0.8.1",
"to-regex": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "minimatch": {
+ "node_modules/minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
- "requires": {
+ "dependencies": {
"brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
}
},
- "minimist": {
+ "node_modules/minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
- "mixin-deep": {
+ "node_modules/mixin-deep": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
"integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
"dev": true,
- "requires": {
+ "dependencies": {
"for-in": "^1.0.2",
"is-extendable": "^1.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/mixin-deep/node_modules/is-extendable": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
+ "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
+ "dev": true,
"dependencies": {
- "is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "requires": {
- "is-plain-object": "^2.0.4"
- }
- }
+ "is-plain-object": "^2.0.4"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "mkdirp": {
+ "node_modules/mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"minimist": "^1.2.5"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
}
},
- "ms": {
+ "node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
},
- "mute-stdout": {
+ "node_modules/mute-stdout": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz",
"integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "nan": {
+ "node_modules/nan": {
"version": "2.14.2",
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
"dev": true,
"optional": true
},
- "nanomatch": {
+ "node_modules/nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
"integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-diff": "^4.0.0",
"array-unique": "^0.3.2",
"define-property": "^2.0.2",
@@ -2399,393 +2901,496 @@
"regex-not": "^1.0.0",
"snapdragon": "^0.8.1",
"to-regex": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "next-tick": {
+ "node_modules/next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true
},
- "normalize-package-data": {
+ "node_modules/normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
"dev": true,
- "requires": {
+ "dependencies": {
"hosted-git-info": "^2.1.4",
"resolve": "^1.10.0",
"semver": "2 || 3 || 4 || 5",
"validate-npm-package-license": "^3.0.1"
}
},
- "normalize-path": {
+ "node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "now-and-later": {
+ "node_modules/now-and-later": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.1.tgz",
"integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"once": "^1.3.2"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "nth-check": {
+ "node_modules/nth-check": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
"dev": true,
- "requires": {
+ "dependencies": {
"boolbase": "~1.0.0"
}
},
- "number-is-nan": {
+ "node_modules/number-is-nan": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "object-assign": {
+ "node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "object-copy": {
+ "node_modules/object-copy": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
"integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=",
"dev": true,
- "requires": {
+ "dependencies": {
"copy-descriptor": "^0.1.0",
"define-property": "^0.2.5",
"kind-of": "^3.0.3"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-copy/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
- }
- },
- "object-keys": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
},
- "object-visit": {
+ "node_modules/object-visit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
"integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=",
"dev": true,
- "requires": {
+ "dependencies": {
"isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "object.assign": {
+ "node_modules/object.assign": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
"dev": true,
- "requires": {
+ "dependencies": {
"define-properties": "^1.1.2",
"function-bind": "^1.1.1",
"has-symbols": "^1.0.0",
"object-keys": "^1.0.11"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
- "object.defaults": {
+ "node_modules/object.defaults": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz",
"integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=",
"dev": true,
- "requires": {
+ "dependencies": {
"array-each": "^1.0.1",
"array-slice": "^1.0.0",
"for-own": "^1.0.0",
"isobject": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "object.map": {
+ "node_modules/object.map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz",
"integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=",
"dev": true,
- "requires": {
+ "dependencies": {
"for-own": "^1.0.0",
"make-iterator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "object.pick": {
+ "node_modules/object.pick": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
"integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=",
"dev": true,
- "requires": {
+ "dependencies": {
"isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "object.reduce": {
+ "node_modules/object.reduce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz",
"integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=",
"dev": true,
- "requires": {
+ "dependencies": {
"for-own": "^1.0.0",
"make-iterator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "once": {
+ "node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
- "requires": {
+ "dependencies": {
"wrappy": "1"
}
},
- "ordered-read-streams": {
+ "node_modules/ordered-read-streams": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz",
"integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=",
"dev": true,
- "requires": {
+ "dependencies": {
"readable-stream": "^2.0.1"
}
},
- "os-locale": {
+ "node_modules/os-locale": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
"dev": true,
- "requires": {
+ "dependencies": {
"lcid": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "os-tmpdir": {
+ "node_modules/os-tmpdir": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "parse-filepath": {
+ "node_modules/parse-filepath": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
"integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=",
"dev": true,
- "requires": {
+ "dependencies": {
"is-absolute": "^1.0.0",
"map-cache": "^0.2.0",
"path-root": "^0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8"
}
},
- "parse-json": {
+ "node_modules/parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
"dev": true,
- "requires": {
+ "dependencies": {
"error-ex": "^1.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "parse-node-version": {
+ "node_modules/parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "parse-passwd": {
+ "node_modules/parse-passwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz",
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "pascalcase": {
+ "node_modules/pascalcase": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
"integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "path-dirname": {
+ "node_modules/path-dirname": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
"integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=",
"dev": true
},
- "path-exists": {
+ "node_modules/path-exists": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=",
"dev": true,
- "requires": {
+ "dependencies": {
"pinkie-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "path-is-absolute": {
+ "node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "path-parse": {
+ "node_modules/path-parse": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
"dev": true
},
- "path-root": {
+ "node_modules/path-root": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
"integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=",
"dev": true,
- "requires": {
+ "dependencies": {
"path-root-regex": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "path-root-regex": {
+ "node_modules/path-root-regex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
"integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "path-type": {
+ "node_modules/path-type": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
"dev": true,
- "requires": {
+ "dependencies": {
"graceful-fs": "^4.1.2",
"pify": "^2.0.0",
"pinkie-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "pause-stream": {
+ "node_modules/pause-stream": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz",
"integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=",
"dev": true,
- "requires": {
+ "dependencies": {
"through": "~2.3"
}
},
- "pify": {
+ "node_modules/pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "pinkie": {
+ "node_modules/pinkie": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "pinkie-promise": {
+ "node_modules/pinkie-promise": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=",
"dev": true,
- "requires": {
+ "dependencies": {
"pinkie": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "plugin-error": {
+ "node_modules/plugin-error": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz",
"integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-colors": "^1.0.1",
"arr-diff": "^4.0.0",
"arr-union": "^3.1.0",
"extend-shallow": "^3.0.2"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "posix-character-classes": {
+ "node_modules/posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "pretty-hrtime": {
+ "node_modules/pretty-hrtime": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
},
- "process-nextick-args": {
+ "node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
"dev": true
},
- "pump": {
+ "node_modules/pump": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
"integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
"dev": true,
- "requires": {
+ "dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
- "pumpify": {
+ "node_modules/pumpify": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
"integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"duplexify": "^3.6.0",
"inherits": "^2.0.3",
"pump": "^2.0.0"
}
},
- "read-pkg": {
+ "node_modules/read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
"dev": true,
- "requires": {
+ "dependencies": {
"load-json-file": "^1.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "read-pkg-up": {
+ "node_modules/read-pkg-up": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz",
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=",
"dev": true,
- "requires": {
+ "dependencies": {
"find-up": "^1.0.0",
"read-pkg": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "readable-stream": {
+ "node_modules/readable-stream": {
"version": "2.3.7",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
"dev": true,
- "requires": {
+ "dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
@@ -2795,221 +3400,274 @@
"util-deprecate": "~1.0.1"
}
},
- "readdirp": {
+ "node_modules/readdirp": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
"integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"graceful-fs": "^4.1.11",
"micromatch": "^3.1.10",
"readable-stream": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10"
}
},
- "rechoir": {
+ "node_modules/rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=",
"dev": true,
- "requires": {
+ "dependencies": {
"resolve": "^1.1.6"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "regex-not": {
+ "node_modules/regex-not": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
"integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
"dev": true,
- "requires": {
+ "dependencies": {
"extend-shallow": "^3.0.2",
"safe-regex": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "remove-bom-buffer": {
+ "node_modules/remove-bom-buffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz",
"integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-buffer": "^1.1.5",
"is-utf8": "^0.2.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "remove-bom-stream": {
+ "node_modules/remove-bom-stream": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz",
"integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=",
"dev": true,
- "requires": {
+ "dependencies": {
"remove-bom-buffer": "^3.0.0",
"safe-buffer": "^5.1.0",
"through2": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "remove-trailing-separator": {
+ "node_modules/remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=",
"dev": true
},
- "repeat-element": {
+ "node_modules/repeat-element": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz",
"integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "repeat-string": {
+ "node_modules/repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10"
+ }
},
- "replace-ext": {
+ "node_modules/replace-ext": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.1.tgz",
"integrity": "sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "replace-homedir": {
+ "node_modules/replace-homedir": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz",
"integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=",
"dev": true,
- "requires": {
+ "dependencies": {
"homedir-polyfill": "^1.0.1",
"is-absolute": "^1.0.0",
"remove-trailing-separator": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "replacestream": {
+ "node_modules/replacestream": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/replacestream/-/replacestream-4.0.3.tgz",
"integrity": "sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA==",
"dev": true,
- "requires": {
+ "dependencies": {
"escape-string-regexp": "^1.0.3",
"object-assign": "^4.0.1",
"readable-stream": "^2.0.2"
}
},
- "require-directory": {
+ "node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "require-main-filename": {
+ "node_modules/require-main-filename": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
- "resolve": {
+ "node_modules/resolve": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.19.0.tgz",
"integrity": "sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==",
"dev": true,
- "requires": {
+ "dependencies": {
"is-core-module": "^2.1.0",
"path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "resolve-dir": {
+ "node_modules/resolve-dir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz",
"integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=",
"dev": true,
- "requires": {
+ "dependencies": {
"expand-tilde": "^2.0.0",
"global-modules": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "resolve-options": {
+ "node_modules/resolve-options": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz",
"integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=",
"dev": true,
- "requires": {
+ "dependencies": {
"value-or-function": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "resolve-url": {
+ "node_modules/resolve-url": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
+ "deprecated": "https://github.com/lydell/resolve-url#deprecated",
"dev": true
},
- "ret": {
+ "node_modules/ret": {
"version": "0.1.15",
"resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
"integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ }
},
- "safe-buffer": {
+ "node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
"dev": true
},
- "safe-regex": {
+ "node_modules/safe-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
"integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=",
"dev": true,
- "requires": {
+ "dependencies": {
"ret": "~0.1.10"
}
},
- "semver": {
+ "node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
},
- "semver-greatest-satisfied-range": {
+ "node_modules/semver-greatest-satisfied-range": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz",
"integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=",
"dev": true,
- "requires": {
+ "dependencies": {
"sver-compat": "^1.5.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "set-blocking": {
+ "node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
"dev": true
},
- "set-value": {
+ "node_modules/set-value": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
"integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
"dev": true,
- "requires": {
+ "dependencies": {
"extend-shallow": "^2.0.1",
"is-extendable": "^0.1.1",
"is-plain-object": "^2.0.3",
"split-string": "^3.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/set-value/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
"dependencies": {
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "snapdragon": {
+ "node_modules/snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
"integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
"dev": true,
- "requires": {
+ "dependencies": {
"base": "^0.11.1",
"debug": "^2.2.0",
"define-property": "^0.2.5",
@@ -3019,110 +3677,140 @@
"source-map-resolve": "^0.5.0",
"use": "^3.1.0"
},
- "dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- },
- "extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
- "dev": true,
- "requires": {
- "is-extendable": "^0.1.0"
- }
- }
- }
- },
- "snapdragon-node": {
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
"integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
"dev": true,
- "requires": {
+ "dependencies": {
"define-property": "^1.0.0",
"isobject": "^3.0.0",
"snapdragon-util": "^3.0.1"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
+ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
+ "dev": true,
+ "dependencies": {
+ "is-descriptor": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/is-accessor-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
+ "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/is-data-descriptor": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
+ "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
+ "deprecated": "Please upgrade to v1.0.1",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-node/node_modules/is-descriptor": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
+ "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^1.0.0"
- }
- },
- "is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "dev": true,
- "requires": {
- "kind-of": "^6.0.0"
- }
- },
- "is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "requires": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- }
- }
- }
- },
- "snapdragon-util": {
+ "is-accessor-descriptor": "^1.0.0",
+ "is-data-descriptor": "^1.0.0",
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-util": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
"integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^3.2.0"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon-util/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
+ "dependencies": {
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
+ "dependencies": {
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/snapdragon/node_modules/extend-shallow": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
+ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
+ "dev": true,
"dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
+ "is-extendable": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "source-map": {
+ "node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "source-map-resolve": {
+ "node_modules/source-map-resolve": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
"integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
+ "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
"dev": true,
- "requires": {
+ "dependencies": {
"atob": "^2.1.2",
"decode-uri-component": "^0.2.0",
"resolve-url": "^0.2.1",
@@ -3130,386 +3818,452 @@
"urix": "^0.1.0"
}
},
- "source-map-support": {
+ "node_modules/source-map-support": {
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
- "requires": {
+ "dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
- },
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
}
},
- "source-map-url": {
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-url": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz",
"integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=",
+ "deprecated": "See https://github.com/lydell/source-map-url#deprecated",
"dev": true
},
- "sparkles": {
+ "node_modules/sparkles": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
"integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "spdx-correct": {
+ "node_modules/spdx-correct": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
"integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
"dev": true,
- "requires": {
+ "dependencies": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
}
},
- "spdx-exceptions": {
+ "node_modules/spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
"dev": true
},
- "spdx-expression-parse": {
+ "node_modules/spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
- "requires": {
+ "dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
- "spdx-license-ids": {
+ "node_modules/spdx-license-ids": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz",
"integrity": "sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ==",
"dev": true
},
- "split": {
+ "node_modules/split": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz",
"integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==",
"dev": true,
- "requires": {
+ "dependencies": {
"through": "2"
+ },
+ "engines": {
+ "node": "*"
}
},
- "split-string": {
+ "node_modules/split-string": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
"integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
"dev": true,
- "requires": {
+ "dependencies": {
"extend-shallow": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "stack-trace": {
+ "node_modules/stack-trace": {
"version": "0.0.10",
"resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz",
"integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
},
- "static-extend": {
+ "node_modules/static-extend": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
"integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=",
"dev": true,
- "requires": {
+ "dependencies": {
"define-property": "^0.2.5",
"object-copy": "^0.1.0"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/static-extend/node_modules/define-property": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
+ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
+ "dev": true,
"dependencies": {
- "define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=",
- "dev": true,
- "requires": {
- "is-descriptor": "^0.1.0"
- }
- }
+ "is-descriptor": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "stream-combiner": {
+ "node_modules/stream-combiner": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz",
"integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=",
"dev": true,
- "requires": {
+ "dependencies": {
"duplexer": "~0.1.1",
"through": "~2.3.4"
}
},
- "stream-exhaust": {
+ "node_modules/stream-exhaust": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz",
"integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==",
"dev": true
},
- "stream-shift": {
+ "node_modules/stream-shift": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
"dev": true
},
- "string-width": {
+ "node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/string-width": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
"dev": true,
- "requires": {
+ "dependencies": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
"strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
- "dev": true,
- "requires": {
- "safe-buffer": "~5.1.0"
- }
- },
- "strip-ansi": {
+ "node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
"dev": true,
- "requires": {
+ "dependencies": {
"ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "strip-bom": {
+ "node_modules/strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=",
"dev": true,
- "requires": {
+ "dependencies": {
"is-utf8": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "sver-compat": {
+ "node_modules/sver-compat": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz",
"integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=",
"dev": true,
- "requires": {
+ "dependencies": {
"es6-iterator": "^2.0.1",
"es6-symbol": "^3.1.1"
}
},
- "temp-write": {
+ "node_modules/temp-write": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/temp-write/-/temp-write-2.1.0.tgz",
"integrity": "sha1-WYkJGODvCdVIqqNC9L00CdhATpY=",
"dev": true,
- "requires": {
+ "dependencies": {
"graceful-fs": "^4.1.2",
"mkdirp": "^0.5.0",
"os-tmpdir": "^1.0.0",
"pify": "^2.2.0",
"pinkie-promise": "^2.0.0",
"uuid": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "ternary-stream": {
+ "node_modules/ternary-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-3.0.0.tgz",
"integrity": "sha512-oIzdi+UL/JdktkT+7KU5tSIQjj8pbShj3OASuvDEhm0NT5lppsm7aXWAmAq4/QMaBIyfuEcNLbAQA+HpaISobQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"duplexify": "^4.1.1",
"fork-stream": "^0.0.4",
"merge-stream": "^2.0.0",
"through2": "^3.0.1"
+ }
+ },
+ "node_modules/ternary-stream/node_modules/duplexify": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz",
+ "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==",
+ "dev": true,
+ "dependencies": {
+ "end-of-stream": "^1.4.1",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "node_modules/ternary-stream/node_modules/readable-stream": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
+ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
},
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/ternary-stream/node_modules/through2": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
+ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
+ "dev": true,
"dependencies": {
- "duplexify": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.1.tgz",
- "integrity": "sha512-DY3xVEmVHTv1wSzKNbwoU6nVjzI369Y6sPoqfYr0/xlx3IdX2n94xIszTcjPO8W8ZIv0Wb0PXNcjuZyT4wiICA==",
- "dev": true,
- "requires": {
- "end-of-stream": "^1.4.1",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1",
- "stream-shift": "^1.0.0"
- }
- },
- "readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- }
- },
- "through2": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz",
- "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==",
- "dev": true,
- "requires": {
- "inherits": "^2.0.4",
- "readable-stream": "2 || 3"
- }
- }
- }
- },
- "terser": {
+ "inherits": "^2.0.4",
+ "readable-stream": "2 || 3"
+ }
+ },
+ "node_modules/terser": {
"version": "3.17.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz",
"integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"commander": "^2.19.0",
"source-map": "~0.6.1",
"source-map-support": "~0.5.10"
},
- "dependencies": {
- "source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
- }
+ "bin": {
+ "terser": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
}
},
- "textextensions": {
+ "node_modules/terser/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/textextensions": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/textextensions/-/textextensions-3.3.0.tgz",
"integrity": "sha512-mk82dS8eRABNbeVJrEiN5/UMSCliINAuz8mkUwH4SwslkNP//gbEzlWNS5au0z5Dpx40SQxzqZevZkn+WYJ9Dw==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://bevry.me/fund"
+ }
},
- "through": {
+ "node_modules/through": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
"dev": true
},
- "through2": {
+ "node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
- "through2-filter": {
+ "node_modules/through2-filter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
"integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
"dev": true,
- "requires": {
+ "dependencies": {
"through2": "~2.0.0",
"xtend": "~4.0.0"
}
},
- "time-stamp": {
+ "node_modules/time-stamp": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "to-absolute-glob": {
+ "node_modules/to-absolute-glob": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
"integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=",
"dev": true,
- "requires": {
+ "dependencies": {
"is-absolute": "^1.0.0",
"is-negated-glob": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "to-object-path": {
+ "node_modules/to-object-path": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
"integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=",
"dev": true,
- "requires": {
+ "dependencies": {
"kind-of": "^3.0.2"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/to-object-path/node_modules/kind-of": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+ "dev": true,
"dependencies": {
- "kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
- "dev": true,
- "requires": {
- "is-buffer": "^1.1.5"
- }
- }
+ "is-buffer": "^1.1.5"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "to-regex": {
+ "node_modules/to-regex": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
"integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
"dev": true,
- "requires": {
+ "dependencies": {
"define-property": "^2.0.2",
"extend-shallow": "^3.0.2",
"regex-not": "^1.0.2",
"safe-regex": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "to-regex-range": {
+ "node_modules/to-regex-range": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
"integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=",
"dev": true,
- "requires": {
+ "dependencies": {
"is-number": "^3.0.0",
"repeat-string": "^1.6.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "to-through": {
+ "node_modules/to-through": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz",
"integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=",
"dev": true,
- "requires": {
+ "dependencies": {
"through2": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "type": {
+ "node_modules/type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
"dev": true
},
- "typedarray": {
+ "node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true
},
- "unc-path-regex": {
+ "node_modules/unc-path-regex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
"integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "undertaker": {
+ "node_modules/undertaker": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.3.0.tgz",
"integrity": "sha512-/RXwi5m/Mu3H6IHQGww3GNt1PNXlbeCuclF2QYR14L/2CHPz3DFZkvB5hZ0N/QUkiXWCACML2jXViIQEQc2MLg==",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-flatten": "^1.0.1",
"arr-map": "^2.0.0",
"bach": "^1.0.0",
@@ -3520,157 +4274,195 @@
"object.defaults": "^1.0.0",
"object.reduce": "^1.0.0",
"undertaker-registry": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "undertaker-registry": {
+ "node_modules/undertaker-registry": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz",
"integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "union-value": {
+ "node_modules/union-value": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
"integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
"dev": true,
- "requires": {
+ "dependencies": {
"arr-union": "^3.1.0",
"get-value": "^2.0.6",
"is-extendable": "^0.1.1",
"set-value": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "unique-stream": {
+ "node_modules/unique-stream": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
"integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
"dev": true,
- "requires": {
+ "dependencies": {
"json-stable-stringify-without-jsonify": "^1.0.1",
"through2-filter": "^3.0.0"
}
},
- "unset-value": {
+ "node_modules/unset-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
"integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=",
"dev": true,
- "requires": {
+ "dependencies": {
"has-value": "^0.3.1",
"isobject": "^3.0.0"
},
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-value": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
+ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
+ "dev": true,
+ "dependencies": {
+ "get-value": "^2.0.3",
+ "has-values": "^0.1.4",
+ "isobject": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-value/node_modules/isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
+ "dev": true,
"dependencies": {
- "has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=",
- "dev": true,
- "requires": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "dependencies": {
- "isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=",
- "dev": true,
- "requires": {
- "isarray": "1.0.0"
- }
- }
- }
- },
- "has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
- "dev": true
- }
- }
- },
- "upath": {
+ "isarray": "1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/unset-value/node_modules/has-values": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
+ "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/upath": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=4",
+ "yarn": "*"
+ }
},
- "urix": {
+ "node_modules/urix": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
+ "deprecated": "Please see https://github.com/lydell/urix#deprecated",
"dev": true
},
- "use": {
+ "node_modules/use": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
- "useref": {
+ "node_modules/useref": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/useref/-/useref-1.4.3.tgz",
"integrity": "sha512-hX0qTEaDdzO3WfFl2KHQnSdaPSk8KqRaQ/nXXjBPrXzanew+12U/gm/Jt7zR978wtKMryOMXGoF0+qhYL2oseQ==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
},
- "util-deprecate": {
+ "node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true
},
- "uuid": {
+ "node_modules/uuid": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
"integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=",
+ "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"dev": true
},
- "v8flags": {
+ "node_modules/v8flags": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.2.0.tgz",
"integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==",
"dev": true,
- "requires": {
+ "dependencies": {
"homedir-polyfill": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "validate-npm-package-license": {
+ "node_modules/validate-npm-package-license": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
"dev": true,
- "requires": {
+ "dependencies": {
"spdx-correct": "^3.0.0",
"spdx-expression-parse": "^3.0.0"
}
},
- "value-or-function": {
+ "node_modules/value-or-function": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz",
"integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
},
- "vinyl": {
+ "node_modules/vinyl": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz",
"integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==",
"dev": true,
- "requires": {
+ "dependencies": {
"clone": "^2.1.1",
"clone-buffer": "^1.0.0",
"clone-stats": "^1.0.0",
"cloneable-readable": "^1.0.0",
"remove-trailing-separator": "^1.0.1",
"replace-ext": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "vinyl-fs": {
+ "node_modules/vinyl-fs": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz",
"integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==",
"dev": true,
- "requires": {
+ "dependencies": {
"fs-mkdirp-stream": "^1.0.0",
"glob-stream": "^6.1.0",
"graceful-fs": "^4.0.0",
@@ -3688,14 +4480,17 @@
"value-or-function": "^3.0.0",
"vinyl": "^2.0.0",
"vinyl-sourcemap": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
}
},
- "vinyl-sourcemap": {
+ "node_modules/vinyl-sourcemap": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz",
"integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=",
"dev": true,
- "requires": {
+ "dependencies": {
"append-buffer": "^1.0.2",
"convert-source-map": "^1.5.0",
"graceful-fs": "^4.1.6",
@@ -3704,67 +4499,80 @@
"remove-bom-buffer": "^3.0.0",
"vinyl": "^2.0.0"
},
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/vinyl-sourcemap/node_modules/normalize-path": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
+ "dev": true,
"dependencies": {
- "normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=",
- "dev": true,
- "requires": {
- "remove-trailing-separator": "^1.0.1"
- }
- }
+ "remove-trailing-separator": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "which": {
+ "node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
}
},
- "which-module": {
+ "node_modules/which-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=",
"dev": true
},
- "wrap-ansi": {
+ "node_modules/wrap-ansi": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
"dev": true,
- "requires": {
+ "dependencies": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
}
},
- "wrappy": {
+ "node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
- "xtend": {
+ "node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true
+ "dev": true,
+ "engines": {
+ "node": ">=0.4"
+ }
},
- "y18n": {
+ "node_modules/y18n": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
"integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==",
"dev": true
},
- "yargs": {
+ "node_modules/yargs": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.1.tgz",
"integrity": "sha512-huO4Fr1f9PmiJJdll5kwoS2e4GqzGSsMT3PPMpOwoVkOK8ckqAewMTZyA6LXVQWflleb/Z8oPBEvNsMft0XE+g==",
"dev": true,
- "requires": {
+ "dependencies": {
"camelcase": "^3.0.0",
"cliui": "^3.2.0",
"decamelize": "^1.1.1",
@@ -3780,12 +4588,12 @@
"yargs-parser": "5.0.0-security.0"
}
},
- "yargs-parser": {
+ "node_modules/yargs-parser": {
"version": "5.0.0-security.0",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0-security.0.tgz",
"integrity": "sha512-T69y4Ps64LNesYxeYGYPvfoMTt/7y1XtfpIslUeK4um+9Hu7hlGoRtaDLvdXb7+/tfq4opVa2HRY5xGip022rQ==",
"dev": true,
- "requires": {
+ "dependencies": {
"camelcase": "^3.0.0",
"object.assign": "^4.1.0"
}
From f4aee564def106d6f1e6dabbe15b4579c20403bc Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Wed, 23 Jul 2025 17:21:04 +1000
Subject: [PATCH 07/13] Fix parameters list being empty after refresh
---
src/js/editor.js | 10 +++-
src/js/modals.js | 143 ++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 149 insertions(+), 4 deletions(-)
diff --git a/src/js/editor.js b/src/js/editor.js
index b6992c93..09cb545d 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -751,11 +751,17 @@ if (typeof module !== 'undefined' && module.exports) {
}
function parameters(){
- // Refresh the parameters list before opening
+ if (!editor.modal || !editor.modal.parameters) {
+ console.error('editor.modal.parameters is not available');
+ return;
+ }
+
+ editor.modal.parameters.open();
+
+ // Ensure the parameters list is rendered when modal opens
if (editor.modal.parameters.renderParametersList) {
editor.modal.parameters.renderParametersList();
}
- editor.modal.parameters.open();
}
function loadFromUrl(url, cb){
diff --git a/src/js/modals.js b/src/js/modals.js
index cbecda6d..4c192c7c 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -347,8 +347,7 @@ editor.modal = {
}
}
- // Store the render function on the modal object so it can be called later
- modal.renderParametersList = renderParametersList;
+ // Note: renderParametersList will be attached to the modal instance after construction
// Show parameter form
function showParameterForm(isEdit = false, parameterId = null) {
@@ -606,4 +605,144 @@ editor.modal = {
});
}
})
+};
+
+// Attach renderParametersList function to the actual modal instance after construction
+editor.modal.parameters.renderParametersList = function() {
+ const parametersContainer = editor.modal.parameters.el.querySelector('#parameters-container');
+ const parametersTable = editor.modal.parameters.el.querySelector('#parameters-table');
+ const parametersEmpty = editor.modal.parameters.el.querySelector('#parameters-empty');
+ const parametersTBody = editor.modal.parameters.el.querySelector('#parameters-tbody');
+
+ const parameters = editor.parametersManager.getParameters();
+ const paramIds = Object.keys(parameters);
+
+ if (paramIds.length === 0) {
+ parametersTable.style.display = 'none';
+ parametersEmpty.style.display = 'block';
+ } else {
+ parametersTable.style.display = 'table';
+ parametersEmpty.style.display = 'none';
+
+ parametersTBody.innerHTML = '';
+
+ // Group parameters by parametric clone groups
+ const cloneGroups = {};
+ const regularParams = [];
+
+ paramIds.forEach(id => {
+ const param = parameters[id];
+ // Check if this is a parametric clone parameter by looking for the timestamp pattern
+ const timestampMatch = param.name.match(/^clone_(cols|rows|spacing_x|spacing_y)_(\d+)$/);
+ if (timestampMatch) {
+ const timestamp = timestampMatch[2];
+ if (!cloneGroups[timestamp]) {
+ cloneGroups[timestamp] = {
+ cols: null,
+ rows: null,
+ spacing_x: null,
+ spacing_y: null
+ };
+ }
+ cloneGroups[timestamp][timestampMatch[1]] = { id, param };
+ } else {
+ regularParams.push({ id, param });
+ }
+ });
+
+ // Render regular parameters first
+ regularParams.forEach(({ id, param }) => {
+ const row = document.createElement('tr');
+ row.style.borderBottom = '1px solid #eee';
+
+ row.innerHTML =
+ '@' + param.name + ' ' +
+ '' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
+ '' + param.defaultValue + ' ' +
+ '' +
+ 'Edit ' +
+ 'Delete ' +
+ ' ';
+
+ parametersTBody.appendChild(row);
+ });
+
+ // Add separator if we have both regular params and clone groups
+ if (regularParams.length > 0 && Object.keys(cloneGroups).length > 0) {
+ const separatorRow = document.createElement('tr');
+ separatorRow.innerHTML = 'Parametric Clone Groups ';
+ parametersTBody.appendChild(separatorRow);
+ }
+
+ // Render parametric clone groups
+ Object.keys(cloneGroups).forEach(timestamp => {
+ const group = cloneGroups[timestamp];
+
+ // Create group header
+ const headerRow = document.createElement('tr');
+ headerRow.style.background = '#f5f5f5';
+ headerRow.innerHTML = 'Clone Group ' + timestamp + ' ';
+ parametersTBody.appendChild(headerRow);
+
+ // Render group parameters in order: cols, rows, spacing_x, spacing_y
+ ['cols', 'rows', 'spacing_x', 'spacing_y'].forEach(type => {
+ if (group[type]) {
+ const { id, param } = group[type];
+ const row = document.createElement('tr');
+ row.style.borderBottom = '1px solid #eee';
+ row.style.paddingLeft = '16px';
+
+ // Friendly names for grid parameters
+ const friendlyNames = {
+ cols: 'Columns',
+ rows: 'Rows',
+ spacing_x: 'Horizontal Spacing',
+ spacing_y: 'Vertical Spacing'
+ };
+
+ row.innerHTML =
+ '└ ' + friendlyNames[type] + ' ' +
+ '' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
+ '' + param.defaultValue + ' ' +
+ '' +
+ 'Edit ' +
+ 'Delete ' +
+ ' ';
+
+ parametersTBody.appendChild(row);
+ }
+ });
+ });
+
+ // Add event listeners for edit/delete buttons (simplified for now)
+ editor.modal.parameters.el.querySelectorAll('.edit-param-btn').forEach(btn => {
+ btn.addEventListener('click', function() {
+ // TODO: Implement edit functionality
+ });
+ });
+
+ editor.modal.parameters.el.querySelectorAll('.delete-param-btn').forEach(btn => {
+ btn.addEventListener('click', function() {
+ const id = this.dataset.id;
+ const param = editor.parametersManager.getParameter(id);
+ if (param && confirm("Are you sure you want to delete parameter \"@" + param.name + "\"?")) {
+ try {
+ editor.parametersManager.deleteParameter(id);
+ editor.modal.parameters.renderParametersList(); // Re-render after deletion
+
+ // Update property validation autocomplete
+ if (editor.propertyValidation) {
+ editor.propertyValidation.addParameterAutocomplete();
+ }
+ } catch (error) {
+ alert('Error deleting parameter: ' + error.message);
+ }
+ }
+ });
+ });
+ }
};
\ No newline at end of file
From 168b76f8e1ff399e4dbd807ea5d5bbdc19ddd1ca Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Thu, 24 Jul 2025 10:30:41 +1000
Subject: [PATCH 08/13] Change parametric clone inputs to objects, improve
behaviour
---
src/js/ContextMenu.js | 9 ++
src/js/Menu.js | 9 ++
src/js/Parameters.js | 1 +
src/js/editor.js | 96 ++++++-------
src/js/modals.js | 323 ++++++++++++++++++++++++++++++++++++------
src/js/svgcanvas.js | 52 ++++---
6 files changed, 379 insertions(+), 111 deletions(-)
diff --git a/src/js/ContextMenu.js b/src/js/ContextMenu.js
index 26fa50e4..5138423b 100644
--- a/src/js/ContextMenu.js
+++ b/src/js/ContextMenu.js
@@ -83,6 +83,15 @@ MD.ContextMenu = function(){
if (isParametricClone) {
editor.editParametricClone(selectedElements[0]);
} else {
+ // Clear any flags when opening from context menu
+ setTimeout(() => {
+ editor.modal.parametricClone.el.removeAttribute('data-opened-from-params');
+ // Clear the name field for new clones
+ const nameInput = editor.modal.parametricClone.el.querySelector('#clone-name');
+ if (nameInput) {
+ nameInput.value = '';
+ }
+ }, 50);
editor.modal.parametricClone.open();
}
break;
diff --git a/src/js/Menu.js b/src/js/Menu.js
index 4c494a59..76db10f4 100644
--- a/src/js/Menu.js
+++ b/src/js/Menu.js
@@ -9,6 +9,15 @@ MD.Menu = function(){
$('#tool_group').on("click", editor.groupSelected);
$('#tool_ungroup').on("click", editor.ungroupSelected);
$('#tool_parametric_clone').on("click", function() {
+ // Clear any flags when opening from menu
+ setTimeout(() => {
+ editor.modal.parametricClone.el.removeAttribute('data-opened-from-params');
+ // Clear the name field for new clones
+ const nameInput = editor.modal.parametricClone.el.querySelector('#clone-name');
+ if (nameInput) {
+ nameInput.value = '';
+ }
+ }, 50);
editor.modal.parametricClone.open();
});
if (window.location.host === "editor.method.ac") {
diff --git a/src/js/Parameters.js b/src/js/Parameters.js
index df05103e..c035e43b 100644
--- a/src/js/Parameters.js
+++ b/src/js/Parameters.js
@@ -12,6 +12,7 @@ MD.Parameters = function(){
color: { label: 'Color', defaultValue: '#000000' },
boolean: { label: 'Boolean', defaultValue: false },
equation: { label: 'Equation', defaultValue: '0' },
+ clone_config: { label: 'Clone Configuration', defaultValue: { num_cols: 3, num_rows: 2, spacing_x: 50, spacing_y: 50 } },
grid_cols: { label: 'Grid Columns', defaultValue: 3 },
grid_rows: { label: 'Grid Rows', defaultValue: 2 },
grid_spacing_x: { label: 'Horizontal Spacing', defaultValue: 50 },
diff --git a/src/js/editor.js b/src/js/editor.js
index 09cb545d..0026c9cf 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -400,14 +400,11 @@ MD.Editor = function(){
const cloneHelperFunctions = [];
cloneGroups.forEach((cloneGroup, index) => {
- const colsParam = cloneGroup.getAttribute('data-cols-param');
- const rowsParam = cloneGroup.getAttribute('data-rows-param');
- const spacingXParam = cloneGroup.getAttribute('data-spacing-x-param');
- const spacingYParam = cloneGroup.getAttribute('data-spacing-y-param');
+ const cloneParam = cloneGroup.getAttribute('data-clone-param');
// Find template group
const templateGroup = cloneGroup.querySelector('[data-template="true"]');
- if (templateGroup) {
+ if (templateGroup && cloneParam) {
// Get template elements as string
const templateElements = Array.from(templateGroup.children).map(child => {
return new XMLSerializer().serializeToString(child);
@@ -419,10 +416,11 @@ MD.Editor = function(){
// Create helper function
const helperFunction = `
function ${funcName}() {
- const cols = ${colsParam};
- const rows = ${rowsParam};
- const spacingX = ${spacingXParam};
- const spacingY = ${spacingYParam};
+ const config = ${cloneParam};
+ const cols = config.num_cols;
+ const rows = config.num_rows;
+ const spacingX = config.spacing_x;
+ const spacingY = config.spacing_y;
let elements = '';
for (let row = 0; row < rows; row++) {
@@ -499,6 +497,9 @@ MD.Editor = function(){
defaultValue = `"${defaultValue}"`;
} else if (param.type === 'boolean') {
defaultValue = defaultValue === 'true' || defaultValue === true ? 'true' : 'false';
+ } else if (param.type === 'clone_config' && typeof defaultValue === 'object') {
+ // Serialize clone config objects properly
+ defaultValue = JSON.stringify(defaultValue);
}
return defaultValue;
@@ -529,7 +530,7 @@ MD.Editor = function(){
const hasAnyParams = hasInputParams || hasEquationParams;
const inputParamComment = hasInputParams
- ? inputParams.map(name => ` * @param {${paramMap[name].type}} ${name} - Default: ${paramMap[name].defaultValue}`).join('\n')
+ ? inputParams.map((name, i) => ` * @param {${paramMap[name].type}} ${name} - Default: ${paramDefaults[i]}`).join('\n')
: '';
const equationParamComment = hasEquationParams
? equationParams.map(name => ` * @calculated {number} ${name} - Equation: ${paramMap[name].defaultValue}`).join('\n')
@@ -550,6 +551,7 @@ MD.Editor = function(){
'color': 'String',
'boolean': 'Boolean',
'equation': 'Number',
+ 'clone_config': 'Object',
'grid_cols': 'Number',
'grid_rows': 'Number',
'grid_spacing_x': 'Number',
@@ -630,7 +632,7 @@ if (typeof module !== 'undefined' && module.exports) {
}
}
- function createParametricClone(cols, rows, spacingX, spacingY) {
+ function createParametricClone(cloneName, cols, rows, spacingX, spacingY) {
// Check if we have selected elements
const selectedElements = svgCanvas.getSelectedElems();
if (!selectedElements || selectedElements.length === 0 || !selectedElements[0]) {
@@ -638,27 +640,22 @@ if (typeof module !== 'undefined' && module.exports) {
return;
}
- // Generate unique parameter names based on timestamp
- const timestamp = Date.now();
- const colsParamName = `clone_cols_${timestamp}`;
- const rowsParamName = `clone_rows_${timestamp}`;
- const spacingXParamName = `clone_spacing_x_${timestamp}`;
- const spacingYParamName = `clone_spacing_y_${timestamp}`;
-
try {
- // Add the grid parameters to the parameter system
- editor.parametersManager.addParameter(colsParamName, 'grid_cols', cols, 'Number of columns in the grid');
- editor.parametersManager.addParameter(rowsParamName, 'grid_rows', rows, 'Number of rows in the grid');
- editor.parametersManager.addParameter(spacingXParamName, 'grid_spacing_x', spacingX, 'Horizontal spacing between elements');
- editor.parametersManager.addParameter(spacingYParamName, 'grid_spacing_y', spacingY, 'Vertical spacing between elements');
+ // Create the clone configuration object
+ const cloneConfig = {
+ num_cols: cols,
+ num_rows: rows,
+ spacing_x: spacingX,
+ spacing_y: spacingY
+ };
+
+ // Add the clone configuration parameter to the parameter system
+ editor.parametersManager.addParameter(cloneName, 'clone_config', cloneConfig, `Configuration for ${cloneName} clone group`);
// Create the parametric clone group using SVG canvas
const cloneGroupId = svgCanvas.createParametricCloneGroup(
selectedElements,
- colsParamName,
- rowsParamName,
- spacingXParamName,
- spacingYParamName
+ cloneName
);
if (cloneGroupId) {
@@ -670,7 +667,7 @@ if (typeof module !== 'undefined' && module.exports) {
}
saveCanvas();
- alert(`Parametric clone created with ${cols}×${rows} grid pattern.`);
+ alert(`Parametric clone "${cloneName}" created with ${cols}×${rows} grid pattern.`);
}
} catch (error) {
alert('Error creating parametric clone: ' + error.message);
@@ -683,28 +680,29 @@ if (typeof module !== 'undefined' && module.exports) {
return;
}
- // Get parameter names from the clone group
- const colsParam = cloneGroup.getAttribute('data-cols-param');
- const rowsParam = cloneGroup.getAttribute('data-rows-param');
- const spacingXParam = cloneGroup.getAttribute('data-spacing-x-param');
- const spacingYParam = cloneGroup.getAttribute('data-spacing-y-param');
+ // Get parameter name from the clone group
+ const cloneParam = cloneGroup.getAttribute('data-clone-param');
- if (!colsParam || !rowsParam || !spacingXParam || !spacingYParam) {
+ if (!cloneParam) {
alert('Parametric clone data is corrupted.');
return;
}
- // Get current parameter values
- const colsParamObj = editor.parametersManager.getParameterByName(colsParam);
- const rowsParamObj = editor.parametersManager.getParameterByName(rowsParam);
- const spacingXParamObj = editor.parametersManager.getParameterByName(spacingXParam);
- const spacingYParamObj = editor.parametersManager.getParameterByName(spacingYParam);
+ // Get current parameter value
+ const cloneParamObj = editor.parametersManager.getParameterByName(cloneParam);
- if (!colsParamObj || !rowsParamObj || !spacingXParamObj || !spacingYParamObj) {
- alert('Could not find associated parameters for this parametric clone.');
+ if (!cloneParamObj || cloneParamObj.type !== 'clone_config') {
+ alert('Could not find associated clone configuration parameter for this parametric clone.');
return;
}
+ // Extract values from the configuration object
+ const config = cloneParamObj.defaultValue;
+ const cols = config.num_cols || 3;
+ const rows = config.num_rows || 2;
+ const spacingX = config.spacing_x || 50;
+ const spacingY = config.spacing_y || 50;
+
// Set up the modal with current values
const modal = editor.modal.parametricClone;
modal.open();
@@ -712,17 +710,15 @@ if (typeof module !== 'undefined' && module.exports) {
// Pre-populate the form with current values
setTimeout(() => {
const modalEl = modal.el;
- modalEl.querySelector('#clone-cols').value = colsParamObj.defaultValue;
- modalEl.querySelector('#clone-rows').value = rowsParamObj.defaultValue;
- modalEl.querySelector('#clone-spacing-x').value = spacingXParamObj.defaultValue;
- modalEl.querySelector('#clone-spacing-y').value = spacingYParamObj.defaultValue;
+ modalEl.querySelector('#clone-name').value = cloneParam;
+ modalEl.querySelector('#clone-cols').value = cols;
+ modalEl.querySelector('#clone-rows').value = rows;
+ modalEl.querySelector('#clone-spacing-x').value = spacingX;
+ modalEl.querySelector('#clone-spacing-y').value = spacingY;
- // Store the parameter names for updating
+ // Store the parameter name and clone group ID for updating
modalEl.setAttribute('data-editing-clone', 'true');
- modalEl.setAttribute('data-cols-param', colsParam);
- modalEl.setAttribute('data-rows-param', rowsParam);
- modalEl.setAttribute('data-spacing-x-param', spacingXParam);
- modalEl.setAttribute('data-spacing-y-param', spacingYParam);
+ modalEl.setAttribute('data-clone-param', cloneParam);
modalEl.setAttribute('data-clone-group-id', cloneGroup.id);
}, 50);
}
diff --git a/src/js/modals.js b/src/js/modals.js
index 4c192c7c..9a535df3 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -104,7 +104,7 @@ editor.modal = {
- Cancel
+ Close
Add Parameter
@@ -145,7 +145,7 @@ editor.modal = {
Cancel
+ style="background: #666; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; margin-right: 10px;">Close
Save
@@ -272,7 +272,7 @@ editor.modal = {
row.innerHTML =
'@' + param.name + ' ' +
'' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
- '' + param.defaultValue + ' ' +
+ '' + formatParameterValue(param) + ' ' +
'' +
'Edit ' +
@@ -319,7 +319,7 @@ editor.modal = {
row.innerHTML =
' └ ' + friendlyNames[type] + ' ' +
'' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
- '' + param.defaultValue + ' ' +
+ '' + formatParameterValue(param) + ' ' +
'' +
'Edit ' +
@@ -389,7 +389,38 @@ editor.modal = {
// Edit parameter
function editParameter(id) {
- showParameterForm(true, id);
+ const param = editor.parametersManager.getParameter(id);
+
+ // If this is a clone configuration parameter, open the parametric clone modal instead
+ if (param && param.type === 'clone_config') {
+ // Find the clone group that uses this parameter
+ const cloneGroups = document.querySelectorAll('[data-parametric-clone="true"]');
+ let targetCloneGroup = null;
+
+ cloneGroups.forEach(group => {
+ if (group.getAttribute('data-clone-param') === param.name) {
+ targetCloneGroup = group;
+ }
+ });
+
+ if (targetCloneGroup) {
+ // Close the parameters modal
+ editor.modal.parameters.close();
+
+ // Mark that we're opening from parameters manager
+ setTimeout(() => {
+ editor.modal.parametricClone.el.setAttribute('data-opened-from-params', 'true');
+ }, 50);
+
+ // Open the parametric clone modal for editing
+ editor.editParametricClone(targetCloneGroup);
+ } else {
+ alert('Could not find the clone group associated with this parameter.');
+ }
+ } else {
+ // Regular parameter editing
+ showParameterForm(true, id);
+ }
}
// Delete parameter
@@ -448,8 +479,13 @@ editor.modal = {
}
try {
+ // Check for manual edit ID first, then fall back to regular editingParameterId
+ const manualEditId = el.getAttribute('data-manual-edit-id');
if (editingParameterId) {
editor.parametersManager.updateParameter(editingParameterId, name, type, defaultValue, description);
+ } else if (manualEditId) {
+ editor.parametersManager.updateParameter(manualEditId, name, type, defaultValue, description);
+ el.removeAttribute('data-manual-edit-id'); // Clean up
} else {
editor.parametersManager.addParameter(name, type, defaultValue, description);
}
@@ -465,6 +501,10 @@ editor.modal = {
alert('Error saving parameter: ' + error.message);
}
});
+
+ // Expose functions for use by renderParametersList
+ this.editParameter = editParameter;
+ this.showParameterForm = showParameterForm;
}
}),
@@ -476,6 +516,12 @@ editor.modal = {
+
+ Clone Group Name:
+
+
+
Columns:
@@ -504,7 +550,7 @@ editor.modal = {
Cancel
- Create Clone
+ Save
`,
@@ -512,58 +558,88 @@ editor.modal = {
js: function(el) {
// Handle cancel button
el.querySelector('#parametric-clone-cancel').addEventListener('click', function() {
+ const openedFromParams = el.getAttribute('data-opened-from-params') === 'true';
editor.modal.parametricClone.close();
+
+ // If opened from Parameters Manager, reopen it
+ if (openedFromParams) {
+ setTimeout(() => {
+ editor.modal.parameters.open();
+ }, 100);
+ }
});
// Handle create button
el.querySelector('#parametric-clone-create').addEventListener('click', function() {
+ const cloneName = el.querySelector('#clone-name').value.trim();
const cols = parseInt(el.querySelector('#clone-cols').value) || 3;
const rows = parseInt(el.querySelector('#clone-rows').value) || 2;
const spacingX = parseInt(el.querySelector('#clone-spacing-x').value) || 50;
const spacingY = parseInt(el.querySelector('#clone-spacing-y').value) || 50;
+ // Validate clone name
+ if (!cloneName) {
+ alert('Please enter a name for the clone group.');
+ return;
+ }
+
+ // Check if name is valid parameter name
+ if (!editor.parametersManager.isValidParameterName(cloneName)) {
+ alert('Invalid parameter name. Use only letters, numbers, and underscores. Cannot start with a number.');
+ return;
+ }
+
const isEditing = el.getAttribute('data-editing-clone') === 'true';
if (isEditing) {
// Update existing parametric clone
- const colsParam = el.getAttribute('data-cols-param');
- const rowsParam = el.getAttribute('data-rows-param');
- const spacingXParam = el.getAttribute('data-spacing-x-param');
- const spacingYParam = el.getAttribute('data-spacing-y-param');
+ const cloneParam = el.getAttribute('data-clone-param');
const cloneGroupId = el.getAttribute('data-clone-group-id');
try {
- // Update parameter values
const parametersManager = editor.parametersManager;
- const colsParamObj = parametersManager.getParameterByName(colsParam);
- const rowsParamObj = parametersManager.getParameterByName(rowsParam);
- const spacingXParamObj = parametersManager.getParameterByName(spacingXParam);
- const spacingYParamObj = parametersManager.getParameterByName(spacingYParam);
+ const cloneParamObj = parametersManager.getParameterByName(cloneParam);
- if (colsParamObj && rowsParamObj && spacingXParamObj && spacingYParamObj) {
- // Get parameter IDs from the parameters object
+ if (cloneParamObj) {
+ // Check if renaming to a different name that already exists
+ if (cloneName !== cloneParam && parametersManager.parameterExists(cloneName)) {
+ const existingParam = parametersManager.getParameterByName(cloneName);
+ if (existingParam && existingParam.type === 'clone_config') {
+ alert(`A parametric clone with the name "${cloneName}" already exists. Please choose a different name.`);
+ } else {
+ alert(`A parameter with the name "${cloneName}" already exists. Please choose a different name.`);
+ }
+ return;
+ }
+
+ // Get parameter ID
const parameters = parametersManager.getParameters();
- let colsId, rowsId, spacingXId, spacingYId;
+ let cloneParamId;
Object.keys(parameters).forEach(id => {
const param = parameters[id];
- if (param.name === colsParam) colsId = id;
- if (param.name === rowsParam) rowsId = id;
- if (param.name === spacingXParam) spacingXId = id;
- if (param.name === spacingYParam) spacingYId = id;
+ if (param.name === cloneParam) cloneParamId = id;
});
- if (colsId) parametersManager.updateParameter(colsId, colsParam, 'grid_cols', cols, colsParamObj.description);
- if (rowsId) parametersManager.updateParameter(rowsId, rowsParam, 'grid_rows', rows, rowsParamObj.description);
- if (spacingXId) parametersManager.updateParameter(spacingXId, spacingXParam, 'grid_spacing_x', spacingX, spacingXParamObj.description);
- if (spacingYId) parametersManager.updateParameter(spacingYId, spacingYParam, 'grid_spacing_y', spacingY, spacingYParamObj.description);
-
- // Regenerate the clone group
- if (typeof svgCanvas.updateParametricCloneGroup === 'function') {
- svgCanvas.updateParametricCloneGroup(cloneGroupId);
+ if (cloneParamId) {
+ const newConfig = { num_cols: cols, num_rows: rows, spacing_x: spacingX, spacing_y: spacingY };
+ parametersManager.updateParameter(cloneParamId, cloneName, 'clone_config', newConfig, cloneParamObj.description);
+
+ // Update the clone group's data attribute if name changed
+ if (cloneName !== cloneParam) {
+ const cloneGroup = svgedit.utilities.getElem(cloneGroupId);
+ if (cloneGroup) {
+ cloneGroup.setAttribute('data-clone-param', cloneName);
+ }
+ }
+
+ // Regenerate the clone group
+ if (typeof svgCanvas.updateParametricCloneGroup === 'function') {
+ svgCanvas.updateParametricCloneGroup(cloneGroupId);
+ }
+
+ alert('Parametric clone updated successfully.');
}
-
- alert('Parametric clone updated successfully.');
}
} catch (error) {
alert('Error updating parametric clone: ' + error.message);
@@ -571,22 +647,50 @@ editor.modal = {
// Clear editing state
el.removeAttribute('data-editing-clone');
- el.removeAttribute('data-cols-param');
- el.removeAttribute('data-rows-param');
- el.removeAttribute('data-spacing-x-param');
- el.removeAttribute('data-spacing-y-param');
+ el.removeAttribute('data-clone-param');
el.removeAttribute('data-clone-group-id');
} else {
+ // Check if parameter name already exists
+ if (editor.parametersManager.parameterExists(cloneName)) {
+ const existingParam = editor.parametersManager.getParameterByName(cloneName);
+ if (existingParam && existingParam.type === 'clone_config') {
+ alert(`A parametric clone with the name "${cloneName}" already exists. Please choose a different name.`);
+ } else {
+ alert(`A parameter with the name "${cloneName}" already exists. Please choose a different name.`);
+ }
+ return;
+ }
+
+ // Double-check: look for existing clone groups with this name
+ const existingCloneGroups = document.querySelectorAll('[data-parametric-clone="true"]');
+ let nameAlreadyUsed = false;
+ existingCloneGroups.forEach(group => {
+ if (group.getAttribute('data-clone-param') === cloneName) {
+ nameAlreadyUsed = true;
+ }
+ });
+
+ if (nameAlreadyUsed) {
+ alert(`A parametric clone with the name "${cloneName}" already exists in the canvas. Please choose a different name.`);
+ return;
+ }
+
// Create new parametric clone
if (typeof editor.createParametricClone === 'function') {
- editor.createParametricClone(cols, rows, spacingX, spacingY);
+ editor.createParametricClone(cloneName, cols, rows, spacingX, spacingY);
}
}
+ // Clear the flag before closing
+ el.removeAttribute('data-opened-from-params');
editor.modal.parametricClone.close();
});
// Ensure input fields are clickable (fix for modal z-index issues)
+ el.querySelector('#clone-name').addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
el.querySelector('#clone-cols').addEventListener('mousedown', function(e) {
e.stopPropagation();
this.focus();
@@ -607,6 +711,143 @@ editor.modal = {
})
};
+// Helper function to format parameter display values
+function formatParameterValue(param) {
+ if (param.type === 'clone_config' && typeof param.defaultValue === 'object') {
+ const config = param.defaultValue;
+ return `${config.num_cols || 1}×${config.num_rows || 1} grid\n${config.spacing_x || 0} × ${config.spacing_y || 0} spacing`;
+ }
+ return param.defaultValue;
+}
+
+// Global editParameter function for parameters modal
+function editParameterGlobal(id) {
+ const param = editor.parametersManager.getParameter(id);
+
+ // If this is a clone configuration parameter, open the parametric clone modal instead
+ if (param && param.type === 'clone_config') {
+ // Find the clone group that uses this parameter
+ const cloneGroups = document.querySelectorAll('[data-parametric-clone="true"]');
+ let targetCloneGroup = null;
+
+ cloneGroups.forEach(group => {
+ if (group.getAttribute('data-clone-param') === param.name) {
+ targetCloneGroup = group;
+ }
+ });
+
+ if (targetCloneGroup) {
+ // Close the parameters modal
+ editor.modal.parameters.close();
+
+ // Mark that we're opening from parameters manager
+ setTimeout(() => {
+ editor.modal.parametricClone.el.setAttribute('data-opened-from-params', 'true');
+ }, 50);
+
+ // Open the parametric clone modal for editing
+ editor.editParametricClone(targetCloneGroup);
+ } else {
+ alert('Could not find the clone group associated with this parameter.');
+ }
+ } else {
+ // Regular parameter editing - try multiple approaches
+ if (editor.modal.parameters.showParameterForm) {
+ editor.modal.parameters.showParameterForm(true, id);
+ } else if (editor.modal.parameters.editParameter) {
+ editor.modal.parameters.editParameter(id);
+ } else {
+ // Use manual parameter form approach
+ if (showParameterFormManually(param, id)) {
+ console.log('Successfully opened parameter form manually');
+ } else {
+ alert('Error: Cannot edit parameter. Please try closing and reopening the Parameters Manager.');
+ }
+ }
+ }
+}
+
+// Simple function to manually show parameter form for editing
+function showParameterFormManually(param, id) {
+ const modal = editor.modal.parameters;
+ const parametersContainer = modal.el.querySelector('#parameters-container');
+ const parameterForm = modal.el.querySelector('#parameter-form');
+ const parameterFormTitle = modal.el.querySelector('#parameter-form-title');
+ const paramNameInput = modal.el.querySelector('#param-name');
+ const paramTypeSelect = modal.el.querySelector('#param-type');
+ const paramDescriptionInput = modal.el.querySelector('#param-description');
+
+ if (!parameterForm || !parametersContainer) return false;
+
+ // Hide parameters list and show form (same as Add Parameter behavior)
+ parametersContainer.style.display = 'none';
+ parameterForm.style.display = 'block';
+ parameterFormTitle.textContent = 'Edit Parameter';
+ paramNameInput.value = param.name || '';
+ paramTypeSelect.value = param.type || 'text';
+ paramDescriptionInput.value = param.description || '';
+
+ // Handle default value input based on type - use the same approach as the original function
+ const updateDefaultValueInput = () => {
+ const type = param.type;
+ let currentElement = modal.el.querySelector('#param-default');
+
+ if (!currentElement) return; // Exit if no default input field found
+
+ const baseStyle = 'width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px; position: relative; z-index: 1001; pointer-events: auto;';
+
+ if (type === 'boolean') {
+ // Replace input with select for boolean
+ if (currentElement.tagName !== 'SELECT') {
+ const select = document.createElement('select');
+ select.id = 'param-default';
+ select.style.cssText = baseStyle;
+ select.innerHTML = '
False True ';
+ select.value = param.defaultValue === true || param.defaultValue === 'true' ? 'true' : 'false';
+ currentElement.parentNode.replaceChild(select, currentElement);
+ }
+ } else {
+ // Replace select with input for non-boolean types, or just update if already input
+ if (currentElement.tagName === 'SELECT') {
+ const input = document.createElement('input');
+ input.id = 'param-default';
+ input.style.cssText = baseStyle;
+ currentElement.parentNode.replaceChild(input, currentElement);
+ currentElement = input;
+ }
+
+ // Set input properties based on type
+ switch (type) {
+ case 'number':
+ currentElement.type = 'number';
+ currentElement.value = param.defaultValue || '';
+ break;
+ case 'color':
+ currentElement.type = 'color';
+ currentElement.value = param.defaultValue || '#000000';
+ break;
+ default:
+ currentElement.type = 'text';
+ currentElement.value = param.defaultValue || '';
+ break;
+ }
+ }
+
+ // Make it clickable
+ currentElement.addEventListener('mousedown', function(e) {
+ e.stopPropagation();
+ this.focus();
+ });
+ };
+
+ updateDefaultValueInput();
+
+ // Store the editing parameter ID for form submission
+ modal.el.setAttribute('data-manual-edit-id', id);
+
+ return true;
+}
+
// Attach renderParametersList function to the actual modal instance after construction
editor.modal.parameters.renderParametersList = function() {
const parametersContainer = editor.modal.parameters.el.querySelector('#parameters-container');
@@ -658,7 +899,7 @@ editor.modal.parameters.renderParametersList = function() {
row.innerHTML =
'
@' + param.name + ' ' +
'
' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
- '
' + param.defaultValue + ' ' +
+ '
' + formatParameterValue(param) + ' ' +
'
' +
'Edit ' +
@@ -705,7 +946,7 @@ editor.modal.parameters.renderParametersList = function() {
row.innerHTML =
' └ ' + friendlyNames[type] + ' ' +
'
' + editor.parametersManager.PARAM_TYPES[param.type].label + ' ' +
- '
' + param.defaultValue + ' ' +
+ '
' + formatParameterValue(param) + ' ' +
'
' +
'Edit ' +
@@ -718,10 +959,10 @@ editor.modal.parameters.renderParametersList = function() {
});
});
- // Add event listeners for edit/delete buttons (simplified for now)
+ // Add event listeners for edit/delete buttons
editor.modal.parameters.el.querySelectorAll('.edit-param-btn').forEach(btn => {
btn.addEventListener('click', function() {
- // TODO: Implement edit functionality
+ editParameterGlobal(this.dataset.id);
});
});
diff --git a/src/js/svgcanvas.js b/src/js/svgcanvas.js
index 1f49dcd5..5099f14c 100644
--- a/src/js/svgcanvas.js
+++ b/src/js/svgcanvas.js
@@ -8126,16 +8126,23 @@ this.groupSelectedElements = function(type) {
// Function: createParametricCloneGroup
// Creates a parametric clone group with grid layout
-this.createParametricCloneGroup = function(templateElements, colsParamName, rowsParamName, spacingXParamName, spacingYParamName) {
+this.createParametricCloneGroup = function(templateElements, cloneParamName) {
if (!templateElements || templateElements.length === 0) {
return null;
}
- // Get the parameter values
- const cols = editor.parametersManager.resolveParameterValue('@' + colsParamName);
- const rows = editor.parametersManager.resolveParameterValue('@' + rowsParamName);
- const spacingX = editor.parametersManager.resolveParameterValue('@' + spacingXParamName);
- const spacingY = editor.parametersManager.resolveParameterValue('@' + spacingYParamName);
+ // Get the clone configuration parameter
+ const cloneConfig = editor.parametersManager.resolveParameterValue('@' + cloneParamName);
+ if (!cloneConfig || typeof cloneConfig !== 'object') {
+ console.error('Invalid clone configuration parameter:', cloneParamName);
+ return null;
+ }
+
+ // Extract values from the configuration object
+ const cols = cloneConfig.num_cols || 3;
+ const rows = cloneConfig.num_rows || 2;
+ const spacingX = cloneConfig.spacing_x || 50;
+ const spacingY = cloneConfig.spacing_y || 50;
const batchCmd = new BatchCommand("Create Parametric Clone");
@@ -8146,10 +8153,7 @@ this.createParametricCloneGroup = function(templateElements, colsParamName, rows
"attr": {
"id": cloneGroupId,
"data-parametric-clone": "true",
- "data-cols-param": colsParamName,
- "data-rows-param": rowsParamName,
- "data-spacing-x-param": spacingXParamName,
- "data-spacing-y-param": spacingYParamName
+ "data-clone-param": cloneParamName
}
});
@@ -8257,17 +8261,25 @@ this.updateParametricCloneGroup = function(cloneGroupId) {
return false;
}
- // Get parameter names
- const colsParamName = cloneGroup.getAttribute('data-cols-param');
- const rowsParamName = cloneGroup.getAttribute('data-rows-param');
- const spacingXParamName = cloneGroup.getAttribute('data-spacing-x-param');
- const spacingYParamName = cloneGroup.getAttribute('data-spacing-y-param');
+ // Get the clone parameter name
+ const cloneParamName = cloneGroup.getAttribute('data-clone-param');
+ if (!cloneParamName) {
+ console.error('Clone parameter name not found in parametric clone group');
+ return false;
+ }
+
+ // Get the clone configuration parameter
+ const cloneConfig = editor.parametersManager.resolveParameterValue('@' + cloneParamName);
+ if (!cloneConfig || typeof cloneConfig !== 'object') {
+ console.error('Invalid clone configuration parameter:', cloneParamName);
+ return false;
+ }
- // Get updated parameter values
- const cols = editor.parametersManager.resolveParameterValue('@' + colsParamName);
- const rows = editor.parametersManager.resolveParameterValue('@' + rowsParamName);
- const spacingX = editor.parametersManager.resolveParameterValue('@' + spacingXParamName);
- const spacingY = editor.parametersManager.resolveParameterValue('@' + spacingYParamName);
+ // Extract values from the configuration object
+ const cols = cloneConfig.num_cols || 3;
+ const rows = cloneConfig.num_rows || 2;
+ const spacingX = cloneConfig.spacing_x || 50;
+ const spacingY = cloneConfig.spacing_y || 50;
const batchCmd = new BatchCommand("Update Parametric Clone");
From 93a5cba8db3675b1995d051e470fda6065b9316d Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Thu, 24 Jul 2025 11:41:38 +1000
Subject: [PATCH 09/13] Add ability to create a new parameter directly from
autocomplete menu
---
src/css/property-validation.css | 64 +++++
src/js/PropertyValidation.js | 447 ++++++++++++++++++++++++++++++--
src/js/modals.js | 56 +++-
3 files changed, 545 insertions(+), 22 deletions(-)
diff --git a/src/css/property-validation.css b/src/css/property-validation.css
index 0e7f1295..87693a87 100644
--- a/src/css/property-validation.css
+++ b/src/css/property-validation.css
@@ -93,6 +93,70 @@ datalist option {
font-family: monospace;
}
+/* Custom parameter autocomplete dropdown */
+.parameter-autocomplete-dropdown {
+ position: absolute;
+ background: white;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+ max-height: 200px;
+ overflow-y: auto;
+ z-index: 1000;
+ min-width: 150px;
+ font-family: monospace;
+ font-size: 12px;
+ display: none;
+}
+
+/* Force hide any lingering dropdown elements */
+.parameter-autocomplete-dropdown[style*="display: none"] {
+ display: none !important;
+ visibility: hidden !important;
+ opacity: 0 !important;
+ pointer-events: none !important;
+}
+
+#parameter-autocomplete-dropdown[style*="display: none"] {
+ display: none !important;
+ visibility: hidden !important;
+ opacity: 0 !important;
+ pointer-events: none !important;
+}
+
+.parameter-autocomplete-item {
+ padding: 8px 12px;
+ cursor: pointer;
+ border-bottom: 1px solid #f0f0f0;
+ color: #007cba;
+ background: #f8f9fa;
+}
+
+.parameter-autocomplete-item:hover,
+.parameter-autocomplete-item.highlighted {
+ background: #007cba;
+ color: white;
+}
+
+.parameter-autocomplete-item:last-child {
+ border-bottom: none;
+}
+
+.parameter-autocomplete-create {
+ padding: 8px 12px;
+ cursor: pointer;
+ color: #28a745;
+ background: #f8fff9;
+ border-top: 1px solid #ddd;
+ font-style: italic;
+}
+
+.parameter-autocomplete-create:hover,
+.parameter-autocomplete-create.highlighted {
+ background: #28a745;
+ color: white;
+}
+
/* Focus states for parameter inputs */
input.param-reference:focus {
box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.25);
diff --git a/src/js/PropertyValidation.js b/src/js/PropertyValidation.js
index 66eb670e..9f1fb19f 100644
--- a/src/js/PropertyValidation.js
+++ b/src/js/PropertyValidation.js
@@ -1,6 +1,9 @@
MD.PropertyValidation = function() {
const _self = this;
+ // Global flag to prevent dropdown recreation during parameter creation
+ let isCreatingParameterFromAutocomplete = false;
+
// Pattern to match parameter references (@paramName)
const PARAM_REFERENCE_PATTERN = /^@[a-zA-Z_][a-zA-Z0-9_]*$/;
@@ -53,6 +56,7 @@ MD.PropertyValidation = function() {
// Add visual feedback to input field based on validation
function updateInputValidation(input) {
+ if (!input || !input.value) return; // Add null check
let value = input.value.trim();
// Handle parameter display format: "@width (200)" - extract just the parameter reference
@@ -268,39 +272,441 @@ MD.PropertyValidation = function() {
// Add autocomplete functionality for parameter names
function addParameterAutocomplete() {
- // Create a datalist element for parameter suggestions
- let datalist = document.getElementById('parameter-suggestions');
- if (!datalist) {
- datalist = document.createElement('datalist');
- datalist.id = 'parameter-suggestions';
- document.body.appendChild(datalist);
+ // If we're in the middle of autocomplete parameter creation, skip recreation
+ if (isCreatingParameterFromAutocomplete) {
+ return;
+ }
+
+ // Remove any existing dropdown elements first
+ const allPossibleDropdowns = document.querySelectorAll(
+ '#parameter-autocomplete-dropdown, ' +
+ '.parameter-autocomplete-dropdown, ' +
+ '[class*="parameter-autocomplete"], ' +
+ '[id*="parameter-autocomplete"]'
+ );
+ allPossibleDropdowns.forEach((el) => {
+ el.style.display = 'none !important';
+ el.style.visibility = 'hidden !important';
+ el.style.opacity = '0 !important';
+ el.innerHTML = '';
+ if (el.parentNode) {
+ el.parentNode.removeChild(el);
+ }
+ });
+
+ // Remove old datalist if it exists
+ const oldDatalist = document.getElementById('parameter-suggestions');
+ if (oldDatalist) {
+ oldDatalist.remove();
+ }
+
+ // Create custom dropdown element
+ let dropdown = document.getElementById('parameter-autocomplete-dropdown');
+ if (!dropdown) {
+ dropdown = document.createElement('div');
+ dropdown.id = 'parameter-autocomplete-dropdown';
+ dropdown.className = 'parameter-autocomplete-dropdown';
+ document.body.appendChild(dropdown);
}
- // Update the datalist with current parameters
- function updateParameterSuggestions() {
+ // Always ensure dropdown is clean and hidden when initializing
+ dropdown.style.display = 'none';
+ dropdown.style.visibility = 'hidden';
+ dropdown.innerHTML = '';
+
+ let currentInput = null;
+ let highlightedIndex = -1;
+ let currentParams = [];
+ let currentTypedText = '';
+
+ // Store autocomplete context for parameter creation
+ let autocompleteContext = {
+ input: null,
+ inputSelector: '',
+ inputAttr: '',
+ parameterName: '',
+ active: false
+ };
+
+ // Show dropdown with parameter suggestions
+ function showDropdown(input, typedText) {
if (!editor.parametersManager) return;
+
+ // Ensure dropdown is back in DOM if it was removed
+ if (!dropdown.parentNode) {
+ document.body.appendChild(dropdown);
+ }
+
+ currentInput = input;
+ currentTypedText = typedText;
+
+ // Store context for potential parameter creation
+ const inputAttr = input.getAttribute('data-attr') || '';
+ const inputId = input.id || '';
+ const inputSelector = inputId ? `#${inputId}` : `input[data-attr="${inputAttr}"]`;
+
+ autocompleteContext = {
+ input: input,
+ inputSelector: inputSelector,
+ inputAttr: inputAttr,
+ parameterName: typedText,
+ active: false // Will be set to true if create option is clicked
+ };
+
+ // Get current parameters
const paramNames = editor.parametersManager.getParameterNames();
- datalist.innerHTML = paramNames.map(name => `@${name} `).join('');
+
+ // Filter parameters based on typed text (without @)
+ const filterText = typedText.toLowerCase();
+ currentParams = paramNames.filter(name =>
+ name.toLowerCase().includes(filterText) || filterText === ''
+ );
+
+ // Build dropdown content
+ let html = '';
+
+ // Add existing parameters
+ currentParams.forEach((name, index) => {
+ html += `@${name}
`;
+ });
+
+ // Add "Create parameter" option if we have typed text
+ if (typedText.length > 0) {
+ const createIndex = currentParams.length;
+ html += `Create '@${typedText}'...
`;
+ }
+
+ dropdown.innerHTML = html;
+
+ // Position dropdown below the input
+ const inputRect = input.getBoundingClientRect();
+ dropdown.style.left = inputRect.left + 'px';
+ dropdown.style.top = (inputRect.bottom + 2) + 'px';
+ dropdown.style.display = 'block';
+ dropdown.style.visibility = 'visible';
+
+ // Reset highlighted index
+ highlightedIndex = -1;
+
+ // Add click handlers to dropdown items
+ dropdown.querySelectorAll('.parameter-autocomplete-item, .parameter-autocomplete-create').forEach(item => {
+ item.addEventListener('click', function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ selectItem(parseInt(this.getAttribute('data-index')));
+ });
+ });
+ }
+
+ // Hide dropdown
+ function hideDropdown() {
+ // Find ALL dropdown elements that might exist
+ const allDropdowns = document.querySelectorAll('#parameter-autocomplete-dropdown, .parameter-autocomplete-dropdown');
+
+ // Hide all of them
+ allDropdowns.forEach((dd) => {
+ dd.style.display = 'none';
+ dd.style.visibility = 'hidden';
+ dd.innerHTML = '';
+ if (dd.parentNode) {
+ dd.parentNode.removeChild(dd);
+ }
+ });
+
+ // Hide our specific dropdown too
+ dropdown.style.display = 'none';
+ dropdown.style.visibility = 'hidden';
+ dropdown.innerHTML = '';
+
+ // Also temporarily remove from DOM to ensure it's really gone
+ if (dropdown.parentNode) {
+ dropdown.parentNode.removeChild(dropdown);
+ }
+
+ currentInput = null;
+ highlightedIndex = -1;
+ currentParams = [];
+ }
+
+ // Highlight item by index
+ function highlightItem(index) {
+ // Remove previous highlights
+ dropdown.querySelectorAll('.highlighted').forEach(item => {
+ item.classList.remove('highlighted');
+ });
+
+ // Highlight new item
+ const items = dropdown.querySelectorAll('.parameter-autocomplete-item, .parameter-autocomplete-create');
+ if (index >= 0 && index < items.length) {
+ items[index].classList.add('highlighted');
+ highlightedIndex = index;
+ } else {
+ highlightedIndex = -1;
+ }
+ }
+
+ // Select item by index
+ function selectItem(index) {
+ const items = dropdown.querySelectorAll('.parameter-autocomplete-item, .parameter-autocomplete-create');
+ if (index < 0 || index >= items.length) return;
+
+ const item = items[index];
+ const isCreateOption = item.hasAttribute('data-create');
+
+ if (isCreateOption) {
+ // Set global flag to prevent dropdown recreation
+ isCreatingParameterFromAutocomplete = true;
+
+ // Activate the context for parameter creation BEFORE hiding dropdown
+ autocompleteContext.parameterName = currentTypedText;
+ autocompleteContext.active = true;
+
+ // Hide dropdown completely
+ hideDropdown();
+
+ // Nuclear option: destroy ALL possible dropdown elements
+ setTimeout(() => {
+ const allPossibleDropdowns = document.querySelectorAll(
+ '#parameter-autocomplete-dropdown, ' +
+ '.parameter-autocomplete-dropdown, ' +
+ '[class*="parameter-autocomplete"], ' +
+ '[id*="parameter-autocomplete"]'
+ );
+ allPossibleDropdowns.forEach(el => {
+ el.style.display = 'none !important';
+ el.style.visibility = 'hidden !important';
+ el.style.opacity = '0 !important';
+ el.innerHTML = '';
+ if (el.parentNode) {
+ el.parentNode.removeChild(el);
+ }
+ });
+ }, 1);
+
+ // Try multiple approaches to open the modal
+ if (editor.modal && editor.modal.parameters) {
+ editor.modal.parameters.open();
+
+ // Small delay to ensure modal is ready
+ setTimeout(() => {
+ // Try to access the showParameterForm function
+ if (editor.modal.parameters.showParameterForm) {
+ editor.modal.parameters.showParameterForm(false, null);
+
+ // Pre-fill the name field
+ setTimeout(() => {
+ const nameInput = editor.modal.parameters.el.querySelector('#param-name');
+ if (nameInput) {
+ nameInput.value = currentTypedText;
+ nameInput.focus();
+ }
+ }, 50);
+ } else {
+ // Fallback 1: Try clicking the Add Parameter button
+ const addParameterBtn = editor.modal.parameters.el.querySelector('#add-parameter-btn');
+ if (addParameterBtn) {
+ addParameterBtn.click();
+
+ // Pre-fill the name field after button click
+ setTimeout(() => {
+ const nameInput = editor.modal.parameters.el.querySelector('#param-name');
+ if (nameInput) {
+ nameInput.value = currentTypedText;
+ nameInput.focus();
+ }
+ }, 50);
+ } else {
+ // Fallback 2: Manual approach - directly manipulate the modal DOM
+ const parametersContainer = editor.modal.parameters.el.querySelector('#parameters-container');
+ const parameterForm = editor.modal.parameters.el.querySelector('#parameter-form');
+ const parameterFormTitle = editor.modal.parameters.el.querySelector('#parameter-form-title');
+ const paramNameInput = editor.modal.parameters.el.querySelector('#param-name');
+ const parameterFormElement = editor.modal.parameters.el.querySelector('#parameter-form-element');
+
+ if (parametersContainer && parameterForm && paramNameInput) {
+ // Hide parameters list and show form
+ parametersContainer.style.display = 'none';
+ parameterForm.style.display = 'block';
+ parameterFormTitle.textContent = 'Add Parameter';
+
+ // Reset form and set name
+ parameterFormElement.reset();
+ paramNameInput.value = currentTypedText;
+ paramNameInput.focus();
+ }
+ }
+ }
+ }, 100);
+ }
+ } else {
+ // Select existing parameter
+ const paramValue = item.getAttribute('data-value');
+ if (currentInput && paramValue) {
+ currentInput.value = paramValue;
+ hideDropdown();
+
+ // Trigger input validation and parameter handling
+ if (currentInput && currentInput.value) {
+ updateInputValidation(currentInput);
+ handleParameterInput(currentInput);
+ }
+ }
+ }
+ }
+
+ // Handle keyboard navigation
+ function handleKeydown(e) {
+ if (dropdown.style.display === 'none') return;
+
+ const items = dropdown.querySelectorAll('.parameter-autocomplete-item, .parameter-autocomplete-create');
+ const itemCount = items.length;
+
+ switch (e.key) {
+ case 'ArrowDown':
+ e.preventDefault();
+ highlightItem((highlightedIndex + 1) % itemCount);
+ break;
+
+ case 'ArrowUp':
+ e.preventDefault();
+ highlightItem(highlightedIndex <= 0 ? itemCount - 1 : highlightedIndex - 1);
+ break;
+
+ case 'Enter':
+ e.preventDefault();
+ if (highlightedIndex >= 0) {
+ selectItem(highlightedIndex);
+ }
+ break;
+
+ case 'Escape':
+ e.preventDefault();
+ hideDropdown();
+ break;
+ }
}
// Add autocomplete to property inputs
const propertyInputs = document.querySelectorAll('.attr_changer, input[data-attr]');
propertyInputs.forEach(input => {
- input.setAttribute('list', 'parameter-suggestions');
+ // Remove old list attribute if it exists
+ input.removeAttribute('list');
- // Update suggestions when input gets focus
- input.addEventListener('focus', updateParameterSuggestions);
-
- // Also trigger on input for @ character
+ // Handle input changes
input.addEventListener('input', function(e) {
- if (e.target.value.includes('@')) {
- updateParameterSuggestions();
+ const value = e.target.value;
+ const atIndex = value.lastIndexOf('@');
+
+ if (atIndex !== -1) {
+ // Extract text after the last @
+ const afterAt = value.substring(atIndex + 1);
+
+ // Only show dropdown if @ is at the start or preceded by non-alphanumeric
+ const beforeAt = atIndex > 0 ? value.charAt(atIndex - 1) : ' ';
+ if (atIndex === 0 || !/[a-zA-Z0-9_]/.test(beforeAt)) {
+ showDropdown(this, afterAt);
+ }
+ } else {
+ hideDropdown();
}
});
+
+ // Handle keyboard events
+ input.addEventListener('keydown', handleKeydown);
+
+ // Hide dropdown when input loses focus (with small delay to allow clicks)
+ input.addEventListener('blur', function() {
+ setTimeout(() => {
+ if (!dropdown.matches(':hover')) {
+ hideDropdown();
+ }
+ }, 150);
+ });
+ });
+
+ // Hide dropdown when clicking outside
+ document.addEventListener('click', function(e) {
+ if (!dropdown.contains(e.target) && currentInput !== e.target) {
+ hideDropdown();
+ }
});
- // Update suggestions when parameters change
- updateParameterSuggestions();
+ // Function to handle parameter creation from autocomplete
+ function handleParameterCreated(parameterName) {
+
+ if (autocompleteContext.active) {
+ // Clear context if empty parameter name (error case) or if parameter matches
+ if (!parameterName || parameterName === autocompleteContext.parameterName) {
+ if (parameterName) {
+ // Try to re-find the input field using multiple methods
+ let targetInput = autocompleteContext.input;
+
+ // If the original reference is stale, try to find it again
+ if (!targetInput || !document.body.contains(targetInput)) {
+ // Try by selector first
+ if (autocompleteContext.inputSelector) {
+ targetInput = document.querySelector(autocompleteContext.inputSelector);
+ }
+
+ // Fallback: find by data-attr
+ if (!targetInput && autocompleteContext.inputAttr) {
+ targetInput = document.querySelector(`input[data-attr="${autocompleteContext.inputAttr}"]`);
+ }
+ }
+
+ if (targetInput) {
+ // Delay field update to happen after modal closes
+ setTimeout(() => {
+ // Update the original input with the new parameter reference
+ const paramRef = '@' + parameterName;
+ targetInput.value = paramRef;
+
+ // Trigger validation and parameter handling immediately
+ updateInputValidation(targetInput);
+ handleParameterInput(targetInput);
+
+ // Trigger change event to ensure all handlers are called
+ const changeEvent = new Event('change', { bubbles: true });
+ targetInput.dispatchEvent(changeEvent);
+
+ // Also trigger input event
+ const inputEvent = new Event('input', { bubbles: true });
+ targetInput.dispatchEvent(inputEvent);
+
+ // Hide any dropdown that might have been recreated
+ hideDropdown();
+ }, 50);
+ }
+ }
+
+ // Store whether this was from autocomplete before clearing
+ const wasFromAutocomplete = autocompleteContext.active && parameterName === autocompleteContext.parameterName;
+
+ // Clear context and global flag
+ autocompleteContext = {
+ input: null,
+ inputSelector: '',
+ inputAttr: '',
+ parameterName: '',
+ active: false
+ };
+
+ // Clear global flag after a delay to ensure all initialization calls are blocked
+ setTimeout(() => {
+ isCreatingParameterFromAutocomplete = false;
+ }, 500);
+
+ // Return true if this was triggered from autocomplete (so modal should close)
+ return wasFromAutocomplete;
+ }
+ }
+
+ // Not from autocomplete, return false (normal behavior)
+ return false;
+ };
+
+ // Expose the handleParameterCreated function globally
+ _self.handleParameterCreated = handleParameterCreated;
}
// Flag to prevent infinite loops during parameter reset
@@ -373,6 +779,11 @@ MD.PropertyValidation = function() {
this.clearAllInputValidation = clearAllInputValidation;
this.resetParameterizedAttributes = resetParameterizedAttributes;
this.hasParameterReferences = hasParameterReferences;
+ this.hideDropdown = function() {
+ if (typeof hideDropdown === 'function') {
+ hideDropdown();
+ }
+ };
this.PARAM_REFERENCE_PATTERN = PARAM_REFERENCE_PATTERN;
this.NUMERIC_PATTERN = NUMERIC_PATTERN;
};
\ No newline at end of file
diff --git a/src/js/modals.js b/src/js/modals.js
index 9a535df3..8257b4ea 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -490,21 +490,69 @@ editor.modal = {
editor.parametersManager.addParameter(name, type, defaultValue, description);
}
- hideParameterForm();
- renderParametersList();
+ // Handle autocomplete parameter creation (if triggered from autocomplete)
+ let shouldCloseModal = false;
+ if (editor.propertyValidation && editor.propertyValidation.handleParameterCreated) {
+ shouldCloseModal = editor.propertyValidation.handleParameterCreated(name);
+ }
+
+ if (shouldCloseModal) {
+ // Close the entire modal if this was triggered from autocomplete
+ // Use a small delay to ensure the callback completes first
+ setTimeout(() => {
+ // Reset modal state before closing
+ editingParameterId = null;
+ parametersContainer.style.display = 'block';
+ parameterForm.style.display = 'none';
+ parameterFormElement.reset();
+
+ editor.modal.parameters.close();
+
+ // Hide any autocomplete dropdown after modal closes
+ if (editor.propertyValidation && editor.propertyValidation.hideDropdown) {
+ setTimeout(() => {
+ editor.propertyValidation.hideDropdown();
+ }, 50);
+ }
+ }, 10);
+ } else {
+ // Normal parameter manager flow
+ hideParameterForm();
+ renderParametersList();
+ }
- // Update property validation autocomplete
- if (editor.propertyValidation) {
+ // Update property validation autocomplete (but not if this was from autocomplete)
+ if (editor.propertyValidation && !shouldCloseModal) {
editor.propertyValidation.addParameterAutocomplete();
}
} catch (error) {
alert('Error saving parameter: ' + error.message);
+
+ // Clear autocomplete context on error too
+ if (editor.propertyValidation && editor.propertyValidation.handleParameterCreated) {
+ editor.propertyValidation.handleParameterCreated(''); // Empty name clears context
+ }
}
});
// Expose functions for use by renderParametersList
this.editParameter = editParameter;
this.showParameterForm = showParameterForm;
+
+ // Reset modal to default state when opened
+ this.open = function() {
+ // Call the original open method
+ MD.Modal.prototype.open.call(this);
+
+ // Reset to show parameters list
+ editingParameterId = null;
+ parametersContainer.style.display = 'block';
+ parameterForm.style.display = 'none';
+ parameterFormElement.reset();
+
+ // Render the parameters list
+ renderParametersList();
+ };
}
}),
From 65b8e8dcf3264a07977bf72fe3db81d2363da731 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Thu, 24 Jul 2025 11:56:03 +1000
Subject: [PATCH 10/13] Fix bug where keyboard actions lost focus
---
src/js/Modal.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/js/Modal.js b/src/js/Modal.js
index 452d5969..235a60b3 100644
--- a/src/js/Modal.js
+++ b/src/js/Modal.js
@@ -23,6 +23,12 @@ MD.Modal = function(config){
}
function close(){
+ // Blur any focused elements within the modal to restore keyboard shortcuts
+ const focusedElement = el.querySelector(':focus');
+ if (focusedElement) {
+ focusedElement.blur();
+ }
+
el.classList.add("hidden");
}
From 59f6b2c039c9b470e4ebf9716d189504be6637b7 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Thu, 24 Jul 2025 12:01:59 +1000
Subject: [PATCH 11/13] Block literal 'width' and 'height' parameter names.
---
src/js/Parameters.js | 11 +++++++++--
src/js/modals.js | 6 +++---
2 files changed, 12 insertions(+), 5 deletions(-)
diff --git a/src/js/Parameters.js b/src/js/Parameters.js
index c035e43b..df11f0df 100644
--- a/src/js/Parameters.js
+++ b/src/js/Parameters.js
@@ -5,6 +5,9 @@ MD.Parameters = function(){
// followed by letters, numbers, or underscores
const PARAM_NAME_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
+ // Reserved parameter names that cannot be used (conflict with platform variables)
+ const RESERVED_NAMES = ['width', 'height'];
+
// Parameter types supported
const PARAM_TYPES = {
number: { label: 'Number', defaultValue: 0 },
@@ -32,6 +35,10 @@ MD.Parameters = function(){
// Validate parameter name
function isValidParameterName(name) {
if (!name || typeof name !== 'string') return false;
+
+ // Check if name is reserved
+ if (RESERVED_NAMES.includes(name.toLowerCase())) return false;
+
return PARAM_NAME_REGEX.test(name);
}
@@ -51,7 +58,7 @@ MD.Parameters = function(){
// Add new parameter
function addParameter(name, type, defaultValue, description = '') {
if (!isValidParameterName(name)) {
- throw new Error('Invalid parameter name. Must start with letter or underscore, followed by letters, numbers, or underscores.');
+ throw new Error('Invalid parameter name. Must start with letter or underscore, followed by letters, numbers, or underscores. Cannot use reserved names: width, height.');
}
if (parameterExists(name)) {
@@ -79,7 +86,7 @@ MD.Parameters = function(){
// Update existing parameter
function updateParameter(id, name, type, defaultValue, description = '') {
if (!isValidParameterName(name)) {
- throw new Error('Invalid parameter name. Must start with letter or underscore, followed by letters, numbers, or underscores.');
+ throw new Error('Invalid parameter name. Must start with letter or underscore, followed by letters, numbers, or underscores. Cannot use reserved names: width, height.');
}
if (parameterExists(name, id)) {
diff --git a/src/js/modals.js b/src/js/modals.js
index 8257b4ea..ec7bd061 100644
--- a/src/js/modals.js
+++ b/src/js/modals.js
@@ -115,9 +115,9 @@ editor.modal = {
Name:
-
- Must start with letter or underscore, followed by letters, numbers, or underscores
+ Must start with letter or underscore, followed by letters, numbers, or underscores. Cannot use: width, height
@@ -633,7 +633,7 @@ editor.modal = {
// Check if name is valid parameter name
if (!editor.parametersManager.isValidParameterName(cloneName)) {
- alert('Invalid parameter name. Use only letters, numbers, and underscores. Cannot start with a number.');
+ alert('Invalid parameter name. Use only letters, numbers, and underscores. Cannot start with a number. Cannot use reserved names: width, height.');
return;
}
From d5cc625cae48b98ff138f27dc47ade09bb25a025 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Thu, 24 Jul 2025 12:37:06 +1000
Subject: [PATCH 12/13] Add ability to save/restore our parameters (in enhanced
SVG format)
---
src/js/sanitize.js | 1 +
src/js/svgcanvas.js | 61 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/src/js/sanitize.js b/src/js/sanitize.js
index 3e5777a2..5fcb06c0 100644
--- a/src/js/sanitize.js
+++ b/src/js/sanitize.js
@@ -34,6 +34,7 @@ nsMap_[xlinkns] = 'xlink';
nsMap_[xmlns] = 'xml';
nsMap_[xmlnsns] = 'xmlns';
nsMap_[se_ns] = 'se';
+nsMap_["http://methoddraw.com/parametric/1.0"] = 'md';
nsMap_[htmlns] = 'xhtml';
nsMap_[mathns] = 'mathml';
diff --git a/src/js/svgcanvas.js b/src/js/svgcanvas.js
index 5099f14c..57d4f982 100644
--- a/src/js/svgcanvas.js
+++ b/src/js/svgcanvas.js
@@ -38,6 +38,7 @@ var svgns = "http://www.w3.org/2000/svg",
xmlns = "http://www.w3.org/XML/1998/namespace",
xmlnsns = "http://www.w3.org/2000/xmlns/", // see http://www.w3.org/TR/REC-xml-names/#xmlReserved
se_ns = "http://svg-edit.googlecode.com",
+ md_ns = "http://methoddraw.com/parametric/1.0", // Method Draw parametric namespace
htmlns = "http://www.w3.org/1999/xhtml",
mathns = "http://www.w3.org/1998/Math/MathML";
@@ -5187,6 +5188,14 @@ this.svgToString = function(elem, indent) {
});
});
+ // Add Method Draw parametric namespace if we have parameters
+ if (typeof editor !== 'undefined' && editor.parametersManager) {
+ var parameters = editor.parametersManager.getParameters();
+ if (parameters && Object.keys(parameters).length > 0) {
+ out.push(' xmlns:md="' + md_ns + '"');
+ }
+ }
+
var i = attrs.length;
var attr_names = ['width','height','xmlns','x','y','viewBox','id','overflow'];
while (i--) {
@@ -5254,6 +5263,26 @@ this.svgToString = function(elem, indent) {
indent++;
var bOneLine = false;
+ // Add parametric metadata for root element
+ if(elem.id === 'svgcontent' && typeof editor !== 'undefined' && editor.parametersManager) {
+ var parameters = editor.parametersManager.getParameters();
+ if (parameters && Object.keys(parameters).length > 0) {
+ out.push("\n");
+ for (var j=0; j");
+ out.push("\n");
+ for (var j=0; j<=indent; j++) out.push(" ");
+ out.push("");
+ out.push("");
+ out.push(" ");
+ out.push("\n");
+ for (var j=0; j");
+ }
+ }
+
for (var i=0; i 0) {
+ try {
+ var parametersJson = metadataElem.text().trim();
+ if (parametersJson) {
+ var parameters = JSON.parse(parametersJson);
+ if (typeof editor !== 'undefined' && editor.parametersManager && parameters) {
+ // Clear existing parameters and restore from SVG
+ state.set('canvasParameters', parameters);
+ console.log('Restored parametric data:', parameters);
+
+ // Trigger parameter UI refresh if parameters modal is available
+ if (editor.modal && editor.modal.parameters && editor.modal.parameters.renderParametersList) {
+ setTimeout(function() {
+ editor.modal.parameters.renderParametersList();
+ }, 100);
+ }
+
+ // Restore parameter references on elements after a short delay to ensure DOM is ready
+ setTimeout(function() {
+ if (editor.propertyValidation && editor.propertyValidation.restoreParameterReferences) {
+ editor.propertyValidation.restoreParameterReferences();
+ }
+ }, 200);
+ }
+ }
+ } catch (e) {
+ console.warn('Failed to parse parametric metadata:', e);
+ }
+ }
+
svgcontent.querySelectorAll('textPath').forEach(function(el){
const href = svgCanvas.getHref(el);
if (!href) return;
From 2252b32ea70a7fde7addf6cfe37c4371a0cab8e0 Mon Sep 17 00:00:00 2001
From: smith120bh <42363318+smith120bh@users.noreply.github.com>
Date: Fri, 25 Jul 2025 14:41:08 +1000
Subject: [PATCH 13/13] Bug - clear parameters when creating a new doc
---
src/js/editor.js | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/src/js/editor.js b/src/js/editor.js
index 0026c9cf..6e88a175 100644
--- a/src/js/editor.js
+++ b/src/js/editor.js
@@ -20,6 +20,15 @@ MD.Editor = function(){
editor.panel.updateContextPanel();
editor.paintBox.fill.prep();
editor.paintBox.stroke.prep();
+
+ // Clear all parameters when creating a new document
+ state.set("canvasParameters", {});
+
+ // Clear parameter validation from inputs if available
+ if (editor.propertyValidation && editor.propertyValidation.clearAllInputValidation) {
+ editor.propertyValidation.clearAllInputValidation();
+ }
+
svgCanvas.runExtensions('onNewDocument');
});
}
@@ -470,6 +479,12 @@ MD.Editor = function(){
});
});
+ // Remove metadata tags that contain parametric data
+ const metadataElements = svgDoc.querySelectorAll('metadata');
+ metadataElements.forEach(metadata => {
+ metadata.parentNode.removeChild(metadata);
+ });
+
// Get the modified SVG string
const serializer = new XMLSerializer();
let modifiedSvgString = serializer.serializeToString(svgDoc.documentElement);