modern-idoc
Version:
Intermediate document for modern codec libs
1,833 lines (1,791 loc) • 54.3 kB
JavaScript
'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 =