UNPKG

modern-idoc

Version:

Intermediate document for modern codec libs

1,833 lines (1,791 loc) 54.3 kB
'use strict'; const colord = require('colord'); const nanoid$1 = require('nanoid'); function normalizeAudio(audio) { if (typeof audio === "string") { return { src: audio }; } else { return audio; } } class EventEmitter { eventListeners = /* @__PURE__ */ new Map(); addEventListener(event, listener, options) { const object = { value: listener, options }; const listeners = this.eventListeners.get(event); if (!listeners) { this.eventListeners.set(event, object); } else if (Array.isArray(listeners)) { listeners.push(object); } else { this.eventListeners.set(event, [listeners, object]); } return this; } removeEventListener(event, listener, options) { if (!listener) { this.eventListeners.delete(event); return this; } const listeners = this.eventListeners.get(event); if (!listeners) { return this; } if (Array.isArray(listeners)) { const events = []; for (let i = 0, length = listeners.length; i < length; i++) { const object = listeners[i]; if (object.value !== listener || typeof options === "object" && options?.once && (typeof object.options === "boolean" || !object.options?.once)) { events.push(object); } } if (events.length) { this.eventListeners.set(event, events.length === 1 ? events[0] : events); } else { this.eventListeners.delete(event); } } else { if (listeners.value === listener && (typeof options === "boolean" || !options?.once || (typeof listeners.options === "boolean" || listeners.options?.once))) { this.eventListeners.delete(event); } } return this; } removeAllListeners() { this.eventListeners.clear(); return this; } hasEventListener(event) { return this.eventListeners.has(event); } dispatchEvent(event, ...args) { const listeners = this.eventListeners.get(event); if (listeners) { if (Array.isArray(listeners)) { for (let len = listeners.length, i = 0; i < len; i++) { const object = listeners[i]; if (typeof object.options === "object" && object.options?.once) { this.off(event, object.value, object.options); } object.value.apply(this, args); } } else { if (typeof listeners.options === "object" && listeners.options?.once) { this.off(event, listeners.value, listeners.options); } listeners.value.apply(this, args); } return true; } else { return false; } } on(event, listener, options) { return this.addEventListener(event, listener, options); } once(event, listener) { return this.addEventListener(event, listener, { once: true }); } off(event, listener, options) { return this.removeEventListener(event, listener, options); } emit(event, ...args) { this.dispatchEvent(event, ...args); } } function isNone(value) { return value === null || value === void 0 || value === "none"; } function round(number, digits = 0, base = 10 ** digits) { return Math.round(base * number) / base + 0; } function clearUndef(obj, deep = false) { if (typeof obj !== "object" || !obj) { return obj; } if (Array.isArray(obj)) { if (deep) { return obj.map((v) => clearUndef(v, deep)); } else { return obj; } } const newObj = {}; for (const key in obj) { const value = obj[key]; if (value === void 0 || value === null) { continue; } if (deep) { newObj[key] = clearUndef(value, deep); } else { newObj[key] = value; } } return newObj; } function pick(obj, keys) { const result = {}; keys.forEach((key) => { if (key in obj) { result[key] = obj[key]; } }); return result; } function isEqualObject(a, b) { if (a === b) return true; if (a && b && typeof a === "object" && typeof b === "object") { const keys = Array.from(/* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)])); return !keys.length || keys.every((key) => a[key] === b[key]); } return false; } function getNestedValue(obj, path, fallback) { const last = path.length - 1; if (last < 0) return obj === void 0 ? fallback : obj; for (let i = 0; i < last; i++) { if (obj == null) { return fallback; } obj = obj[path[i]]; } if (obj == null) return fallback; return obj[path[last]] === void 0 ? fallback : obj[path[last]]; } function setNestedValue(obj, path, value) { const last = path.length - 1; for (let i = 0; i < last; i++) { if (typeof obj[path[i]] !== "object") obj[path[i]] = {}; obj = obj[path[i]]; } obj[path[last]] = value; } function getObjectValueByPath(obj, path, fallback) { if (obj == null || !path || typeof path !== "string") return fallback; if (obj[path] !== void 0) return obj[path]; path = path.replace(/\[(\w+)\]/g, ".$1"); path = path.replace(/^\./, ""); return getNestedValue(obj, path.split("."), fallback); } function setObjectValueByPath(obj, path, value) { if (typeof obj !== "object" || !path) return; path = path.replace(/\[(\w+)\]/g, ".$1"); path = path.replace(/^\./, ""); return setNestedValue(obj, path.split("."), value); } class Observable { _observers = /* @__PURE__ */ new Map(); on(event, listener) { let set = this._observers.get(event); if (set === void 0) { this._observers.set(event, set = /* @__PURE__ */ new Set()); } set.add(listener); return this; } once(event, listener) { const _f = (...args) => { this.off(event, _f); listener(...args); }; this.on(event, _f); return this; } off(event, listener) { const observers = this._observers.get(event); if (observers !== void 0) { observers.delete(listener); if (observers.size === 0) { this._observers.delete(event); } } return this; } emit(event, ...args) { Array.from((this._observers.get(event) || /* @__PURE__ */ new Map()).values()).forEach((f) => f(...args)); return this; } destroy() { this._observers = /* @__PURE__ */ new Map(); } } class RawWeakMap { _map = /* @__PURE__ */ new WeakMap(); // fix: vue reactive object _toRaw(value) { if (value && typeof value === "object") { const raw = value.__v_raw; if (raw) { value = this._toRaw(raw); } } return value; } delete(key) { return this._map.delete(this._toRaw(key)); } get(key) { return this._map.get(this._toRaw(key)); } has(key) { return this._map.has(this._toRaw(key)); } set(key, value) { this._map.set(this._toRaw(key), this._toRaw(value)); return this; } } const propertiesSymbol = Symbol("properties"); const initedSymbol = Symbol("inited"); function getDeclarations(constructor) { let declarations; if (Object.hasOwn(constructor, propertiesSymbol)) { declarations = constructor[propertiesSymbol]; } else { const superConstructor = Object.getPrototypeOf(constructor); declarations = new Map(superConstructor ? getDeclarations(superConstructor) : void 0); constructor[propertiesSymbol] = declarations; } return declarations; } function propertyOffsetSet(target, key, newValue, declaration) { const { alias, internalKey } = declaration; const oldValue = target[key]; if (alias) { setObjectValueByPath(target, alias, newValue); } else { target[internalKey] = newValue; } target.onUpdateProperty?.(key, newValue, oldValue); } function propertyOffsetGet(target, key, declaration) { const { alias, internalKey } = declaration; let result; if (alias) { result = getObjectValueByPath(target, alias); } else { result = target[internalKey]; } result = result ?? propertyOffsetDefaultValue(target, key, declaration); return result; } function propertyOffsetDefaultValue(target, key, declaration) { const { default: _default, fallback } = declaration; let result; if (_default !== void 0 && !target[initedSymbol]) { target[initedSymbol] = true; const defaultValue = typeof _default === "function" ? _default() : _default; if (defaultValue !== void 0) { target[key] = defaultValue; result = defaultValue; } } result = result ?? (typeof fallback === "function" ? fallback() : fallback); return result; } function getPropertyDescriptor(key, declaration) { function get() { if (typeof this.getProperty !== "undefined") { return this.getProperty(key); } else { return propertyOffsetGet(this, key, declaration); } } function set(newValue) { if (typeof this.setProperty !== "undefined") { this.setProperty(key, newValue); } else { propertyOffsetSet(this, key, newValue, declaration); } } return { get, set }; } function defineProperty(constructor, key, declaration = {}) { const _declaration = { ...declaration, internalKey: Symbol(key) }; getDeclarations(constructor).set(key, _declaration); const descriptor = getPropertyDescriptor(key, _declaration); Object.defineProperty(constructor.prototype, key, { get() { return descriptor.get.call(this); }, set(newValue) { descriptor.set.call(this, newValue); }, configurable: true, enumerable: true }); } function property(declaration) { return function(target, key) { if (typeof key !== "string") { throw new TypeError("Failed to @property decorator, prop name cannot be a symbol"); } defineProperty(target.constructor, key, declaration); }; } function property2(declaration = {}) { return function(_, context) { const key = context.name; if (typeof key !== "string") { throw new TypeError("Failed to @property decorator, prop name cannot be a symbol"); } const _declaration = { ...declaration, internalKey: Symbol(key) }; const descriptor = getPropertyDescriptor(key, _declaration); return { init(v) { getDeclarations(this.constructor).set(key, _declaration); descriptor.set.call(this, v); return v; }, get() { return descriptor.get.call(this); }, set(newValue) { descriptor.set.call(this, newValue); } }; }; } class Reactivable extends Observable { _propertyAccessor; _properties = /* @__PURE__ */ new Map(); _updatedProperties = /* @__PURE__ */ new Map(); _changedProperties = /* @__PURE__ */ new Set(); _updatingPromise = Promise.resolve(); _updating = false; constructor(properties) { super(); this.setProperties(properties); } isDirty(key) { return key ? this._updatedProperties.has(key) : this._updatedProperties.size > 0; } getProperty(key) { const declaration = this.getPropertyDeclaration(key); if (declaration) { if (declaration.internal || declaration.alias) { return propertyOffsetGet(this, key, declaration); } else { let result; if (this._propertyAccessor?.getProperty) { result = this._propertyAccessor.getProperty(key); } else { result = this._properties.get(key); } return result ?? propertyOffsetDefaultValue(this, key, declaration); } } return void 0; } setProperty(key, newValue) { const declaration = this.getPropertyDeclaration(key); if (declaration) { if (declaration.internal || declaration.alias) { propertyOffsetSet(this, key, newValue, declaration); } else { const oldValue = this.getProperty(key); this._propertyAccessor?.setProperty?.(key, newValue); this._properties.set(key, newValue); this.onUpdateProperty?.(key, newValue, oldValue); } } } getProperties(keys) { const properties = {}; for (const [name, declaration] of this.getPropertyDeclarations()) { if (!declaration.internal && !declaration.alias && (!keys || keys.includes(name))) { properties[name] = this.getProperty(name); } } return properties; } setProperties(properties) { if (properties && typeof properties === "object") { for (const name in properties) { this.setProperty(name, properties[name]); } } return this; } resetProperties() { for (const [name, declaration] of this.getPropertyDeclarations()) { this.setProperty( name, typeof declaration.default === "function" ? declaration.default() : declaration.default ); } return this; } getPropertyDeclarations() { return getDeclarations(this.constructor); } getPropertyDeclaration(key) { return this.getPropertyDeclarations().get(key); } setPropertyAccessor(accessor) { const declarations = this.getPropertyDeclarations(); this._propertyAccessor = void 0; const oldValues = {}; declarations.forEach((_declaration, key) => { oldValues[key] = this.getProperty(key); }); this._propertyAccessor = accessor; declarations.forEach((declaration, key) => { const newValue = this.getProperty(key); const oldValue = oldValues[key]; if (newValue !== void 0 && !Object.is(newValue, oldValue)) { this.setProperty(key, newValue); if (!declaration.internal && !declaration.alias) { this.requestUpdate(key, newValue, oldValue); } } }); return this; } async _nextTick() { if ("requestAnimationFrame" in globalThis) { return new Promise((r) => globalThis.requestAnimationFrame(r)); } return Promise.resolve(); } async _enqueueUpdate() { this._updating = true; try { await this._updatingPromise; } catch (e) { Promise.reject(e); } await this._nextTick(); if (!this._updating) return; this.onUpdate(); this._updating = false; } onUpdate() { this._update(this._updatedProperties); this._updatedProperties = /* @__PURE__ */ new Map(); } onUpdateProperty(key, newValue, oldValue) { if (!Object.is(newValue, oldValue)) { this.requestUpdate(key, newValue, oldValue); } } requestUpdate(key, newValue, oldValue) { if (key !== void 0) { this._updatedProperties.set(key, oldValue); this._changedProperties.add(key); this._updateProperty(key, newValue, oldValue); this.emit("updateProperty", key, newValue, oldValue); } if (!this._updating) { this._updatingPromise = this._enqueueUpdate(); } } // eslint-disable-next-line unused-imports/no-unused-vars _update(changed) { } // eslint-disable-next-line unused-imports/no-unused-vars _updateProperty(key, newValue, oldValue) { } toJSON() { const json = {}; this._properties.forEach((value, key) => { if (value === void 0) { return; } if (value && typeof value === "object") { if ("toJSON" in value && typeof value.toJSON === "function") { json[key] = value.toJSON(); } else if (Array.isArray(value)) { json[key] = [...value]; } else { json[key] = { ...value }; } } else { json[key] = value; } }); return json; } clone() { return new this.constructor(this.toJSON()); } } function parseColor(color) { let input; if (typeof color === "number") { input = { r: color >> 24 & 255, g: color >> 16 & 255, b: color >> 8 & 255, a: (color & 255) / 255 }; } else { input = color; } return colord.colord(input); } function roundRgba(rgba) { return { r: round(rgba.r), g: round(rgba.g), b: round(rgba.b), a: round(rgba.a, 3) }; } function format(number) { const hex = number.toString(16); return hex.length < 2 ? `0${hex}` : hex; } const defaultColor = "#000000FF"; function isColor(value) { return parseColor(value).isValid(); } function normalizeColor(color, orFail = false) { const parsed = parseColor(color); if (!parsed.isValid()) { if (typeof color === "string") { return color; } const message = `Failed to normalizeColor ${color}`; if (orFail) { throw new Error(message); } else { console.warn(message); return defaultColor; } } const { r, g, b, a } = roundRgba(parsed.rgba); return `#${format(r)}${format(g)}${format(b)}${format(round(a * 255))}`; } var GradientParser$1 = GradientParser$1 || {}; GradientParser$1.parse = /* @__PURE__ */ (function() { const tokens = { linearGradient: /^(-(webkit|o|ms|moz)-)?(linear-gradient)/i, repeatingLinearGradient: /^(-(webkit|o|ms|moz)-)?(repeating-linear-gradient)/i, radialGradient: /^(-(webkit|o|ms|moz)-)?(radial-gradient)/i, repeatingRadialGradient: /^(-(webkit|o|ms|moz)-)?(repeating-radial-gradient)/i, sideOrCorner: /^to (left (top|bottom)|right (top|bottom)|top (left|right)|bottom (left|right)|left|right|top|bottom)/i, extentKeywords: /^(closest-side|closest-corner|farthest-side|farthest-corner|contain|cover)/, positionKeywords: /^(left|center|right|top|bottom)/i, pixelValue: /^(-?((\d*\.\d+)|(\d+\.?)))px/, percentageValue: /^(-?((\d*\.\d+)|(\d+\.?)))%/, emValue: /^(-?((\d*\.\d+)|(\d+\.?)))em/, angleValue: /^(-?((\d*\.\d+)|(\d+\.?)))deg/, radianValue: /^(-?((\d*\.\d+)|(\d+\.?)))rad/, startCall: /^\(/, endCall: /^\)/, comma: /^,/, hexColor: /^#([0-9a-f]+)/i, literalColor: /^([a-z]+)/i, rgbColor: /^rgb/i, rgbaColor: /^rgba/i, varColor: /^var/i, calcValue: /^calc/i, variableName: /^(--[a-z0-9-,\s#]+)/i, number: /^((\d*\.\d+)|(\d+\.?))/, hslColor: /^hsl/i, hslaColor: /^hsla/i }; let input = ""; function error(msg) { const err = new Error(`${input}: ${msg}`); err.source = input; throw err; } function getAST() { const ast = matchListDefinitions(); if (input.length > 0) { error("Invalid input not EOF"); } return ast; } function matchListDefinitions() { return matchListing(matchDefinition); } function matchDefinition() { return matchGradient( "linear-gradient", tokens.linearGradient, matchLinearOrientation ) || matchGradient( "repeating-linear-gradient", tokens.repeatingLinearGradient, matchLinearOrientation ) || matchGradient( "radial-gradient", tokens.radialGradient, matchListRadialOrientations ) || matchGradient( "repeating-radial-gradient", tokens.repeatingRadialGradient, matchListRadialOrientations ); } function matchGradient(gradientType, pattern, orientationMatcher) { return matchCall(pattern, (captures) => { const orientation = orientationMatcher(); if (orientation) { if (!scan(tokens.comma)) { error("Missing comma before color stops"); } } return { type: gradientType, orientation, colorStops: matchListing(matchColorStop) }; }); } function matchCall(pattern, callback) { const captures = scan(pattern); if (captures) { if (!scan(tokens.startCall)) { error("Missing ("); } const result = callback(captures); if (!scan(tokens.endCall)) { error("Missing )"); } return result; } } function matchLinearOrientation() { const sideOrCorner = matchSideOrCorner(); if (sideOrCorner) { return sideOrCorner; } const legacyDirection = match("position-keyword", tokens.positionKeywords, 1); if (legacyDirection) { return { type: "directional", value: legacyDirection.value }; } return matchAngle(); } function matchSideOrCorner() { return match("directional", tokens.sideOrCorner, 1); } function matchAngle() { return match("angular", tokens.angleValue, 1) || match("angular", tokens.radianValue, 1); } function matchListRadialOrientations() { let radialOrientations; let radialOrientation = matchRadialOrientation(); let lookaheadCache; if (radialOrientation) { radialOrientations = []; radialOrientations.push(radialOrientation); lookaheadCache = input; if (scan(tokens.comma)) { radialOrientation = matchRadialOrientation(); if (radialOrientation) { radialOrientations.push(radialOrientation); } else { input = lookaheadCache; } } } return radialOrientations; } function matchRadialOrientation() { let radialType = matchCircle() || matchEllipse(); if (radialType) { radialType.at = matchAtPosition(); } else { const extent = matchExtentKeyword(); if (extent) { radialType = extent; const positionAt = matchAtPosition(); if (positionAt) { radialType.at = positionAt; } } else { const atPosition = matchAtPosition(); if (atPosition) { radialType = { type: "default-radial", at: atPosition }; } else { const defaultPosition = matchPositioning(); if (defaultPosition) { radialType = { type: "default-radial", at: defaultPosition }; } } } } return radialType; } function matchCircle() { const circle = match("shape", /^(circle)/i, 0); if (circle) { circle.style = matchLength() || matchExtentKeyword(); } return circle; } function matchEllipse() { const ellipse = match("shape", /^(ellipse)/i, 0); if (ellipse) { ellipse.style = matchPositioning() || matchDistance() || matchExtentKeyword(); } return ellipse; } function matchExtentKeyword() { return match("extent-keyword", tokens.extentKeywords, 1); } function matchAtPosition() { if (match("position", /^at/, 0)) { const positioning = matchPositioning(); if (!positioning) { error("Missing positioning value"); } return positioning; } } function matchPositioning() { const location = matchCoordinates(); if (location.x || location.y) { return { type: "position", value: location }; } } function matchCoordinates() { return { x: matchDistance(), y: matchDistance() }; } function matchListing(matcher) { let captures = matcher(); const result = []; if (captures) { result.push(captures); while (scan(tokens.comma)) { captures = matcher(); if (captures) { result.push(captures); } else { error("One extra comma"); } } } return result; } function matchColorStop() { const color = matchColor(); if (!color) { error("Expected color definition"); } color.length = matchDistance(); return color; } function matchColor() { return matchHexColor() || matchHSLAColor() || matchHSLColor() || matchRGBAColor() || matchRGBColor() || matchVarColor() || matchLiteralColor(); } function matchLiteralColor() { return match("literal", tokens.literalColor, 0); } function matchHexColor() { return match("hex", tokens.hexColor, 1); } function matchRGBColor() { return matchCall(tokens.rgbColor, () => { return { type: "rgb", value: matchListing(matchNumber) }; }); } function matchRGBAColor() { return matchCall(tokens.rgbaColor, () => { return { type: "rgba", value: matchListing(matchNumber) }; }); } function matchVarColor() { return matchCall(tokens.varColor, () => { return { type: "var", value: matchVariableName() }; }); } function matchHSLColor() { return matchCall(tokens.hslColor, () => { const lookahead = scan(tokens.percentageValue); if (lookahead) { error("HSL hue value must be a number in degrees (0-360) or normalized (-360 to 360), not a percentage"); } const hue = matchNumber(); scan(tokens.comma); let captures = scan(tokens.percentageValue); const sat = captures ? captures[1] : null; scan(tokens.comma); captures = scan(tokens.percentageValue); const light = captures ? captures[1] : null; if (!sat || !light) { error("Expected percentage value for saturation and lightness in HSL"); } return { type: "hsl", value: [hue, sat, light] }; }); } function matchHSLAColor() { return matchCall(tokens.hslaColor, () => { const hue = matchNumber(); scan(tokens.comma); let captures = scan(tokens.percentageValue); const sat = captures ? captures[1] : null; scan(tokens.comma); captures = scan(tokens.percentageValue); const light = captures ? captures[1] : null; scan(tokens.comma); const alpha = matchNumber(); if (!sat || !light) { error("Expected percentage value for saturation and lightness in HSLA"); } return { type: "hsla", value: [hue, sat, light, alpha] }; }); } function matchVariableName() { return scan(tokens.variableName)[1]; } function matchNumber() { return scan(tokens.number)[1]; } function matchDistance() { return match("%", tokens.percentageValue, 1) || matchPositionKeyword() || matchCalc() || matchLength(); } function matchPositionKeyword() { return match("position-keyword", tokens.positionKeywords, 1); } function matchCalc() { return matchCall(tokens.calcValue, () => { let openParenCount = 1; let i = 0; while (openParenCount > 0 && i < input.length) { const char = input.charAt(i); if (char === "(") { openParenCount++; } else if (char === ")") { openParenCount--; } i++; } if (openParenCount > 0) { error("Missing closing parenthesis in calc() expression"); } const calcContent = input.substring(0, i - 1); consume(i - 1); return { type: "calc", value: calcContent }; }); } function matchLength() { return match("px", tokens.pixelValue, 1) || match("em", tokens.emValue, 1); } function match(type, pattern, captureIndex) { const captures = scan(pattern); if (captures) { return { type, value: captures[captureIndex] }; } } function scan(regexp) { let captures, blankCaptures; blankCaptures = /^\s+/.exec(input); if (blankCaptures) { consume(blankCaptures[0].length); } captures = regexp.exec(input); if (captures) { consume(captures[0].length); } return captures; } function consume(size) { input = input.substr(size); } return function(code) { input = code.toString().trim(); if (input.endsWith(";")) { input = input.slice(0, -1); } return getAST(); }; })(); const parseGradient = GradientParser$1.parse.bind(GradientParser$1); var GradientParser = GradientParser || {}; GradientParser.stringify = /* @__PURE__ */ (function() { var visitor = { "visit_linear-gradient": function(node) { return visitor.visit_gradient(node); }, "visit_repeating-linear-gradient": function(node) { return visitor.visit_gradient(node); }, "visit_radial-gradient": function(node) { return visitor.visit_gradient(node); }, "visit_repeating-radial-gradient": function(node) { return visitor.visit_gradient(node); }, "visit_gradient": function(node) { var orientation = visitor.visit(node.orientation); if (orientation) { orientation += ", "; } return node.type + "(" + orientation + visitor.visit(node.colorStops) + ")"; }, "visit_shape": function(node) { var result = node.value, at = visitor.visit(node.at), style = visitor.visit(node.style); if (style) { result += " " + style; } if (at) { result += " at " + at; } return result; }, "visit_default-radial": function(node) { var result = "", at = visitor.visit(node.at); if (at) { result += at; } return result; }, "visit_extent-keyword": function(node) { var result = node.value, at = visitor.visit(node.at); if (at) { result += " at " + at; } return result; }, "visit_position-keyword": function(node) { return node.value; }, "visit_position": function(node) { return visitor.visit(node.value.x) + " " + visitor.visit(node.value.y); }, "visit_%": function(node) { return node.value + "%"; }, "visit_em": function(node) { return node.value + "em"; }, "visit_px": function(node) { return node.value + "px"; }, "visit_calc": function(node) { return "calc(" + node.value + ")"; }, "visit_literal": function(node) { return visitor.visit_color(node.value, node); }, "visit_hex": function(node) { return visitor.visit_color("#" + node.value, node); }, "visit_rgb": function(node) { return visitor.visit_color("rgb(" + node.value.join(", ") + ")", node); }, "visit_rgba": function(node) { return visitor.visit_color("rgba(" + node.value.join(", ") + ")", node); }, "visit_hsl": function(node) { return visitor.visit_color("hsl(" + node.value[0] + ", " + node.value[1] + "%, " + node.value[2] + "%)", node); }, "visit_hsla": function(node) { return visitor.visit_color("hsla(" + node.value[0] + ", " + node.value[1] + "%, " + node.value[2] + "%, " + node.value[3] + ")", node); }, "visit_var": function(node) { return visitor.visit_color("var(" + node.value + ")", node); }, "visit_color": function(resultColor, node) { var result = resultColor, length = visitor.visit(node.length); if (length) { result += " " + length; } return result; }, "visit_angular": function(node) { return node.value + "deg"; }, "visit_directional": function(node) { return "to " + node.value; }, "visit_array": function(elements) { var result = "", size = elements.length; elements.forEach(function(element, i) { result += visitor.visit(element); if (i < size - 1) { result += ", "; } }); return result; }, "visit_object": function(obj) { if (obj.width && obj.height) { return visitor.visit(obj.width) + " " + visitor.visit(obj.height); } return ""; }, "visit": function(element) { if (!element) { return ""; } if (element instanceof Array) { return visitor.visit_array(element); } else if (typeof element === "object" && !element.type) { return visitor.visit_object(element); } else if (element.type) { var nodeVisitor = visitor["visit_" + element.type]; if (nodeVisitor) { return nodeVisitor(element); } else { throw Error("Missing visitor visit_" + element.type); } } else { throw Error("Invalid node."); } } }; return function(root) { return visitor.visit(root); }; })(); const stringifyGradient = GradientParser.stringify.bind(GradientParser); function parseColorStopNodeList(colorStops) { const count = colorStops.length - 1; return colorStops.map((stop, index) => { const value = stop.value; let offset = round(index / count, 3); let color = "#00000000"; switch (stop.type) { case "rgb": color = normalizeColor({ r: Number(value[0] ?? 0), g: Number(value[1] ?? 0), b: Number(value[2] ?? 0) }); break; case "rgba": color = normalizeColor({ r: Number(value[0] ?? 0), g: Number(value[1] ?? 0), b: Number(value[2] ?? 0), a: Number(value[3] ?? 0) }); break; case "literal": color = normalizeColor(stop.value); break; case "hex": color = normalizeColor(`#${stop.value}`); break; } switch (stop.length?.type) { case "%": offset = Number(stop.length.value) / 100; break; } return { offset, color }; }); } function parseLinearGradientNode(node) { let angle = 0; switch (node.orientation?.type) { case "angular": angle = Number(node.orientation.value); break; } return { type: "linear-gradient", angle, stops: parseColorStopNodeList(node.colorStops) }; } function parseRadialGradientNode(node) { node.orientation?.map((item) => { switch (item?.type) { case "shape": case "default-radial": case "extent-keyword": default: return null; } }); return { type: "radial-gradient", stops: parseColorStopNodeList(node.colorStops) }; } function isGradient(cssText) { return cssText.startsWith("linear-gradient(") || cssText.startsWith("radial-gradient("); } function normalizeGradient(cssText) { return parseGradient(cssText).map((node) => { switch (node?.type) { case "linear-gradient": return parseLinearGradientNode(node); case "repeating-linear-gradient": return { ...parseLinearGradientNode(node), repeat: true }; case "radial-gradient": return parseRadialGradientNode(node); case "repeating-radial-gradient": return { ...parseRadialGradientNode(node), repeat: true }; default: return void 0; } }).filter(Boolean); } function normalizeColorFill(fill) { let obj; if (typeof fill === "string") { obj = { color: fill }; } else { obj = { ...fill }; } return { color: normalizeColor(obj.color) }; } function normalizeGradientFill(fill) { let obj; if (typeof fill === "string") { obj = { image: fill }; } else { obj = { ...fill }; } if (obj.image) { const { type, ...props } = normalizeGradient(obj.image)[0] ?? {}; switch (type) { case "radial-gradient": return { radialGradient: props }; case "linear-gradient": return { linearGradient: props }; } } return pick(obj, [ "linearGradient", "radialGradient", "rotateWithShape" ]); } function normalizeImageFill(fill) { let obj; if (typeof fill === "string") { obj = { image: fill }; } else { obj = { ...fill }; } return pick(obj, [ "image", "cropRect", "stretchRect", "tile", "dpi", "opacity", "rotateWithShape" ]); } function normalizePresetFill(fill) { let obj; if (typeof fill === "string") { obj = { preset: fill }; } else { obj = { ...fill }; } if (isNone(obj.foregroundColor)) { delete obj.foregroundColor; } else { obj.foregroundColor = normalizeColor(obj.foregroundColor); } if (isNone(obj.backgroundColor)) { delete obj.backgroundColor; } else { obj.backgroundColor = normalizeColor(obj.backgroundColor); } return pick(obj, [ "preset", "foregroundColor", "backgroundColor" ]); } function isColorFillObject(fill) { return !isNone(fill.color); } function isColorFill(fill) { return typeof fill === "string" ? isColor(fill) : isColorFillObject(fill); } function isGradientFillObject(fill) { return !isNone(fill.image) && isGradient(fill.image) || Boolean(fill.linearGradient) || Boolean(fill.radialGradient); } function isGradientFill(fill) { return typeof fill === "string" ? isGradient(fill) : isGradientFillObject(fill); } function isImageFillObject(fill) { return !isNone(fill.image) && !isGradient(fill.image); } function isImageFill(fill) { return typeof fill === "string" ? !isGradient(fill) : isImageFillObject(fill); } function isPresetFillObject(fill) { return !isNone(fill.preset); } function isPresetFill(fill) { return typeof fill === "string" ? false : isPresetFillObject(fill); } function normalizeFill(fill) { const enabled = fill && typeof fill === "object" ? fill.enabled : void 0; if (isColorFill(fill)) { return clearUndef({ enabled, ...normalizeColorFill(fill) }); } else if (isGradientFill(fill)) { return clearUndef({ enabled, ...normalizeGradientFill(fill) }); } else if (isImageFill(fill)) { return clearUndef({ enabled, ...normalizeImageFill(fill) }); } else if (isPresetFill(fill)) { return clearUndef({ enabled, ...normalizePresetFill(fill) }); } return {}; } function normalizeBackground(background) { if (typeof background === "string") { return { ...normalizeFill(background) }; } else { return { ...normalizeFill(background), ...pick(background, ["fillWithShape"]) }; } } function getDefaultInnerShadow() { return { color: defaultColor, offsetX: 0, offsetY: 0, blurRadius: 1 }; } function normalizeInnerShadow(shadow) { return { ...getDefaultInnerShadow(), ...clearUndef({ ...shadow, color: isNone(shadow.color) ? defaultColor : normalizeColor(shadow.color) }) }; } function getDefaultOuterShadow() { return { ...getDefaultInnerShadow(), scaleX: 1, scaleY: 1 }; } function normalizeOuterShadow(shadow) { return { ...getDefaultOuterShadow(), ...normalizeInnerShadow(shadow) }; } function normalizeSoftEdge(softEdge) { return softEdge; } function normalizeEffect(effect) { return clearUndef({ ...effect, softEdge: isNone(effect.softEdge) ? void 0 : normalizeSoftEdge(effect.softEdge), outerShadow: isNone(effect.outerShadow) ? void 0 : normalizeOuterShadow(effect.outerShadow), innerShadow: isNone(effect.innerShadow) ? void 0 : normalizeInnerShadow(effect.innerShadow) }); } function normalizeForeground(foreground) { if (typeof foreground === "string") { return { ...normalizeFill(foreground) }; } else { return { ...normalizeFill(foreground), ...pick(foreground, ["fillWithShape"]) }; } } const nanoid = () => { return nanoid$1.nanoid(10); }; const idGenerator = nanoid; function normalizeOutline(outline) { if (typeof outline === "string") { return { ...normalizeFill(outline) }; } else { return { ...normalizeFill(outline), ...pick(outline, [ "width", "style", "lineCap", "lineJoin", "headEnd", "tailEnd" ]) }; } } function normalizeShadow(shadow) { if (typeof shadow === "string") { return { color: normalizeColor(shadow) }; } else { return { ...shadow, color: isNone(shadow.color) ? defaultColor : normalizeColor(shadow.color) }; } } function getDefaultShadowStyle() { return { boxShadow: "none" }; } function normalizeShape(shape) { if (typeof shape === "string") { if (shape.startsWith("<svg")) { return { svg: shape }; } else { return { paths: [ { data: shape } ] }; } } else if (Array.isArray(shape)) { return { paths: shape.map((data) => { if (typeof data === "string") { return { data }; } return data; }) }; } else { return shape; } } function getDefaultLayoutStyle() { return { // box overflow: "visible", direction: void 0, display: void 0, boxSizing: void 0, width: void 0, height: void 0, maxHeight: void 0, maxWidth: void 0, minHeight: void 0, minWidth: void 0, // position position: void 0, left: 0, top: 0, right: void 0, bottom: void 0, // border borderTop: void 0, borderLeft: void 0, borderRight: void 0, borderBottom: void 0, borderWidth: 0, border: void 0, // flex flex: void 0, flexBasis: void 0, flexDirection: void 0, flexGrow: void 0, flexShrink: void 0, flexWrap: void 0, justifyContent: void 0, gap: void 0, alignContent: void 0, alignItems: void 0, alignSelf: void 0, // margin marginTop: void 0, marginLeft: void 0, marginRight: void 0, marginBottom: void 0, margin: void 0, // padding paddingTop: void 0, paddingLeft: void 0, paddingRight: void 0, paddingBottom: void 0, padding: void 0 }; } function getDefaultTransformStyle() { return { rotate: 0, scaleX: 1, scaleY: 1, skewX: 0, skewY: 0, translateX: 0, translateY: 0, transform: "none", transformOrigin: "center" }; } function getDefaultElementStyle() { return { ...getDefaultLayoutStyle(), ...getDefaultTransformStyle(), ...getDefaultShadowStyle(), // background backgroundImage: "none", backgroundSize: "auto, auto", backgroundColor: "none", backgroundColormap: "none", // border borderRadius: 0, borderColor: "none", borderStyle: "solid", // outline outlineWidth: 0, outlineOffset: 0, outlineColor: "rgb(0, 0, 0)", outlineStyle: "none", // other visibility: "visible", filter: "none", opacity: 1, pointerEvents: "auto", maskImage: "none" }; } function getDefaultHighlightStyle() { return { highlight: {}, highlightImage: "none", highlightReferImage: "none", highlightColormap: "none", highlightLine: "none", highlightSize: "cover", highlightThickness: "100%" }; } function getDefaultListStyleStyle() { return { listStyle: {}, listStyleType: "none", listStyleImage: "none", listStyleColormap: "none", listStyleSize: "cover", listStylePosition: "outside" }; } function getDefaultTextInlineStyle() { return { ...getDefaultHighlightStyle(), color: "rgb(0, 0, 0)", verticalAlign: "baseline", letterSpacing: 0, wordSpacing: 0, // font fontSize: 14, fontWeight: "normal", fontFamily: "", fontStyle: "normal", fontKerning: "normal", // text textTransform: "none", textOrientation: "mixed", textDecoration: "none" }; } function getDefaultTextLineStyle() { return { ...getDefaultListStyleStyle(), writingMode: "horizontal-tb", textWrap: "wrap", textAlign: "start", textIndent: 0, lineHeight: 1.2 }; } function getDefaultTextStyle() { return { ...getDefaultTextLineStyle(), ...getDefaultTextInlineStyle(), // textStroke textStrokeWidth: 0, textStrokeColor: "rgb(0, 0, 0)" }; } function normalizeStyle(style) { return clearUndef({ ...style, color: isNone(style.color) ? void 0 : normalizeColor(style.color), backgroundColor: isNone(style.backgroundColor) ? void 0 : normalizeColor(style.backgroundColor), borderColor: isNone(style.borderColor) ? void 0 : normalizeColor(style.borderColor), outlineColor: isNone(style.outlineColor) ? void 0 : normalizeColor(style.outlineColor), shadowColor: isNone(style.shadowColor) ? void 0 : normalizeColor(style.shadowColor) }); } function getDefaultStyle() { return { ...getDefaultElementStyle(), ...getDefaultTextStyle() }; } const CRLF_RE = /\r\n|\n\r|\n|\r/; const NORMALIZE_CRLF_RE = new RegExp(`${CRLF_RE.source}|<br\\/>`, "g"); const IS_CRLF_RE = new RegExp(`^(${CRLF_RE.source})$`); const NORMALIZED_CRLF = "\n"; function hasCRLF(content) { return CRLF_RE.test(content); } function isCRLF(char) { return IS_CRLF_RE.test(char); } function normalizeCRLF(content) { return content.replace(NORMALIZE_CRLF_RE, NORMALIZED_CRLF); } function normalizeTextContent(value) { const paragraphs = []; function lastParagraph() { return paragraphs[paragraphs.length - 1]; } function addParagraph(styleOption, fillOption, outlineOption) { const style = styleOption ? normalizeStyle(styleOption) : {}; const fill = fillOption ? normalizeFill(fillOption) : void 0; const outline = outlineOption ? normalizeOutline(outlineOption) : void 0; const paragraph = clearUndef({ ...style, fill, outline, fragments: [] }); if (paragraphs[paragraphs.length - 1]?.fragments.length === 0) { paragraphs[paragraphs.length - 1] = paragraph; } else { paragraphs.push(paragraph); } return paragraph; } function addFragment(content = "", styleOption, fillOption, outlineOption) { const style = styleOption ? normalizeStyle(styleOption) : {}; const fill = fillOption ? normalizeFill(fillOption) : void 0; const outline = outlineOption ? normalizeOutline(outlineOption) : void 0; Array.from(content).forEach((c) => { if (isCRLF(c)) { const { fragments, fill: pFill, outline: pOutline, ...pStyle } = lastParagraph() || addParagraph(); if (!fragments.length) { fragments.push(clearUndef({ ...style, fill, outline, content: NORMALIZED_CRLF })); } addParagraph(pStyle, pFill, pOutline); } else { const paragraph = lastParagraph() || addParagraph(); const fragment = paragraph.fragments[paragraph.fragments.length - 1]; if (fragment) { const { content: content2, fill: fFill, outline: fOutline, ...fStyle } = fragment; if (isEqualObject(fill, fFill) && isEqualObject(outline, fOutline) && isEqualObject(style, fStyle)) { fragment.content = `${content2}${c}`; return; } } paragraph.fragments.push(clearUndef({ ...style, fill, outline, content: c })); } }); } const list = Array.isArray(value) ? value : [value]; list.forEach((p) => { if (typeof p === "string") { addParagraph(); addFragment(p); } else if (isFragmentObject(p)) { const { content, fill: fFill, outline: fOutline, ...fStyle } = p; addParagraph(fStyle, fFill, fOutline); addFragment(content); } else if (isParagraphObject(p)) { const { fragments, fill: pFill, outline: pOutline, ...pStyle } = p; addParagraph(pStyle, pFill, pOutline); fragments.forEach((f) => { const { content, fill: fFill, outline: fOutline, ...fStyle } = f; addFragment(content, fStyle, fFill, fOutline); }); } else if (Array.isArray(p)) { addParagraph(); p.forEach((f) => { if (typeof f === "string") { addFragment(f); } else if (isFragmentObject(f)) { const { content, fill: fFill, outline: fOutline, ...fStyle } = f; addFragment(content, fStyle, fFill, fOutline); } }); } else { console.warn("Failed to parse text content", p); } }); const lastP = lastParagraph(); if (lastP && !lastP.fragments.length) { lastP.fragments.push({ content: "" }); } return paragraphs; } function isParagraphObject(value) { return value && typeof value === "object" && "fragments" in value && Array.isArray(value.fragments); } function isFragmentObject(value) { return value && typeof value === "object" && "content" in value && typeof value.content === "string"; } function normalizeText(value) { if (typeof value === "string" || Array.isArray(value)) { return { content: normalizeTextContent(value) }; } else { return clearUndef({ ...value, content: normalizeTextContent(value.content ?? ""), style: value.style ? normalizeStyle(value.style) : void 0, effects: value.effects ? value.effects.map((v) => normalizeStyle(v)) : void 0, measureDom: value.measureDom, fonts: value.fonts, fill: value.fill ? normalizeFill(value.fill) : void 0, outline: value.outline ? normalizeOutline(value.outline) : void 0 }); } } function textContentToString(value) { return normalizeTextContent(value).map((p) => { const content = normalizeCRLF( p.fragments.flatMap((f) => f.content).join("") ); if (isCRLF(content)) { return ""; } return content; }).join(NORMALIZED_CRLF); } function normalizeVideo(video) { if (typeof video === "string") { return { src: video }; } else { return video; } } function normalizeElement(element) { return clearUndef({ ...element, id: element.id ?? idGenerator(), style: isNone(element.style) ? void 0 : normalizeStyle(element.style), text: isNone(element.text) ? void 0 : normalizeText(element.text), background: isNone(element.background) ? void 0 : normalizeBackground(element.background), shape: isNone(element.shape) ? void 0 : normalizeShape(element.shape), fill: isNone(element.fill) ? void 0 : normalizeFill(element.fill), outline: isNone(element.outline) ? void 0 : normalizeOutline(element.outline), foreground: isNone(element.foreground) ? void 0 : normalizeForeground(element.foreground), shadow: isNone(element.shadow) ? void 0 : normalizeShadow(element.shadow), video: isNone(element.video) ? void 0 : normalizeVideo(element.video), audio: isNone(element.audio) ? void 0 : normalizeAudio(element.audio), effect: isNone(element.effect) ? void 0 : normalizeEffect(element.effect), children: element.children?.map((child) => normalizeElement(child)) }); } function normalizeDocument(doc) { return normalizeElement(doc); } function normalizeFlatDocument(doc) { const children = {}; for (const key in doc.children) { const value = normalizeElement(doc.children[key]); delete value.children; children[key] = value; } return { ...doc, children }; } function flatDocumentToDocument(flatDoc) { const { children, ...restProps } = flatDoc; function toElement(flatElement) { const { parentId, childrenIds, ...element } = flatElement; return { ...element, children: [] }; } const docElementMap =