@xrubik/fabric-to-leafer 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +81 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +81 -28
- package/dist/index.mjs.map +1 -1
- package/dist/leafer.cjs +81 -28
- package/dist/leafer.cjs.map +1 -1
- package/dist/leafer.mjs +81 -28
- package/dist/leafer.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/context.js","../src/nodes.js","../src/geometry.js","../src/attributes/transform.js","../src/colors.js","../src/gradient.js","../src/assets.js","../src/pattern.js","../src/attributes/fill.js","../src/attributes/meta.js","../src/attributes/index.js","../src/elements/rect.js","../src/elements/ellipse.js","../src/elements/circle.js","../src/elements/triangle.js","../src/elements/polyline.js","../src/elements/line.js","../src/elements/polygon.js","../src/elements/path.js","../src/attributes/text.js","../src/elements/text.js","../src/elements/image.js","../src/lib.js","../src/elements/group.js","../src/elements/lib.js","../src/elements/button.js","../src/elements/bar.js","../src/elements/placeholder.js","../src/elements/index.js","../src/document.js","../src/convert.js","../src/leafer2fabric.js"],"sourcesContent":["/**\n * 转换上下文:一次 convert 调用对应一个 ctx。\n * 里面放「跨模块共享的东西」:配置、告警收集、资源解析、递归转换函数。\n */\n\nexport function createContext(options = {}) {\n const warnings = []\n\n const resolveAsset = typeof options.resolveAsset === 'function'\n ? options.resolveAsset\n : (path) => path\n\n return {\n options,\n warnings,\n resolveAsset,\n\n /** 收集告警,不打断转换;CLI 可以把 warnings 打到 stderr */\n warn(message) {\n warnings.push(String(message))\n },\n\n /**\n * 递归转换入口,由 convert.js 注入。\n * 这样 group/lib 不需要 import 分发表,避免循环依赖。\n */\n convert: null\n }\n}\n","/**\n * Leafer JSON 节点工厂:只产出纯对象,不 import leafer-ui。\n * 值为 undefined 的字段直接丢弃,避免把空属性写进输出。\n */\nexport function node(tag, props = {}) {\n const result = { tag }\n Object.keys(props).forEach((key) => {\n const value = props[key]\n if (value !== undefined) {\n result[key] = value\n }\n })\n return result\n}\n\n/** 安全取数字,取不到时返回 fallback */\nexport function num(value, fallback = 0) {\n const number = Number(value)\n return Number.isFinite(number) ? number : fallback\n}\n\n/** 取可选的数字:undefined / 非法值返回 undefined,而不是 0 */\nexport function optionalNum(value) {\n if (value === undefined || value === null || value === '') return undefined\n const number = Number(value)\n return Number.isFinite(number) ? number : undefined\n}\n","/**\n * 几何工具:定位、翻转位移、点集处理、Fabric path 转字符串。\n * 这里只做纯计算,不依赖任何渲染引擎。\n */\n\nimport { num, optionalNum } from './nodes.js'\n\n/**\n * Fabric 的 group 子元素坐标是相对组中心的,Leafer 是相对左上角,\n * 所以子元素要加上父级宽高的一半。根节点没有 parent,不加偏移。\n */\nexport function place(node, object, parent, offsetY = 0) {\n const parentWidth = parent ? num(parent.width) : 0\n const parentHeight = parent ? num(parent.height) : 0\n node.x = num(object.left) + parentWidth / 2\n node.y = num(object.top) + parentHeight / 2 + offsetY\n return node\n}\n\n/**\n * 零长度轴上超过这个量级的 scale 只可能是脏数据(CAD 导入端用\n * `目标尺寸 / (max - min)` 算缩放, 除数是 1e-38 级的浮点噪声)。\n * Fabric 自己的包围盒是 0, 所以这个 scale 在 Fabric 里不改变图形。\n */\nconst MAX_DEGENERATE_SCALE = 1e4\n\n/** 零长度轴(浮点误差也算)上的脏 scale 归一化成 ±1(保留翻转的符号) */\nconst DEGENERATE_EXTENT = 1e-6\n\nexport function normalizeScale(scale, extent) {\n if (Math.abs(extent) < DEGENERATE_EXTENT && Math.abs(scale) > MAX_DEGENERATE_SCALE) {\n return scale < 0 ? -1 : 1\n }\n return scale\n}\n\n/** Fabric 的 originX / originY → 比例 */\nconst ORIGIN_FRACTION = {\n left: 0,\n center: 0.5,\n right: 1,\n top: 0,\n bottom: 1\n}\n\n/**\n * 点集元素(polyline / polygon / line)的落点,父级坐标。\n *\n * Fabric 的包围盒把描边算在内(平台全局 strokeUniform):盒宽 = 路径跨度 * scale + strokeWidth,\n * left/top 是原点\n * (originX / originY 那一角)的位置,绘制时以盒中心为基准平移到路径包围盒中心。\n * Leafer 的节点原点是路径包围盒左上角、描边画在盒外,所以落点得按 Fabric 的\n * 变换矩阵反推,否则整条线会按描边宽度的一半错位(带 scale 时偏差还会被放大)。\n */\nexport function pathPlaceOrigin(object, bounds) {\n if (!bounds) {\n return { left: num(object.left), top: num(object.top) }\n }\n if (optionalNum(object.left) === undefined) {\n return { left: bounds.minX, top: bounds.minY }\n }\n const strokeWidth = Math.abs(num(object.strokeWidth))\n const width = bounds.width\n const height = bounds.height\n // 偏离被 Julia 归一化的脏 scale, 这里同样要清掉, 否则落点会被放大到 1e37\n const scaleX = Math.abs(normalizeScale(num(object.scaleX, 1) || 1, width))\n const scaleY = Math.abs(normalizeScale(num(object.scaleY, 1) || 1, height))\n const fractionX = ORIGIN_FRACTION[object.originX === undefined ? 'left' : object.originX] || 0\n const fractionY = ORIGIN_FRACTION[object.originY === undefined ? 'top' : object.originY] || 0\n const angle = num(object.angle) * Math.PI / 180\n const cos = Math.cos(angle)\n const sin = Math.sin(angle)\n const rotate = (x, y) => [cos * x - sin * y, sin * x + cos * y]\n\n // 盒中心相对 left/top 的偏移(Fabric 的变换矩阵就平移到盒中心)。\n // 平台把 strokeUniform 全局打开了, 盒尺寸 = 路径跨度 * scale + 描边(描边不缩放)\n const [offsetX, offsetY] = rotate(\n (0.5 - fractionX) * (width * scaleX + strokeWidth),\n (0.5 - fractionY) * (height * scaleY + strokeWidth)\n )\n // 盒中心 → 路径包围盒左上角(Leafer 节点的本地原点)\n const [pivotX, pivotY] = rotate(-0.5 * width * scaleX, -0.5 * height * scaleY)\n return {\n left: num(object.left) + offsetX + pivotX,\n top: num(object.top) + offsetY + pivotY\n }\n}\n\n/** 点集包围盒;没有有效点时返回 null */\nexport function pointsBounds(points) {\n if (!Array.isArray(points)) return null\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n points.forEach((point) => {\n if (!point) return\n const x = Number(point.x)\n const y = Number(point.y)\n if (!Number.isFinite(x) || !Number.isFinite(y)) return\n if (x < minX) minX = x\n if (x > maxX) maxX = x\n if (y < minY) minY = y\n if (y > maxY) maxY = y\n })\n\n if (minX === Infinity) return null\n return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 去掉相邻的重复点,避免 Leafer 画出零长度线段 */\nexport function dedupePoints(points) {\n const result = []\n const tolerance = 0.001\n for (let i = 0; i < points.length; i += 2) {\n const x = points[i]\n const y = points[i + 1]\n const lastX = result[result.length - 2]\n const lastY = result[result.length - 1]\n if (lastX !== undefined && Math.abs(x - lastX) < tolerance && Math.abs(y - lastY) < tolerance) {\n continue\n }\n result.push(x, y)\n }\n return result\n}\n\n/**\n * Fabric 的 points 是 [{x,y}],Leafer 要扁平数组 [x1,y1,x2,y2]。\n *\n * points 里存的是画布绝对坐标:Fabric 渲染时会先减掉点集包围盒(pathOffset)\n * 再按 left/top 摆放,所以 Leafer 这边必须换成节点本地坐标(减包围盒左上角),\n * 否则整条线会按绝对坐标再叠加一次 left/top,直接跑到画布外。\n *\n * 翻转也在这里烘焙成坐标(path/polyline/polygon 用这种方式,\n * 因为 Leafer 的负 scale 会把描边宽度一起镜像),镜像基准是点集包围盒。\n */\nexport function convertPoints(points, options = {}) {\n const { flipX = false, flipY = false } = options\n const bounds = pointsBounds(points)\n if (!bounds) {\n return []\n }\n\n const result = []\n points.forEach((point) => {\n if (!point) return\n let x = Number(point.x)\n let y = Number(point.y)\n if (!Number.isFinite(x) || !Number.isFinite(y)) {\n return\n }\n x -= bounds.minX\n y -= bounds.minY\n if (flipX) x = bounds.width - x\n if (flipY) y = bounds.height - y\n result.push(x, y)\n })\n\n return dedupePoints(result)\n}\n\n/** 判断这种元素是不是把翻转烘焙进几何,而不是用 scale 取负 */\nexport const FLIP_BAKED_TYPES = ['path', 'polyline', 'polygon', 'line']\n\nexport function shouldBakeFlip(object) {\n return !!object && FLIP_BAKED_TYPES.includes(object.type)\n}\n\n/**\n * Fabric 的 path 是 ['M', x, y, 'L', ...] 或 [{ command }] 数组,\n * 转成 SVG path 字符串。数字保留 4 位小数,避免输出一大串浮点尾数。\n */\nexport function convertPathData(pathData, object) {\n if (typeof pathData === 'string') {\n return pathData\n }\n if (!Array.isArray(pathData)) {\n return ''\n }\n\n const bakeFlip = shouldBakeFlip(object) && (object.flipX === true || object.flipY === true)\n const width = num(object && object.width)\n const height = num(object && object.height)\n\n return pathData.map((command) => {\n if (!Array.isArray(command)) {\n return String(command)\n }\n\n const next = command.slice()\n if (bakeFlip) {\n const type = String(next[0] || '')\n // A/a 命令的前 5 个参数不是坐标,从第 6 个开始才是 x,y\n const startIndex = /[Aa]/.test(type) ? 6 : 1\n for (let i = startIndex; i < next.length - 1; i += 2) {\n if (typeof next[i] === 'number' && typeof next[i + 1] === 'number') {\n if (object.flipX === true) next[i] = width - next[i]\n if (object.flipY === true) next[i + 1] = height - next[i + 1]\n }\n }\n // H/V 只有一个坐标\n if (/[Hh]/.test(type) && object.flipX === true && typeof next[1] === 'number') {\n next[1] = width - next[1]\n }\n if (/[Vv]/.test(type) && object.flipY === true && typeof next[1] === 'number') {\n next[1] = height - next[1]\n }\n }\n\n return next\n .map((item) => (typeof item === 'number' ? Number(item.toFixed(4)) : item))\n .join(' ')\n }).join(' ')\n}\n\n/**\n * Fabric 的 originX/originY 组合 → Leafer 的 around 九宫格。\n * 两边都是「旋转/缩放围绕哪个点」,但命名不同。\n */\nexport function aroundOf(object) {\n const originX = object.originX === undefined ? 'left' : object.originX\n const originY = object.originY === undefined ? 'top' : object.originY\n const map = {\n left: { top: 'top-left', center: 'left', bottom: 'bottom-left' },\n center: { top: 'top', center: 'center', bottom: 'bottom' },\n right: { top: 'top-right', center: 'right', bottom: 'bottom-right' }\n }\n return (map[originX] && map[originX][originY]) || 'top-left'\n}\n\n/** Leafer 的 around 取值 → 相对包围盒的比例 */\nconst AROUND_FRACTION = {\n 'top-left': { x: 0, y: 0 },\n top: { x: 0.5, y: 0 },\n 'top-right': { x: 1, y: 0 },\n left: { x: 0, y: 0.5 },\n center: { x: 0.5, y: 0.5 },\n right: { x: 1, y: 0.5 },\n 'bottom-left': { x: 0, y: 1 },\n bottom: { x: 0.5, y: 1 },\n 'bottom-right': { x: 1, y: 1 }\n}\n\n/**\n * around → 相对包围盒的比例。\n * 字符串是 Leafer 的方位名; 对象是显式点, type 为 percent 时本身就是比例,\n * 否则是像素值, 换算成比例。认不出来时按 Leafer 默认的左上角。\n */\nexport function aroundFraction(around, width, height) {\n if (around && typeof around === 'object') {\n const x = num(around.x)\n const y = num(around.y)\n if (around.type === 'percent') {\n return { x, y }\n }\n return { x: width ? x / width : 0, y: height ? y / height : 0 }\n }\n return AROUND_FRACTION[around] || AROUND_FRACTION['top-left']\n}\n\n/** 节点自身坐标系里的包围盒左上角在 (0,0) 还是别处, 由子元素决定 */\nfunction innerBoxOf(node, fallback) {\n const children = Array.isArray(node.children) ? node.children : null\n if (children && children.length) {\n return unionBoxes(children.map((child) => nodeBox(child)))\n }\n // 负宽高在 Leafer 里会被改写成\"正宽高 + 取反 scale\", 包围盒永远从 0 起算\n const width = optionalNum(node.width) !== undefined ? optionalNum(node.width) : optionalNum(fallback && fallback.width)\n const height = optionalNum(node.height) !== undefined ? optionalNum(node.height) : optionalNum(fallback && fallback.height)\n return { x: 0, y: 0, width: Math.abs(width || 0), height: Math.abs(height || 0) }\n}\n\n/**\n * 节点在父级坐标系里的包围盒, 算法和 Leafer 一致:\n * 局部矩阵 = 旋转 · 斜切 · 缩放, 围绕点固定在 (x, y), 再作用到自身包围盒四角。\n *\n * fallback 是 Fabric 原始对象: 文本没写死宽高时 Leafer 会自适应,\n * 转换后的节点上没有 width/height, 用它兜底估算组尺寸。\n */\nexport function nodeBox(node, fallback) {\n const inner = innerBoxOf(node, fallback)\n const around = aroundFraction(node.around, inner.width, inner.height)\n const aroundX = inner.x + around.x * inner.width\n const aroundY = inner.y + around.y * inner.height\n // 和 Leafer 的 setLayout 完全一致: rotate -> skew -> scale\n const rotation = num(node.rotation) * Math.PI / 180\n const scaleX = node.scaleX === undefined ? 1 : num(node.scaleX, 1)\n const scaleY = node.scaleY === undefined ? 1 : num(node.scaleY, 1)\n const skewX = num(node.skewX) * Math.PI / 180\n const skewY = num(node.skewY) * Math.PI / 180\n const cosR = Math.cos(rotation)\n const sinR = Math.sin(rotation)\n let a\n let b\n let c\n let d\n if (skewX || skewY) {\n a = (cosR + skewY * -sinR) * scaleX\n b = (sinR + skewY * cosR) * scaleX\n c = (-sinR + skewX * cosR) * scaleY\n d = (cosR + skewX * sinR) * scaleY\n } else {\n a = cosR * scaleX\n b = sinR * scaleX\n c = -sinR * scaleY\n d = cosR * scaleY\n }\n const x = num(node.x)\n const y = num(node.y)\n const corners = [\n [inner.x, inner.y],\n [inner.x + inner.width, inner.y],\n [inner.x + inner.width, inner.y + inner.height],\n [inner.x, inner.y + inner.height]\n ]\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n corners.forEach((corner) => {\n const dx = corner[0] - aroundX\n const dy = corner[1] - aroundY\n const px = x + a * dx + c * dy\n const py = y + b * dx + d * dy\n if (px < minX) minX = px\n if (px > maxX) maxX = px\n if (py < minY) minY = py\n if (py > maxY) maxY = py\n })\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 多个包围盒取并集 */\nexport function unionBoxes(boxes) {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n boxes.forEach((box) => {\n if (!box) return\n if (box.x < minX) minX = box.x\n if (box.y < minY) minY = box.y\n if (box.x + box.width > maxX) maxX = box.x + box.width\n if (box.y + box.height > maxY) maxY = box.y + box.height\n })\n if (minX === Infinity) return { x: 0, y: 0, width: 0, height: 0 }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 这些类型的负宽高只取绝对值: Fabric 里文字是重新量尺寸的, 不会镜像字模 */\nconst ABS_ONLY_TYPES = new Set(['text', 'i-text', 'itext', 'textbox', 'group'])\n\n/**\n * Fabric 的宽高允许是负数(编辑器把拖拽缩放的 scale 烘焙进了 width/height)。\n * Leafer 只认正宽高, 收到负值会自己改成 -scaleX 并打警告, 而转换器随后又要写\n * 自己的 scaleX, 两边抢次序 —— 结果是镜像丢失或位置错一个宽。\n * 这里统一改成\"正宽高\", 图形类把符号并进 scaleX/scaleY(和 Fabric 的镜像渲染一致),\n * 文字/组只取绝对值(Fabric 里文字不镜像, 组的宽高只是元数据)。\n */\nexport function normalizeSizeSign(object) {\n if (!object || typeof object !== 'object') return object\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n const signX = width !== undefined && width < 0 ? -1 : 1\n const signY = height !== undefined && height < 0 ? -1 : 1\n if (signX === 1 && signY === 1) return object\n const normalized = { ...object }\n if (width !== undefined) normalized.width = Math.abs(width)\n if (height !== undefined) normalized.height = Math.abs(height)\n if (ABS_ONLY_TYPES.has(object.type)) return normalized\n normalized.scaleX = (object.scaleX === undefined ? 1 : num(object.scaleX, 1)) * signX\n normalized.scaleY = (object.scaleY === undefined ? 1 : num(object.scaleY, 1)) * signY\n return normalized\n}\n\n/** 翻转后为了让包围盒位置不变,x/y 需要补偿的位移 */\nexport function flipOffset(size, scale, originFraction) {\n return size * Math.abs(scale) * (1 - 2 * originFraction)\n}\n","/**\n * 变换属性:位置之外的 rotation / scale / skew / 翻转 / 透明度 / 可见性。\n * 位置(x/y)由各元素调用 geometry.place 设置,这里只处理围绕点之后的变换。\n */\n\nimport { num, optionalNum } from '../nodes.js'\nimport { aroundOf, shouldBakeFlip, pointsBounds, normalizeScale } from '../geometry.js'\n\n/** originX/originY 对应的比例,用于算围绕点和翻转后的位置补偿 */\nconst ORIGIN_FRACTION = {\n left: 0,\n center: 0.5,\n right: 1,\n top: 0,\n bottom: 1\n}\n\n/**\n * 零长度轴上的脏 scale 归一化成 ±1, 否则 Leafer 会把描边一起放大\n * (实测 scaleX 7e37 + strokeWidth 4 → worldStrokeBounds 宽 2.8e38),\n * 编辑态的选中框 / 组包围盒直接炸掉。\n */\n\n/** 落点由 geometry.pathPlaceOrigin 负责的点集类型 */\nconst PATH_PLACED_TYPES = ['polyline', 'polygon', 'line']\n\n/**\n * Fabric 这一层全局开了 strokeUniform(platform/canvas/config.js): 描边不随 scale 放大。\n * Leafer 没有这个开关, 描边会被节点的 scale 一起拉宽 —— 宽高只有零点几像素的\n * CAD 线放大几百倍后就成了粗带子。所以点集元素把 scale 直接烘焙进 points、\n * 节点 scale 归 1, 描边保持原宽度。\n */\nfunction bakePointsScale(node, object, scaleX, scaleY) {\n if (!PATH_PLACED_TYPES.includes(object.type)) return false\n if (!Array.isArray(node.points) || !node.points.length) return false\n const absX = Math.abs(scaleX)\n const absY = Math.abs(scaleY)\n // 负 scale 也要烘焙: 节点围绕点是左上角, 留个负 scale 会绕左上角镜像,\n // 整个图形左移一个宽度(实测 43.89 宽的多边形差 43.89)。\n const mirrorX = scaleX < 0\n const mirrorY = scaleY < 0\n if (absX === 1 && absY === 1 && !mirrorX && !mirrorY) return false\n\n node.points = node.points.map((value, index) => (index % 2 === 0 ? value * absX : value * absY))\n if (node.width !== undefined) node.width = Math.abs(num(node.width)) * absX\n if (node.height !== undefined) node.height = Math.abs(num(node.height)) * absY\n // 镜像按烘焙后的宽高在自己的包围盒里翻, 和 Fabric 绕中心翻完包围盒不变一致\n if (mirrorX) {\n const width = node.width !== undefined ? Math.abs(num(node.width)) : maxOf(node.points, 0)\n node.points = node.points.map((value, index) => (index % 2 === 0 ? width - value : value))\n }\n if (mirrorY) {\n const height = node.height !== undefined ? Math.abs(num(node.height)) : maxOf(node.points, 1)\n node.points = node.points.map((value, index) => (index % 2 === 1 ? height - value : value))\n }\n return true\n}\n\n/** 点集在某个轴上的最大值(宽高没写时兜底) */\nfunction maxOf(points, axis) {\n let max = -Infinity\n for (let i = axis; i < points.length; i += 2) {\n if (points[i] > max) max = points[i]\n }\n return Number.isFinite(max) ? max : 0\n}\n\n/** 元素自身的几何长度: 点集用包围盒, 其它元素用 fabric 的 width/height */\nfunction extentOf(object) {\n if (Array.isArray(object.points)) {\n const bounds = pointsBounds(object.points)\n return bounds ? { x: bounds.width, y: bounds.height } : null\n }\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n if (width === undefined && height === undefined) return null\n return { x: width, y: height }\n}\n\nexport function applyTransform(node, object, ctx) {\n // 旋转:Fabric 的 angle 是角度,Leafer 的 rotation 也是角度\n if (optionalNum(object.angle) !== undefined) {\n node.rotation = num(object.angle)\n }\n\n // 围绕点必须显式给,否则 Leafer 默认中心旋转,和 Fabric 对不上。\n // 组在 convertGroup 里已经按子元素实际包围盒算好了,这里不要覆盖。\n if (node.around === undefined) node.around = aroundOf(object)\n\n const extent = extentOf(object)\n const scaleX = normalizeScale(\n object.scaleX === undefined ? 1 : num(object.scaleX, 1),\n extent && extent.x\n )\n const scaleY = normalizeScale(\n object.scaleY === undefined ? 1 : num(object.scaleY, 1),\n extent && extent.y\n )\n // 翻转:path / polyline / polygon 在几何层面已经烘焙过,其余用负 scale 表达\n const baked = shouldBakeFlip(object)\n const scaleXFinal = !baked && object.flipX === true ? -Math.abs(scaleX) : scaleX\n const scaleYFinal = !baked && object.flipY === true ? -Math.abs(scaleY) : scaleY\n\n // 点集元素的 scale 烘焙进几何(描边不跟着变粗), 节点 scale 归 1\n const bakedScale = bakePointsScale(node, object, scaleXFinal, scaleYFinal)\n\n node.scaleX = bakedScale ? 1 : scaleXFinal\n // button 的 scaleY 已由 convertButton 烘焙进几何, 不能再作用到组上;\n // scaleY 为 0 / null 时几何仍按 1 倍高度生成,这里也必须保持 1,否则按钮不可见。\n node.scaleY = object.type === 'button' || bakedScale ? 1 : scaleYFinal\n applyPosition(node, object, scaleXFinal, node.scaleY)\n\n // 斜切:Fabric 和 Leafer 都用弧度\n if (object.skewX) node.skewX = num(object.skewX)\n if (object.skewY) node.skewY = num(object.skewY)\n\n if (object.opacity !== undefined) {\n node.opacity = num(object.opacity, 1)\n }\n if (object.visible === false) {\n node.visible = false\n }\n\n return node\n}\n\n/**\n * 位置修正。\n *\n * Fabric 的旋转/缩放中心是\"原点向尺寸中心的对角点\",left/top 本身不动;Leafer 的\n * x/y 则是围绕点的位置,旋转、翻转都绕围绕点做。两者只在 angle 为 0 且没翻转时\n * 等价,所以有旋转或翻转时要按变换矩阵反推围绕点:\n *\n * x = 原点 + R·(off·尺寸) + R·S·(A - 尺寸/2)\n *\n * off 是\"原点 → 尺寸中心\"的比例,A 是围绕点在局部坐标里的位置。\n * angle 为 0 时它退化成\"按原点比例补偿一次位移\",和以前的结果完全一致;\n * angle 为 180° 时旋转本身就把该轴镜像了,补偿量正好抵消 —— 以前会多补一倍宽高,\n * 翻转过的组(比如 180° + flipX 的图元)会整块错位一个图元的宽度。\n */\nfunction applyPosition(node, object, scaleX, scaleY) {\n if (node.x === undefined || node.y === undefined) return\n // 点集元素(polyline / polygon / line)的落点已按 Fabric 的变换矩阵算好\n // (geometry.pathPlaceOrigin),这边再补偿一次会重复位移\n if (PATH_PLACED_TYPES.includes(object.type)) return\n\n const width = num(object.width)\n const height = num(object.height)\n const fractionX = ORIGIN_FRACTION[object.originX === undefined ? 'left' : object.originX]\n const fractionY = ORIGIN_FRACTION[object.originY === undefined ? 'top' : object.originY]\n if (fractionX === undefined || fractionY === undefined) return\n // 只有旋转或翻转会改变包围盒落点, 其余情况保持原值, 避免浮点尾数污染 JSON\n const single = scaleX > 0 && scaleY > 0 && !num(node.rotation, 0)\n if (single) return\n\n const angle = num(node.rotation, 0) * Math.PI / 180\n const cos = Math.cos(angle)\n const sin = Math.sin(angle)\n const rotate = (x, y) => [cos * x - sin * y, sin * x + cos * y]\n\n // 原点 → 尺寸中心的偏移(Fabric 绕这一点旋转/缩放)\n const [centerX, centerY] = rotate(\n (0.5 - fractionX) * Math.abs(scaleX) * width,\n (0.5 - fractionY) * Math.abs(scaleY) * height\n )\n // 围绕点相对尺寸中心的偏移(Leafer 绕这一点做变换)\n const [shiftX, shiftY] = rotate(\n scaleX * (fractionX * width - width / 2),\n scaleY * (fractionY * height - height / 2)\n )\n\n node.x = num(node.x) + centerX + shiftX\n node.y = num(node.y) + centerY + shiftY\n}\n","/**\n * 颜色工具:Fabric 的颜色写法比 Leafer 宽松,这里统一成 Leafer 能吃的格式。\n * - `#RRGGBBAA` → `rgba(r,g,b,a)`\n * - `rgba(r,g,b,128)` 这种 0~255 的 alpha → 0~1\n * - 其余原样返回\n */\n\nexport function normalizeColor(color) {\n if (typeof color !== 'string') {\n return color\n }\n const value = color.trim()\n\n // rgba/rgb 里 alpha 可能是 0~255(Fabric 老数据),统一到 0~1\n const rgba = value.match(/^rgba?\\(\\s*([^)]+)\\)$/i)\n if (rgba) {\n const parts = rgba[1].split(',').map((item) => item.trim())\n if (parts.length === 4) {\n const alpha = Number(parts[3])\n if (Number.isFinite(alpha) && alpha > 1) {\n const normalized = Math.max(0, Math.min(1, alpha / 255))\n return `rgba(${parts[0]},${parts[1]},${parts[2]},${Math.round(normalized * 1000) / 1000})`\n }\n }\n return value\n }\n\n // 8 位 hex:前 6 位是颜色,后 2 位是 alpha\n const rgbaHex = value.match(/^#([0-9a-fA-F]{8})$/)\n if (!rgbaHex) {\n return value\n }\n const hex = rgbaHex[1]\n const alpha = parseInt(hex.slice(6, 8), 16)\n if (alpha === 255) {\n return '#' + hex.slice(0, 6)\n }\n const r = parseInt(hex.slice(0, 2), 16)\n const g = parseInt(hex.slice(2, 4), 16)\n const b = parseInt(hex.slice(4, 6), 16)\n return `rgba(${r},${g},${b},${Math.round((alpha / 255) * 1000) / 1000})`\n}\n\n/** 判断颜色是否完全透明(含空值、transparent、none、alpha=0) */\nexport function isTransparentColor(color) {\n if (color === '' || color === null || color === undefined) {\n return true\n }\n if (typeof color !== 'string') {\n return false\n }\n const value = color.trim().toLowerCase()\n if (value === 'transparent' || value === 'none') {\n return true\n }\n if (/^rgba\\([^)]*,\\s*0(?:\\.0+)?\\s*\\)$/.test(value)) {\n return true\n }\n if (/^#([0-9a-f]{6})00$/.test(value)) {\n return true\n }\n return false\n}\n","/**\n * Fabric 渐变 → Leafer 渐变。\n * Fabric: { type, colorStops: [{ offset, color }], coords: { x1,y1,x2,y2,r1,r2 } }\n * Leafer: { type, stops: [{ offset, color }], from: {type,x,y}, to: {type,x,y} }\n *\n * 两边都兼容:如果传入的已经是 Leafer 结构(from/to/stops),直接沿用。\n */\n\nimport { normalizeColor } from './colors.js'\n\nfunction hasNumber(value) {\n return value !== undefined && value !== null && Number.isFinite(Number(value))\n}\n\n/** 判断一个 fill 值是不是渐变对象 */\nexport function isGradient(value) {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nexport function convertGradient(gradient, ctx) {\n const sourceStops = gradient.colorStops || gradient.stops || []\n const stops = sourceStops.map((item) => ({\n offset: Number(item.offset) || 0,\n color: normalizeColor(item.color)\n }))\n\n const coords = gradient.coords || {}\n const from = gradient.from || {}\n const to = gradient.to || {}\n\n const paint = {\n // Fabric 只有 linear / radial 两种;Leafer 还支持 angular/conic\n type: gradient.type || 'linear',\n stops\n }\n\n // Fabric 的 coords 是相对对象包围盒的 0~1 比例,Leafer 用 percent 表达同一含义\n paint.from = {\n type: 'percent',\n x: hasNumber(from.x) ? Number(from.x) : (hasNumber(coords.x1) ? Number(coords.x1) : 0),\n y: hasNumber(from.y) ? Number(from.y) : (hasNumber(coords.y1) ? Number(coords.y1) : 0)\n }\n paint.to = {\n type: 'percent',\n x: hasNumber(to.x) ? Number(to.x) : (hasNumber(coords.x2) ? Number(coords.x2) : 1),\n y: hasNumber(to.y) ? Number(to.y) : (hasNumber(coords.y2) ? Number(coords.y2) : 0)\n }\n\n if (paint.type === 'radial') {\n // Fabric 径向渐变用 r2 表示半径;x2/y2 常常和圆心重合\n const radius = hasNumber(coords.r2)\n ? Number(coords.r2)\n : (hasNumber(gradient.r2) ? Number(gradient.r2) : 0.5)\n\n if (paint.from.x === paint.to.x && paint.from.y === paint.to.y) {\n paint.to = {\n type: 'percent',\n x: paint.from.x + Math.max(0.0001, radius),\n y: paint.from.y\n }\n }\n }\n\n // 记录原始结构,方便排查转换问题(不参与渲染)\n if (ctx && ctx.options && ctx.options.debug) {\n paint.__fabricGradient = gradient\n }\n\n return paint\n}\n","/**\n * 资源路径解析。\n * 转换器不知道平台的资源系统(OSS / 本地 fs / 相对路径),\n * 只把「逻辑路径」交给 options.resolveAsset,由调用方决定最终 URL。\n */\n\n/** data/blob/http/绝对路径直接透传,不经过平台资源系统 */\nconst ABSOLUTE = /^(data:|blob:|https?:\\/\\/|\\/fs\\/open|\\/)/i\n\nexport function resolveImageUrl(src, rsrc, ctx) {\n const raw = typeof src === 'string' && src\n ? src\n : (rsrc === undefined || rsrc === null ? '' : String(rsrc))\n\n if (!raw) {\n return undefined\n }\n if (ABSOLUTE.test(raw)) {\n return raw\n }\n\n // 统一成 image/xxx 这种平台约定的逻辑路径\n let path = raw.replace(/^\\.?\\//, '')\n if (!path.startsWith('image/')) {\n path = 'image/' + path\n }\n return ctx.resolveAsset(path, 'image')\n}\n","/**\n * Fabric 的 Pattern 填充 → Leafer 的图片 paint。\n * Fabric: { type: 'pattern', source, repeat, offsetX, offsetY, patternTransform }\n * Leafer: { type: 'image', url, mode, repeat, offset, scale, rotation }\n *\n * source 一般是导出时内联的 data URL,也兼容平台逻辑路径(走 resolveAsset)。\n */\n\nimport { resolveImageUrl } from './assets.js'\n\n/** 判断一个 fill / stroke 值是不是 Fabric 的 Pattern 对象 */\nexport function isPattern(value) {\n return !!value && typeof value === 'object' && !Array.isArray(value) &&\n (value.type === 'pattern' ||\n (typeof value.source === 'string' && value.source !== '' && value.repeat !== undefined))\n}\n\n/** patternTransform 是 [a, b, c, d, e, f] → 平移 / 缩放 / 旋转 */\nfunction decomposeTransform(transform) {\n const list = Array.isArray(transform) ? transform.map(Number) : []\n if (list.length < 6 || list.some((item) => !Number.isFinite(item))) {\n return undefined\n }\n const [a, b, c, d, e, f] = list\n if (a === 1 && b === 0 && c === 0 && d === 1 && e === 0 && f === 0) {\n return undefined\n }\n return {\n scaleX: Math.hypot(a, b),\n scaleY: Math.hypot(c, d),\n rotation: (Math.atan2(b, a) * 180) / Math.PI,\n offsetX: e,\n offsetY: f\n }\n}\n\n/** Fabric 的 repeat → Leafer 的 mode + repeat */\nfunction applyRepeat(paint, repeat) {\n if (repeat === 'repeat-x') {\n paint.mode = 'repeat'\n paint.repeat = 'x'\n } else if (repeat === 'repeat-y') {\n paint.mode = 'repeat'\n paint.repeat = 'y'\n } else if (repeat === 'no-repeat') {\n // 只画一张,位置和大小由 offset / scale 决定\n paint.mode = 'normal'\n } else {\n paint.mode = 'repeat'\n paint.repeat = true\n }\n}\n\n/** Fabric 的 Pattern → Leafer 的 IImagePaint */\nexport function convertPattern(pattern, ctx) {\n const url = resolveImageUrl(pattern.source, undefined, ctx)\n if (!url) {\n if (ctx && typeof ctx.warn === 'function') {\n ctx.warn('pattern 填充缺少 source,已当作透明')\n }\n return 'transparent'\n }\n\n const paint = { type: 'image', url }\n applyRepeat(paint, pattern.repeat)\n\n const offsetX = Number(pattern.offsetX) || 0\n const offsetY = Number(pattern.offsetY) || 0\n const transform = decomposeTransform(pattern.patternTransform)\n const x = offsetX + (transform ? transform.offsetX : 0)\n const y = offsetY + (transform ? transform.offsetY : 0)\n if (x || y) {\n paint.offset = { x, y }\n }\n if (transform) {\n if (transform.scaleX !== 1 || transform.scaleY !== 1) {\n paint.scale = { x: transform.scaleX, y: transform.scaleY }\n }\n if (transform.rotation) {\n paint.rotation = transform.rotation\n }\n }\n return paint\n}\n","/**\n * 外观属性:fill / stroke / 虚线 / 阴影 / 混合模式。\n * Fabric 的 fill 可能是颜色字符串,也可能是渐变对象;\n * 空值统一成 transparent,避免 Leafer 把 undefined 当成黑色。\n */\n\nimport { normalizeColor, isTransparentColor } from '../colors.js'\nimport { convertGradient, isGradient } from '../gradient.js'\nimport { convertPattern, isPattern } from '../pattern.js'\nimport { optionalNum } from '../nodes.js'\n\n/** 把 Fabric 的 fill 值转成 Leafer 的 paint 值 */\nexport function paintOf(value, ctx) {\n if (value === undefined || value === null || value === '') {\n return 'transparent'\n }\n if (isPattern(value)) {\n return convertPattern(value, ctx)\n }\n if (isGradient(value)) {\n return convertGradient(value, ctx)\n }\n return normalizeColor(value)\n}\n\n/** fill / stroke / 描边宽度 / 虚线 / 阴影,元素模块可以直接复用 */\nexport function applyPaint(node, object, ctx) {\n if (object.fill !== undefined && node.fill === undefined) {\n node.fill = paintOf(object.fill, ctx)\n }\n if (object.stroke !== undefined && object.stroke !== null && object.stroke !== '') {\n node.stroke = paintOf(object.stroke, ctx)\n const strokeWidth = optionalNum(object.strokeWidth)\n if (strokeWidth !== undefined) {\n node.strokeWidth = strokeWidth\n }\n if (Array.isArray(object.strokeDashArray) && object.strokeDashArray.length) {\n node.dashPattern = object.strokeDashArray\n }\n }\n if (object.shadow !== undefined) {\n const shadow = convertShadow(object.shadow)\n if (shadow) node.shadow = shadow\n }\n}\n\n/**\n * Fabric 的 backgroundColor 是图形底层的背景色,Leafer 没有同名属性。\n * 当 fill 透明时用它兜底,避免旧画面的背景色完全消失。\n */\nexport function applyBackgroundFallback(node, object, ctx) {\n if (!object.backgroundColor) {\n return\n }\n if (isTransparentColor(node.fill)) {\n node.fill = paintOf(object.backgroundColor, ctx)\n }\n}\n\n/** Fabric 阴影 → Leafer 阴影数组(Leafer 只认数组形式) */\nexport function convertShadow(shadow) {\n if (!shadow) {\n return undefined\n }\n const list = Array.isArray(shadow) ? shadow : [shadow]\n return list.filter(Boolean).map((item) => ({\n x: Number(item.offsetX !== undefined ? item.offsetX : (item.x || 0)),\n y: Number(item.offsetY !== undefined ? item.offsetY : (item.y || 0)),\n blur: Number(item.blur || 0),\n color: normalizeColor(item.color || 'rgba(0,0,0,0.5)'),\n spread: Number(item.spread || 0)\n }))\n}\n\n/** Fabric 的 globalCompositeOperation 直接映射成 Leafer 的 blendMode */\nexport function applyBlendMode(node, object) {\n const mode = object.globalCompositeOperation\n if (mode && mode !== 'source-over') {\n node.blendMode = mode\n }\n}\n\n/** 描边端点:Fabric butt/square/round → Leafer(butt 是默认值,不输出) */\nexport function strokeCapOf(value) {\n if (!value || value === 'butt') return undefined\n return value === 'square' ? 'square' : 'round'\n}\n\n/** 描边拐角:miter/round/bevel 两边一致 */\nexport function strokeJoinOf(value) {\n if (!value) return undefined\n return ['miter', 'round', 'bevel'].includes(value) ? value : undefined\n}\n","/**\n * 元数据透传:平台自定义字段原样带到 Leafer JSON 里。\n * 这些字段由平台启动时 UI.addAttr 注册,转换器只负责搬运,不解释含义。\n * 注意:这里不能 import leafer-ui,否则转换器就和引擎绑死了。\n */\n\nconst PASSTHROUGH_KEYS = [\n 'name',\n 'libName',\n 'param',\n 'originParam',\n 'noScaleWithParent',\n 'rsrc',\n 'config',\n 'template',\n 'script',\n 'props',\n 'keyboardEvent',\n 'dyn',\n 'action',\n 'ctxmenu',\n 'hasLocalValue',\n 'disabled'\n]\n\n/**\n * Fabric 类型 → 平台(leafer) 类型。\n * i-text 转成自定义元素 IText(文字铺满包围盒), 平台上它是独立图元类型 i-text,\n * 编辑器里对应\"拉伸文字\"工具。\n */\nconst TYPE_MAP = {\n 'i-text': 'i-text',\n itext: 'i-text'\n}\n\nexport function applyMeta(node, object, ctx) {\n // type 一定要写:平台运行态靠它区分业务类型(button/bar/chart…)\n node.type = TYPE_MAP[object.type] || object.type\n\n PASSTHROUGH_KEYS.forEach((key) => {\n if (object[key] !== undefined) {\n node[key] = object[key]\n }\n })\n\n // 运行态默认不可拖拽,编辑器再单独打开\n if (!ctx || !ctx.options || ctx.options.draggable !== true) {\n node.draggable = false\n }\n\n const strokeCap = object.strokeLineCap\n if (strokeCap && strokeCap !== 'butt') {\n node.strokeCap = strokeCap === 'square' ? 'square' : 'round'\n }\n const strokeJoin = object.strokeLineJoin\n if (strokeJoin && ['miter', 'round', 'bevel'].includes(strokeJoin)) {\n node.strokeJoin = strokeJoin\n }\n\n return node\n}\n","/**\n * 属性装配入口。\n * 元素模块只负责「这个类型有哪些几何字段」,公共属性统一在这里补,\n * 避免每个元素都复制一遍 rotation / scale / opacity 这些逻辑。\n */\n\nimport { applyTransform } from './transform.js'\nimport { applyPaint, applyBackgroundFallback, applyBlendMode } from './fill.js'\nimport { applyMeta } from './meta.js'\n\n/**\n * 内容由平台浮层(DOM)绘制的类型:画布上的节点只当锚点,不画填充和描边,\n * 否则图表 / 控件底下会多出一块底色和边框。\n */\nconst OVERLAY_TYPES = new Set(['chart', 'component'])\n\n/** 元素自身已经设置过 fill 的类型,不再做 backgroundColor 兜底 */\nconst NO_FILL_FALLBACK = new Set([\n 'text', 'i-text', 'textbox', 'group', 'lib', 'image', 'rubik-image',\n 'rubik-gif', 'button', 'bar', 'chart', 'component', 'line'\n])\n\n/**\n * 给节点补全公共属性。\n * 顺序有讲究:先变换(会影响 x/y),再外观,最后元数据。\n */\nexport function applyCommon(node, object, ctx) {\n applyTransform(node, object, ctx)\n if (!OVERLAY_TYPES.has(object.type)) {\n applyPaint(node, object, ctx)\n }\n\n if (!NO_FILL_FALLBACK.has(object.type)) {\n applyBackgroundFallback(node, object, ctx)\n }\n\n applyBlendMode(node, object)\n applyMeta(node, object, ctx)\n return node\n}\n","/** 矩形(Fabric rect)→ Leafer Rect */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\n/** Fabric 的 rx/ry 圆角 → Leafer 的 cornerRadius(数字或 [x, y]) */\nexport function cornerRadiusOf(object) {\n const rx = optionalNum(object.rx)\n const ry = optionalNum(object.ry)\n if (rx === undefined && ry === undefined) {\n return undefined\n }\n if (ry === undefined || ry === rx) {\n return rx !== undefined ? rx : ry\n }\n return [Math.max(0, rx || 0), Math.max(0, ry || 0)]\n}\n\nexport function convertRect(object, ctx, parent) {\n const rect = node('Rect', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: paintOf(object.fill, ctx),\n cornerRadius: cornerRadiusOf(object)\n })\n place(rect, object, parent)\n return rect\n}\n","/** 椭圆(Fabric ellipse)→ Leafer Ellipse */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertEllipse(object, ctx, parent) {\n const ellipse = node('Ellipse', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: paintOf(object.fill, ctx)\n })\n place(ellipse, object, parent)\n return ellipse\n}\n","/**\n * 圆(Fabric circle)→ Leafer Ellipse。\n *\n * 注意:Fabric 的 circle 支持 startAngle/endAngle 画圆弧,\n * 标准 Leafer 的 Ellipse 不支持角度,这里只还原整圆。\n * 如果平台以后注册了自定义 Circle 元素,可以在 elements 包里覆盖这个转换器。\n */\n\nimport { node, num } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertCircle(object, ctx, parent) {\n const radius = num(object.radius)\n const circle = node('Ellipse', {\n width: radius * 2,\n height: radius * 2,\n fill: paintOf(object.fill, ctx)\n })\n place(circle, object, parent)\n\n if (object.startAngle !== undefined || object.endAngle !== undefined) {\n ctx.warn('fabric circle 的 startAngle/endAngle 圆弧暂不支持,已按整圆输出')\n }\n return circle\n}\n","/** 三角形(Fabric triangle)→ Leafer Polygon */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertTriangle(object, ctx, parent) {\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n const w = width || 0\n const h = height || 0\n\n const triangle = node('Polygon', {\n width,\n height,\n // 顶点在正上方,底边贴底:和 Fabric 的三角形一致\n points: [w / 2, 0, w, h, 0, h],\n fill: paintOf(object.fill, ctx),\n closed: true\n })\n place(triangle, object, parent)\n return triangle\n}\n","/**\n * 折线(Fabric polyline)→ Leafer Line。\n * Fabric 的 points 是画布绝对坐标,geometry 会归一化成节点本地坐标(减包围盒左上角)。\n */\n\nimport { node } from '../nodes.js'\nimport { place, convertPoints, pathPlaceOrigin, pointsBounds } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertPolyline(object, ctx, parent) {\n // 同上: 不显式给宽高会落到 Leafer 的 100x100 默认值\n const bounds = pointsBounds(object.points)\n const line = node('Line', {\n width: bounds ? bounds.width : undefined,\n height: bounds ? bounds.height : undefined,\n points: convertPoints(object.points, {\n flipX: object.flipX === true,\n flipY: object.flipY === true\n }),\n // 节点原点是路径包围盒左上角,落点按 Fabric 的盒(含描边)反推\n around: 'top-left',\n fill: paintOf(object.fill, ctx),\n closed: false\n })\n place(line, { ...object, ...pathPlaceOrigin(object, bounds) }, parent)\n return line\n}\n","/**\n * 直线(Fabric line)→ Leafer Line。\n *\n * Fabric 的 x1/y1/x2/y2 和 polyline 的 points 一样是画布坐标,\n * geometry.convertPoints 会归一化成节点本地坐标(减包围盒左上角),\n * 再按 fabric 的 left/top 摆位,否则线会按绝对坐标再叠加一次位移跑到画布外。\n *\n * Fabric 的 line 只画描边(_render 里 strokeStyle = stroke || fillStyle,\n * 但没 stroke 时不调 _renderStroke),所以这里不输出 fill。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place, convertPoints, pointsBounds, pathPlaceOrigin } from '../geometry.js'\nimport { strokeCapOf, strokeJoinOf } from '../attributes/fill.js'\n\nexport function convertLine(object, ctx, parent) {\n const x1 = optionalNum(object.x1) || 0\n const y1 = optionalNum(object.y1) || 0\n const x2 = optionalNum(object.x2) || 0\n const y2 = optionalNum(object.y2) || 0\n\n const line = node('Line', {\n // Leafer 的 Line 宽度默认 100, 必须显式给, 否则选中框和属性面板尺寸都是错的\n width: Math.abs(x2 - x1),\n height: Math.abs(y2 - y1),\n points: convertPoints([{ x: x1, y: y1 }, { x: x2, y: y2 }], {\n flipX: object.flipX === true,\n flipY: object.flipY === true\n }),\n closed: false,\n // 节点原点是路径包围盒左上角,落点按 Fabric 的盒(含描边)反推\n around: 'top-left',\n // 端点: Fabric butt 对应 Leafer 的默认值, 不需要输出\n strokeCap: strokeCapOf(object.strokeLineCap),\n strokeJoin: strokeJoinOf(object.strokeLineJoin)\n })\n place(line, { ...object, ...pathPlaceOrigin(object, pointsBounds([{ x: x1, y: y1 }, { x: x2, y: y2 }])) }, parent)\n return line\n}\n","/** 多边形(Fabric polygon)→ Leafer Polygon,闭合路径;points 由 geometry 归一化成节点本地坐标 */\n\nimport { node } from '../nodes.js'\nimport { place, convertPoints, pathPlaceOrigin, pointsBounds } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertPolygon(object, ctx, parent) {\n // Leafer 的 Polygon 不传 width 时会用默认的 100x100, 节点尺寸就对不上了,\n // 组包围盒也会被这个假尺寸带偏, 所以按点集包围盒显式给宽高。\n const bounds = pointsBounds(object.points)\n const polygon = node('Polygon', {\n width: bounds ? bounds.width : undefined,\n height: bounds ? bounds.height : undefined,\n points: convertPoints(object.points, {\n flipX: object.flipX === true,\n flipY: object.flipY === true\n }),\n // 节点原点是路径包围盒左上角,落点按 Fabric 的盒(含描边)反推\n around: 'top-left',\n fill: paintOf(object.fill, ctx),\n closed: true\n })\n place(polygon, { ...object, ...pathPlaceOrigin(object, bounds) }, parent)\n return polygon\n}\n","/**\n * 路径(Fabric path)→ Leafer Path。\n * Fabric 的 path 是命令数组,Leafer 要 SVG path 字符串;\n * flipX/flipY 直接改写坐标,而不是用负 scale(否则描边会被镜像)。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place, convertPathData } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertPath(object, ctx, parent) {\n const path = node('Path', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n path: convertPathData(object.path, object),\n fill: paintOf(object.fill, ctx)\n })\n place(path, object, parent)\n return path\n}\n","/**\n * 文本属性:字体、对齐、换行、字距、装饰、背景。\n * 单位差异是这里最容易出错的地方,注释里逐个标了。\n */\n\nimport { normalizeColor } from '../colors.js'\nimport { convertShadow, paintOf } from './fill.js'\nimport { optionalNum, num } from '../nodes.js'\n\n/**\n * Fabric 的默认字体是 Times New Roman:没写 fontFamily 的文本在 Fabric 里就是按它\n * 量尺寸的。这里不补上,Leafer 会用自带默认字体,量出来的宽高和 Fabric 包围盒不一致。\n */\nexport const FABRIC_DEFAULT_FONT = 'Times New Roman'\n\n/**\n * Fabric wordWrap: 'word' | 'char' | undefined\n * Leafer textWrap: 'normal'(按词换行)| 'break'(按字符换行)| 'none'(不换行)\n */\nexport function convertWordWrap(wordWrap, splitByGrapheme) {\n // 只有显式按字符换行才换行: 空值 / none / word 一律转成不换行,\n // 与平台里 Fabric 文本的实际观感一致(默认值 word 不打断整行)\n if (splitByGrapheme || wordWrap === 'char') {\n return 'break'\n }\n return 'none'\n}\n\n/**\n * Fabric charSpacing 单位是 1/1000 em,Leafer letterSpacing 单位是像素。\n * 换算:charSpacing / 1000 * fontSize\n */\nexport function convertLetterSpacing(charSpacing, fontSize) {\n const spacing = optionalNum(charSpacing)\n if (spacing === undefined) {\n return undefined\n }\n return (spacing / 1000) * num(fontSize)\n}\n\n/** Fabric 的 underline / linethrough → Leafer 的 textDecoration 组合值 */\nexport function textDecorationOf(object) {\n if (object.underline && object.linethrough) return 'under-delete'\n if (object.underline) return 'underline'\n if (object.linethrough) return 'delete'\n return undefined\n}\n\n/**\n * Fabric 的 textAlign 比 Leafer 多出 justify-left / justify-center / justify-right\n * 这类值,Leafer 只认 left / center / right / justify 等。\n * 直接透传会让 Leafer 识别失败并回退到默认对齐,这里统一映射。\n */\nconst TEXT_ALIGN_MAP = {\n left: 'left',\n center: 'center',\n right: 'right',\n justify: 'justify',\n 'justify-left': 'left',\n 'justify-center': 'center',\n 'justify-right': 'right',\n 'justify-start': 'left',\n 'justify-end': 'right',\n 'justify-letter': 'justify-letter',\n both: 'both',\n 'both-letter': 'both-letter'\n}\n\nexport function convertTextAlign(textAlign) {\n if (!textAlign) return 'left'\n const value = String(textAlign).trim().toLowerCase()\n return TEXT_ALIGN_MAP[value] || 'left'\n}\n\n/**\n * Fabric 的 lineHeight 是相对字号的倍数(默认 1.16)。\n * Leafer 的 lineHeight 如果写成纯数字会被当成像素,倍数必须写成 percent 对象,\n * 否则文字高度会塌成 1.2px,选中框和实际文字完全对不上。\n * 兼容旧数据里直接写像素值(>= 10)的情况。\n */\nexport function convertLineHeight(lineHeight) {\n const value = optionalNum(lineHeight)\n if (value === undefined) {\n return undefined\n }\n if (value < 10) {\n return { type: 'percent', value }\n }\n return value\n}\n\n/** 组装 Text 节点除位置/变换外的全部属性 */\nexport function textProps(object, ctx) {\n const props = {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n text: object.text === undefined ? '' : String(object.text),\n fontSize: optionalNum(object.fontSize),\n fontFamily: object.fontFamily || FABRIC_DEFAULT_FONT,\n fontWeight: object.fontWeight,\n // 'normal' 是默认值,不输出,减小 JSON 体积\n fontStyle: object.fontStyle === 'normal' ? undefined : object.fontStyle,\n textAlign: convertTextAlign(object.textAlign),\n textWrap: convertWordWrap(object.wordWrap, object.splitByGrapheme),\n lineHeight: convertLineHeight(object.lineHeight),\n letterSpacing: convertLetterSpacing(object.charSpacing, object.fontSize),\n fill: object.fill ? paintOf(object.fill, ctx) : '#000000',\n shadow: object.shadow ? convertShadow(object.shadow) : undefined,\n verticalAlign: 'middle',\n textDecoration: textDecorationOf(object)\n }\n\n // Fabric 的 textBackgroundColor 是逐行背景;Leafer Text 没有同名能力,\n // 单行/标签场景用 boxStyle 兜底,至少保证背景不丢。\n const backgroundColor = object.backgroundColor || object.textBackgroundColor\n if (backgroundColor) {\n props.boxStyle = { fill: normalizeColor(backgroundColor) }\n }\n if (object.textBackgroundColor) {\n props.textBackgroundColor = normalizeColor(object.textBackgroundColor)\n }\n\n // 编辑器需要保留原始 Fabric 对象,运行态不需要\n if (ctx && ctx.options && ctx.options.mode === 'editor') {\n props.editable = true\n }\n\n return props\n}\n","/**\n * 文本转换。\n * - i-text:Fabric 里它的包围盒是\"排版尺寸 × scale\",编辑态拖角改的也是 scale,文字\n * 会跟着变形。Leafer 没有这种图元,交给自定义 IText:宽高就是权威的包围盒,文字被\n * 拉伸铺满它。转换时不带宽高(交给内容自适应),Fabric 的 scaleX/scaleY 原样留在\n * 节点上——否则图源参数把文本换长/换短后,盒子还是定义页那天的尺寸,文字会被横向\n * 压扁或拉长(Fabric 的 i-text 换文本会重新量尺寸,不会变形)。\n * - text / textbox:维持原来的 Leafer Text,尺寸和换行行为不变。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { textProps } from '../attributes/text.js'\n\n/**\n * Fabric 没写 lineHeight 时估一个,让 Leafer 排出来的行高和 Fabric 一致:\n * 单行文本的包围盒高度就是字形行高,多行按行数摊开。\n */\nfunction estimateLineHeight(object) {\n const fontSize = optionalNum(object.fontSize)\n const height = optionalNum(object.height)\n if (!fontSize || !height) return undefined\n const content = object.text === undefined ? '' : String(object.text)\n const lines = Math.max(1, content.split('\\n').length)\n const ratio = Math.round((height / (fontSize * lines)) * 1000) / 1000\n // 明显是画框尺寸(而不是字形行高)时不要,交给 Leafer 默认行高。\n // 正常字形行高就是 1.1 ~ 1.4,取一个窄区间,免得把画框高度当成行高\n if (!(ratio > 0.8 && ratio < 1.6)) return undefined\n return { type: 'percent', value: ratio }\n}\n\nfunction isIText(object) {\n return object.type === 'i-text' || object.type === 'itext'\n}\n\nexport function convertText(object, ctx, parent) {\n const props = textProps(object, ctx)\n const itext = isIText(object)\n const text = itext\n ? node('IText', {\n ...props,\n lineHeight: props.lineHeight || estimateLineHeight(object)\n })\n : node('Text', props)\n // 不额外偏移: 早期为了\"视觉更接近\"整体上移过 2px, 但和 Fabric 的包围盒对不上,\n // 按 comparator 逐图元比对, 不带偏移时误差为 0\n place(text, object, parent)\n\n if (itext) {\n // i-text 的盒宽由文字自身决定(拉伸走节点 scaleX/scaleY), 见文件头注释\n delete text.width\n delete text.height\n } else if (optionalNum(object.width) === undefined) {\n // 没有宽度时交给 Leafer 自适应,避免被压成 0 宽\n delete text.width\n }\n return text\n}\n","/**\n * 图片(Fabric image / rubik-image / rubik-gif)→ Leafer Image。\n * 图片地址走 resolveAsset,转换器本身不拼平台 URL。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { resolveImageUrl } from '../assets.js'\n\nexport function convertImage(object, ctx, parent) {\n const image = node('Image', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: 'transparent',\n url: resolveImageUrl(object.src, object.rsrc, ctx)\n })\n place(image, object, parent)\n\n if (object.cropX || object.cropY) {\n // Fabric 的裁剪信息 Leafer 没有直接对应字段,先留警告\n ctx.warn('fabric image 的 cropX/cropY 暂未转换')\n }\n return image\n}\n","/**\n * lib(组件库实例)相关:参数替换 + 页面跳转动作清理。\n *\n * 平台把可复用组件存成 lib,实例上通过 param 覆盖文本/颜色等内容。\n * Fabric JSON 里用 `{key}` 占位,转换时替换成实例参数。\n */\n\n/** 深拷贝,避免转换过程改到原始 Fabric JSON(调用方可能还要用) */\nexport function cloneData(value) {\n if (value === null || value === undefined) {\n return value\n }\n return JSON.parse(JSON.stringify(value))\n}\n\n/** 统一 lib 路径:去掉 mmi/ 前缀、.json 后缀和开头斜杠 */\nexport function normalizeLibName(libName) {\n return String(libName || '')\n .replace(/\\\\/g, '/')\n .replace(/^\\/+/, '')\n .replace(/^\\.?\\//, '')\n .replace(/^mmi\\//, '')\n .replace(/\\.json$/i, '')\n}\n\n/** 递归把字符串里的 {key} 替换成 params[key] */\nexport function replaceDataParams(value, params) {\n if (typeof value === 'string') {\n let result = value\n Object.keys(params || {}).forEach((key) => {\n const replacement = params[key] === null || params[key] === undefined\n ? ''\n : String(params[key])\n result = result.split('{' + key + '}').join(replacement)\n })\n return result\n }\n if (Array.isArray(value)) {\n return value.map((item) => replaceDataParams(item, params))\n }\n if (value && typeof value === 'object') {\n Object.keys(value).forEach((key) => {\n value[key] = replaceDataParams(value[key], params)\n })\n }\n return value\n}\n\n/** 页面跳转动作:点整组就跳页,子元素上的同类动作要去掉,避免抢事件 */\nfunction isPageAction(action) {\n return !!action && (action.act === 'openPad' || action.act === 'openWindow') && !!action.pic\n}\n\nexport function getPageActionEvents(actionMap) {\n const events = new Set()\n Object.keys(actionMap || {}).forEach((eventName) => {\n if (isPageAction(actionMap[eventName])) {\n events.add(eventName)\n }\n })\n return events\n}\n\n/** 删除子元素上和父级重复的页面跳转动作 */\nexport function stripChildPageActions(object, parentPageActionEvents) {\n if (!object || !parentPageActionEvents || parentPageActionEvents.size === 0) {\n return object\n }\n\n if (object.action) {\n Object.keys(object.action).forEach((eventName) => {\n if (parentPageActionEvents.has(eventName) && isPageAction(object.action[eventName])) {\n delete object.action[eventName]\n }\n })\n if (Object.keys(object.action).length === 0) {\n delete object.action\n }\n }\n\n if (Array.isArray(object.objects)) {\n object.objects.forEach((child) => stripChildPageActions(child, parentPageActionEvents))\n }\n return object\n}\n\n/** lib 节点:Fabric 用 type=lib,Leafer 转换后额外用 tag=Lib 区分 */\nexport function isLibNode(node) {\n return !!node && (node.type === 'lib' || node.tag === 'Lib')\n}\n\n/** lib 保存时只保留引用,内部图元由页面定义在加载时补全 */\nexport function stripLibChildren(value) {\n if (!value || typeof value !== 'object') return value\n if (Array.isArray(value)) {\n value.forEach((item) => stripLibChildren(item))\n return value\n }\n if (isLibNode(value)) {\n delete value.children\n return value\n }\n if (Array.isArray(value.children)) {\n value.children.forEach((child) => stripLibChildren(child))\n }\n return value\n}\n\nfunction definitionParams(definition) {\n return {\n ...((definition && definition.header && definition.header.param) || {}),\n ...((definition && definition.param) || {})\n }\n}\n\nfunction libParams(definition, node) {\n return {\n ...definitionParams(definition),\n ...((node && node.originParam) || {}),\n ...((node && node.param) || {})\n }\n}\n\n// 实例没有存宽高时的兜底: 用定义页尺寸; 定义页也没有就不写(让 Leafer 按内部图元算),\n// 不要凭空写 100x100, 否则实例框和 Fabric 里看到的大小对不上。\nfunction libSize(definition) {\n const header = (definition && definition.header) || {}\n const width = Number(header.width)\n const height = Number(header.height)\n return {\n width: width > 0 ? width : undefined,\n height: height > 0 ? height : undefined\n }\n}\n\n// 同步扫一遍树, 找出还没有内部图元的 lib 引用。\n// 原来每个节点都 await 一次(上千个节点就是上千次微任务), 4~5ms 全花在调度上。\nfunction collectLibNodes(children, stack) {\n const pending = []\n const walk = (list, chain) => {\n for (let i = 0; i < list.length; i++) {\n const node = list[i]\n if (!node || typeof node !== 'object') continue\n if (isLibNode(node) && node.libName) {\n const name = String(node.libName)\n const missing = !Array.isArray(node.children) || !node.children.length\n if (missing && chain.indexOf(name) === -1) {\n pending.push({ node, name, stack: chain })\n continue\n }\n }\n if (Array.isArray(node.children)) walk(node.children, chain)\n }\n }\n walk(children, stack)\n return pending\n}\n\n// lib 会嵌套, 展开出来的定义里可能还有 lib, 所以循环到没有待展开节点为止\nasync function hydrateLibChildren(children, loadDefinition, stack) {\n let pending = collectLibNodes(children, stack)\n while (pending.length) {\n const definitions = await Promise.all(pending.map((item) => {\n // 缺失的 lib 定义不能阻断整页加载,保留空 lib 让用户看到问题位置\n return Promise.resolve(loadDefinition(item.name)).catch(() => null)\n }))\n let next = []\n definitions.forEach((definition, index) => {\n if (!definition) return\n const item = pending[index]\n const node = item.node\n const params = libParams(definition, node)\n const size = libSize(definition)\n const children = replaceDataParams(cloneData(definition.children || []), params)\n const box = rebaseChildren(children)\n const hydrated = {\n children,\n originParam: node.originParam || definitionParams(definition),\n param: node.param || {}\n }\n // 实例框取内容包围盒, 没有尺寸信息才退回定义页尺寸\n const width = box && box.width > 0 ? box.width : size.width\n const height = box && box.height > 0 ? box.height : size.height\n if (width !== undefined) hydrated.width = width\n if (height !== undefined) hydrated.height = height\n Object.assign(node, hydrated)\n next = next.concat(collectLibNodes(hydrated.children, item.stack.concat(item.name)))\n })\n pending = next\n }\n}\n\n/** 内容由平台浮层绘制的类型 */\nconst OVERLAY_TYPES = new Set(['chart', 'component'])\n\n/**\n * 图表 / 控件的内容是浮层(DOM)画出来的,锚点节点本身不该带填充和描边。\n * 旧文件里存过 fill / stroke,加载时统一清掉,免得底下多一块底框。\n */\nexport function stripOverlayPaint(value) {\n if (!value || typeof value !== 'object') return value\n if (Array.isArray(value)) {\n value.forEach((item) => stripOverlayPaint(item))\n return value\n }\n if (OVERLAY_TYPES.has(value.type)) {\n value.fill = 'transparent'\n delete value.stroke\n delete value.strokeWidth\n if (value.border) delete value.border\n }\n if (Array.isArray(value.children)) {\n value.children.forEach((item) => stripOverlayPaint(item))\n }\n return value\n}\n\n/**\n * 把 Leafer 文档里只有 libName 的 lib 引用补全成完整图元。\n * loadDefinition(libName) 由宿主提供,返回 Leafer document。\n */\nexport async function hydrateLeaferDocument(document, loadDefinition) {\n if (!document || !Array.isArray(document.children)) {\n return document\n }\n stripOverlayPaint(document.children)\n if (typeof loadDefinition !== 'function') {\n return document\n }\n await hydrateLibChildren(document.children, loadDefinition, [])\n return document\n}\n\n// lib 内部图元的坐标必须归到 0 起的局部坐标:\n// 平台给 Lib 定的包围盒是 (0,0,width,height), 子图元若还带着定义页的绝对坐标,\n// 就会整体偏到包围盒外面, 和 Fabric 的组(内容贴包围盒)不一致。\n// 原点(around)和 scale 都会让\"存下来的 x/y\"不等于视觉左上角, 必须一起算。\n\n/** around 是 Leafer 的围绕点, 决定 x/y 指的是盒子的哪一点 */\nfunction originFraction(around) {\n if (!around) return { x: 0, y: 0 }\n if (typeof around === 'object') {\n const x = Number(around.x)\n const y = Number(around.y)\n if (Number.isFinite(x) || Number.isFinite(y)) {\n return { x: Number.isFinite(x) ? x : 0, y: Number.isFinite(y) ? y : 0 }\n }\n return { x: 0, y: 0 }\n }\n const text = String(around)\n const center = text.indexOf('center') > -1\n return {\n x: text.indexOf('right') > -1 ? 1 : (center ? 0.5 : 0),\n y: text.indexOf('bottom') > -1 ? 1 : (center ? 0.5 : 0)\n }\n}\n\nfunction nodeSize(child) {\n const scaleX = Math.abs(Number(child.scaleX))\n const scaleY = Math.abs(Number(child.scaleY))\n const width = Number(child.width) * (Number.isFinite(scaleX) ? scaleX : 1)\n const height = Number(child.height) * (Number.isFinite(scaleY) ? scaleY : 1)\n // 文本等自适应尺寸在数据里可能没有 width/height, 不能参与坐标计算\n return {\n width: Number.isFinite(width) ? width : 0,\n height: Number.isFinite(height) ? height : 0\n }\n}\n\n/** 子图元并集的视觉包围盒(父级局部坐标, 已考虑 around 与 scale) */\nexport function contentBox(children, offsetX = 0, offsetY = 0) {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n const merge = (box) => {\n if (!box) return\n minX = Math.min(minX, box.x)\n minY = Math.min(minY, box.y)\n maxX = Math.max(maxX, box.x + box.width)\n maxY = Math.max(maxY, box.y + box.height)\n }\n ;(children || []).forEach((child) => {\n if (!child || typeof child !== 'object') return\n const x = Number.isFinite(Number(child.x)) ? Number(child.x) : 0\n const y = Number.isFinite(Number(child.y)) ? Number(child.y) : 0\n const origin = originFraction(child.around)\n const size = nodeSize(child)\n // 盒子左上角: x/y 是围绕点, 减去绕点占的比例\n const left = offsetX + x - size.width * origin.x\n const top = offsetY + y - size.height * origin.y\n if (size.width > 0 && size.height > 0) {\n merge({ x: left, y: top, width: size.width, height: size.height })\n return\n }\n if (Array.isArray(child.children) && child.children.length) {\n merge(contentBox(child.children, left, top))\n return\n }\n merge({ x: left, y: top, width: 0, height: 0 })\n })\n if (!Number.isFinite(minX)) return null\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 把子图元平移到 0 起的局部坐标, 返回平移前的视觉包围盒 */\nexport function rebaseChildren(children) {\n const box = contentBox(children)\n if (!box) return null\n if (box.x || box.y) {\n // 平移围绕点即可整体挪动盒子, 不用管 around/scale\n ;(children || []).forEach((child) => {\n if (!child || typeof child !== 'object') return\n const x = Number.isFinite(Number(child.x)) ? Number(child.x) : 0\n const y = Number.isFinite(Number(child.y)) ? Number(child.y) : 0\n child.x = x - box.x\n child.y = y - box.y\n })\n }\n return box\n}\n\nexport function createLibGroupData(definition, libName, position) {\n if (!definition) return null\n const params = libParams(definition, null)\n const children = replaceDataParams(cloneData(definition.children || []), params)\n const box = rebaseChildren(children)\n const size = libSize(definition)\n const point = position || { x: 0, y: 0 }\n // 实例框就是内容包围盒, 落点即内容左上角\n const width = box && box.width > 0 ? box.width : size.width\n const height = box && box.height > 0 ? box.height : size.height\n return {\n tag: 'Lib',\n type: 'lib',\n libName: String(libName || ''),\n x: Number(point.x) || 0,\n y: Number(point.y) || 0,\n width,\n height,\n fill: 'transparent',\n originParam: definitionParams(definition),\n param: {},\n children\n }\n}\n","/**\n * 组(Fabric group)→ Leafer Group。\n * Fabric 子元素坐标相对组中心,geometry.place 会自动加父级宽高的一半;\n * 另外 Fabric 的组是按存下来的宽高定位/旋转的,Leafer 却按子元素现算包围盒,\n * 所以这里还要把围绕点钉回 Fabric 的组中心,见下面的注释。\n */\n\nimport { node, num, optionalNum } from '../nodes.js'\nimport { aroundFraction, aroundOf, nodeBox, place, unionBoxes } from '../geometry.js'\nimport { cloneData, getPageActionEvents, stripChildPageActions } from '../lib.js'\n\nexport function convertGroup(object, ctx, parent) {\n const group = node('Group', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: 'transparent'\n })\n place(group, object, parent)\n\n // 整组绑定了页面跳转时,子元素上的同类动作要去掉,否则子元素会先吃掉点击\n const pageActionEvents = getPageActionEvents(object.action)\n const pairs = []\n\n ;(object.objects || []).forEach((child) => {\n const source = pageActionEvents.size\n ? stripChildPageActions(cloneData(child), pageActionEvents)\n : child\n const converted = ctx.convert(source, group)\n if (converted) {\n pairs.push({ node: converted, source })\n }\n })\n\n if (pairs.length) {\n group.children = pairs.map((pair) => pair.node)\n group.around = anchorOf(object, unionBoxes(pairs.map((pair) => nodeBox(pair.node, pair.source))))\n }\n return group\n}\n\n/**\n * 组的围绕点百分比。\n *\n * Fabric 的组按\"存下来的宽高\"定位和旋转,Leafer 的 Group 包围盒却永远按子元素\n * 现算;子元素被拖过/转过之后两个尺寸就对不上,整组会绕错中心。所以用百分比把\n * 围绕点钉回 Fabric 的原点(place 用的就是这一点),位置和旋转基准都回到 Fabric。\n *\n * Leafer 的百分比是相对 boxBounds 的,而运行态会把组包围盒撑成\"子元素并集 ∪\n * 存下来的宽高\"(leaferCanvas/compat 里的补丁),这里按同一口径算,否则并集比存下来的\n * 宽高小时百分比会偏,转了角度的组就会错位。\n */\nfunction anchorOf(object, box) {\n const width = num(object.width)\n const height = num(object.height)\n const origin = aroundFraction(aroundOf(object))\n const left = Math.min(box.x, 0)\n const top = Math.min(box.y, 0)\n const right = Math.max(box.x + box.width, width)\n const bottom = Math.max(box.y + box.height, height)\n return {\n type: 'percent',\n x: right - left ? (origin.x * width - left) / (right - left) : 0.5,\n y: bottom - top ? (origin.y * height - top) / (bottom - top) : 0.5\n }\n}\n","/**\n * 组件实例(Fabric lib)→ Leafer Lib 自定义元素。\n * lib 本质是「带参数、内部图元按需水合的组」:先把 {key} 占位替换成实例参数,再按组转换。\n *\n * 定义页里取出来的图元坐标是页面坐标(左上角为原点),不像 Fabric 组的子图元那样是\n * 相对组中心的,所以这里不能按父组补半个宽高的偏移——补了会让同一个图源比「打开\n * leafer 文件」时整体右下偏半个实例尺寸。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { cloneData, rebaseChildren, replaceDataParams } from '../lib.js'\n\nexport function convertLib(object, ctx, parent) {\n const group = node('Lib', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: 'transparent'\n })\n place(group, object, parent)\n\n // 实例参数优先于定义时的默认参数\n const params = { ...(object.originParam || {}), ...(object.param || {}) }\n const children = []\n\n ;(object.objects || []).forEach((child) => {\n const source = replaceDataParams(cloneData(child), params)\n const converted = ctx.convert(source, null)\n if (converted) {\n children.push(converted)\n }\n })\n\n if (children.length) {\n // 子图元归到 0 起的局部坐标: 平台给 Lib 的包围盒是 (0,0,width,height)\n rebaseChildren(children)\n group.children = children\n }\n return group\n}\n","/**\n * 按钮(Fabric 平台自定义 button)→ Leafer 自定义原子元素 Button。\n *\n * Button 的字、边框、按压效果都由 @rubik/fabric-to-leafer-elements 内部绘制,\n * 转换结果不能再是 Group + Box + Text + Line,否则编辑态会把它当成组合。\n */\n\nimport { node, optionalNum, num } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\nimport { normalizeColor } from '../colors.js'\nimport { FABRIC_DEFAULT_FONT } from '../attributes/text.js'\n\n// 与自定义 Button 的默认值保持一致\nconst DEFAULT_FILL = '#969696'\nconst DEFAULT_FONT_SIZE = 12\n\nexport function convertButton(object, ctx, parent) {\n // 某些 Fabric 画面里按钮的 width/height 会被存成 null,\n // 真正的尺寸在 buttonScaleBase* 上;优先用主尺寸,缺失时回退到基准尺寸。\n const baseWidth = optionalNum(object.buttonScaleBaseWidth)\n const baseHeight = optionalNum(object.buttonScaleBaseHeight)\n const width = optionalNum(object.width) || baseWidth || 0\n const height = optionalNum(object.height) || baseHeight || 0\n // Fabric 自定义 Button 用 scaleY 表示显示高度; 把 scaleY 烘焙进高度,\n // 避免 Leafer 的 scaleY 把文字一起拉变形。\n const scaleY = num(object.scaleY, 1)\n const displayHeight = height * (scaleY > 0 ? scaleY : 1)\n\n const backgroundFill = object.backgroundColor === undefined || object.backgroundColor === ''\n ? (object.fill === undefined || object.fill === '' ? DEFAULT_FILL : object.fill)\n : object.backgroundColor\n\n const button = node('Button', {\n width,\n height: displayHeight,\n text: object.text === undefined ? '' : String(object.text),\n fontSize: optionalNum(object.fontSize) || DEFAULT_FONT_SIZE,\n fontFamily: object.fontFamily || FABRIC_DEFAULT_FONT,\n fontWeight: object.fontWeight || 'normal',\n fontColor: normalizeColor(object.fontColor || '#000000'),\n fill: paintOf(backgroundFill, ctx),\n backgroundColor: paintOf(backgroundFill, ctx),\n stroke: object.stroke === undefined || object.stroke === null || object.stroke === ''\n ? undefined\n : normalizeColor(object.stroke),\n strokeWidth: optionalNum(object.strokeWidth),\n cornerRadius: optionalNum(object.rx) || optionalNum(object.ry),\n wordWrap: object.wordWrap || 'word',\n down: object.down === true,\n buttonScaleBaseWidth: baseWidth || width,\n buttonScaleBaseHeight: baseHeight || displayHeight\n })\n place(button, object, parent)\n return button\n}\n","/**\n * 进度条 / 滑动条(Fabric 平台自定义 bar)→ Leafer 自定义原子元素 Bar。\n *\n * Bar 内部由 @rubik/fabric-to-leafer-elements 自己绘制背景和填充,\n * 转换结果不能再是 Group + 子元素,否则编辑态会把它当成可解组的组合。\n *\n * fpct:0~1 的进度;fdir:方向(0 左→右,1 右→左);\n * fstyle:'rect' 直角 / 'circle' 圆角。\n */\n\nimport { node, optionalNum, num } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertBar(object, ctx, parent) {\n const width = optionalNum(object.width) || 0\n const height = optionalNum(object.height) || 0\n const direction = num(object.fdir, 0) % 5\n const fdir = direction < 0 ? direction + 5 : direction\n let percent = num(object.fpct, 0.6)\n // 和 Fabric Bar 一致:方向 4 是中心向外,允许 -1~1;其它方向只允许 0~1\n percent = Math.max(fdir === 4 ? -1 : 0, Math.min(1, percent))\n\n const bar = node('Bar', {\n width,\n height,\n fill: paintOf(object.fill, ctx),\n backgroundFill: paintOf(object.backgroundColor || 'transparent', ctx),\n stroke: object.stroke === undefined || object.stroke === null || object.stroke === ''\n ? undefined\n : paintOf(object.stroke, ctx),\n strokeWidth: optionalNum(object.strokeWidth),\n fpct: percent,\n fdir,\n fstyle: object.fstyle || 'rect'\n })\n place(bar, object, parent)\n return bar\n}\n","/**\n * chart / component → 画布上的锚点盒。\n *\n * 它们不是 Leafer 图形,平台用 DOM 浮层画真实内容(图表走 echarts,控件走 Vue 组件):\n * 浮层按节点的世界矩阵定位、按宽高定尺寸、跟随可见性/透明度,锚点盒就是它唯一的依据。\n * config / template / script / props 由 meta 的透传字段原样带走,浮层据此渲染。\n * 所以这里不是\"占位不渲染\",去掉它页面上的图表和控件会直接消失。\n *\n * 锚点盒自己什么也不画:图表 / 控件的内容是浮层画出来的,再给底色和边框只会多出一块框。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\n\nexport function convertPlaceholder(object, ctx, parent) {\n const box = node('Box', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n hitFill: 'all',\n fill: 'transparent'\n })\n place(box, object, parent)\n return box\n}","/**\n * 元素分发表:Fabric 类型 → 转换函数。\n *\n * 加新元素只要两步:\n * 1. 新建 elements/xxx.js 导出 convertXxx(object, ctx, parent)\n * 2. 在下面的表里登记类型\n */\n\nimport { applyCommon } from '../attributes/index.js'\nimport { normalizeSizeSign } from '../geometry.js'\n\nimport { convertRect } from './rect.js'\nimport { convertEllipse } from './ellipse.js'\nimport { convertCircle } from './circle.js'\nimport { convertTriangle } from './triangle.js'\nimport { convertPolyline } from './polyline.js'\nimport { convertLine } from './line.js'\nimport { convertPolygon } from './polygon.js'\nimport { convertPath } from './path.js'\nimport { convertText } from './text.js'\nimport { convertImage } from './image.js'\nimport { convertGroup } from './group.js'\nimport { convertLib } from './lib.js'\nimport { convertButton } from './button.js'\nimport { convertBar } from './bar.js'\nimport { convertPlaceholder } from './placeholder.js'\n\nconst CONVERTERS = {\n rect: convertRect,\n ellipse: convertEllipse,\n circle: convertCircle,\n triangle: convertTriangle,\n polyline: convertPolyline,\n line: convertLine,\n polygon: convertPolygon,\n path: convertPath,\n text: convertText,\n 'i-text': convertText,\n textbox: convertText,\n image: convertImage,\n 'rubik-image': convertImage,\n 'rubik-gif': convertImage,\n group: convertGroup,\n lib: convertLib,\n button: convertButton,\n bar: convertBar,\n chart: convertPlaceholder,\n component: convertPlaceholder\n}\n\n/**\n * 转换单个 Fabric 对象。parent 用来算组内坐标偏移。\n * 返回 null 表示这个对象被跳过(未知类型或不可见),调用方过滤掉即可。\n */\nexport function convertObject(object, ctx, parent = null) {\n if (!object || typeof object !== 'object') {\n return null\n }\n\n const convert = CONVERTERS[object.type]\n if (!convert) {\n ctx.warn(`未知的 Fabric 对象类型:${object.type}`)\n return null\n }\n\n // Fabric 存下来的负宽高先换成正宽高(图形类把符号并进 scale), 否则 Leafer 会自己\n // 镜像 + 打警告, 而且和后面写入的 scaleX 抢次序\n const source = normalizeSizeSign(object)\n const result = convert(source, ctx, parent)\n if (!result) {\n return null\n }\n\n return applyCommon(result, source, ctx)\n}\n\n/** 判断某个 Fabric 类型是否已支持,测试和 CLI 可以用 */\nexport function isSupportedType(type) {\n return Object.prototype.hasOwnProperty.call(CONVERTERS, type)\n}\n","/**\n * 根文档组装:把转换出来的 children 和 Fabric 的 header / param 拼成\n * 平台约定的 Leafer 文档结构。\n */\n\nexport const DOCUMENT_VERSION = '4.4.0'\n\nexport function buildDocument(fabricJson, children) {\n const source = fabricJson || {}\n const header = source.header || {}\n const param = source.param || {}\n\n return {\n version: DOCUMENT_VERSION,\n engine: 'leafer',\n format: 'leafer',\n header: {\n ...header,\n // 画布级参数 = header 里的默认值 + 文件级 param 覆盖\n param: { ...(header.param || {}), ...param },\n background: source.background !== undefined ? source.background : header.background\n },\n param,\n keyboardEvent: source.keyboardEvent || [],\n children\n }\n}\n","/**\n * 转换主流程。\n *\n * Fabric JSON(objects 数组)→ Leafer JSON(children 数组)。\n * 这里只做遍历和组装,具体类型在 elements/,公共属性在 attributes/。\n */\n\nimport { createContext } from './context.js'\nimport { convertObject } from './elements/index.js'\nimport { buildDocument } from './document.js'\nimport { cloneData, normalizeLibName } from './lib.js'\n\n// 平台保存的 lib 只有 libName,没有内部 objects;转换前由调用方提供的\n// loadLib 把页面定义补进来。纯数据层不关心文件/URL 从哪来。\nasync function hydrateLibObject(object, loadLib, stack) {\n if (!object || typeof object !== 'object') return\n if (object.type === 'lib' && object.libName && (!Array.isArray(object.objects) || !object.objects.length)) {\n const name = normalizeLibName(object.libName)\n if (!name || stack.indexOf(name) > -1) return\n try {\n const page = await loadLib(name)\n if (page && Array.isArray(page.objects)) {\n object.objects = page.objects\n if (!object.originParam) {\n object.originParam = {\n ...((page.header && page.header.param) || {}),\n ...(page.param || {})\n }\n }\n await hydrateLibObjects(object.objects, loadLib, stack.concat(name))\n }\n } catch (error) {\n // lib 定义缺失时保留空组,不能阻断整页转换\n }\n } else if (Array.isArray(object.objects)) {\n await hydrateLibObjects(object.objects, loadLib, stack)\n }\n}\n\nasync function hydrateLibObjects(objects, loadLib, stack = []) {\n if (!Array.isArray(objects) || typeof loadLib !== 'function') return\n // 同层 lib 之间互不依赖,并行拉取/展开,减少首屏串行等待\n await Promise.all(objects.map((object) => hydrateLibObject(object, loadLib, stack)))\n}\n\n/** 只在确实存在待补全的 lib 引用时才深拷贝整份 Fabric JSON */\nfunction hasMissingLibObjects(objects) {\n if (!Array.isArray(objects)) return false\n return objects.some((object) => {\n if (!object || typeof object !== 'object') return false\n if (object.type === 'lib' && object.libName &&\n (!Array.isArray(object.objects) || !object.objects.length)) {\n return true\n }\n return Array.isArray(object.objects) && hasMissingLibObjects(object.objects)\n })\n}\n\nasync function prepareSource(fabricJson, options) {\n if (!fabricJson || !Array.isArray(fabricJson.objects) || typeof options.loadLib !== 'function') {\n return fabricJson\n }\n if (!hasMissingLibObjects(fabricJson.objects)) return fabricJson\n const source = cloneData(fabricJson)\n await hydrateLibObjects(source.objects, options.loadLib)\n return source\n}\n\nfunction run(fabricJson, options) {\n const ctx = createContext(options)\n\n // 注入递归转换函数:group/lib 用它转子元素\n ctx.convert = (object, parent) => convertObject(object, ctx, parent)\n\n const objects = fabricJson && Array.isArray(fabricJson.objects)\n ? fabricJson.objects\n : null\n\n if (!objects) {\n ctx.warn('无效的 Fabric JSON:缺少 objects 数组')\n return { document: buildDocument(fabricJson || {}, []), warnings: ctx.warnings }\n }\n\n const children = []\n objects.forEach((object) => {\n const converted = convertObject(object, ctx, null)\n if (converted) {\n children.push(converted)\n }\n })\n\n return {\n document: buildDocument(fabricJson, children),\n warnings: ctx.warnings\n }\n}\n\n/** 异步入口,保持和文档/调用方约定的 API 一致 */\nexport async function convert(fabricJson, options = {}) {\n const source = await prepareSource(fabricJson, options)\n return run(source, options)\n}\n\n/** 同步入口:不依赖异步资源时(Node / 单测 / CLI)直接用 */\nexport function convertSync(fabricJson, options = {}) {\n return run(fabricJson, options)\n}\n","/**\n * Leafer JSON → Fabric JSON(fabric-to-leafer 的反向转换)。\n *\n * 目标:把平台保存的 Leafer 文档还原成 Fabric 编辑器能打开的 JSON。\n * 约束:\n * - 纯 JSON 变换,不 import leafer-ui,Node / 浏览器都能跑;\n * - 能精确逆的(位置、尺寸、文本、元数据)精确逆;\n * - 不可逆的(点集翻转、烘焙静态背景图、自定义 around)按最接近的语义还原。\n *\n * 与正向的对应关系见各元素转换器:\n * - 位置:正向 place() 加了父级宽高的一半,反向减回去;旋转/翻转/缩放再逆\n * attributes/transform.js 的 applyPosition 补偿;\n * - 点集(line / polyline / polygon):正向把 scale 和翻转烘焙进 points,节点\n * scale 归 1,反向把 points 当本地坐标、按节点落点平移回 Fabric 的绝对坐标;\n * - 文本 / 按钮 / 进度条 / lib / 图表锚点:字段名基本一一对应。\n */\n\nimport { num } from './nodes.js'\nimport { aroundFraction } from './geometry.js'\nimport { isTransparentColor } from './colors.js'\n\n/** 平台自定义字段:正向 attributes/meta.js 原样搬过来的那些,反向原样搬回去 */\nconst META_KEYS = [\n 'name',\n 'libName',\n 'param',\n 'originParam',\n 'noScaleWithParent',\n 'rsrc',\n 'config',\n 'template',\n 'script',\n 'props',\n 'keyboardEvent',\n 'dyn',\n 'action',\n 'ctxmenu',\n 'hasLocalValue',\n 'disabled'\n]\n\n/** 数值保留 4 位小数,避免 1e-15 级浮点尾数写进 JSON */\nfunction round(value, digits = 4) {\n const number = Number(value)\n if (!Number.isFinite(number)) return 0\n const factor = Math.pow(10, digits)\n return Math.round(number * factor) / factor\n}\n\n/** Leafer 节点 tag + 正向透传的 type → Fabric 类型 */\nfunction fabricTypeOf(node, ctx) {\n const tag = node.tag\n const type = node.type\n switch (tag) {\n case 'Button': return 'button'\n case 'Bar': return 'bar'\n case 'Circle': return 'circle'\n case 'Lib': return 'lib'\n // Fabric 没有图层概念, 导出时把层当普通组展开, 所有图元仍在同一层\n case 'Layer': return 'group'\n case 'IText': return 'i-text'\n case 'Rect': return 'rect'\n case 'Ellipse': return type === 'circle' ? 'circle' : 'ellipse'\n case 'Text': return type === 'text' ? 'text' : 'textbox'\n case 'Image': return typeof type === 'string' && type ? type : 'image'\n case 'Group': return 'group'\n case 'Box': return type === 'chart' || type === 'component' ? type : 'component'\n // 正向把 line / polyline 都输出成 Leafer 的 Line,靠 type 区分\n case 'Line': return type === 'polyline' ? 'polyline' : 'line'\n // 正向把 polygon / triangle 都输出成 Leafer 的 Polygon\n case 'Polygon': return type === 'triangle' ? 'triangle' : 'polygon'\n case 'Path': return 'path'\n default:\n if (ctx && tag) {\n ctx.warnings.push(`未知的 Leafer 节点 tag: ${tag},已按 rect 输出`)\n }\n return 'rect'\n }\n}\n\n/** Leafer 渐变 paint → Fabric 渐变 */\nfunction gradientToFabric(paint) {\n const from = paint.from && typeof paint.from === 'object' ? paint.from : {}\n const to = paint.to && typeof paint.to === 'object' ? paint.to : {}\n const coords = {\n x1: round(num(from.x)),\n y1: round(num(from.y)),\n x2: round(num(to.x)),\n y2: round(num(to.y))\n }\n if (paint.type === 'radial') {\n // Fabric 径向渐变用 r2 表示半径,圆心是 (x1, y1)\n coords.r2 = round(Math.hypot(coords.x2 - coords.x1, coords.y2 - coords.y1)) || 0.5\n }\n return {\n type: paint.type === 'radial' ? 'radial' : 'linear',\n colorStops: (paint.stops || []).map((stop) => ({\n offset: round(num(stop.offset)),\n color: stop.color\n })),\n coords\n }\n}\n\n/** Leafer 图片 paint → Fabric Pattern */\nfunction patternToFabric(paint) {\n const repeat = paint.mode === 'normal'\n ? 'no-repeat'\n : (paint.repeat === 'x' ? 'repeat-x' : (paint.repeat === 'y' ? 'repeat-y' : 'repeat'))\n const pattern = { type: 'pattern', source: paint.url, repeat }\n const offsetX = paint.offset ? num(paint.offset.x) : 0\n const offsetY = paint.offset ? num(paint.offset.y) : 0\n if (offsetX || offsetY) {\n pattern.offsetX = round(offsetX)\n pattern.offsetY = round(offsetY)\n }\n const rotation = num(paint.rotation)\n const scaleX = paint.scale ? num(paint.scale.x, 1) : 1\n const scaleY = paint.scale ? num(paint.scale.y, 1) : 1\n if (rotation || scaleX !== 1 || scaleY !== 1) {\n const rad = rotation * Math.PI / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n pattern.patternTransform = [\n round(scaleX * cos),\n round(scaleX * sin),\n round(-scaleY * sin),\n round(scaleY * cos),\n round(offsetX),\n round(offsetY)\n ]\n }\n return pattern\n}\n\n/** Leafer paint(颜色 / 渐变 / 图片)→ Fabric fill 值;完全透明统一成空字符串 */\nfunction fabricPaint(value) {\n if (value === undefined || value === null || value === '') return ''\n if (typeof value === 'string') {\n return isTransparentColor(value) ? '' : value\n }\n if (Array.isArray(value.stops)) {\n return gradientToFabric(value)\n }\n if (value.type === 'image' && value.url) {\n return patternToFabric(value)\n }\n return value\n}\n\n/** Leafer 阴影数组 → Fabric shadow */\nfunction fabricShadow(value) {\n const list = Array.isArray(value) ? value : [value]\n return list.filter(Boolean).map((item) => ({\n offsetX: round(num(item.x)),\n offsetY: round(num(item.y)),\n blur: round(num(item.blur)),\n color: item.color || 'rgba(0,0,0,0.5)',\n spread: round(num(item.spread))\n }))\n}\n\n/** 填充 / 描边 / 阴影 / 混合模式:形状类的公共外观 */\nfunction applyFillStroke(object, node, options = {}) {\n if (options.fill !== false) {\n object.fill = fabricPaint(node.fill)\n }\n if (options.stroke !== false) {\n const stroke = fabricPaint(node.stroke)\n if (stroke !== '') {\n object.stroke = stroke\n if (node.strokeWidth !== undefined) {\n object.strokeWidth = round(num(node.strokeWidth))\n }\n if (Array.isArray(node.dashPattern) && node.dashPattern.length) {\n object.strokeDashArray = node.dashPattern.slice()\n }\n }\n }\n if (node.shadow !== undefined) {\n object.shadow = fabricShadow(node.shadow)\n }\n if (node.strokeCap) object.strokeLineCap = node.strokeCap\n if (node.strokeJoin) object.strokeLineJoin = node.strokeJoin\n if (node.blendMode) object.globalCompositeOperation = node.blendMode\n}\n\n/** 文本字段:Leafer 的 textWrap / lineHeight / letterSpacing 等还原成 Fabric 写法 */\nfunction applyTextProps(object, node) {\n object.text = node.text === undefined ? '' : String(node.text)\n if (node.fontSize !== undefined) object.fontSize = round(num(node.fontSize))\n if (node.fontFamily !== undefined) object.fontFamily = node.fontFamily\n if (node.fontWeight !== undefined && node.fontWeight !== 'normal') {\n object.fontWeight = node.fontWeight\n }\n if (node.fontStyle && node.fontStyle !== 'normal') {\n object.fontStyle = node.fontStyle\n }\n if (node.textAlign && node.textAlign !== 'left') {\n object.textAlign = node.textAlign\n }\n if (node.textWrap === 'normal') {\n object.wordWrap = 'word'\n } else if (node.textWrap === 'break') {\n object.wordWrap = 'char'\n object.splitByGrapheme = true\n }\n if (node.lineHeight !== undefined) {\n object.lineHeight = node.lineHeight && typeof node.lineHeight === 'object'\n ? round(num(node.lineHeight.value))\n : round(num(node.lineHeight))\n }\n if (node.letterSpacing !== undefined) {\n const fontSize = num(node.fontSize)\n if (fontSize) {\n object.charSpacing = round(num(node.letterSpacing) / fontSize * 1000, 3)\n }\n }\n if (node.textDecoration) {\n const decoration = String(node.textDecoration)\n if (decoration.indexOf('under') > -1) object.underline = true\n if (decoration.indexOf('delete') > -1) object.linethrough = true\n }\n // 正向给文字兜了 #000000,这里还原成同色,避免重新转换时默认色发生变化\n const fill = fabricPaint(node.fill)\n object.fill = fill === '' ? '#000000' : fill\n if (node.shadow !== undefined) {\n object.shadow = fabricShadow(node.shadow)\n }\n const boxStyle = node.boxStyle\n if (boxStyle && boxStyle.fill) {\n object.backgroundColor = fabricPaint(boxStyle.fill)\n }\n if (node.textBackgroundColor) {\n object.backgroundColor = fabricPaint(node.textBackgroundColor)\n }\n}\n\n/** 平台自定义字段原样搬回 */\nfunction applyMeta(object, node) {\n META_KEYS.forEach((key) => {\n if (node[key] !== undefined) {\n object[key] = node[key]\n }\n })\n}\n\n/** 按钮字段(对应 elements/button.js 的 toJSON) */\nfunction applyButtonProps(object, node) {\n object.text = node.text === undefined ? '' : String(node.text)\n object.fontSize = round(num(node.fontSize, 12))\n if (node.fontFamily !== undefined) object.fontFamily = node.fontFamily\n if (node.fontWeight && node.fontWeight !== 'normal') object.fontWeight = node.fontWeight\n object.fontColor = node.fontColor || '#000000'\n\n const background = fabricPaint(node.backgroundColor !== undefined ? node.backgroundColor : node.fill)\n if (background !== '') object.backgroundColor = background\n const fill = fabricPaint(node.fill)\n if (fill !== '') object.fill = fill\n\n const stroke = fabricPaint(node.stroke)\n if (stroke !== '') {\n object.stroke = stroke\n if (node.strokeWidth !== undefined) object.strokeWidth = round(num(node.strokeWidth))\n }\n if (node.cornerRadius !== undefined && node.cornerRadius !== null) {\n if (Array.isArray(node.cornerRadius)) {\n object.rx = round(num(node.cornerRadius[0]))\n object.ry = round(num(node.cornerRadius[1]))\n } else {\n object.rx = round(num(node.cornerRadius))\n object.ry = round(num(node.cornerRadius))\n }\n }\n if (node.buttonScaleBaseWidth !== undefined) {\n object.buttonScaleBaseWidth = round(num(node.buttonScaleBaseWidth))\n }\n if (node.buttonScaleBaseHeight !== undefined) {\n object.buttonScaleBaseHeight = round(num(node.buttonScaleBaseHeight))\n }\n if (node.wordWrap !== undefined) object.wordWrap = node.wordWrap\n if (node.down === true) object.down = true\n}\n\n/** 进度条字段(对应 elements/bar.js 的 toJSON) */\nfunction applyBarProps(object, node) {\n object.fill = fabricPaint(node.fill)\n const background = fabricPaint(node.backgroundFill)\n if (background !== '') object.backgroundColor = background\n const stroke = fabricPaint(node.stroke)\n if (stroke !== '') {\n object.stroke = stroke\n object.strokeWidth = node.strokeWidth === undefined ? 1 : round(num(node.strokeWidth))\n }\n object.fpct = round(num(node.fpct, 0.6))\n object.fdir = num(node.fdir, 0)\n object.fstyle = node.fstyle || 'rect'\n}\n\n/** 点集(line / polyline / polygon):Leafer 本地 points → Fabric 绝对坐标 */\nfunction applyPointShape(object, node) {\n const points = Array.isArray(node.points) ? node.points : []\n const left = num(object.left)\n const top = num(object.top)\n const absolute = points.map((value, index) => (\n round(index % 2 === 0 ? num(value) + left : num(value) + top)\n ))\n if (object.type === 'line') {\n if (absolute.length >= 4) {\n object.x1 = absolute[0]\n object.y1 = absolute[1]\n object.x2 = absolute[2]\n object.y2 = absolute[3]\n }\n } else {\n object.points = []\n for (let i = 0; i + 1 < absolute.length; i += 2) {\n object.points.push({ x: absolute[i], y: absolute[i + 1] })\n }\n }\n}\n\n/**\n * 变换逆运算。\n *\n * 正向:place() 先按父级宽高补半宽,再 applyPosition() 按 Fabric 的原点、\n * 旋转、翻转、缩放反推 Leafer 的围绕点。这里把两步一起逆回来。\n *\n * 点集元素不同:正向把 scale / 翻转烘焙进 points、节点 scale 归 1,落点是\n * pathPlaceOrigin() 按描边宽度反推的,所以反向单独用 stroke/2 还原。\n */\nfunction applyTransform(object, node, parent) {\n const tag = node.tag\n const type = object.type\n const width = Math.abs(num(node.width))\n const height = Math.abs(num(node.height))\n const parentWidth = parent ? num(parent.width) : 0\n const parentHeight = parent ? num(parent.height) : 0\n\n // 正向 line / polyline / polygon 的落点走 pathPlaceOrigin(不含 triangle)\n const pointsPlaced = (tag === 'Line' || tag === 'Polygon') && type !== 'triangle'\n const rotation = num(node.rotation)\n let scaleX = node.scaleX === undefined ? 1 : num(node.scaleX, 1)\n let scaleY = node.scaleY === undefined ? 1 : num(node.scaleY, 1)\n\n // 正向 button 的 scaleY 烘焙进了高度;点集的 scale 烘焙进了 points\n if (tag === 'Button') scaleY = 1\n if (pointsPlaced) {\n scaleX = 1\n scaleY = 1\n }\n\n // 围绕点比例:组可能是 percent 对象,其它是九宫格字符串\n const fraction = aroundFraction(node.around, width, height)\n const originX = fraction.x < 0.25 ? 'left' : (fraction.x > 0.75 ? 'right' : 'center')\n const originY = fraction.y < 0.25 ? 'top' : (fraction.y > 0.75 ? 'bottom' : 'center')\n\n let x = num(node.x) - parentWidth / 2\n let y = num(node.y) - parentHeight / 2\n\n if (pointsPlaced) {\n // 正向 pathPlaceOrigin:left' = left + R·(stroke/2, stroke/2)\n const stroke = Math.abs(num(node.strokeWidth))\n const rad = rotation * Math.PI / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n x -= ((cos - sin) * stroke) / 2\n y -= ((sin + cos) * stroke) / 2\n } else {\n const single = scaleX > 0 && scaleY > 0 && !rotation\n if (!single) {\n const rad = rotation * Math.PI / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n const rotate = (dx, dy) => [cos * dx - sin * dy, sin * dx + cos * dy]\n const [centerX, centerY] = rotate(\n (0.5 - fraction.x) * Math.abs(scaleX) * width,\n (0.5 - fraction.y) * Math.abs(scaleY) * height\n )\n const [shiftX, shiftY] = rotate(\n scaleX * (fraction.x * width - width / 2),\n scaleY * (fraction.y * height - height / 2)\n )\n x -= centerX + shiftX\n y -= centerY + shiftY\n }\n }\n\n object.left = round(x)\n object.top = round(y)\n if (rotation) object.angle = round(rotation)\n if (originX !== 'left') object.originX = originX\n if (originY !== 'top') object.originY = originY\n\n if (!pointsPlaced) {\n if (type === 'path') {\n // path 的翻转已烘焙进路径数据,负 scale 原样保留(Fabric 里同样表示镜像)\n if (scaleX !== 1) object.scaleX = round(scaleX)\n if (scaleY !== 1) object.scaleY = round(scaleY)\n } else {\n // 其余类型的负 scale 来自 Fabric 的 flipX / flipY,还原成翻转标记\n if (scaleX < 0) {\n object.flipX = true\n scaleX = -scaleX\n }\n if (scaleY < 0) {\n object.flipY = true\n scaleY = -scaleY\n }\n if (scaleX !== 1) object.scaleX = round(scaleX)\n if (scaleY !== 1) object.scaleY = round(scaleY)\n }\n }\n\n if (node.skewX) object.skewX = num(node.skewX)\n if (node.skewY) object.skewY = num(node.skewY)\n if (node.opacity !== undefined && num(node.opacity) !== 1) {\n object.opacity = num(node.opacity)\n }\n if (node.visible === false) object.visible = false\n}\n\nfunction convertChildren(node, ctx) {\n return (node.children || [])\n .map((child) => convertNode(child, ctx, node))\n .filter(Boolean)\n}\n\n/** 单个 Leafer 节点 → Fabric 对象 */\nfunction convertNode(node, ctx, parent) {\n if (!node || typeof node !== 'object') return null\n const tag = node.tag\n const type = fabricTypeOf(node, ctx)\n const object = { type }\n applyTransform(object, node, parent)\n applyMeta(object, node)\n\n const width = Math.abs(num(node.width))\n const height = Math.abs(num(node.height))\n\n switch (tag) {\n case 'Rect': {\n object.width = round(width)\n object.height = round(height)\n const radius = node.cornerRadius\n if (radius !== undefined && radius !== null) {\n if (Array.isArray(radius)) {\n object.rx = round(num(radius[0]))\n object.ry = round(num(radius[1]))\n } else {\n object.rx = round(num(radius))\n object.ry = round(num(radius))\n }\n }\n applyFillStroke(object, node)\n break\n }\n case 'Ellipse': {\n if (type === 'circle') {\n object.radius = round(width / 2)\n object.width = round(width)\n object.height = round(height)\n } else {\n object.width = round(width)\n object.height = round(height)\n }\n applyFillStroke(object, node)\n break\n }\n case 'Circle': {\n // 自定义 Circle(elements 包)内部是圆弧 Path,角度单位是弧度\n object.width = round(width)\n object.height = round(height)\n object.radius = round(width / 2)\n if (node.startAngle !== undefined) {\n object.startAngle = round(num(node.startAngle) * 180 / Math.PI)\n }\n if (node.endAngle !== undefined) {\n object.endAngle = round(num(node.endAngle) * 180 / Math.PI)\n }\n applyFillStroke(object, node)\n break\n }\n case 'IText':\n case 'Text': {\n applyTextProps(object, node)\n if (node.width !== undefined) object.width = round(width)\n if (node.height !== undefined) object.height = round(height)\n break\n }\n case 'Image': {\n object.width = round(width)\n object.height = round(height)\n object.src = node.url === undefined ? '' : node.url\n break\n }\n // 层就是恒等变换的组, Fabric 没有层概念, 导出时按组展开\n case 'Group':\n case 'Layer': {\n if (node.width !== undefined) object.width = round(width)\n if (node.height !== undefined) object.height = round(height)\n object.objects = convertChildren(node, ctx)\n break\n }\n case 'Lib': {\n if (node.width !== undefined) object.width = round(width)\n if (node.height !== undefined) object.height = round(height)\n object.libName = node.libName || ''\n object.param = node.param || {}\n if (node.originParam !== undefined) object.originParam = node.originParam\n if (Array.isArray(node.children) && node.children.length) {\n object.objects = convertChildren(node, ctx)\n }\n break\n }\n case 'Box': {\n object.width = round(width)\n object.height = round(height)\n break\n }\n case 'Button': {\n object.width = round(width)\n object.height = round(height)\n applyButtonProps(object, node)\n break\n }\n case 'Bar': {\n object.width = round(width)\n object.height = round(height)\n applyBarProps(object, node)\n break\n }\n case 'Line': {\n object.width = round(width)\n object.height = round(height)\n applyPointShape(object, node)\n applyFillStroke(object, node, { fill: type === 'polyline' })\n break\n }\n case 'Polygon': {\n object.width = round(width)\n object.height = round(height)\n if (type === 'triangle') {\n applyFillStroke(object, node)\n break\n }\n applyPointShape(object, node)\n applyFillStroke(object, node)\n break\n }\n case 'Path': {\n object.width = round(width)\n object.height = round(height)\n object.path = node.path === undefined ? '' : node.path\n applyFillStroke(object, node)\n break\n }\n default: {\n object.width = round(width)\n object.height = round(height)\n applyFillStroke(object, node)\n break\n }\n }\n\n return object\n}\n\n/**\n * Leafer 文档 → Fabric 文档。\n *\n * @param {object} leaferDocument 形如 { header, param, keyboardEvent, children }\n * @param {object} [options]\n * @param {string} [options.version] 写入根节点的 Fabric 版本号(平台文件里一般是 5.x)\n * @returns {{ document: object, warnings: string[] }}\n */\nexport function leaferToFabric(leaferDocument, options = {}) {\n const warnings = []\n const ctx = { warnings, options }\n const source = leaferDocument || {}\n const header = { ...(source.header || {}) }\n const background = header.background\n delete header.background\n if (header.backgroundImage !== undefined) {\n warnings.push('Leafer header.backgroundImage 是烘焙静态图,Fabric 没有对应字段,已省略')\n delete header.backgroundImage\n }\n\n const document = {\n header,\n param: source.param || {},\n keyboardEvent: source.keyboardEvent || [],\n objects: (source.children || []).map((node) => convertNode(node, ctx, null)).filter(Boolean)\n }\n // 平台真实文件把背景色放在根上(button.json / DCS 页面都是),这里保持一致\n if (background !== undefined) {\n document.background = background\n }\n if (options.version) {\n document.version = options.version\n }\n\n return { document, warnings }\n}"],"mappings":";AAKO,SAAS,cAAc,UAAU,CAAC,GAAG;AAC1C,QAAM,WAAW,CAAC;AAElB,QAAM,eAAe,OAAO,QAAQ,iBAAiB,aACjD,QAAQ,eACR,CAAC,SAAS;AAEd,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA;AAAA,IAGA,KAAK,SAAS;AACZ,eAAS,KAAK,OAAO,OAAO,CAAC;AAAA,IAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,IAMA,SAAS;AAAA,EACX;AACF;;;ACxBO,SAAS,KAAK,KAAK,QAAQ,CAAC,GAAG;AACpC,QAAM,SAAS,EAAE,IAAI;AACrB,SAAO,KAAK,KAAK,EAAE,QAAQ,CAAC,QAAQ;AAClC,UAAM,QAAQ,MAAM,GAAG;AACvB,QAAI,UAAU,QAAW;AACvB,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,SAAS,IAAI,OAAO,WAAW,GAAG;AACvC,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;AAGO,SAAS,YAAY,OAAO;AACjC,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI,QAAO;AAClE,QAAM,SAAS,OAAO,KAAK;AAC3B,SAAO,OAAO,SAAS,MAAM,IAAI,SAAS;AAC5C;;;ACfO,SAAS,MAAMA,OAAM,QAAQ,QAAQ,UAAU,GAAG;AACvD,QAAM,cAAc,SAAS,IAAI,OAAO,KAAK,IAAI;AACjD,QAAM,eAAe,SAAS,IAAI,OAAO,MAAM,IAAI;AACnD,EAAAA,MAAK,IAAI,IAAI,OAAO,IAAI,IAAI,cAAc;AAC1C,EAAAA,MAAK,IAAI,IAAI,OAAO,GAAG,IAAI,eAAe,IAAI;AAC9C,SAAOA;AACT;AAOA,IAAM,uBAAuB;AAG7B,IAAM,oBAAoB;AAEnB,SAAS,eAAe,OAAO,QAAQ;AAC5C,MAAI,KAAK,IAAI,MAAM,IAAI,qBAAqB,KAAK,IAAI,KAAK,IAAI,sBAAsB;AAClF,WAAO,QAAQ,IAAI,KAAK;AAAA,EAC1B;AACA,SAAO;AACT;AAGA,IAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,QAAQ;AACV;AAWO,SAAS,gBAAgB,QAAQ,QAAQ;AAC9C,MAAI,CAAC,QAAQ;AACX,WAAO,EAAE,MAAM,IAAI,OAAO,IAAI,GAAG,KAAK,IAAI,OAAO,GAAG,EAAE;AAAA,EACxD;AACA,MAAI,YAAY,OAAO,IAAI,MAAM,QAAW;AAC1C,WAAO,EAAE,MAAM,OAAO,MAAM,KAAK,OAAO,KAAK;AAAA,EAC/C;AACA,QAAM,cAAc,KAAK,IAAI,IAAI,OAAO,WAAW,CAAC;AACpD,QAAM,QAAQ,OAAO;AACrB,QAAM,SAAS,OAAO;AAEtB,QAAM,SAAS,KAAK,IAAI,eAAe,IAAI,OAAO,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC;AACzE,QAAM,SAAS,KAAK,IAAI,eAAe,IAAI,OAAO,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC;AAC1E,QAAM,YAAY,gBAAgB,OAAO,YAAY,SAAY,SAAS,OAAO,OAAO,KAAK;AAC7F,QAAM,YAAY,gBAAgB,OAAO,YAAY,SAAY,QAAQ,OAAO,OAAO,KAAK;AAC5F,QAAM,QAAQ,IAAI,OAAO,KAAK,IAAI,KAAK,KAAK;AAC5C,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAI9D,QAAM,CAAC,SAAS,OAAO,IAAI;AAAA,KACxB,MAAM,cAAc,QAAQ,SAAS;AAAA,KACrC,MAAM,cAAc,SAAS,SAAS;AAAA,EACzC;AAEA,QAAM,CAAC,QAAQ,MAAM,IAAI,OAAO,OAAO,QAAQ,QAAQ,OAAO,SAAS,MAAM;AAC7E,SAAO;AAAA,IACL,MAAM,IAAI,OAAO,IAAI,IAAI,UAAU;AAAA,IACnC,KAAK,IAAI,OAAO,GAAG,IAAI,UAAU;AAAA,EACnC;AACF;AAGO,SAAS,aAAa,QAAQ;AACnC,MAAI,CAAC,MAAM,QAAQ,MAAM,EAAG,QAAO;AAEnC,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AAEX,SAAO,QAAQ,CAAC,UAAU;AACxB,QAAI,CAAC,MAAO;AACZ,UAAM,IAAI,OAAO,MAAM,CAAC;AACxB,UAAM,IAAI,OAAO,MAAM,CAAC;AACxB,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,EAAG;AAChD,QAAI,IAAI,KAAM,QAAO;AACrB,QAAI,IAAI,KAAM,QAAO;AACrB,QAAI,IAAI,KAAM,QAAO;AACrB,QAAI,IAAI,KAAM,QAAO;AAAA,EACvB,CAAC;AAED,MAAI,SAAS,SAAU,QAAO;AAC9B,SAAO,EAAE,MAAM,MAAM,MAAM,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AAC3E;AAGO,SAAS,aAAa,QAAQ;AACnC,QAAM,SAAS,CAAC;AAChB,QAAM,YAAY;AAClB,WAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK,GAAG;AACzC,UAAM,IAAI,OAAO,CAAC;AAClB,UAAM,IAAI,OAAO,IAAI,CAAC;AACtB,UAAM,QAAQ,OAAO,OAAO,SAAS,CAAC;AACtC,UAAM,QAAQ,OAAO,OAAO,SAAS,CAAC;AACtC,QAAI,UAAU,UAAa,KAAK,IAAI,IAAI,KAAK,IAAI,aAAa,KAAK,IAAI,IAAI,KAAK,IAAI,WAAW;AAC7F;AAAA,IACF;AACA,WAAO,KAAK,GAAG,CAAC;AAAA,EAClB;AACA,SAAO;AACT;AAYO,SAAS,cAAc,QAAQ,UAAU,CAAC,GAAG;AAClD,QAAM,EAAE,QAAQ,OAAO,QAAQ,MAAM,IAAI;AACzC,QAAM,SAAS,aAAa,MAAM;AAClC,MAAI,CAAC,QAAQ;AACX,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,SAAS,CAAC;AAChB,SAAO,QAAQ,CAAC,UAAU;AACxB,QAAI,CAAC,MAAO;AACZ,QAAI,IAAI,OAAO,MAAM,CAAC;AACtB,QAAI,IAAI,OAAO,MAAM,CAAC;AACtB,QAAI,CAAC,OAAO,SAAS,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,GAAG;AAC9C;AAAA,IACF;AACA,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,QAAI,MAAO,KAAI,OAAO,QAAQ;AAC9B,QAAI,MAAO,KAAI,OAAO,SAAS;AAC/B,WAAO,KAAK,GAAG,CAAC;AAAA,EAClB,CAAC;AAED,SAAO,aAAa,MAAM;AAC5B;AAGO,IAAM,mBAAmB,CAAC,QAAQ,YAAY,WAAW,MAAM;AAE/D,SAAS,eAAe,QAAQ;AACrC,SAAO,CAAC,CAAC,UAAU,iBAAiB,SAAS,OAAO,IAAI;AAC1D;AAMO,SAAS,gBAAgB,UAAU,QAAQ;AAChD,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO;AAAA,EACT;AACA,MAAI,CAAC,MAAM,QAAQ,QAAQ,GAAG;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,eAAe,MAAM,MAAM,OAAO,UAAU,QAAQ,OAAO,UAAU;AACtF,QAAM,QAAQ,IAAI,UAAU,OAAO,KAAK;AACxC,QAAM,SAAS,IAAI,UAAU,OAAO,MAAM;AAE1C,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,QAAI,CAAC,MAAM,QAAQ,OAAO,GAAG;AAC3B,aAAO,OAAO,OAAO;AAAA,IACvB;AAEA,UAAM,OAAO,QAAQ,MAAM;AAC3B,QAAI,UAAU;AACZ,YAAM,OAAO,OAAO,KAAK,CAAC,KAAK,EAAE;AAEjC,YAAM,aAAa,OAAO,KAAK,IAAI,IAAI,IAAI;AAC3C,eAAS,IAAI,YAAY,IAAI,KAAK,SAAS,GAAG,KAAK,GAAG;AACpD,YAAI,OAAO,KAAK,CAAC,MAAM,YAAY,OAAO,KAAK,IAAI,CAAC,MAAM,UAAU;AAClE,cAAI,OAAO,UAAU,KAAM,MAAK,CAAC,IAAI,QAAQ,KAAK,CAAC;AACnD,cAAI,OAAO,UAAU,KAAM,MAAK,IAAI,CAAC,IAAI,SAAS,KAAK,IAAI,CAAC;AAAA,QAC9D;AAAA,MACF;AAEA,UAAI,OAAO,KAAK,IAAI,KAAK,OAAO,UAAU,QAAQ,OAAO,KAAK,CAAC,MAAM,UAAU;AAC7E,aAAK,CAAC,IAAI,QAAQ,KAAK,CAAC;AAAA,MAC1B;AACA,UAAI,OAAO,KAAK,IAAI,KAAK,OAAO,UAAU,QAAQ,OAAO,KAAK,CAAC,MAAM,UAAU;AAC7E,aAAK,CAAC,IAAI,SAAS,KAAK,CAAC;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO,KACJ,IAAI,CAAC,SAAU,OAAO,SAAS,WAAW,OAAO,KAAK,QAAQ,CAAC,CAAC,IAAI,IAAK,EACzE,KAAK,GAAG;AAAA,EACb,CAAC,EAAE,KAAK,GAAG;AACb;AAMO,SAAS,SAAS,QAAQ;AAC/B,QAAM,UAAU,OAAO,YAAY,SAAY,SAAS,OAAO;AAC/D,QAAM,UAAU,OAAO,YAAY,SAAY,QAAQ,OAAO;AAC9D,QAAM,MAAM;AAAA,IACV,MAAM,EAAE,KAAK,YAAY,QAAQ,QAAQ,QAAQ,cAAc;AAAA,IAC/D,QAAQ,EAAE,KAAK,OAAO,QAAQ,UAAU,QAAQ,SAAS;AAAA,IACzD,OAAO,EAAE,KAAK,aAAa,QAAQ,SAAS,QAAQ,eAAe;AAAA,EACrE;AACA,SAAQ,IAAI,OAAO,KAAK,IAAI,OAAO,EAAE,OAAO,KAAM;AACpD;AAGA,IAAM,kBAAkB;AAAA,EACtB,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACzB,KAAK,EAAE,GAAG,KAAK,GAAG,EAAE;AAAA,EACpB,aAAa,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC1B,MAAM,EAAE,GAAG,GAAG,GAAG,IAAI;AAAA,EACrB,QAAQ,EAAE,GAAG,KAAK,GAAG,IAAI;AAAA,EACzB,OAAO,EAAE,GAAG,GAAG,GAAG,IAAI;AAAA,EACtB,eAAe,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EAC5B,QAAQ,EAAE,GAAG,KAAK,GAAG,EAAE;AAAA,EACvB,gBAAgB,EAAE,GAAG,GAAG,GAAG,EAAE;AAC/B;AAOO,SAAS,eAAe,QAAQ,OAAO,QAAQ;AACpD,MAAI,UAAU,OAAO,WAAW,UAAU;AACxC,UAAM,IAAI,IAAI,OAAO,CAAC;AACtB,UAAM,IAAI,IAAI,OAAO,CAAC;AACtB,QAAI,OAAO,SAAS,WAAW;AAC7B,aAAO,EAAE,GAAG,EAAE;AAAA,IAChB;AACA,WAAO,EAAE,GAAG,QAAQ,IAAI,QAAQ,GAAG,GAAG,SAAS,IAAI,SAAS,EAAE;AAAA,EAChE;AACA,SAAO,gBAAgB,MAAM,KAAK,gBAAgB,UAAU;AAC9D;AAGA,SAAS,WAAWA,OAAM,UAAU;AAClC,QAAM,WAAW,MAAM,QAAQA,MAAK,QAAQ,IAAIA,MAAK,WAAW;AAChE,MAAI,YAAY,SAAS,QAAQ;AAC/B,WAAO,WAAW,SAAS,IAAI,CAAC,UAAU,QAAQ,KAAK,CAAC,CAAC;AAAA,EAC3D;AAEA,QAAM,QAAQ,YAAYA,MAAK,KAAK,MAAM,SAAY,YAAYA,MAAK,KAAK,IAAI,YAAY,YAAY,SAAS,KAAK;AACtH,QAAM,SAAS,YAAYA,MAAK,MAAM,MAAM,SAAY,YAAYA,MAAK,MAAM,IAAI,YAAY,YAAY,SAAS,MAAM;AAC1H,SAAO,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,KAAK,IAAI,SAAS,CAAC,GAAG,QAAQ,KAAK,IAAI,UAAU,CAAC,EAAE;AAClF;AASO,SAAS,QAAQA,OAAM,UAAU;AACtC,QAAM,QAAQ,WAAWA,OAAM,QAAQ;AACvC,QAAM,SAAS,eAAeA,MAAK,QAAQ,MAAM,OAAO,MAAM,MAAM;AACpE,QAAM,UAAU,MAAM,IAAI,OAAO,IAAI,MAAM;AAC3C,QAAM,UAAU,MAAM,IAAI,OAAO,IAAI,MAAM;AAE3C,QAAM,WAAW,IAAIA,MAAK,QAAQ,IAAI,KAAK,KAAK;AAChD,QAAM,SAASA,MAAK,WAAW,SAAY,IAAI,IAAIA,MAAK,QAAQ,CAAC;AACjE,QAAM,SAASA,MAAK,WAAW,SAAY,IAAI,IAAIA,MAAK,QAAQ,CAAC;AACjE,QAAM,QAAQ,IAAIA,MAAK,KAAK,IAAI,KAAK,KAAK;AAC1C,QAAM,QAAQ,IAAIA,MAAK,KAAK,IAAI,KAAK,KAAK;AAC1C,QAAM,OAAO,KAAK,IAAI,QAAQ;AAC9B,QAAM,OAAO,KAAK,IAAI,QAAQ;AAC9B,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,SAAS,OAAO;AAClB,SAAK,OAAO,QAAQ,CAAC,QAAQ;AAC7B,SAAK,OAAO,QAAQ,QAAQ;AAC5B,SAAK,CAAC,OAAO,QAAQ,QAAQ;AAC7B,SAAK,OAAO,QAAQ,QAAQ;AAAA,EAC9B,OAAO;AACL,QAAI,OAAO;AACX,QAAI,OAAO;AACX,QAAI,CAAC,OAAO;AACZ,QAAI,OAAO;AAAA,EACb;AACA,QAAM,IAAI,IAAIA,MAAK,CAAC;AACpB,QAAM,IAAI,IAAIA,MAAK,CAAC;AACpB,QAAM,UAAU;AAAA,IACd,CAAC,MAAM,GAAG,MAAM,CAAC;AAAA,IACjB,CAAC,MAAM,IAAI,MAAM,OAAO,MAAM,CAAC;AAAA,IAC/B,CAAC,MAAM,IAAI,MAAM,OAAO,MAAM,IAAI,MAAM,MAAM;AAAA,IAC9C,CAAC,MAAM,GAAG,MAAM,IAAI,MAAM,MAAM;AAAA,EAClC;AACA,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,UAAQ,QAAQ,CAAC,WAAW;AAC1B,UAAM,KAAK,OAAO,CAAC,IAAI;AACvB,UAAM,KAAK,OAAO,CAAC,IAAI;AACvB,UAAM,KAAK,IAAI,IAAI,KAAK,IAAI;AAC5B,UAAM,KAAK,IAAI,IAAI,KAAK,IAAI;AAC5B,QAAI,KAAK,KAAM,QAAO;AACtB,QAAI,KAAK,KAAM,QAAO;AACtB,QAAI,KAAK,KAAM,QAAO;AACtB,QAAI,KAAK,KAAM,QAAO;AAAA,EACxB,CAAC;AACD,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AACrE;AAGO,SAAS,WAAW,OAAO;AAChC,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,QAAM,QAAQ,CAAC,QAAQ;AACrB,QAAI,CAAC,IAAK;AACV,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,KAAM,QAAO,IAAI;AAC7B,QAAI,IAAI,IAAI,IAAI,QAAQ,KAAM,QAAO,IAAI,IAAI,IAAI;AACjD,QAAI,IAAI,IAAI,IAAI,SAAS,KAAM,QAAO,IAAI,IAAI,IAAI;AAAA,EACpD,CAAC;AACD,MAAI,SAAS,SAAU,QAAO,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,EAAE;AAChE,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AACrE;AAGA,IAAM,iBAAiB,oBAAI,IAAI,CAAC,QAAQ,UAAU,SAAS,WAAW,OAAO,CAAC;AASvE,SAAS,kBAAkB,QAAQ;AACxC,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAM,QAAQ,YAAY,OAAO,KAAK;AACtC,QAAM,SAAS,YAAY,OAAO,MAAM;AACxC,QAAM,QAAQ,UAAU,UAAa,QAAQ,IAAI,KAAK;AACtD,QAAM,QAAQ,WAAW,UAAa,SAAS,IAAI,KAAK;AACxD,MAAI,UAAU,KAAK,UAAU,EAAG,QAAO;AACvC,QAAM,aAAa,EAAE,GAAG,OAAO;AAC/B,MAAI,UAAU,OAAW,YAAW,QAAQ,KAAK,IAAI,KAAK;AAC1D,MAAI,WAAW,OAAW,YAAW,SAAS,KAAK,IAAI,MAAM;AAC7D,MAAI,eAAe,IAAI,OAAO,IAAI,EAAG,QAAO;AAC5C,aAAW,UAAU,OAAO,WAAW,SAAY,IAAI,IAAI,OAAO,QAAQ,CAAC,KAAK;AAChF,aAAW,UAAU,OAAO,WAAW,SAAY,IAAI,IAAI,OAAO,QAAQ,CAAC,KAAK;AAChF,SAAO;AACT;;;AC/WA,IAAMC,mBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,KAAK;AAAA,EACL,QAAQ;AACV;AASA,IAAM,oBAAoB,CAAC,YAAY,WAAW,MAAM;AAQxD,SAAS,gBAAgBC,OAAM,QAAQ,QAAQ,QAAQ;AACrD,MAAI,CAAC,kBAAkB,SAAS,OAAO,IAAI,EAAG,QAAO;AACrD,MAAI,CAAC,MAAM,QAAQA,MAAK,MAAM,KAAK,CAACA,MAAK,OAAO,OAAQ,QAAO;AAC/D,QAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,QAAM,OAAO,KAAK,IAAI,MAAM;AAG5B,QAAM,UAAU,SAAS;AACzB,QAAM,UAAU,SAAS;AACzB,MAAI,SAAS,KAAK,SAAS,KAAK,CAAC,WAAW,CAAC,QAAS,QAAO;AAE7D,EAAAA,MAAK,SAASA,MAAK,OAAO,IAAI,CAAC,OAAO,UAAW,QAAQ,MAAM,IAAI,QAAQ,OAAO,QAAQ,IAAK;AAC/F,MAAIA,MAAK,UAAU,OAAW,CAAAA,MAAK,QAAQ,KAAK,IAAI,IAAIA,MAAK,KAAK,CAAC,IAAI;AACvE,MAAIA,MAAK,WAAW,OAAW,CAAAA,MAAK,SAAS,KAAK,IAAI,IAAIA,MAAK,MAAM,CAAC,IAAI;AAE1E,MAAI,SAAS;AACX,UAAM,QAAQA,MAAK,UAAU,SAAY,KAAK,IAAI,IAAIA,MAAK,KAAK,CAAC,IAAI,MAAMA,MAAK,QAAQ,CAAC;AACzF,IAAAA,MAAK,SAASA,MAAK,OAAO,IAAI,CAAC,OAAO,UAAW,QAAQ,MAAM,IAAI,QAAQ,QAAQ,KAAM;AAAA,EAC3F;AACA,MAAI,SAAS;AACX,UAAM,SAASA,MAAK,WAAW,SAAY,KAAK,IAAI,IAAIA,MAAK,MAAM,CAAC,IAAI,MAAMA,MAAK,QAAQ,CAAC;AAC5F,IAAAA,MAAK,SAASA,MAAK,OAAO,IAAI,CAAC,OAAO,UAAW,QAAQ,MAAM,IAAI,SAAS,QAAQ,KAAM;AAAA,EAC5F;AACA,SAAO;AACT;AAGA,SAAS,MAAM,QAAQ,MAAM;AAC3B,MAAI,MAAM;AACV,WAAS,IAAI,MAAM,IAAI,OAAO,QAAQ,KAAK,GAAG;AAC5C,QAAI,OAAO,CAAC,IAAI,IAAK,OAAM,OAAO,CAAC;AAAA,EACrC;AACA,SAAO,OAAO,SAAS,GAAG,IAAI,MAAM;AACtC;AAGA,SAAS,SAAS,QAAQ;AACxB,MAAI,MAAM,QAAQ,OAAO,MAAM,GAAG;AAChC,UAAM,SAAS,aAAa,OAAO,MAAM;AACzC,WAAO,SAAS,EAAE,GAAG,OAAO,OAAO,GAAG,OAAO,OAAO,IAAI;AAAA,EAC1D;AACA,QAAM,QAAQ,YAAY,OAAO,KAAK;AACtC,QAAM,SAAS,YAAY,OAAO,MAAM;AACxC,MAAI,UAAU,UAAa,WAAW,OAAW,QAAO;AACxD,SAAO,EAAE,GAAG,OAAO,GAAG,OAAO;AAC/B;AAEO,SAAS,eAAeA,OAAM,QAAQ,KAAK;AAEhD,MAAI,YAAY,OAAO,KAAK,MAAM,QAAW;AAC3C,IAAAA,MAAK,WAAW,IAAI,OAAO,KAAK;AAAA,EAClC;AAIA,MAAIA,MAAK,WAAW,OAAW,CAAAA,MAAK,SAAS,SAAS,MAAM;AAE5D,QAAM,SAAS,SAAS,MAAM;AAC9B,QAAM,SAAS;AAAA,IACb,OAAO,WAAW,SAAY,IAAI,IAAI,OAAO,QAAQ,CAAC;AAAA,IACtD,UAAU,OAAO;AAAA,EACnB;AACA,QAAM,SAAS;AAAA,IACb,OAAO,WAAW,SAAY,IAAI,IAAI,OAAO,QAAQ,CAAC;AAAA,IACtD,UAAU,OAAO;AAAA,EACnB;AAEA,QAAM,QAAQ,eAAe,MAAM;AACnC,QAAM,cAAc,CAAC,SAAS,OAAO,UAAU,OAAO,CAAC,KAAK,IAAI,MAAM,IAAI;AAC1E,QAAM,cAAc,CAAC,SAAS,OAAO,UAAU,OAAO,CAAC,KAAK,IAAI,MAAM,IAAI;AAG1E,QAAM,aAAa,gBAAgBA,OAAM,QAAQ,aAAa,WAAW;AAEzE,EAAAA,MAAK,SAAS,aAAa,IAAI;AAG/B,EAAAA,MAAK,SAAS,OAAO,SAAS,YAAY,aAAa,IAAI;AAC3D,gBAAcA,OAAM,QAAQ,aAAaA,MAAK,MAAM;AAGpD,MAAI,OAAO,MAAO,CAAAA,MAAK,QAAQ,IAAI,OAAO,KAAK;AAC/C,MAAI,OAAO,MAAO,CAAAA,MAAK,QAAQ,IAAI,OAAO,KAAK;AAE/C,MAAI,OAAO,YAAY,QAAW;AAChC,IAAAA,MAAK,UAAU,IAAI,OAAO,SAAS,CAAC;AAAA,EACtC;AACA,MAAI,OAAO,YAAY,OAAO;AAC5B,IAAAA,MAAK,UAAU;AAAA,EACjB;AAEA,SAAOA;AACT;AAgBA,SAAS,cAAcA,OAAM,QAAQ,QAAQ,QAAQ;AACnD,MAAIA,MAAK,MAAM,UAAaA,MAAK,MAAM,OAAW;AAGlD,MAAI,kBAAkB,SAAS,OAAO,IAAI,EAAG;AAE7C,QAAM,QAAQ,IAAI,OAAO,KAAK;AAC9B,QAAM,SAAS,IAAI,OAAO,MAAM;AAChC,QAAM,YAAYD,iBAAgB,OAAO,YAAY,SAAY,SAAS,OAAO,OAAO;AACxF,QAAM,YAAYA,iBAAgB,OAAO,YAAY,SAAY,QAAQ,OAAO,OAAO;AACvF,MAAI,cAAc,UAAa,cAAc,OAAW;AAExD,QAAM,SAAS,SAAS,KAAK,SAAS,KAAK,CAAC,IAAIC,MAAK,UAAU,CAAC;AAChE,MAAI,OAAQ;AAEZ,QAAM,QAAQ,IAAIA,MAAK,UAAU,CAAC,IAAI,KAAK,KAAK;AAChD,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAM,MAAM,KAAK,IAAI,KAAK;AAC1B,QAAM,SAAS,CAAC,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC;AAG9D,QAAM,CAAC,SAAS,OAAO,IAAI;AAAA,KACxB,MAAM,aAAa,KAAK,IAAI,MAAM,IAAI;AAAA,KACtC,MAAM,aAAa,KAAK,IAAI,MAAM,IAAI;AAAA,EACzC;AAEA,QAAM,CAAC,QAAQ,MAAM,IAAI;AAAA,IACvB,UAAU,YAAY,QAAQ,QAAQ;AAAA,IACtC,UAAU,YAAY,SAAS,SAAS;AAAA,EAC1C;AAEA,EAAAA,MAAK,IAAI,IAAIA,MAAK,CAAC,IAAI,UAAU;AACjC,EAAAA,MAAK,IAAI,IAAIA,MAAK,CAAC,IAAI,UAAU;AACnC;;;ACtKO,SAAS,eAAe,OAAO;AACpC,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,MAAM,KAAK;AAGzB,QAAM,OAAO,MAAM,MAAM,wBAAwB;AACjD,MAAI,MAAM;AACR,UAAM,QAAQ,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAC1D,QAAI,MAAM,WAAW,GAAG;AACtB,YAAMC,SAAQ,OAAO,MAAM,CAAC,CAAC;AAC7B,UAAI,OAAO,SAASA,MAAK,KAAKA,SAAQ,GAAG;AACvC,cAAM,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGA,SAAQ,GAAG,CAAC;AACvD,eAAO,QAAQ,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC,IAAI,KAAK,MAAM,aAAa,GAAI,IAAI,GAAI;AAAA,MACzF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,MAAM,MAAM,qBAAqB;AACjD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AACA,QAAM,MAAM,QAAQ,CAAC;AACrB,QAAM,QAAQ,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AAC1C,MAAI,UAAU,KAAK;AACjB,WAAO,MAAM,IAAI,MAAM,GAAG,CAAC;AAAA,EAC7B;AACA,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AACtC,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AACtC,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AACtC,SAAO,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,MAAO,QAAQ,MAAO,GAAI,IAAI,GAAI;AACvE;AAGO,SAAS,mBAAmB,OAAO;AACxC,MAAI,UAAU,MAAM,UAAU,QAAQ,UAAU,QAAW;AACzD,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,MAAM,KAAK,EAAE,YAAY;AACvC,MAAI,UAAU,iBAAiB,UAAU,QAAQ;AAC/C,WAAO;AAAA,EACT;AACA,MAAI,mCAAmC,KAAK,KAAK,GAAG;AAClD,WAAO;AAAA,EACT;AACA,MAAI,qBAAqB,KAAK,KAAK,GAAG;AACpC,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;ACpDA,SAAS,UAAU,OAAO;AACxB,SAAO,UAAU,UAAa,UAAU,QAAQ,OAAO,SAAS,OAAO,KAAK,CAAC;AAC/E;AAGO,SAAS,WAAW,OAAO;AAChC,SAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK;AACrE;AAEO,SAAS,gBAAgB,UAAU,KAAK;AAC7C,QAAM,cAAc,SAAS,cAAc,SAAS,SAAS,CAAC;AAC9D,QAAM,QAAQ,YAAY,IAAI,CAAC,UAAU;AAAA,IACvC,QAAQ,OAAO,KAAK,MAAM,KAAK;AAAA,IAC/B,OAAO,eAAe,KAAK,KAAK;AAAA,EAClC,EAAE;AAEF,QAAM,SAAS,SAAS,UAAU,CAAC;AACnC,QAAM,OAAO,SAAS,QAAQ,CAAC;AAC/B,QAAM,KAAK,SAAS,MAAM,CAAC;AAE3B,QAAM,QAAQ;AAAA;AAAA,IAEZ,MAAM,SAAS,QAAQ;AAAA,IACvB;AAAA,EACF;AAGA,QAAM,OAAO;AAAA,IACX,MAAM;AAAA,IACN,GAAG,UAAU,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAK,UAAU,OAAO,EAAE,IAAI,OAAO,OAAO,EAAE,IAAI;AAAA,IACpF,GAAG,UAAU,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,IAAK,UAAU,OAAO,EAAE,IAAI,OAAO,OAAO,EAAE,IAAI;AAAA,EACtF;AACA,QAAM,KAAK;AAAA,IACT,MAAM;AAAA,IACN,GAAG,UAAU,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,IAAK,UAAU,OAAO,EAAE,IAAI,OAAO,OAAO,EAAE,IAAI;AAAA,IAChF,GAAG,UAAU,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,IAAK,UAAU,OAAO,EAAE,IAAI,OAAO,OAAO,EAAE,IAAI;AAAA,EAClF;AAEA,MAAI,MAAM,SAAS,UAAU;AAE3B,UAAM,SAAS,UAAU,OAAO,EAAE,IAC9B,OAAO,OAAO,EAAE,IACf,UAAU,SAAS,EAAE,IAAI,OAAO,SAAS,EAAE,IAAI;AAEpD,QAAI,MAAM,KAAK,MAAM,MAAM,GAAG,KAAK,MAAM,KAAK,MAAM,MAAM,GAAG,GAAG;AAC9D,YAAM,KAAK;AAAA,QACT,MAAM;AAAA,QACN,GAAG,MAAM,KAAK,IAAI,KAAK,IAAI,MAAQ,MAAM;AAAA,QACzC,GAAG,MAAM,KAAK;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,OAAO,IAAI,WAAW,IAAI,QAAQ,OAAO;AAC3C,UAAM,mBAAmB;AAAA,EAC3B;AAEA,SAAO;AACT;;;AC9DA,IAAM,WAAW;AAEV,SAAS,gBAAgB,KAAK,MAAM,KAAK;AAC9C,QAAM,MAAM,OAAO,QAAQ,YAAY,MACnC,MACC,SAAS,UAAa,SAAS,OAAO,KAAK,OAAO,IAAI;AAE3D,MAAI,CAAC,KAAK;AACR,WAAO;AAAA,EACT;AACA,MAAI,SAAS,KAAK,GAAG,GAAG;AACtB,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,IAAI,QAAQ,UAAU,EAAE;AACnC,MAAI,CAAC,KAAK,WAAW,QAAQ,GAAG;AAC9B,WAAO,WAAW;AAAA,EACpB;AACA,SAAO,IAAI,aAAa,MAAM,OAAO;AACvC;;;AChBO,SAAS,UAAU,OAAO;AAC/B,SAAO,CAAC,CAAC,SAAS,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,MAChE,MAAM,SAAS,aACb,OAAO,MAAM,WAAW,YAAY,MAAM,WAAW,MAAM,MAAM,WAAW;AACnF;AAGA,SAAS,mBAAmB,WAAW;AACrC,QAAM,OAAO,MAAM,QAAQ,SAAS,IAAI,UAAU,IAAI,MAAM,IAAI,CAAC;AACjE,MAAI,KAAK,SAAS,KAAK,KAAK,KAAK,CAAC,SAAS,CAAC,OAAO,SAAS,IAAI,CAAC,GAAG;AAClE,WAAO;AAAA,EACT;AACA,QAAM,CAAC,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC,IAAI;AAC3B,MAAI,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM,GAAG;AAClE,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,QAAQ,KAAK,MAAM,GAAG,CAAC;AAAA,IACvB,QAAQ,KAAK,MAAM,GAAG,CAAC;AAAA,IACvB,UAAW,KAAK,MAAM,GAAG,CAAC,IAAI,MAAO,KAAK;AAAA,IAC1C,SAAS;AAAA,IACT,SAAS;AAAA,EACX;AACF;AAGA,SAAS,YAAY,OAAO,QAAQ;AAClC,MAAI,WAAW,YAAY;AACzB,UAAM,OAAO;AACb,UAAM,SAAS;AAAA,EACjB,WAAW,WAAW,YAAY;AAChC,UAAM,OAAO;AACb,UAAM,SAAS;AAAA,EACjB,WAAW,WAAW,aAAa;AAEjC,UAAM,OAAO;AAAA,EACf,OAAO;AACL,UAAM,OAAO;AACb,UAAM,SAAS;AAAA,EACjB;AACF;AAGO,SAAS,eAAe,SAAS,KAAK;AAC3C,QAAM,MAAM,gBAAgB,QAAQ,QAAQ,QAAW,GAAG;AAC1D,MAAI,CAAC,KAAK;AACR,QAAI,OAAO,OAAO,IAAI,SAAS,YAAY;AACzC,UAAI,KAAK,6EAA2B;AAAA,IACtC;AACA,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,EAAE,MAAM,SAAS,IAAI;AACnC,cAAY,OAAO,QAAQ,MAAM;AAEjC,QAAM,UAAU,OAAO,QAAQ,OAAO,KAAK;AAC3C,QAAM,UAAU,OAAO,QAAQ,OAAO,KAAK;AAC3C,QAAM,YAAY,mBAAmB,QAAQ,gBAAgB;AAC7D,QAAM,IAAI,WAAW,YAAY,UAAU,UAAU;AACrD,QAAM,IAAI,WAAW,YAAY,UAAU,UAAU;AACrD,MAAI,KAAK,GAAG;AACV,UAAM,SAAS,EAAE,GAAG,EAAE;AAAA,EACxB;AACA,MAAI,WAAW;AACb,QAAI,UAAU,WAAW,KAAK,UAAU,WAAW,GAAG;AACpD,YAAM,QAAQ,EAAE,GAAG,UAAU,QAAQ,GAAG,UAAU,OAAO;AAAA,IAC3D;AACA,QAAI,UAAU,UAAU;AACtB,YAAM,WAAW,UAAU;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;;;ACvEO,SAAS,QAAQ,OAAO,KAAK;AAClC,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,IAAI;AACzD,WAAO;AAAA,EACT;AACA,MAAI,UAAU,KAAK,GAAG;AACpB,WAAO,eAAe,OAAO,GAAG;AAAA,EAClC;AACA,MAAI,WAAW,KAAK,GAAG;AACrB,WAAO,gBAAgB,OAAO,GAAG;AAAA,EACnC;AACA,SAAO,eAAe,KAAK;AAC7B;AAGO,SAAS,WAAWC,OAAM,QAAQ,KAAK;AAC5C,MAAI,OAAO,SAAS,UAAaA,MAAK,SAAS,QAAW;AACxD,IAAAA,MAAK,OAAO,QAAQ,OAAO,MAAM,GAAG;AAAA,EACtC;AACA,MAAI,OAAO,WAAW,UAAa,OAAO,WAAW,QAAQ,OAAO,WAAW,IAAI;AACjF,IAAAA,MAAK,SAAS,QAAQ,OAAO,QAAQ,GAAG;AACxC,UAAM,cAAc,YAAY,OAAO,WAAW;AAClD,QAAI,gBAAgB,QAAW;AAC7B,MAAAA,MAAK,cAAc;AAAA,IACrB;AACA,QAAI,MAAM,QAAQ,OAAO,eAAe,KAAK,OAAO,gBAAgB,QAAQ;AAC1E,MAAAA,MAAK,cAAc,OAAO;AAAA,IAC5B;AAAA,EACF;AACA,MAAI,OAAO,WAAW,QAAW;AAC/B,UAAM,SAAS,cAAc,OAAO,MAAM;AAC1C,QAAI,OAAQ,CAAAA,MAAK,SAAS;AAAA,EAC5B;AACF;AAMO,SAAS,wBAAwBA,OAAM,QAAQ,KAAK;AACzD,MAAI,CAAC,OAAO,iBAAiB;AAC3B;AAAA,EACF;AACA,MAAI,mBAAmBA,MAAK,IAAI,GAAG;AACjC,IAAAA,MAAK,OAAO,QAAQ,OAAO,iBAAiB,GAAG;AAAA,EACjD;AACF;AAGO,SAAS,cAAc,QAAQ;AACpC,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AACA,QAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AACrD,SAAO,KAAK,OAAO,OAAO,EAAE,IAAI,CAAC,UAAU;AAAA,IACzC,GAAG,OAAO,KAAK,YAAY,SAAY,KAAK,UAAW,KAAK,KAAK,CAAE;AAAA,IACnE,GAAG,OAAO,KAAK,YAAY,SAAY,KAAK,UAAW,KAAK,KAAK,CAAE;AAAA,IACnE,MAAM,OAAO,KAAK,QAAQ,CAAC;AAAA,IAC3B,OAAO,eAAe,KAAK,SAAS,iBAAiB;AAAA,IACrD,QAAQ,OAAO,KAAK,UAAU,CAAC;AAAA,EACjC,EAAE;AACJ;AAGO,SAAS,eAAeA,OAAM,QAAQ;AAC3C,QAAM,OAAO,OAAO;AACpB,MAAI,QAAQ,SAAS,eAAe;AAClC,IAAAA,MAAK,YAAY;AAAA,EACnB;AACF;AAGO,SAAS,YAAY,OAAO;AACjC,MAAI,CAAC,SAAS,UAAU,OAAQ,QAAO;AACvC,SAAO,UAAU,WAAW,WAAW;AACzC;AAGO,SAAS,aAAa,OAAO;AAClC,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,CAAC,SAAS,SAAS,OAAO,EAAE,SAAS,KAAK,IAAI,QAAQ;AAC/D;;;ACtFA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAOA,IAAM,WAAW;AAAA,EACf,UAAU;AAAA,EACV,OAAO;AACT;AAEO,SAAS,UAAUC,OAAM,QAAQ,KAAK;AAE3C,EAAAA,MAAK,OAAO,SAAS,OAAO,IAAI,KAAK,OAAO;AAE5C,mBAAiB,QAAQ,CAAC,QAAQ;AAChC,QAAI,OAAO,GAAG,MAAM,QAAW;AAC7B,MAAAA,MAAK,GAAG,IAAI,OAAO,GAAG;AAAA,IACxB;AAAA,EACF,CAAC;AAGD,MAAI,CAAC,OAAO,CAAC,IAAI,WAAW,IAAI,QAAQ,cAAc,MAAM;AAC1D,IAAAA,MAAK,YAAY;AAAA,EACnB;AAEA,QAAM,YAAY,OAAO;AACzB,MAAI,aAAa,cAAc,QAAQ;AACrC,IAAAA,MAAK,YAAY,cAAc,WAAW,WAAW;AAAA,EACvD;AACA,QAAM,aAAa,OAAO;AAC1B,MAAI,cAAc,CAAC,SAAS,SAAS,OAAO,EAAE,SAAS,UAAU,GAAG;AAClE,IAAAA,MAAK,aAAa;AAAA,EACpB;AAEA,SAAOA;AACT;;;AC9CA,IAAM,gBAAgB,oBAAI,IAAI,CAAC,SAAS,WAAW,CAAC;AAGpD,IAAM,mBAAmB,oBAAI,IAAI;AAAA,EAC/B;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAW;AAAA,EAAS;AAAA,EAAO;AAAA,EAAS;AAAA,EACtD;AAAA,EAAa;AAAA,EAAU;AAAA,EAAO;AAAA,EAAS;AAAA,EAAa;AACtD,CAAC;AAMM,SAAS,YAAYC,OAAM,QAAQ,KAAK;AAC7C,iBAAeA,OAAM,QAAQ,GAAG;AAChC,MAAI,CAAC,cAAc,IAAI,OAAO,IAAI,GAAG;AACnC,eAAWA,OAAM,QAAQ,GAAG;AAAA,EAC9B;AAEA,MAAI,CAAC,iBAAiB,IAAI,OAAO,IAAI,GAAG;AACtC,4BAAwBA,OAAM,QAAQ,GAAG;AAAA,EAC3C;AAEA,iBAAeA,OAAM,MAAM;AAC3B,YAAUA,OAAM,QAAQ,GAAG;AAC3B,SAAOA;AACT;;;AChCO,SAAS,eAAe,QAAQ;AACrC,QAAM,KAAK,YAAY,OAAO,EAAE;AAChC,QAAM,KAAK,YAAY,OAAO,EAAE;AAChC,MAAI,OAAO,UAAa,OAAO,QAAW;AACxC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAa,OAAO,IAAI;AACjC,WAAO,OAAO,SAAY,KAAK;AAAA,EACjC;AACA,SAAO,CAAC,KAAK,IAAI,GAAG,MAAM,CAAC,GAAG,KAAK,IAAI,GAAG,MAAM,CAAC,CAAC;AACpD;AAEO,SAAS,YAAY,QAAQ,KAAK,QAAQ;AAC/C,QAAM,OAAO,KAAK,QAAQ;AAAA,IACxB,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,IAC9B,cAAc,eAAe,MAAM;AAAA,EACrC,CAAC;AACD,QAAM,MAAM,QAAQ,MAAM;AAC1B,SAAO;AACT;;;ACtBO,SAAS,eAAe,QAAQ,KAAK,QAAQ;AAClD,QAAM,UAAU,KAAK,WAAW;AAAA,IAC9B,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,EAChC,CAAC;AACD,QAAM,SAAS,QAAQ,MAAM;AAC7B,SAAO;AACT;;;ACFO,SAAS,cAAc,QAAQ,KAAK,QAAQ;AACjD,QAAM,SAAS,IAAI,OAAO,MAAM;AAChC,QAAM,SAAS,KAAK,WAAW;AAAA,IAC7B,OAAO,SAAS;AAAA,IAChB,QAAQ,SAAS;AAAA,IACjB,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,EAChC,CAAC;AACD,QAAM,QAAQ,QAAQ,MAAM;AAE5B,MAAI,OAAO,eAAe,UAAa,OAAO,aAAa,QAAW;AACpE,QAAI,KAAK,yHAAmD;AAAA,EAC9D;AACA,SAAO;AACT;;;ACnBO,SAAS,gBAAgB,QAAQ,KAAK,QAAQ;AACnD,QAAM,QAAQ,YAAY,OAAO,KAAK;AACtC,QAAM,SAAS,YAAY,OAAO,MAAM;AACxC,QAAM,IAAI,SAAS;AACnB,QAAM,IAAI,UAAU;AAEpB,QAAM,WAAW,KAAK,WAAW;AAAA,IAC/B;AAAA,IACA;AAAA;AAAA,IAEA,QAAQ,CAAC,IAAI,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAAA,IAC7B,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,IAC9B,QAAQ;AAAA,EACV,CAAC;AACD,QAAM,UAAU,QAAQ,MAAM;AAC9B,SAAO;AACT;;;ACbO,SAAS,gBAAgB,QAAQ,KAAK,QAAQ;AAEnD,QAAM,SAAS,aAAa,OAAO,MAAM;AACzC,QAAM,OAAO,KAAK,QAAQ;AAAA,IACxB,OAAO,SAAS,OAAO,QAAQ;AAAA,IAC/B,QAAQ,SAAS,OAAO,SAAS;AAAA,IACjC,QAAQ,cAAc,OAAO,QAAQ;AAAA,MACnC,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,IAC1B,CAAC;AAAA;AAAA,IAED,QAAQ;AAAA,IACR,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,IAC9B,QAAQ;AAAA,EACV,CAAC;AACD,QAAM,MAAM,EAAE,GAAG,QAAQ,GAAG,gBAAgB,QAAQ,MAAM,EAAE,GAAG,MAAM;AACrE,SAAO;AACT;;;ACXO,SAAS,YAAY,QAAQ,KAAK,QAAQ;AAC/C,QAAM,KAAK,YAAY,OAAO,EAAE,KAAK;AACrC,QAAM,KAAK,YAAY,OAAO,EAAE,KAAK;AACrC,QAAM,KAAK,YAAY,OAAO,EAAE,KAAK;AACrC,QAAM,KAAK,YAAY,OAAO,EAAE,KAAK;AAErC,QAAM,OAAO,KAAK,QAAQ;AAAA;AAAA,IAExB,OAAO,KAAK,IAAI,KAAK,EAAE;AAAA,IACvB,QAAQ,KAAK,IAAI,KAAK,EAAE;AAAA,IACxB,QAAQ,cAAc,CAAC,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC,GAAG;AAAA,MAC1D,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,IAC1B,CAAC;AAAA,IACD,QAAQ;AAAA;AAAA,IAER,QAAQ;AAAA;AAAA,IAER,WAAW,YAAY,OAAO,aAAa;AAAA,IAC3C,YAAY,aAAa,OAAO,cAAc;AAAA,EAChD,CAAC;AACD,QAAM,MAAM,EAAE,GAAG,QAAQ,GAAG,gBAAgB,QAAQ,aAAa,CAAC,EAAE,GAAG,IAAI,GAAG,GAAG,GAAG,EAAE,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM;AACjH,SAAO;AACT;;;AChCO,SAAS,eAAe,QAAQ,KAAK,QAAQ;AAGlD,QAAM,SAAS,aAAa,OAAO,MAAM;AACzC,QAAM,UAAU,KAAK,WAAW;AAAA,IAC9B,OAAO,SAAS,OAAO,QAAQ;AAAA,IAC/B,QAAQ,SAAS,OAAO,SAAS;AAAA,IACjC,QAAQ,cAAc,OAAO,QAAQ;AAAA,MACnC,OAAO,OAAO,UAAU;AAAA,MACxB,OAAO,OAAO,UAAU;AAAA,IAC1B,CAAC;AAAA;AAAA,IAED,QAAQ;AAAA,IACR,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,IAC9B,QAAQ;AAAA,EACV,CAAC;AACD,QAAM,SAAS,EAAE,GAAG,QAAQ,GAAG,gBAAgB,QAAQ,MAAM,EAAE,GAAG,MAAM;AACxE,SAAO;AACT;;;ACdO,SAAS,YAAY,QAAQ,KAAK,QAAQ;AAC/C,QAAM,OAAO,KAAK,QAAQ;AAAA,IACxB,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM,gBAAgB,OAAO,MAAM,MAAM;AAAA,IACzC,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,EAChC,CAAC;AACD,QAAM,MAAM,QAAQ,MAAM;AAC1B,SAAO;AACT;;;ACNO,IAAM,sBAAsB;AAM5B,SAAS,gBAAgB,UAAU,iBAAiB;AAGzD,MAAI,mBAAmB,aAAa,QAAQ;AAC1C,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAMO,SAAS,qBAAqB,aAAa,UAAU;AAC1D,QAAM,UAAU,YAAY,WAAW;AACvC,MAAI,YAAY,QAAW;AACzB,WAAO;AAAA,EACT;AACA,SAAQ,UAAU,MAAQ,IAAI,QAAQ;AACxC;AAGO,SAAS,iBAAiB,QAAQ;AACvC,MAAI,OAAO,aAAa,OAAO,YAAa,QAAO;AACnD,MAAI,OAAO,UAAW,QAAO;AAC7B,MAAI,OAAO,YAAa,QAAO;AAC/B,SAAO;AACT;AAOA,IAAM,iBAAiB;AAAA,EACrB,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,eAAe;AACjB;AAEO,SAAS,iBAAiB,WAAW;AAC1C,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,QAAQ,OAAO,SAAS,EAAE,KAAK,EAAE,YAAY;AACnD,SAAO,eAAe,KAAK,KAAK;AAClC;AAQO,SAAS,kBAAkB,YAAY;AAC5C,QAAM,QAAQ,YAAY,UAAU;AACpC,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,IAAI;AACd,WAAO,EAAE,MAAM,WAAW,MAAM;AAAA,EAClC;AACA,SAAO;AACT;AAGO,SAAS,UAAU,QAAQ,KAAK;AACrC,QAAM,QAAQ;AAAA,IACZ,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM,OAAO,SAAS,SAAY,KAAK,OAAO,OAAO,IAAI;AAAA,IACzD,UAAU,YAAY,OAAO,QAAQ;AAAA,IACrC,YAAY,OAAO,cAAc;AAAA,IACjC,YAAY,OAAO;AAAA;AAAA,IAEnB,WAAW,OAAO,cAAc,WAAW,SAAY,OAAO;AAAA,IAC9D,WAAW,iBAAiB,OAAO,SAAS;AAAA,IAC5C,UAAU,gBAAgB,OAAO,UAAU,OAAO,eAAe;AAAA,IACjE,YAAY,kBAAkB,OAAO,UAAU;AAAA,IAC/C,eAAe,qBAAqB,OAAO,aAAa,OAAO,QAAQ;AAAA,IACvE,MAAM,OAAO,OAAO,QAAQ,OAAO,MAAM,GAAG,IAAI;AAAA,IAChD,QAAQ,OAAO,SAAS,cAAc,OAAO,MAAM,IAAI;AAAA,IACvD,eAAe;AAAA,IACf,gBAAgB,iBAAiB,MAAM;AAAA,EACzC;AAIA,QAAM,kBAAkB,OAAO,mBAAmB,OAAO;AACzD,MAAI,iBAAiB;AACnB,UAAM,WAAW,EAAE,MAAM,eAAe,eAAe,EAAE;AAAA,EAC3D;AACA,MAAI,OAAO,qBAAqB;AAC9B,UAAM,sBAAsB,eAAe,OAAO,mBAAmB;AAAA,EACvE;AAGA,MAAI,OAAO,IAAI,WAAW,IAAI,QAAQ,SAAS,UAAU;AACvD,UAAM,WAAW;AAAA,EACnB;AAEA,SAAO;AACT;;;AC9GA,SAAS,mBAAmB,QAAQ;AAClC,QAAM,WAAW,YAAY,OAAO,QAAQ;AAC5C,QAAM,SAAS,YAAY,OAAO,MAAM;AACxC,MAAI,CAAC,YAAY,CAAC,OAAQ,QAAO;AACjC,QAAM,UAAU,OAAO,SAAS,SAAY,KAAK,OAAO,OAAO,IAAI;AACnE,QAAM,QAAQ,KAAK,IAAI,GAAG,QAAQ,MAAM,IAAI,EAAE,MAAM;AACpD,QAAM,QAAQ,KAAK,MAAO,UAAU,WAAW,SAAU,GAAI,IAAI;AAGjE,MAAI,EAAE,QAAQ,OAAO,QAAQ,KAAM,QAAO;AAC1C,SAAO,EAAE,MAAM,WAAW,OAAO,MAAM;AACzC;AAEA,SAAS,QAAQ,QAAQ;AACvB,SAAO,OAAO,SAAS,YAAY,OAAO,SAAS;AACrD;AAEO,SAAS,YAAY,QAAQ,KAAK,QAAQ;AAC/C,QAAM,QAAQ,UAAU,QAAQ,GAAG;AACnC,QAAM,QAAQ,QAAQ,MAAM;AAC5B,QAAM,OAAO,QACT,KAAK,SAAS;AAAA,IACd,GAAG;AAAA,IACH,YAAY,MAAM,cAAc,mBAAmB,MAAM;AAAA,EAC3D,CAAC,IACC,KAAK,QAAQ,KAAK;AAGtB,QAAM,MAAM,QAAQ,MAAM;AAE1B,MAAI,OAAO;AAET,WAAO,KAAK;AACZ,WAAO,KAAK;AAAA,EACd,WAAW,YAAY,OAAO,KAAK,MAAM,QAAW;AAElD,WAAO,KAAK;AAAA,EACd;AACA,SAAO;AACT;;;AChDO,SAAS,aAAa,QAAQ,KAAK,QAAQ;AAChD,QAAM,QAAQ,KAAK,SAAS;AAAA,IAC1B,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM;AAAA,IACN,KAAK,gBAAgB,OAAO,KAAK,OAAO,MAAM,GAAG;AAAA,EACnD,CAAC;AACD,QAAM,OAAO,QAAQ,MAAM;AAE3B,MAAI,OAAO,SAAS,OAAO,OAAO;AAEhC,QAAI,KAAK,0DAAiC;AAAA,EAC5C;AACA,SAAO;AACT;;;ACfO,SAAS,UAAU,OAAO;AAC/B,MAAI,UAAU,QAAQ,UAAU,QAAW;AACzC,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AACzC;AAGO,SAAS,iBAAiB,SAAS;AACxC,SAAO,OAAO,WAAW,EAAE,EACxB,QAAQ,OAAO,GAAG,EAClB,QAAQ,QAAQ,EAAE,EAClB,QAAQ,UAAU,EAAE,EACpB,QAAQ,UAAU,EAAE,EACpB,QAAQ,YAAY,EAAE;AAC3B;AAGO,SAAS,kBAAkB,OAAO,QAAQ;AAC/C,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,SAAS;AACb,WAAO,KAAK,UAAU,CAAC,CAAC,EAAE,QAAQ,CAAC,QAAQ;AACzC,YAAM,cAAc,OAAO,GAAG,MAAM,QAAQ,OAAO,GAAG,MAAM,SACxD,KACA,OAAO,OAAO,GAAG,CAAC;AACtB,eAAS,OAAO,MAAM,MAAM,MAAM,GAAG,EAAE,KAAK,WAAW;AAAA,IACzD,CAAC;AACD,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,MAAM,IAAI,CAAC,SAAS,kBAAkB,MAAM,MAAM,CAAC;AAAA,EAC5D;AACA,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,WAAO,KAAK,KAAK,EAAE,QAAQ,CAAC,QAAQ;AAClC,YAAM,GAAG,IAAI,kBAAkB,MAAM,GAAG,GAAG,MAAM;AAAA,IACnD,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAGA,SAAS,aAAa,QAAQ;AAC5B,SAAO,CAAC,CAAC,WAAW,OAAO,QAAQ,aAAa,OAAO,QAAQ,iBAAiB,CAAC,CAAC,OAAO;AAC3F;AAEO,SAAS,oBAAoB,WAAW;AAC7C,QAAM,SAAS,oBAAI,IAAI;AACvB,SAAO,KAAK,aAAa,CAAC,CAAC,EAAE,QAAQ,CAAC,cAAc;AAClD,QAAI,aAAa,UAAU,SAAS,CAAC,GAAG;AACtC,aAAO,IAAI,SAAS;AAAA,IACtB;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAGO,SAAS,sBAAsB,QAAQ,wBAAwB;AACpE,MAAI,CAAC,UAAU,CAAC,0BAA0B,uBAAuB,SAAS,GAAG;AAC3E,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,QAAQ;AACjB,WAAO,KAAK,OAAO,MAAM,EAAE,QAAQ,CAAC,cAAc;AAChD,UAAI,uBAAuB,IAAI,SAAS,KAAK,aAAa,OAAO,OAAO,SAAS,CAAC,GAAG;AACnF,eAAO,OAAO,OAAO,SAAS;AAAA,MAChC;AAAA,IACF,CAAC;AACD,QAAI,OAAO,KAAK,OAAO,MAAM,EAAE,WAAW,GAAG;AAC3C,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AAEA,MAAI,MAAM,QAAQ,OAAO,OAAO,GAAG;AACjC,WAAO,QAAQ,QAAQ,CAAC,UAAU,sBAAsB,OAAO,sBAAsB,CAAC;AAAA,EACxF;AACA,SAAO;AACT;AAGO,SAAS,UAAUC,OAAM;AAC9B,SAAO,CAAC,CAACA,UAASA,MAAK,SAAS,SAASA,MAAK,QAAQ;AACxD;AAGO,SAAS,iBAAiB,OAAO;AACtC,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,QAAQ,CAAC,SAAS,iBAAiB,IAAI,CAAC;AAC9C,WAAO;AAAA,EACT;AACA,MAAI,UAAU,KAAK,GAAG;AACpB,WAAO,MAAM;AACb,WAAO;AAAA,EACT;AACA,MAAI,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjC,UAAM,SAAS,QAAQ,CAAC,UAAU,iBAAiB,KAAK,CAAC;AAAA,EAC3D;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,YAAY;AACpC,SAAO;AAAA,IACL,GAAK,cAAc,WAAW,UAAU,WAAW,OAAO,SAAU,CAAC;AAAA,IACrE,GAAK,cAAc,WAAW,SAAU,CAAC;AAAA,EAC3C;AACF;AAEA,SAAS,UAAU,YAAYA,OAAM;AACnC,SAAO;AAAA,IACL,GAAG,iBAAiB,UAAU;AAAA,IAC9B,GAAKA,SAAQA,MAAK,eAAgB,CAAC;AAAA,IACnC,GAAKA,SAAQA,MAAK,SAAU,CAAC;AAAA,EAC/B;AACF;AAIA,SAAS,QAAQ,YAAY;AAC3B,QAAM,SAAU,cAAc,WAAW,UAAW,CAAC;AACrD,QAAM,QAAQ,OAAO,OAAO,KAAK;AACjC,QAAM,SAAS,OAAO,OAAO,MAAM;AACnC,SAAO;AAAA,IACL,OAAO,QAAQ,IAAI,QAAQ;AAAA,IAC3B,QAAQ,SAAS,IAAI,SAAS;AAAA,EAChC;AACF;AAIA,SAAS,gBAAgB,UAAU,OAAO;AACxC,QAAM,UAAU,CAAC;AACjB,QAAM,OAAO,CAAC,MAAM,UAAU;AAC5B,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAMA,QAAO,KAAK,CAAC;AACnB,UAAI,CAACA,SAAQ,OAAOA,UAAS,SAAU;AACvC,UAAI,UAAUA,KAAI,KAAKA,MAAK,SAAS;AACnC,cAAM,OAAO,OAAOA,MAAK,OAAO;AAChC,cAAM,UAAU,CAAC,MAAM,QAAQA,MAAK,QAAQ,KAAK,CAACA,MAAK,SAAS;AAChE,YAAI,WAAW,MAAM,QAAQ,IAAI,MAAM,IAAI;AACzC,kBAAQ,KAAK,EAAE,MAAAA,OAAM,MAAM,OAAO,MAAM,CAAC;AACzC;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,QAAQA,MAAK,QAAQ,EAAG,MAAKA,MAAK,UAAU,KAAK;AAAA,IAC7D;AAAA,EACF;AACA,OAAK,UAAU,KAAK;AACpB,SAAO;AACT;AAGA,eAAe,mBAAmB,UAAU,gBAAgB,OAAO;AACjE,MAAI,UAAU,gBAAgB,UAAU,KAAK;AAC7C,SAAO,QAAQ,QAAQ;AACrB,UAAM,cAAc,MAAM,QAAQ,IAAI,QAAQ,IAAI,CAAC,SAAS;AAE1D,aAAO,QAAQ,QAAQ,eAAe,KAAK,IAAI,CAAC,EAAE,MAAM,MAAM,IAAI;AAAA,IACpE,CAAC,CAAC;AACF,QAAI,OAAO,CAAC;AACZ,gBAAY,QAAQ,CAAC,YAAY,UAAU;AACzC,UAAI,CAAC,WAAY;AACjB,YAAM,OAAO,QAAQ,KAAK;AAC1B,YAAMA,QAAO,KAAK;AAClB,YAAM,SAAS,UAAU,YAAYA,KAAI;AACzC,YAAM,OAAO,QAAQ,UAAU;AAC/B,YAAMC,YAAW,kBAAkB,UAAU,WAAW,YAAY,CAAC,CAAC,GAAG,MAAM;AAC/E,YAAM,MAAM,eAAeA,SAAQ;AACnC,YAAM,WAAW;AAAA,QACf,UAAAA;AAAA,QACA,aAAaD,MAAK,eAAe,iBAAiB,UAAU;AAAA,QAC5D,OAAOA,MAAK,SAAS,CAAC;AAAA,MACxB;AAEA,YAAM,QAAQ,OAAO,IAAI,QAAQ,IAAI,IAAI,QAAQ,KAAK;AACtD,YAAM,SAAS,OAAO,IAAI,SAAS,IAAI,IAAI,SAAS,KAAK;AACzD,UAAI,UAAU,OAAW,UAAS,QAAQ;AAC1C,UAAI,WAAW,OAAW,UAAS,SAAS;AAC5C,aAAO,OAAOA,OAAM,QAAQ;AAC5B,aAAO,KAAK,OAAO,gBAAgB,SAAS,UAAU,KAAK,MAAM,OAAO,KAAK,IAAI,CAAC,CAAC;AAAA,IACrF,CAAC;AACD,cAAU;AAAA,EACZ;AACF;AAGA,IAAME,iBAAgB,oBAAI,IAAI,CAAC,SAAS,WAAW,CAAC;AAM7C,SAAS,kBAAkB,OAAO;AACvC,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAM,QAAQ,CAAC,SAAS,kBAAkB,IAAI,CAAC;AAC/C,WAAO;AAAA,EACT;AACA,MAAIA,eAAc,IAAI,MAAM,IAAI,GAAG;AACjC,UAAM,OAAO;AACb,WAAO,MAAM;AACb,WAAO,MAAM;AACb,QAAI,MAAM,OAAQ,QAAO,MAAM;AAAA,EACjC;AACA,MAAI,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjC,UAAM,SAAS,QAAQ,CAAC,SAAS,kBAAkB,IAAI,CAAC;AAAA,EAC1D;AACA,SAAO;AACT;AAMA,eAAsB,sBAAsB,UAAU,gBAAgB;AACpE,MAAI,CAAC,YAAY,CAAC,MAAM,QAAQ,SAAS,QAAQ,GAAG;AAClD,WAAO;AAAA,EACT;AACA,oBAAkB,SAAS,QAAQ;AACnC,MAAI,OAAO,mBAAmB,YAAY;AACxC,WAAO;AAAA,EACT;AACA,QAAM,mBAAmB,SAAS,UAAU,gBAAgB,CAAC,CAAC;AAC9D,SAAO;AACT;AAQA,SAAS,eAAe,QAAQ;AAC9B,MAAI,CAAC,OAAQ,QAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AACjC,MAAI,OAAO,WAAW,UAAU;AAC9B,UAAM,IAAI,OAAO,OAAO,CAAC;AACzB,UAAM,IAAI,OAAO,OAAO,CAAC;AACzB,QAAI,OAAO,SAAS,CAAC,KAAK,OAAO,SAAS,CAAC,GAAG;AAC5C,aAAO,EAAE,GAAG,OAAO,SAAS,CAAC,IAAI,IAAI,GAAG,GAAG,OAAO,SAAS,CAAC,IAAI,IAAI,EAAE;AAAA,IACxE;AACA,WAAO,EAAE,GAAG,GAAG,GAAG,EAAE;AAAA,EACtB;AACA,QAAM,OAAO,OAAO,MAAM;AAC1B,QAAM,SAAS,KAAK,QAAQ,QAAQ,IAAI;AACxC,SAAO;AAAA,IACL,GAAG,KAAK,QAAQ,OAAO,IAAI,KAAK,IAAK,SAAS,MAAM;AAAA,IACpD,GAAG,KAAK,QAAQ,QAAQ,IAAI,KAAK,IAAK,SAAS,MAAM;AAAA,EACvD;AACF;AAEA,SAAS,SAAS,OAAO;AACvB,QAAM,SAAS,KAAK,IAAI,OAAO,MAAM,MAAM,CAAC;AAC5C,QAAM,SAAS,KAAK,IAAI,OAAO,MAAM,MAAM,CAAC;AAC5C,QAAM,QAAQ,OAAO,MAAM,KAAK,KAAK,OAAO,SAAS,MAAM,IAAI,SAAS;AACxE,QAAM,SAAS,OAAO,MAAM,MAAM,KAAK,OAAO,SAAS,MAAM,IAAI,SAAS;AAE1E,SAAO;AAAA,IACL,OAAO,OAAO,SAAS,KAAK,IAAI,QAAQ;AAAA,IACxC,QAAQ,OAAO,SAAS,MAAM,IAAI,SAAS;AAAA,EAC7C;AACF;AAGO,SAAS,WAAW,UAAU,UAAU,GAAG,UAAU,GAAG;AAC7D,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,MAAI,OAAO;AACX,QAAM,QAAQ,CAAC,QAAQ;AACrB,QAAI,CAAC,IAAK;AACV,WAAO,KAAK,IAAI,MAAM,IAAI,CAAC;AAC3B,WAAO,KAAK,IAAI,MAAM,IAAI,CAAC;AAC3B,WAAO,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI,KAAK;AACvC,WAAO,KAAK,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM;AAAA,EAC1C;AACC,GAAC,YAAY,CAAC,GAAG,QAAQ,CAAC,UAAU;AACnC,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,UAAM,IAAI,OAAO,SAAS,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI;AAC/D,UAAM,IAAI,OAAO,SAAS,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI;AAC/D,UAAM,SAAS,eAAe,MAAM,MAAM;AAC1C,UAAM,OAAO,SAAS,KAAK;AAE3B,UAAM,OAAO,UAAU,IAAI,KAAK,QAAQ,OAAO;AAC/C,UAAM,MAAM,UAAU,IAAI,KAAK,SAAS,OAAO;AAC/C,QAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,GAAG;AACrC,YAAM,EAAE,GAAG,MAAM,GAAG,KAAK,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AACjE;AAAA,IACF;AACA,QAAI,MAAM,QAAQ,MAAM,QAAQ,KAAK,MAAM,SAAS,QAAQ;AAC1D,YAAM,WAAW,MAAM,UAAU,MAAM,GAAG,CAAC;AAC3C;AAAA,IACF;AACA,UAAM,EAAE,GAAG,MAAM,GAAG,KAAK,OAAO,GAAG,QAAQ,EAAE,CAAC;AAAA,EAChD,CAAC;AACD,MAAI,CAAC,OAAO,SAAS,IAAI,EAAG,QAAO;AACnC,SAAO,EAAE,GAAG,MAAM,GAAG,MAAM,OAAO,OAAO,MAAM,QAAQ,OAAO,KAAK;AACrE;AAGO,SAAS,eAAe,UAAU;AACvC,QAAM,MAAM,WAAW,QAAQ;AAC/B,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI,IAAI,KAAK,IAAI,GAAG;AAElB;AAAC,KAAC,YAAY,CAAC,GAAG,QAAQ,CAAC,UAAU;AACnC,UAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,YAAM,IAAI,OAAO,SAAS,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI;AAC/D,YAAM,IAAI,OAAO,SAAS,OAAO,MAAM,CAAC,CAAC,IAAI,OAAO,MAAM,CAAC,IAAI;AAC/D,YAAM,IAAI,IAAI,IAAI;AAClB,YAAM,IAAI,IAAI,IAAI;AAAA,IACpB,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEO,SAAS,mBAAmB,YAAY,SAAS,UAAU;AAChE,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,SAAS,UAAU,YAAY,IAAI;AACzC,QAAM,WAAW,kBAAkB,UAAU,WAAW,YAAY,CAAC,CAAC,GAAG,MAAM;AAC/E,QAAM,MAAM,eAAe,QAAQ;AACnC,QAAM,OAAO,QAAQ,UAAU;AAC/B,QAAM,QAAQ,YAAY,EAAE,GAAG,GAAG,GAAG,EAAE;AAEvC,QAAM,QAAQ,OAAO,IAAI,QAAQ,IAAI,IAAI,QAAQ,KAAK;AACtD,QAAM,SAAS,OAAO,IAAI,SAAS,IAAI,IAAI,SAAS,KAAK;AACzD,SAAO;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,SAAS,OAAO,WAAW,EAAE;AAAA,IAC7B,GAAG,OAAO,MAAM,CAAC,KAAK;AAAA,IACtB,GAAG,OAAO,MAAM,CAAC,KAAK;AAAA,IACtB;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,aAAa,iBAAiB,UAAU;AAAA,IACxC,OAAO,CAAC;AAAA,IACR;AAAA,EACF;AACF;;;AC9UO,SAAS,aAAa,QAAQ,KAAK,QAAQ;AAChD,QAAM,QAAQ,KAAK,SAAS;AAAA,IAC1B,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM;AAAA,EACR,CAAC;AACD,QAAM,OAAO,QAAQ,MAAM;AAG3B,QAAM,mBAAmB,oBAAoB,OAAO,MAAM;AAC1D,QAAM,QAAQ,CAAC;AAEd,GAAC,OAAO,WAAW,CAAC,GAAG,QAAQ,CAAC,UAAU;AACzC,UAAM,SAAS,iBAAiB,OAC5B,sBAAsB,UAAU,KAAK,GAAG,gBAAgB,IACxD;AACJ,UAAM,YAAY,IAAI,QAAQ,QAAQ,KAAK;AAC3C,QAAI,WAAW;AACb,YAAM,KAAK,EAAE,MAAM,WAAW,OAAO,CAAC;AAAA,IACxC;AAAA,EACF,CAAC;AAED,MAAI,MAAM,QAAQ;AAChB,UAAM,WAAW,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAC9C,UAAM,SAAS,SAAS,QAAQ,WAAW,MAAM,IAAI,CAAC,SAAS,QAAQ,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC;AAAA,EAClG;AACA,SAAO;AACT;AAaA,SAAS,SAAS,QAAQ,KAAK;AAC7B,QAAM,QAAQ,IAAI,OAAO,KAAK;AAC9B,QAAM,SAAS,IAAI,OAAO,MAAM;AAChC,QAAM,SAAS,eAAe,SAAS,MAAM,CAAC;AAC9C,QAAM,OAAO,KAAK,IAAI,IAAI,GAAG,CAAC;AAC9B,QAAM,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC;AAC7B,QAAM,QAAQ,KAAK,IAAI,IAAI,IAAI,IAAI,OAAO,KAAK;AAC/C,QAAM,SAAS,KAAK,IAAI,IAAI,IAAI,IAAI,QAAQ,MAAM;AAClD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,GAAG,QAAQ,QAAQ,OAAO,IAAI,QAAQ,SAAS,QAAQ,QAAQ;AAAA,IAC/D,GAAG,SAAS,OAAO,OAAO,IAAI,SAAS,QAAQ,SAAS,OAAO;AAAA,EACjE;AACF;;;ACnDO,SAAS,WAAW,QAAQ,KAAK,QAAQ;AAC9C,QAAM,QAAQ,KAAK,OAAO;AAAA,IACxB,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,MAAM;AAAA,EACR,CAAC;AACD,QAAM,OAAO,QAAQ,MAAM;AAG3B,QAAM,SAAS,EAAE,GAAI,OAAO,eAAe,CAAC,GAAI,GAAI,OAAO,SAAS,CAAC,EAAG;AACxE,QAAM,WAAW,CAAC;AAEjB,GAAC,OAAO,WAAW,CAAC,GAAG,QAAQ,CAAC,UAAU;AACzC,UAAM,SAAS,kBAAkB,UAAU,KAAK,GAAG,MAAM;AACzD,UAAM,YAAY,IAAI,QAAQ,QAAQ,IAAI;AAC1C,QAAI,WAAW;AACb,eAAS,KAAK,SAAS;AAAA,IACzB;AAAA,EACF,CAAC;AAED,MAAI,SAAS,QAAQ;AAEnB,mBAAe,QAAQ;AACvB,UAAM,WAAW;AAAA,EACnB;AACA,SAAO;AACT;;;ACzBA,IAAM,eAAe;AACrB,IAAM,oBAAoB;AAEnB,SAAS,cAAc,QAAQ,KAAK,QAAQ;AAGjD,QAAM,YAAY,YAAY,OAAO,oBAAoB;AACzD,QAAM,aAAa,YAAY,OAAO,qBAAqB;AAC3D,QAAM,QAAQ,YAAY,OAAO,KAAK,KAAK,aAAa;AACxD,QAAM,SAAS,YAAY,OAAO,MAAM,KAAK,cAAc;AAG3D,QAAM,SAAS,IAAI,OAAO,QAAQ,CAAC;AACnC,QAAM,gBAAgB,UAAU,SAAS,IAAI,SAAS;AAEtD,QAAM,iBAAiB,OAAO,oBAAoB,UAAa,OAAO,oBAAoB,KACrF,OAAO,SAAS,UAAa,OAAO,SAAS,KAAK,eAAe,OAAO,OACzE,OAAO;AAEX,QAAM,SAAS,KAAK,UAAU;AAAA,IAC5B;AAAA,IACA,QAAQ;AAAA,IACR,MAAM,OAAO,SAAS,SAAY,KAAK,OAAO,OAAO,IAAI;AAAA,IACzD,UAAU,YAAY,OAAO,QAAQ,KAAK;AAAA,IAC1C,YAAY,OAAO,cAAc;AAAA,IACjC,YAAY,OAAO,cAAc;AAAA,IACjC,WAAW,eAAe,OAAO,aAAa,SAAS;AAAA,IACvD,MAAM,QAAQ,gBAAgB,GAAG;AAAA,IACjC,iBAAiB,QAAQ,gBAAgB,GAAG;AAAA,IAC5C,QAAQ,OAAO,WAAW,UAAa,OAAO,WAAW,QAAQ,OAAO,WAAW,KAC/E,SACA,eAAe,OAAO,MAAM;AAAA,IAChC,aAAa,YAAY,OAAO,WAAW;AAAA,IAC3C,cAAc,YAAY,OAAO,EAAE,KAAK,YAAY,OAAO,EAAE;AAAA,IAC7D,UAAU,OAAO,YAAY;AAAA,IAC7B,MAAM,OAAO,SAAS;AAAA,IACtB,sBAAsB,aAAa;AAAA,IACnC,uBAAuB,cAAc;AAAA,EACvC,CAAC;AACD,QAAM,QAAQ,QAAQ,MAAM;AAC5B,SAAO;AACT;;;ACzCO,SAAS,WAAW,QAAQ,KAAK,QAAQ;AAC9C,QAAM,QAAQ,YAAY,OAAO,KAAK,KAAK;AAC3C,QAAM,SAAS,YAAY,OAAO,MAAM,KAAK;AAC7C,QAAM,YAAY,IAAI,OAAO,MAAM,CAAC,IAAI;AACxC,QAAM,OAAO,YAAY,IAAI,YAAY,IAAI;AAC7C,MAAI,UAAU,IAAI,OAAO,MAAM,GAAG;AAElC,YAAU,KAAK,IAAI,SAAS,IAAI,KAAK,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC;AAE5D,QAAM,MAAM,KAAK,OAAO;AAAA,IACtB;AAAA,IACA;AAAA,IACA,MAAM,QAAQ,OAAO,MAAM,GAAG;AAAA,IAC9B,gBAAgB,QAAQ,OAAO,mBAAmB,eAAe,GAAG;AAAA,IACpE,QAAQ,OAAO,WAAW,UAAa,OAAO,WAAW,QAAQ,OAAO,WAAW,KAC/E,SACA,QAAQ,OAAO,QAAQ,GAAG;AAAA,IAC9B,aAAa,YAAY,OAAO,WAAW;AAAA,IAC3C,MAAM;AAAA,IACN;AAAA,IACA,QAAQ,OAAO,UAAU;AAAA,EAC3B,CAAC;AACD,QAAM,KAAK,QAAQ,MAAM;AACzB,SAAO;AACT;;;ACxBO,SAAS,mBAAmB,QAAQ,KAAK,QAAQ;AACtD,QAAM,MAAM,KAAK,OAAO;AAAA,IACtB,OAAO,YAAY,OAAO,KAAK;AAAA,IAC/B,QAAQ,YAAY,OAAO,MAAM;AAAA,IACjC,SAAS;AAAA,IACT,MAAM;AAAA,EACR,CAAC;AACD,QAAM,KAAK,QAAQ,MAAM;AACzB,SAAO;AACT;;;ACIA,IAAM,aAAa;AAAA,EACjB,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AAAA,EACV,SAAS;AAAA,EACT,OAAO;AAAA,EACP,eAAe;AAAA,EACf,aAAa;AAAA,EACb,OAAO;AAAA,EACP,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,OAAO;AAAA,EACP,WAAW;AACb;AAMO,SAAS,cAAc,QAAQ,KAAK,SAAS,MAAM;AACxD,MAAI,CAAC,UAAU,OAAO,WAAW,UAAU;AACzC,WAAO;AAAA,EACT;AAEA,QAAMC,WAAU,WAAW,OAAO,IAAI;AACtC,MAAI,CAACA,UAAS;AACZ,QAAI,KAAK,2DAAmB,OAAO,IAAI,EAAE;AACzC,WAAO;AAAA,EACT;AAIA,QAAM,SAAS,kBAAkB,MAAM;AACvC,QAAM,SAASA,SAAQ,QAAQ,KAAK,MAAM;AAC1C,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,SAAO,YAAY,QAAQ,QAAQ,GAAG;AACxC;AAGO,SAAS,gBAAgB,MAAM;AACpC,SAAO,OAAO,UAAU,eAAe,KAAK,YAAY,IAAI;AAC9D;;;AC1EO,IAAM,mBAAmB;AAEzB,SAAS,cAAc,YAAY,UAAU;AAClD,QAAM,SAAS,cAAc,CAAC;AAC9B,QAAM,SAAS,OAAO,UAAU,CAAC;AACjC,QAAM,QAAQ,OAAO,SAAS,CAAC;AAE/B,SAAO;AAAA,IACL,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,GAAG;AAAA;AAAA,MAEH,OAAO,EAAE,GAAI,OAAO,SAAS,CAAC,GAAI,GAAG,MAAM;AAAA,MAC3C,YAAY,OAAO,eAAe,SAAY,OAAO,aAAa,OAAO;AAAA,IAC3E;AAAA,IACA;AAAA,IACA,eAAe,OAAO,iBAAiB,CAAC;AAAA,IACxC;AAAA,EACF;AACF;;;ACZA,eAAe,iBAAiB,QAAQ,SAAS,OAAO;AACtD,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,MAAI,OAAO,SAAS,SAAS,OAAO,YAAY,CAAC,MAAM,QAAQ,OAAO,OAAO,KAAK,CAAC,OAAO,QAAQ,SAAS;AACzG,UAAM,OAAO,iBAAiB,OAAO,OAAO;AAC5C,QAAI,CAAC,QAAQ,MAAM,QAAQ,IAAI,IAAI,GAAI;AACvC,QAAI;AACF,YAAM,OAAO,MAAM,QAAQ,IAAI;AAC/B,UAAI,QAAQ,MAAM,QAAQ,KAAK,OAAO,GAAG;AACvC,eAAO,UAAU,KAAK;AACtB,YAAI,CAAC,OAAO,aAAa;AACvB,iBAAO,cAAc;AAAA,YACnB,GAAK,KAAK,UAAU,KAAK,OAAO,SAAU,CAAC;AAAA,YAC3C,GAAI,KAAK,SAAS,CAAC;AAAA,UACrB;AAAA,QACF;AACA,cAAM,kBAAkB,OAAO,SAAS,SAAS,MAAM,OAAO,IAAI,CAAC;AAAA,MACrE;AAAA,IACF,SAAS,OAAO;AAAA,IAEhB;AAAA,EACF,WAAW,MAAM,QAAQ,OAAO,OAAO,GAAG;AACxC,UAAM,kBAAkB,OAAO,SAAS,SAAS,KAAK;AAAA,EACxD;AACF;AAEA,eAAe,kBAAkB,SAAS,SAAS,QAAQ,CAAC,GAAG;AAC7D,MAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,OAAO,YAAY,WAAY;AAE9D,QAAM,QAAQ,IAAI,QAAQ,IAAI,CAAC,WAAW,iBAAiB,QAAQ,SAAS,KAAK,CAAC,CAAC;AACrF;AAGA,SAAS,qBAAqB,SAAS;AACrC,MAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,QAAO;AACpC,SAAO,QAAQ,KAAK,CAAC,WAAW;AAC9B,QAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAClD,QAAI,OAAO,SAAS,SAAS,OAAO,YACjC,CAAC,MAAM,QAAQ,OAAO,OAAO,KAAK,CAAC,OAAO,QAAQ,SAAS;AAC5D,aAAO;AAAA,IACT;AACA,WAAO,MAAM,QAAQ,OAAO,OAAO,KAAK,qBAAqB,OAAO,OAAO;AAAA,EAC7E,CAAC;AACH;AAEA,eAAe,cAAc,YAAY,SAAS;AAChD,MAAI,CAAC,cAAc,CAAC,MAAM,QAAQ,WAAW,OAAO,KAAK,OAAO,QAAQ,YAAY,YAAY;AAC9F,WAAO;AAAA,EACT;AACA,MAAI,CAAC,qBAAqB,WAAW,OAAO,EAAG,QAAO;AACtD,QAAM,SAAS,UAAU,UAAU;AACnC,QAAM,kBAAkB,OAAO,SAAS,QAAQ,OAAO;AACvD,SAAO;AACT;AAEA,SAAS,IAAI,YAAY,SAAS;AAChC,QAAM,MAAM,cAAc,OAAO;AAGjC,MAAI,UAAU,CAAC,QAAQ,WAAW,cAAc,QAAQ,KAAK,MAAM;AAEnE,QAAM,UAAU,cAAc,MAAM,QAAQ,WAAW,OAAO,IAC1D,WAAW,UACX;AAEJ,MAAI,CAAC,SAAS;AACZ,QAAI,KAAK,uEAA+B;AACxC,WAAO,EAAE,UAAU,cAAc,cAAc,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,IAAI,SAAS;AAAA,EACjF;AAEA,QAAM,WAAW,CAAC;AAClB,UAAQ,QAAQ,CAAC,WAAW;AAC1B,UAAM,YAAY,cAAc,QAAQ,KAAK,IAAI;AACjD,QAAI,WAAW;AACb,eAAS,KAAK,SAAS;AAAA,IACzB;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,UAAU,cAAc,YAAY,QAAQ;AAAA,IAC5C,UAAU,IAAI;AAAA,EAChB;AACF;AAGA,eAAsB,QAAQ,YAAY,UAAU,CAAC,GAAG;AACtD,QAAM,SAAS,MAAM,cAAc,YAAY,OAAO;AACtD,SAAO,IAAI,QAAQ,OAAO;AAC5B;AAGO,SAAS,YAAY,YAAY,UAAU,CAAC,GAAG;AACpD,SAAO,IAAI,YAAY,OAAO;AAChC;;;ACpFA,IAAM,YAAY;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,MAAM,OAAO,SAAS,GAAG;AAChC,QAAM,SAAS,OAAO,KAAK;AAC3B,MAAI,CAAC,OAAO,SAAS,MAAM,EAAG,QAAO;AACrC,QAAM,SAAS,KAAK,IAAI,IAAI,MAAM;AAClC,SAAO,KAAK,MAAM,SAAS,MAAM,IAAI;AACvC;AAGA,SAAS,aAAaC,OAAM,KAAK;AAC/B,QAAM,MAAMA,MAAK;AACjB,QAAM,OAAOA,MAAK;AAClB,UAAQ,KAAK;AAAA,IACX,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAO,aAAO;AAAA,IACnB,KAAK;AAAU,aAAO;AAAA,IACtB,KAAK;AAAO,aAAO;AAAA;AAAA,IAEnB,KAAK;AAAS,aAAO;AAAA,IACrB,KAAK;AAAS,aAAO;AAAA,IACrB,KAAK;AAAQ,aAAO;AAAA,IACpB,KAAK;AAAW,aAAO,SAAS,WAAW,WAAW;AAAA,IACtD,KAAK;AAAQ,aAAO,SAAS,SAAS,SAAS;AAAA,IAC/C,KAAK;AAAS,aAAO,OAAO,SAAS,YAAY,OAAO,OAAO;AAAA,IAC/D,KAAK;AAAS,aAAO;AAAA,IACrB,KAAK;AAAO,aAAO,SAAS,WAAW,SAAS,cAAc,OAAO;AAAA;AAAA,IAErE,KAAK;AAAQ,aAAO,SAAS,aAAa,aAAa;AAAA;AAAA,IAEvD,KAAK;AAAW,aAAO,SAAS,aAAa,aAAa;AAAA,IAC1D,KAAK;AAAQ,aAAO;AAAA,IACpB;AACE,UAAI,OAAO,KAAK;AACd,YAAI,SAAS,KAAK,+CAAsB,GAAG,sCAAa;AAAA,MAC1D;AACA,aAAO;AAAA,EACX;AACF;AAGA,SAAS,iBAAiB,OAAO;AAC/B,QAAM,OAAO,MAAM,QAAQ,OAAO,MAAM,SAAS,WAAW,MAAM,OAAO,CAAC;AAC1E,QAAM,KAAK,MAAM,MAAM,OAAO,MAAM,OAAO,WAAW,MAAM,KAAK,CAAC;AAClE,QAAM,SAAS;AAAA,IACb,IAAI,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IACrB,IAAI,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IACrB,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;AAAA,IACnB,IAAI,MAAM,IAAI,GAAG,CAAC,CAAC;AAAA,EACrB;AACA,MAAI,MAAM,SAAS,UAAU;AAE3B,WAAO,KAAK,MAAM,KAAK,MAAM,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC,KAAK;AAAA,EACjF;AACA,SAAO;AAAA,IACL,MAAM,MAAM,SAAS,WAAW,WAAW;AAAA,IAC3C,aAAa,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,UAAU;AAAA,MAC7C,QAAQ,MAAM,IAAI,KAAK,MAAM,CAAC;AAAA,MAC9B,OAAO,KAAK;AAAA,IACd,EAAE;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,gBAAgB,OAAO;AAC9B,QAAM,SAAS,MAAM,SAAS,WAC1B,cACC,MAAM,WAAW,MAAM,aAAc,MAAM,WAAW,MAAM,aAAa;AAC9E,QAAM,UAAU,EAAE,MAAM,WAAW,QAAQ,MAAM,KAAK,OAAO;AAC7D,QAAM,UAAU,MAAM,SAAS,IAAI,MAAM,OAAO,CAAC,IAAI;AACrD,QAAM,UAAU,MAAM,SAAS,IAAI,MAAM,OAAO,CAAC,IAAI;AACrD,MAAI,WAAW,SAAS;AACtB,YAAQ,UAAU,MAAM,OAAO;AAC/B,YAAQ,UAAU,MAAM,OAAO;AAAA,EACjC;AACA,QAAM,WAAW,IAAI,MAAM,QAAQ;AACnC,QAAM,SAAS,MAAM,QAAQ,IAAI,MAAM,MAAM,GAAG,CAAC,IAAI;AACrD,QAAM,SAAS,MAAM,QAAQ,IAAI,MAAM,MAAM,GAAG,CAAC,IAAI;AACrD,MAAI,YAAY,WAAW,KAAK,WAAW,GAAG;AAC5C,UAAM,MAAM,WAAW,KAAK,KAAK;AACjC,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,YAAQ,mBAAmB;AAAA,MACzB,MAAM,SAAS,GAAG;AAAA,MAClB,MAAM,SAAS,GAAG;AAAA,MAClB,MAAM,CAAC,SAAS,GAAG;AAAA,MACnB,MAAM,SAAS,GAAG;AAAA,MAClB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,YAAY,OAAO;AAC1B,MAAI,UAAU,UAAa,UAAU,QAAQ,UAAU,GAAI,QAAO;AAClE,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,mBAAmB,KAAK,IAAI,KAAK;AAAA,EAC1C;AACA,MAAI,MAAM,QAAQ,MAAM,KAAK,GAAG;AAC9B,WAAO,iBAAiB,KAAK;AAAA,EAC/B;AACA,MAAI,MAAM,SAAS,WAAW,MAAM,KAAK;AACvC,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AACA,SAAO;AACT;AAGA,SAAS,aAAa,OAAO;AAC3B,QAAM,OAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;AAClD,SAAO,KAAK,OAAO,OAAO,EAAE,IAAI,CAAC,UAAU;AAAA,IACzC,SAAS,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IAC1B,SAAS,MAAM,IAAI,KAAK,CAAC,CAAC;AAAA,IAC1B,MAAM,MAAM,IAAI,KAAK,IAAI,CAAC;AAAA,IAC1B,OAAO,KAAK,SAAS;AAAA,IACrB,QAAQ,MAAM,IAAI,KAAK,MAAM,CAAC;AAAA,EAChC,EAAE;AACJ;AAGA,SAAS,gBAAgB,QAAQA,OAAM,UAAU,CAAC,GAAG;AACnD,MAAI,QAAQ,SAAS,OAAO;AAC1B,WAAO,OAAO,YAAYA,MAAK,IAAI;AAAA,EACrC;AACA,MAAI,QAAQ,WAAW,OAAO;AAC5B,UAAM,SAAS,YAAYA,MAAK,MAAM;AACtC,QAAI,WAAW,IAAI;AACjB,aAAO,SAAS;AAChB,UAAIA,MAAK,gBAAgB,QAAW;AAClC,eAAO,cAAc,MAAM,IAAIA,MAAK,WAAW,CAAC;AAAA,MAClD;AACA,UAAI,MAAM,QAAQA,MAAK,WAAW,KAAKA,MAAK,YAAY,QAAQ;AAC9D,eAAO,kBAAkBA,MAAK,YAAY,MAAM;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AACA,MAAIA,MAAK,WAAW,QAAW;AAC7B,WAAO,SAAS,aAAaA,MAAK,MAAM;AAAA,EAC1C;AACA,MAAIA,MAAK,UAAW,QAAO,gBAAgBA,MAAK;AAChD,MAAIA,MAAK,WAAY,QAAO,iBAAiBA,MAAK;AAClD,MAAIA,MAAK,UAAW,QAAO,2BAA2BA,MAAK;AAC7D;AAGA,SAAS,eAAe,QAAQA,OAAM;AACpC,SAAO,OAAOA,MAAK,SAAS,SAAY,KAAK,OAAOA,MAAK,IAAI;AAC7D,MAAIA,MAAK,aAAa,OAAW,QAAO,WAAW,MAAM,IAAIA,MAAK,QAAQ,CAAC;AAC3E,MAAIA,MAAK,eAAe,OAAW,QAAO,aAAaA,MAAK;AAC5D,MAAIA,MAAK,eAAe,UAAaA,MAAK,eAAe,UAAU;AACjE,WAAO,aAAaA,MAAK;AAAA,EAC3B;AACA,MAAIA,MAAK,aAAaA,MAAK,cAAc,UAAU;AACjD,WAAO,YAAYA,MAAK;AAAA,EAC1B;AACA,MAAIA,MAAK,aAAaA,MAAK,cAAc,QAAQ;AAC/C,WAAO,YAAYA,MAAK;AAAA,EAC1B;AACA,MAAIA,MAAK,aAAa,UAAU;AAC9B,WAAO,WAAW;AAAA,EACpB,WAAWA,MAAK,aAAa,SAAS;AACpC,WAAO,WAAW;AAClB,WAAO,kBAAkB;AAAA,EAC3B;AACA,MAAIA,MAAK,eAAe,QAAW;AACjC,WAAO,aAAaA,MAAK,cAAc,OAAOA,MAAK,eAAe,WAC9D,MAAM,IAAIA,MAAK,WAAW,KAAK,CAAC,IAChC,MAAM,IAAIA,MAAK,UAAU,CAAC;AAAA,EAChC;AACA,MAAIA,MAAK,kBAAkB,QAAW;AACpC,UAAM,WAAW,IAAIA,MAAK,QAAQ;AAClC,QAAI,UAAU;AACZ,aAAO,cAAc,MAAM,IAAIA,MAAK,aAAa,IAAI,WAAW,KAAM,CAAC;AAAA,IACzE;AAAA,EACF;AACA,MAAIA,MAAK,gBAAgB;AACvB,UAAM,aAAa,OAAOA,MAAK,cAAc;AAC7C,QAAI,WAAW,QAAQ,OAAO,IAAI,GAAI,QAAO,YAAY;AACzD,QAAI,WAAW,QAAQ,QAAQ,IAAI,GAAI,QAAO,cAAc;AAAA,EAC9D;AAEA,QAAM,OAAO,YAAYA,MAAK,IAAI;AAClC,SAAO,OAAO,SAAS,KAAK,YAAY;AACxC,MAAIA,MAAK,WAAW,QAAW;AAC7B,WAAO,SAAS,aAAaA,MAAK,MAAM;AAAA,EAC1C;AACA,QAAM,WAAWA,MAAK;AACtB,MAAI,YAAY,SAAS,MAAM;AAC7B,WAAO,kBAAkB,YAAY,SAAS,IAAI;AAAA,EACpD;AACA,MAAIA,MAAK,qBAAqB;AAC5B,WAAO,kBAAkB,YAAYA,MAAK,mBAAmB;AAAA,EAC/D;AACF;AAGA,SAASC,WAAU,QAAQD,OAAM;AAC/B,YAAU,QAAQ,CAAC,QAAQ;AACzB,QAAIA,MAAK,GAAG,MAAM,QAAW;AAC3B,aAAO,GAAG,IAAIA,MAAK,GAAG;AAAA,IACxB;AAAA,EACF,CAAC;AACH;AAGA,SAAS,iBAAiB,QAAQA,OAAM;AACtC,SAAO,OAAOA,MAAK,SAAS,SAAY,KAAK,OAAOA,MAAK,IAAI;AAC7D,SAAO,WAAW,MAAM,IAAIA,MAAK,UAAU,EAAE,CAAC;AAC9C,MAAIA,MAAK,eAAe,OAAW,QAAO,aAAaA,MAAK;AAC5D,MAAIA,MAAK,cAAcA,MAAK,eAAe,SAAU,QAAO,aAAaA,MAAK;AAC9E,SAAO,YAAYA,MAAK,aAAa;AAErC,QAAM,aAAa,YAAYA,MAAK,oBAAoB,SAAYA,MAAK,kBAAkBA,MAAK,IAAI;AACpG,MAAI,eAAe,GAAI,QAAO,kBAAkB;AAChD,QAAM,OAAO,YAAYA,MAAK,IAAI;AAClC,MAAI,SAAS,GAAI,QAAO,OAAO;AAE/B,QAAM,SAAS,YAAYA,MAAK,MAAM;AACtC,MAAI,WAAW,IAAI;AACjB,WAAO,SAAS;AAChB,QAAIA,MAAK,gBAAgB,OAAW,QAAO,cAAc,MAAM,IAAIA,MAAK,WAAW,CAAC;AAAA,EACtF;AACA,MAAIA,MAAK,iBAAiB,UAAaA,MAAK,iBAAiB,MAAM;AACjE,QAAI,MAAM,QAAQA,MAAK,YAAY,GAAG;AACpC,aAAO,KAAK,MAAM,IAAIA,MAAK,aAAa,CAAC,CAAC,CAAC;AAC3C,aAAO,KAAK,MAAM,IAAIA,MAAK,aAAa,CAAC,CAAC,CAAC;AAAA,IAC7C,OAAO;AACL,aAAO,KAAK,MAAM,IAAIA,MAAK,YAAY,CAAC;AACxC,aAAO,KAAK,MAAM,IAAIA,MAAK,YAAY,CAAC;AAAA,IAC1C;AAAA,EACF;AACA,MAAIA,MAAK,yBAAyB,QAAW;AAC3C,WAAO,uBAAuB,MAAM,IAAIA,MAAK,oBAAoB,CAAC;AAAA,EACpE;AACA,MAAIA,MAAK,0BAA0B,QAAW;AAC5C,WAAO,wBAAwB,MAAM,IAAIA,MAAK,qBAAqB,CAAC;AAAA,EACtE;AACA,MAAIA,MAAK,aAAa,OAAW,QAAO,WAAWA,MAAK;AACxD,MAAIA,MAAK,SAAS,KAAM,QAAO,OAAO;AACxC;AAGA,SAAS,cAAc,QAAQA,OAAM;AACnC,SAAO,OAAO,YAAYA,MAAK,IAAI;AACnC,QAAM,aAAa,YAAYA,MAAK,cAAc;AAClD,MAAI,eAAe,GAAI,QAAO,kBAAkB;AAChD,QAAM,SAAS,YAAYA,MAAK,MAAM;AACtC,MAAI,WAAW,IAAI;AACjB,WAAO,SAAS;AAChB,WAAO,cAAcA,MAAK,gBAAgB,SAAY,IAAI,MAAM,IAAIA,MAAK,WAAW,CAAC;AAAA,EACvF;AACA,SAAO,OAAO,MAAM,IAAIA,MAAK,MAAM,GAAG,CAAC;AACvC,SAAO,OAAO,IAAIA,MAAK,MAAM,CAAC;AAC9B,SAAO,SAASA,MAAK,UAAU;AACjC;AAGA,SAAS,gBAAgB,QAAQA,OAAM;AACrC,QAAM,SAAS,MAAM,QAAQA,MAAK,MAAM,IAAIA,MAAK,SAAS,CAAC;AAC3D,QAAM,OAAO,IAAI,OAAO,IAAI;AAC5B,QAAM,MAAM,IAAI,OAAO,GAAG;AAC1B,QAAM,WAAW,OAAO,IAAI,CAAC,OAAO,UAClC,MAAM,QAAQ,MAAM,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,KAAK,IAAI,GAAG,CAC7D;AACD,MAAI,OAAO,SAAS,QAAQ;AAC1B,QAAI,SAAS,UAAU,GAAG;AACxB,aAAO,KAAK,SAAS,CAAC;AACtB,aAAO,KAAK,SAAS,CAAC;AACtB,aAAO,KAAK,SAAS,CAAC;AACtB,aAAO,KAAK,SAAS,CAAC;AAAA,IACxB;AAAA,EACF,OAAO;AACL,WAAO,SAAS,CAAC;AACjB,aAAS,IAAI,GAAG,IAAI,IAAI,SAAS,QAAQ,KAAK,GAAG;AAC/C,aAAO,OAAO,KAAK,EAAE,GAAG,SAAS,CAAC,GAAG,GAAG,SAAS,IAAI,CAAC,EAAE,CAAC;AAAA,IAC3D;AAAA,EACF;AACF;AAWA,SAASE,gBAAe,QAAQF,OAAM,QAAQ;AAC5C,QAAM,MAAMA,MAAK;AACjB,QAAM,OAAO,OAAO;AACpB,QAAM,QAAQ,KAAK,IAAI,IAAIA,MAAK,KAAK,CAAC;AACtC,QAAM,SAAS,KAAK,IAAI,IAAIA,MAAK,MAAM,CAAC;AACxC,QAAM,cAAc,SAAS,IAAI,OAAO,KAAK,IAAI;AACjD,QAAM,eAAe,SAAS,IAAI,OAAO,MAAM,IAAI;AAGnD,QAAM,gBAAgB,QAAQ,UAAU,QAAQ,cAAc,SAAS;AACvE,QAAM,WAAW,IAAIA,MAAK,QAAQ;AAClC,MAAI,SAASA,MAAK,WAAW,SAAY,IAAI,IAAIA,MAAK,QAAQ,CAAC;AAC/D,MAAI,SAASA,MAAK,WAAW,SAAY,IAAI,IAAIA,MAAK,QAAQ,CAAC;AAG/D,MAAI,QAAQ,SAAU,UAAS;AAC/B,MAAI,cAAc;AAChB,aAAS;AACT,aAAS;AAAA,EACX;AAGA,QAAM,WAAW,eAAeA,MAAK,QAAQ,OAAO,MAAM;AAC1D,QAAM,UAAU,SAAS,IAAI,OAAO,SAAU,SAAS,IAAI,OAAO,UAAU;AAC5E,QAAM,UAAU,SAAS,IAAI,OAAO,QAAS,SAAS,IAAI,OAAO,WAAW;AAE5E,MAAI,IAAI,IAAIA,MAAK,CAAC,IAAI,cAAc;AACpC,MAAI,IAAI,IAAIA,MAAK,CAAC,IAAI,eAAe;AAErC,MAAI,cAAc;AAEhB,UAAM,SAAS,KAAK,IAAI,IAAIA,MAAK,WAAW,CAAC;AAC7C,UAAM,MAAM,WAAW,KAAK,KAAK;AACjC,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAM,MAAM,KAAK,IAAI,GAAG;AACxB,UAAO,MAAM,OAAO,SAAU;AAC9B,UAAO,MAAM,OAAO,SAAU;AAAA,EAChC,OAAO;AACL,UAAM,SAAS,SAAS,KAAK,SAAS,KAAK,CAAC;AAC5C,QAAI,CAAC,QAAQ;AACX,YAAM,MAAM,WAAW,KAAK,KAAK;AACjC,YAAM,MAAM,KAAK,IAAI,GAAG;AACxB,YAAM,MAAM,KAAK,IAAI,GAAG;AACxB,YAAM,SAAS,CAAC,IAAI,OAAO,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,MAAM,EAAE;AACpE,YAAM,CAAC,SAAS,OAAO,IAAI;AAAA,SACxB,MAAM,SAAS,KAAK,KAAK,IAAI,MAAM,IAAI;AAAA,SACvC,MAAM,SAAS,KAAK,KAAK,IAAI,MAAM,IAAI;AAAA,MAC1C;AACA,YAAM,CAAC,QAAQ,MAAM,IAAI;AAAA,QACvB,UAAU,SAAS,IAAI,QAAQ,QAAQ;AAAA,QACvC,UAAU,SAAS,IAAI,SAAS,SAAS;AAAA,MAC3C;AACA,WAAK,UAAU;AACf,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAEA,SAAO,OAAO,MAAM,CAAC;AACrB,SAAO,MAAM,MAAM,CAAC;AACpB,MAAI,SAAU,QAAO,QAAQ,MAAM,QAAQ;AAC3C,MAAI,YAAY,OAAQ,QAAO,UAAU;AACzC,MAAI,YAAY,MAAO,QAAO,UAAU;AAExC,MAAI,CAAC,cAAc;AACjB,QAAI,SAAS,QAAQ;AAEnB,UAAI,WAAW,EAAG,QAAO,SAAS,MAAM,MAAM;AAC9C,UAAI,WAAW,EAAG,QAAO,SAAS,MAAM,MAAM;AAAA,IAChD,OAAO;AAEL,UAAI,SAAS,GAAG;AACd,eAAO,QAAQ;AACf,iBAAS,CAAC;AAAA,MACZ;AACA,UAAI,SAAS,GAAG;AACd,eAAO,QAAQ;AACf,iBAAS,CAAC;AAAA,MACZ;AACA,UAAI,WAAW,EAAG,QAAO,SAAS,MAAM,MAAM;AAC9C,UAAI,WAAW,EAAG,QAAO,SAAS,MAAM,MAAM;AAAA,IAChD;AAAA,EACF;AAEA,MAAIA,MAAK,MAAO,QAAO,QAAQ,IAAIA,MAAK,KAAK;AAC7C,MAAIA,MAAK,MAAO,QAAO,QAAQ,IAAIA,MAAK,KAAK;AAC7C,MAAIA,MAAK,YAAY,UAAa,IAAIA,MAAK,OAAO,MAAM,GAAG;AACzD,WAAO,UAAU,IAAIA,MAAK,OAAO;AAAA,EACnC;AACA,MAAIA,MAAK,YAAY,MAAO,QAAO,UAAU;AAC/C;AAEA,SAAS,gBAAgBA,OAAM,KAAK;AAClC,UAAQA,MAAK,YAAY,CAAC,GACvB,IAAI,CAAC,UAAU,YAAY,OAAO,KAAKA,KAAI,CAAC,EAC5C,OAAO,OAAO;AACnB;AAGA,SAAS,YAAYA,OAAM,KAAK,QAAQ;AACtC,MAAI,CAACA,SAAQ,OAAOA,UAAS,SAAU,QAAO;AAC9C,QAAM,MAAMA,MAAK;AACjB,QAAM,OAAO,aAAaA,OAAM,GAAG;AACnC,QAAM,SAAS,EAAE,KAAK;AACtB,EAAAE,gBAAe,QAAQF,OAAM,MAAM;AACnC,EAAAC,WAAU,QAAQD,KAAI;AAEtB,QAAM,QAAQ,KAAK,IAAI,IAAIA,MAAK,KAAK,CAAC;AACtC,QAAM,SAAS,KAAK,IAAI,IAAIA,MAAK,MAAM,CAAC;AAExC,UAAQ,KAAK;AAAA,IACX,KAAK,QAAQ;AACX,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,YAAM,SAASA,MAAK;AACpB,UAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,YAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,iBAAO,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC;AAChC,iBAAO,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC;AAAA,QAClC,OAAO;AACL,iBAAO,KAAK,MAAM,IAAI,MAAM,CAAC;AAC7B,iBAAO,KAAK,MAAM,IAAI,MAAM,CAAC;AAAA,QAC/B;AAAA,MACF;AACA,sBAAgB,QAAQA,KAAI;AAC5B;AAAA,IACF;AAAA,IACA,KAAK,WAAW;AACd,UAAI,SAAS,UAAU;AACrB,eAAO,SAAS,MAAM,QAAQ,CAAC;AAC/B,eAAO,QAAQ,MAAM,KAAK;AAC1B,eAAO,SAAS,MAAM,MAAM;AAAA,MAC9B,OAAO;AACL,eAAO,QAAQ,MAAM,KAAK;AAC1B,eAAO,SAAS,MAAM,MAAM;AAAA,MAC9B;AACA,sBAAgB,QAAQA,KAAI;AAC5B;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AAEb,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,aAAO,SAAS,MAAM,QAAQ,CAAC;AAC/B,UAAIA,MAAK,eAAe,QAAW;AACjC,eAAO,aAAa,MAAM,IAAIA,MAAK,UAAU,IAAI,MAAM,KAAK,EAAE;AAAA,MAChE;AACA,UAAIA,MAAK,aAAa,QAAW;AAC/B,eAAO,WAAW,MAAM,IAAIA,MAAK,QAAQ,IAAI,MAAM,KAAK,EAAE;AAAA,MAC5D;AACA,sBAAgB,QAAQA,KAAI;AAC5B;AAAA,IACF;AAAA,IACA,KAAK;AAAA,IACL,KAAK,QAAQ;AACX,qBAAe,QAAQA,KAAI;AAC3B,UAAIA,MAAK,UAAU,OAAW,QAAO,QAAQ,MAAM,KAAK;AACxD,UAAIA,MAAK,WAAW,OAAW,QAAO,SAAS,MAAM,MAAM;AAC3D;AAAA,IACF;AAAA,IACA,KAAK,SAAS;AACZ,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,aAAO,MAAMA,MAAK,QAAQ,SAAY,KAAKA,MAAK;AAChD;AAAA,IACF;AAAA;AAAA,IAEA,KAAK;AAAA,IACL,KAAK,SAAS;AACZ,UAAIA,MAAK,UAAU,OAAW,QAAO,QAAQ,MAAM,KAAK;AACxD,UAAIA,MAAK,WAAW,OAAW,QAAO,SAAS,MAAM,MAAM;AAC3D,aAAO,UAAU,gBAAgBA,OAAM,GAAG;AAC1C;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,UAAIA,MAAK,UAAU,OAAW,QAAO,QAAQ,MAAM,KAAK;AACxD,UAAIA,MAAK,WAAW,OAAW,QAAO,SAAS,MAAM,MAAM;AAC3D,aAAO,UAAUA,MAAK,WAAW;AACjC,aAAO,QAAQA,MAAK,SAAS,CAAC;AAC9B,UAAIA,MAAK,gBAAgB,OAAW,QAAO,cAAcA,MAAK;AAC9D,UAAI,MAAM,QAAQA,MAAK,QAAQ,KAAKA,MAAK,SAAS,QAAQ;AACxD,eAAO,UAAU,gBAAgBA,OAAM,GAAG;AAAA,MAC5C;AACA;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,uBAAiB,QAAQA,KAAI;AAC7B;AAAA,IACF;AAAA,IACA,KAAK,OAAO;AACV,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,oBAAc,QAAQA,KAAI;AAC1B;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,sBAAgB,QAAQA,KAAI;AAC5B,sBAAgB,QAAQA,OAAM,EAAE,MAAM,SAAS,WAAW,CAAC;AAC3D;AAAA,IACF;AAAA,IACA,KAAK,WAAW;AACd,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,UAAI,SAAS,YAAY;AACvB,wBAAgB,QAAQA,KAAI;AAC5B;AAAA,MACF;AACA,sBAAgB,QAAQA,KAAI;AAC5B,sBAAgB,QAAQA,KAAI;AAC5B;AAAA,IACF;AAAA,IACA,KAAK,QAAQ;AACX,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,aAAO,OAAOA,MAAK,SAAS,SAAY,KAAKA,MAAK;AAClD,sBAAgB,QAAQA,KAAI;AAC5B;AAAA,IACF;AAAA,IACA,SAAS;AACP,aAAO,QAAQ,MAAM,KAAK;AAC1B,aAAO,SAAS,MAAM,MAAM;AAC5B,sBAAgB,QAAQA,KAAI;AAC5B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAUO,SAAS,eAAe,gBAAgB,UAAU,CAAC,GAAG;AAC3D,QAAM,WAAW,CAAC;AAClB,QAAM,MAAM,EAAE,UAAU,QAAQ;AAChC,QAAM,SAAS,kBAAkB,CAAC;AAClC,QAAM,SAAS,EAAE,GAAI,OAAO,UAAU,CAAC,EAAG;AAC1C,QAAM,aAAa,OAAO;AAC1B,SAAO,OAAO;AACd,MAAI,OAAO,oBAAoB,QAAW;AACxC,aAAS,KAAK,6IAAwD;AACtE,WAAO,OAAO;AAAA,EAChB;AAEA,QAAM,WAAW;AAAA,IACf;AAAA,IACA,OAAO,OAAO,SAAS,CAAC;AAAA,IACxB,eAAe,OAAO,iBAAiB,CAAC;AAAA,IACxC,UAAU,OAAO,YAAY,CAAC,GAAG,IAAI,CAACA,UAAS,YAAYA,OAAM,KAAK,IAAI,CAAC,EAAE,OAAO,OAAO;AAAA,EAC7F;AAEA,MAAI,eAAe,QAAW;AAC5B,aAAS,aAAa;AAAA,EACxB;AACA,MAAI,QAAQ,SAAS;AACnB,aAAS,UAAU,QAAQ;AAAA,EAC7B;AAEA,SAAO,EAAE,UAAU,SAAS;AAC9B;","names":["node","ORIGIN_FRACTION","node","alpha","node","node","node","node","children","OVERLAY_TYPES","convert","node","applyMeta","applyTransform"]}
|
|
1
|
+
{"version":3,"sources":["../src/context.js","../src/nodes.js","../src/geometry.js","../src/attributes/transform.js","../src/colors.js","../src/gradient.js","../src/assets.js","../src/pattern.js","../src/attributes/fill.js","../src/attributes/meta.js","../src/attributes/index.js","../src/elements/rect.js","../src/elements/ellipse.js","../src/elements/circle.js","../src/elements/triangle.js","../src/elements/polyline.js","../src/elements/line.js","../src/elements/polygon.js","../src/elements/path.js","../src/attributes/text.js","../src/elements/text.js","../src/elements/image.js","../src/lib.js","../src/elements/group.js","../src/elements/lib.js","../src/elements/button.js","../src/elements/bar.js","../src/elements/placeholder.js","../src/elements/index.js","../src/document.js","../src/convert.js","../src/leafer2fabric.js"],"sourcesContent":["/**\n * 转换上下文:一次 convert 调用对应一个 ctx。\n * 里面放「跨模块共享的东西」:配置、告警收集、资源解析、递归转换函数。\n */\n\nexport function createContext(options = {}) {\n const warnings = []\n\n const resolveAsset = typeof options.resolveAsset === 'function'\n ? options.resolveAsset\n : (path) => path\n\n return {\n options,\n warnings,\n resolveAsset,\n\n /** 收集告警,不打断转换;CLI 可以把 warnings 打到 stderr */\n warn(message) {\n warnings.push(String(message))\n },\n\n /**\n * 递归转换入口,由 convert.js 注入。\n * 这样 group/lib 不需要 import 分发表,避免循环依赖。\n */\n convert: null\n }\n}\n","/**\n * Leafer JSON 节点工厂:只产出纯对象,不 import leafer-ui。\n * 值为 undefined 的字段直接丢弃,避免把空属性写进输出。\n */\nexport function node(tag, props = {}) {\n const result = { tag }\n Object.keys(props).forEach((key) => {\n const value = props[key]\n if (value !== undefined) {\n result[key] = value\n }\n })\n return result\n}\n\n/** 安全取数字,取不到时返回 fallback */\nexport function num(value, fallback = 0) {\n const number = Number(value)\n return Number.isFinite(number) ? number : fallback\n}\n\n/** 取可选的数字:undefined / 非法值返回 undefined,而不是 0 */\nexport function optionalNum(value) {\n if (value === undefined || value === null || value === '') return undefined\n const number = Number(value)\n return Number.isFinite(number) ? number : undefined\n}\n","/**\n * 几何工具:定位、翻转位移、点集处理、Fabric path 转字符串。\n * 这里只做纯计算,不依赖任何渲染引擎。\n */\n\nimport { num, optionalNum } from './nodes.js'\n\n/**\n * Fabric 的 group 子元素坐标是相对组中心的,Leafer 是相对左上角,\n * 所以子元素要加上父级宽高的一半。根节点没有 parent,不加偏移。\n */\nexport function place(node, object, parent, offsetY = 0) {\n const parentWidth = parent ? num(parent.width) : 0\n const parentHeight = parent ? num(parent.height) : 0\n node.x = num(object.left) + parentWidth / 2\n node.y = num(object.top) + parentHeight / 2 + offsetY\n return node\n}\n\n/**\n * 零长度轴上超过这个量级的 scale 只可能是脏数据(CAD 导入端用\n * `目标尺寸 / (max - min)` 算缩放, 除数是 1e-38 级的浮点噪声)。\n * Fabric 自己的包围盒是 0, 所以这个 scale 在 Fabric 里不改变图形。\n */\nconst MAX_DEGENERATE_SCALE = 1e4\n\n/** 零长度轴(浮点误差也算)上的脏 scale 归一化成 ±1(保留翻转的符号) */\nconst DEGENERATE_EXTENT = 1e-6\n\nexport function normalizeScale(scale, extent) {\n if (Math.abs(extent) < DEGENERATE_EXTENT && Math.abs(scale) > MAX_DEGENERATE_SCALE) {\n return scale < 0 ? -1 : 1\n }\n return scale\n}\n\n/** Fabric 的 originX / originY → 比例 */\nconst ORIGIN_FRACTION = {\n left: 0,\n center: 0.5,\n right: 1,\n top: 0,\n bottom: 1\n}\n\n/**\n * originX / originY → 0~1 的比例。\n * 老数据里可能是字符串(left/center/right/top/bottom),也可能是数字(0 / 0.5 / 1),\n * 数字直接当比例用,别再落到默认值上,否则 0.5/0.5 的图元旋转/翻转后会整个错位。\n */\nexport function originFraction(value, fallback = 0) {\n if (value === undefined || value === null || value === '') return fallback\n if (typeof value === 'number') return Number.isFinite(value) ? value : fallback\n const named = ORIGIN_FRACTION[String(value).trim().toLowerCase()]\n return named === undefined ? fallback : named\n}\n\n/**\n * 点集元素(polyline / polygon / line)的落点,父级坐标。\n *\n * Fabric 的包围盒把描边算在内(平台全局 strokeUniform):盒宽 = 路径跨度 * scale + strokeWidth,\n * left/top 是原点\n * (originX / originY 那一角)的位置,绘制时以盒中心为基准平移到路径包围盒中心。\n * Leafer 的节点原点是路径包围盒左上角、描边画在盒外,所以落点得按 Fabric 的\n * 变换矩阵反推,否则整条线会按描边宽度的一半错位(带 scale 时偏差还会被放大)。\n */\nexport function pathPlaceOrigin(object, bounds) {\n if (!bounds) {\n return { left: num(object.left), top: num(object.top) }\n }\n if (optionalNum(object.left) === undefined) {\n return { left: bounds.minX, top: bounds.minY }\n }\n const strokeWidth = Math.abs(num(object.strokeWidth))\n const width = bounds.width\n const height = bounds.height\n // 偏离被 Julia 归一化的脏 scale, 这里同样要清掉, 否则落点会被放大到 1e37\n const scaleX = Math.abs(normalizeScale(num(object.scaleX, 1) || 1, width))\n const scaleY = Math.abs(normalizeScale(num(object.scaleY, 1) || 1, height))\n const fractionX = originFraction(object.originX)\n const fractionY = originFraction(object.originY)\n const angle = num(object.angle) * Math.PI / 180\n const cos = Math.cos(angle)\n const sin = Math.sin(angle)\n const rotate = (x, y) => [cos * x - sin * y, sin * x + cos * y]\n\n // 盒中心相对 left/top 的偏移(Fabric 的变换矩阵就平移到盒中心)。\n // 平台把 strokeUniform 全局打开了, 盒尺寸 = 路径跨度 * scale + 描边(描边不缩放)\n const [offsetX, offsetY] = rotate(\n (0.5 - fractionX) * (width * scaleX + strokeWidth),\n (0.5 - fractionY) * (height * scaleY + strokeWidth)\n )\n // 盒中心 → 路径包围盒左上角(Leafer 节点的本地原点)\n const [pivotX, pivotY] = rotate(-0.5 * width * scaleX, -0.5 * height * scaleY)\n return {\n left: num(object.left) + offsetX + pivotX,\n top: num(object.top) + offsetY + pivotY\n }\n}\n\n/** 点集包围盒;没有有效点时返回 null */\nexport function pointsBounds(points) {\n if (!Array.isArray(points)) return null\n\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n\n points.forEach((point) => {\n if (!point) return\n const x = Number(point.x)\n const y = Number(point.y)\n if (!Number.isFinite(x) || !Number.isFinite(y)) return\n if (x < minX) minX = x\n if (x > maxX) maxX = x\n if (y < minY) minY = y\n if (y > maxY) maxY = y\n })\n\n if (minX === Infinity) return null\n return { minX, minY, maxX, maxY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 去掉相邻的重复点,避免 Leafer 画出零长度线段 */\nexport function dedupePoints(points) {\n const result = []\n const tolerance = 0.001\n for (let i = 0; i < points.length; i += 2) {\n const x = points[i]\n const y = points[i + 1]\n const lastX = result[result.length - 2]\n const lastY = result[result.length - 1]\n if (lastX !== undefined && Math.abs(x - lastX) < tolerance && Math.abs(y - lastY) < tolerance) {\n continue\n }\n result.push(x, y)\n }\n return result\n}\n\n/**\n * Fabric 的 points 是 [{x,y}],Leafer 要扁平数组 [x1,y1,x2,y2]。\n *\n * points 里存的是画布绝对坐标:Fabric 渲染时会先减掉点集包围盒(pathOffset)\n * 再按 left/top 摆放,所以 Leafer 这边必须换成节点本地坐标(减包围盒左上角),\n * 否则整条线会按绝对坐标再叠加一次 left/top,直接跑到画布外。\n *\n * 翻转也在这里烘焙成坐标(path/polyline/polygon 用这种方式,\n * 因为 Leafer 的负 scale 会把描边宽度一起镜像),镜像基准是点集包围盒。\n */\nexport function convertPoints(points, options = {}) {\n const { flipX = false, flipY = false } = options\n const bounds = pointsBounds(points)\n if (!bounds) {\n return []\n }\n\n const result = []\n points.forEach((point) => {\n if (!point) return\n let x = Number(point.x)\n let y = Number(point.y)\n if (!Number.isFinite(x) || !Number.isFinite(y)) {\n return\n }\n x -= bounds.minX\n y -= bounds.minY\n if (flipX) x = bounds.width - x\n if (flipY) y = bounds.height - y\n result.push(x, y)\n })\n\n return dedupePoints(result)\n}\n\n/** 判断这种元素是不是把翻转烘焙进几何,而不是用 scale 取负 */\nexport const FLIP_BAKED_TYPES = ['path', 'polyline', 'polygon', 'line']\n\nexport function shouldBakeFlip(object) {\n return !!object && FLIP_BAKED_TYPES.includes(object.type)\n}\n\n/**\n * Fabric 的 path 是 ['M', x, y, 'L', ...] 或 [{ command }] 数组,\n * 转成 SVG path 字符串。数字保留 4 位小数,避免输出一大串浮点尾数。\n */\nexport function convertPathData(pathData, object) {\n if (typeof pathData === 'string') {\n return pathData\n }\n if (!Array.isArray(pathData)) {\n return ''\n }\n\n const bakeFlip = shouldBakeFlip(object) && (object.flipX === true || object.flipY === true)\n const width = num(object && object.width)\n const height = num(object && object.height)\n\n return pathData.map((command) => {\n if (!Array.isArray(command)) {\n return String(command)\n }\n\n const next = command.slice()\n if (bakeFlip) {\n const type = String(next[0] || '')\n // A/a 命令的前 5 个参数不是坐标,从第 6 个开始才是 x,y\n const startIndex = /[Aa]/.test(type) ? 6 : 1\n for (let i = startIndex; i < next.length - 1; i += 2) {\n if (typeof next[i] === 'number' && typeof next[i + 1] === 'number') {\n if (object.flipX === true) next[i] = width - next[i]\n if (object.flipY === true) next[i + 1] = height - next[i + 1]\n }\n }\n // H/V 只有一个坐标\n if (/[Hh]/.test(type) && object.flipX === true && typeof next[1] === 'number') {\n next[1] = width - next[1]\n }\n if (/[Vv]/.test(type) && object.flipY === true && typeof next[1] === 'number') {\n next[1] = height - next[1]\n }\n }\n\n return next\n .map((item) => (typeof item === 'number' ? Number(item.toFixed(4)) : item))\n .join(' ')\n }).join(' ')\n}\n\n/**\n * Fabric 的 originX/originY 组合 → Leafer 的 around 九宫格。\n * 两边都是「旋转/缩放围绕哪个点」,但命名不同。\n */\nexport function aroundOf(object) {\n // 数字 origin(0 / 0.5 / 1)也要认, 按比例就近归到九宫格\n const axisOf = (fraction, low, center, high) => {\n if (fraction <= 0.25) return low\n if (fraction >= 0.75) return high\n return center\n }\n const originX = axisOf(originFraction(object.originX), 'left', 'center', 'right')\n const originY = axisOf(originFraction(object.originY), 'top', 'center', 'bottom')\n const map = {\n left: { top: 'top-left', center: 'left', bottom: 'bottom-left' },\n center: { top: 'top', center: 'center', bottom: 'bottom' },\n right: { top: 'top-right', center: 'right', bottom: 'bottom-right' }\n }\n return (map[originX] && map[originX][originY]) || 'top-left'\n}\n\n/** Leafer 的 around 取值 → 相对包围盒的比例 */\nconst AROUND_FRACTION = {\n 'top-left': { x: 0, y: 0 },\n top: { x: 0.5, y: 0 },\n 'top-right': { x: 1, y: 0 },\n left: { x: 0, y: 0.5 },\n center: { x: 0.5, y: 0.5 },\n right: { x: 1, y: 0.5 },\n 'bottom-left': { x: 0, y: 1 },\n bottom: { x: 0.5, y: 1 },\n 'bottom-right': { x: 1, y: 1 }\n}\n\n/**\n * around → 相对包围盒的比例。\n * 字符串是 Leafer 的方位名; 对象是显式点, type 为 percent 时本身就是比例,\n * 否则是像素值, 换算成比例。认不出来时按 Leafer 默认的左上角。\n */\nexport function aroundFraction(around, width, height) {\n if (around && typeof around === 'object') {\n const x = num(around.x)\n const y = num(around.y)\n if (around.type === 'percent') {\n return { x, y }\n }\n return { x: width ? x / width : 0, y: height ? y / height : 0 }\n }\n return AROUND_FRACTION[around] || AROUND_FRACTION['top-left']\n}\n\n/** 节点自身坐标系里的包围盒左上角在 (0,0) 还是别处, 由子元素决定 */\nfunction innerBoxOf(node, fallback) {\n const children = Array.isArray(node.children) ? node.children : null\n if (children && children.length) {\n return unionBoxes(children.map((child) => nodeBox(child)))\n }\n // 负宽高在 Leafer 里会被改写成\"正宽高 + 取反 scale\", 包围盒永远从 0 起算\n const width = optionalNum(node.width) !== undefined ? optionalNum(node.width) : optionalNum(fallback && fallback.width)\n const height = optionalNum(node.height) !== undefined ? optionalNum(node.height) : optionalNum(fallback && fallback.height)\n return { x: 0, y: 0, width: Math.abs(width || 0), height: Math.abs(height || 0) }\n}\n\n/**\n * 节点在父级坐标系里的包围盒, 算法和 Leafer 一致:\n * 局部矩阵 = 旋转 · 斜切 · 缩放, 围绕点固定在 (x, y), 再作用到自身包围盒四角。\n *\n * fallback 是 Fabric 原始对象: 文本没写死宽高时 Leafer 会自适应,\n * 转换后的节点上没有 width/height, 用它兜底估算组尺寸。\n */\nexport function nodeBox(node, fallback) {\n const inner = innerBoxOf(node, fallback)\n const around = aroundFraction(node.around, inner.width, inner.height)\n const aroundX = inner.x + around.x * inner.width\n const aroundY = inner.y + around.y * inner.height\n // 和 Leafer 的 setLayout 完全一致: rotate -> skew -> scale\n const rotation = num(node.rotation) * Math.PI / 180\n const scaleX = node.scaleX === undefined ? 1 : num(node.scaleX, 1)\n const scaleY = node.scaleY === undefined ? 1 : num(node.scaleY, 1)\n const skewX = num(node.skewX) * Math.PI / 180\n const skewY = num(node.skewY) * Math.PI / 180\n const cosR = Math.cos(rotation)\n const sinR = Math.sin(rotation)\n let a\n let b\n let c\n let d\n if (skewX || skewY) {\n a = (cosR + skewY * -sinR) * scaleX\n b = (sinR + skewY * cosR) * scaleX\n c = (-sinR + skewX * cosR) * scaleY\n d = (cosR + skewX * sinR) * scaleY\n } else {\n a = cosR * scaleX\n b = sinR * scaleX\n c = -sinR * scaleY\n d = cosR * scaleY\n }\n const x = num(node.x)\n const y = num(node.y)\n const corners = [\n [inner.x, inner.y],\n [inner.x + inner.width, inner.y],\n [inner.x + inner.width, inner.y + inner.height],\n [inner.x, inner.y + inner.height]\n ]\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n corners.forEach((corner) => {\n const dx = corner[0] - aroundX\n const dy = corner[1] - aroundY\n const px = x + a * dx + c * dy\n const py = y + b * dx + d * dy\n if (px < minX) minX = px\n if (px > maxX) maxX = px\n if (py < minY) minY = py\n if (py > maxY) maxY = py\n })\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 多个包围盒取并集 */\nexport function unionBoxes(boxes) {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n boxes.forEach((box) => {\n if (!box) return\n if (box.x < minX) minX = box.x\n if (box.y < minY) minY = box.y\n if (box.x + box.width > maxX) maxX = box.x + box.width\n if (box.y + box.height > maxY) maxY = box.y + box.height\n })\n if (minX === Infinity) return { x: 0, y: 0, width: 0, height: 0 }\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 这些类型的负宽高只取绝对值: Fabric 里文字是重新量尺寸的, 不会镜像字模 */\nconst ABS_ONLY_TYPES = new Set(['text', 'i-text', 'itext', 'textbox', 'group'])\n\n/**\n * Fabric 的宽高允许是负数(编辑器把拖拽缩放的 scale 烘焙进了 width/height)。\n * Leafer 只认正宽高, 收到负值会自己改成 -scaleX 并打警告, 而转换器随后又要写\n * 自己的 scaleX, 两边抢次序 —— 结果是镜像丢失或位置错一个宽。\n * 这里统一改成\"正宽高\", 图形类把符号并进 scaleX/scaleY(和 Fabric 的镜像渲染一致),\n * 文字/组只取绝对值(Fabric 里文字不镜像, 组的宽高只是元数据)。\n */\nexport function normalizeSizeSign(object) {\n if (!object || typeof object !== 'object') return object\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n const signX = width !== undefined && width < 0 ? -1 : 1\n const signY = height !== undefined && height < 0 ? -1 : 1\n if (signX === 1 && signY === 1) return object\n const normalized = { ...object }\n if (width !== undefined) normalized.width = Math.abs(width)\n if (height !== undefined) normalized.height = Math.abs(height)\n if (ABS_ONLY_TYPES.has(object.type)) return normalized\n normalized.scaleX = (object.scaleX === undefined ? 1 : num(object.scaleX, 1)) * signX\n normalized.scaleY = (object.scaleY === undefined ? 1 : num(object.scaleY, 1)) * signY\n return normalized\n}\n\n/** 翻转后为了让包围盒位置不变,x/y 需要补偿的位移 */\nexport function flipOffset(size, scale, fraction) {\n return size * Math.abs(scale) * (1 - 2 * fraction)\n}\n","/**\n * 变换属性:位置之外的 rotation / scale / skew / 翻转 / 透明度 / 可见性。\n * 位置(x/y)由各元素调用 geometry.place 设置,这里只处理围绕点之后的变换。\n */\n\nimport { num, optionalNum } from '../nodes.js'\nimport { aroundOf, originFraction, shouldBakeFlip, pointsBounds, normalizeScale } from '../geometry.js'\n\n/**\n * 零长度轴上的脏 scale 归一化成 ±1, 否则 Leafer 会把描边一起放大\n * (实测 scaleX 7e37 + strokeWidth 4 → worldStrokeBounds 宽 2.8e38),\n * 编辑态的选中框 / 组包围盒直接炸掉。\n */\n\n/** 落点由 geometry.pathPlaceOrigin 负责的点集类型 */\nconst PATH_PLACED_TYPES = ['polyline', 'polygon', 'line']\n\n/**\n * Fabric 这一层全局开了 strokeUniform(platform/canvas/config.js): 描边不随 scale 放大。\n * Leafer 没有这个开关, 描边会被节点的 scale 一起拉宽 —— 宽高只有零点几像素的\n * CAD 线放大几百倍后就成了粗带子。所以点集元素把 scale 直接烘焙进 points、\n * 节点 scale 归 1, 描边保持原宽度。\n */\nfunction bakePointsScale(node, object, scaleX, scaleY) {\n if (!PATH_PLACED_TYPES.includes(object.type)) return false\n if (!Array.isArray(node.points) || !node.points.length) return false\n const absX = Math.abs(scaleX)\n const absY = Math.abs(scaleY)\n // 负 scale 也要烘焙: 节点围绕点是左上角, 留个负 scale 会绕左上角镜像,\n // 整个图形左移一个宽度(实测 43.89 宽的多边形差 43.89)。\n const mirrorX = scaleX < 0\n const mirrorY = scaleY < 0\n if (absX === 1 && absY === 1 && !mirrorX && !mirrorY) return false\n\n node.points = node.points.map((value, index) => (index % 2 === 0 ? value * absX : value * absY))\n if (node.width !== undefined) node.width = Math.abs(num(node.width)) * absX\n if (node.height !== undefined) node.height = Math.abs(num(node.height)) * absY\n // 镜像按烘焙后的宽高在自己的包围盒里翻, 和 Fabric 绕中心翻完包围盒不变一致\n if (mirrorX) {\n const width = node.width !== undefined ? Math.abs(num(node.width)) : maxOf(node.points, 0)\n node.points = node.points.map((value, index) => (index % 2 === 0 ? width - value : value))\n }\n if (mirrorY) {\n const height = node.height !== undefined ? Math.abs(num(node.height)) : maxOf(node.points, 1)\n node.points = node.points.map((value, index) => (index % 2 === 1 ? height - value : value))\n }\n return true\n}\n\n/** 点集在某个轴上的最大值(宽高没写时兜底) */\nfunction maxOf(points, axis) {\n let max = -Infinity\n for (let i = axis; i < points.length; i += 2) {\n if (points[i] > max) max = points[i]\n }\n return Number.isFinite(max) ? max : 0\n}\n\n/** 元素自身的几何长度: 点集用包围盒, 其它元素用 fabric 的 width/height */\nfunction extentOf(object) {\n if (Array.isArray(object.points)) {\n const bounds = pointsBounds(object.points)\n return bounds ? { x: bounds.width, y: bounds.height } : null\n }\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n if (width === undefined && height === undefined) return null\n return { x: width, y: height }\n}\n\nexport function applyTransform(node, object, ctx) {\n // 旋转:Fabric 的 angle 是角度,Leafer 的 rotation 也是角度\n if (optionalNum(object.angle) !== undefined) {\n node.rotation = num(object.angle)\n }\n\n // 围绕点必须显式给,否则 Leafer 默认中心旋转,和 Fabric 对不上。\n // 组在 convertGroup 里已经按子元素实际包围盒算好了,这里不要覆盖。\n if (node.around === undefined) node.around = aroundOf(object)\n\n const extent = extentOf(object)\n const scaleX = normalizeScale(\n object.scaleX === undefined ? 1 : num(object.scaleX, 1),\n extent && extent.x\n )\n const scaleY = normalizeScale(\n object.scaleY === undefined ? 1 : num(object.scaleY, 1),\n extent && extent.y\n )\n // 翻转:path / polyline / polygon 在几何层面已经烘焙过,其余用负 scale 表达\n const baked = shouldBakeFlip(object)\n const scaleXFinal = !baked && object.flipX === true ? -Math.abs(scaleX) : scaleX\n const scaleYFinal = !baked && object.flipY === true ? -Math.abs(scaleY) : scaleY\n\n // 点集元素的 scale 烘焙进几何(描边不跟着变粗), 节点 scale 归 1\n const bakedScale = bakePointsScale(node, object, scaleXFinal, scaleYFinal)\n\n node.scaleX = bakedScale ? 1 : scaleXFinal\n // button 的 scaleY 已由 convertButton 烘焙进几何, 不能再作用到组上;\n // scaleY 为 0 / null 时几何仍按 1 倍高度生成,这里也必须保持 1,否则按钮不可见。\n node.scaleY = object.type === 'button' || bakedScale ? 1 : scaleYFinal\n applyPosition(node, object, scaleXFinal, node.scaleY)\n\n // 斜切:Fabric 和 Leafer 都用弧度\n if (object.skewX) node.skewX = num(object.skewX)\n if (object.skewY) node.skewY = num(object.skewY)\n\n if (object.opacity !== undefined) {\n node.opacity = num(object.opacity, 1)\n }\n if (object.visible === false) {\n node.visible = false\n }\n\n return node\n}\n\n/**\n * 位置修正。\n *\n * Fabric 的旋转/缩放中心是\"原点向尺寸中心的对角点\",left/top 本身不动;Leafer 的\n * x/y 则是围绕点的位置,旋转、翻转都绕围绕点做。两者只在 angle 为 0 且没翻转时\n * 等价,所以有旋转或翻转时要按变换矩阵反推围绕点:\n *\n * x = 原点 + R·(off·尺寸) + R·S·(A - 尺寸/2)\n *\n * off 是\"原点 → 尺寸中心\"的比例,A 是围绕点在局部坐标里的位置。\n * angle 为 0 时它退化成\"按原点比例补偿一次位移\",和以前的结果完全一致;\n * angle 为 180° 时旋转本身就把该轴镜像了,补偿量正好抵消 —— 以前会多补一倍宽高,\n * 翻转过的组(比如 180° + flipX 的图元)会整块错位一个图元的宽度。\n */\nfunction applyPosition(node, object, scaleX, scaleY) {\n if (node.x === undefined || node.y === undefined) return\n // 点集元素(polyline / polygon / line)的落点已按 Fabric 的变换矩阵算好\n // (geometry.pathPlaceOrigin),这边再补偿一次会重复位移\n if (PATH_PLACED_TYPES.includes(object.type)) return\n\n const width = num(object.width)\n const height = num(object.height)\n // 字符串和数字(0 / 0.5 / 1)两种 origin 写法都要认\n const fractionX = originFraction(object.originX)\n const fractionY = originFraction(object.originY)\n // 只有旋转或翻转会改变包围盒落点, 其余情况保持原值, 避免浮点尾数污染 JSON\n const single = scaleX > 0 && scaleY > 0 && !num(node.rotation, 0)\n if (single) return\n\n const angle = num(node.rotation, 0) * Math.PI / 180\n const cos = Math.cos(angle)\n const sin = Math.sin(angle)\n const rotate = (x, y) => [cos * x - sin * y, sin * x + cos * y]\n\n // 原点 → 尺寸中心的偏移(Fabric 绕这一点旋转/缩放)\n const [centerX, centerY] = rotate(\n (0.5 - fractionX) * Math.abs(scaleX) * width,\n (0.5 - fractionY) * Math.abs(scaleY) * height\n )\n // 围绕点相对尺寸中心的偏移(Leafer 绕这一点做变换)\n const [shiftX, shiftY] = rotate(\n scaleX * (fractionX * width - width / 2),\n scaleY * (fractionY * height - height / 2)\n )\n\n node.x = num(node.x) + centerX + shiftX\n node.y = num(node.y) + centerY + shiftY\n}\n","/**\n * 颜色工具:Fabric 的颜色写法比 Leafer 宽松,这里统一成 Leafer 能吃的格式。\n * - `#RRGGBBAA` → `rgba(r,g,b,a)`\n * - `rgba(r,g,b,128)` 这种 0~255 的 alpha → 0~1\n * - 其余原样返回\n */\n\nexport function normalizeColor(color) {\n if (typeof color !== 'string') {\n return color\n }\n const value = color.trim()\n\n // rgba/rgb 里 alpha 可能是 0~255(Fabric 老数据),统一到 0~1\n const rgba = value.match(/^rgba?\\(\\s*([^)]+)\\)$/i)\n if (rgba) {\n const parts = rgba[1].split(',').map((item) => item.trim())\n if (parts.length === 4) {\n const alpha = Number(parts[3])\n if (Number.isFinite(alpha) && alpha > 1) {\n const normalized = Math.max(0, Math.min(1, alpha / 255))\n return `rgba(${parts[0]},${parts[1]},${parts[2]},${Math.round(normalized * 1000) / 1000})`\n }\n }\n return value\n }\n\n // 8 位 hex:前 6 位是颜色,后 2 位是 alpha\n const rgbaHex = value.match(/^#([0-9a-fA-F]{8})$/)\n if (!rgbaHex) {\n return value\n }\n const hex = rgbaHex[1]\n const alpha = parseInt(hex.slice(6, 8), 16)\n if (alpha === 255) {\n return '#' + hex.slice(0, 6)\n }\n const r = parseInt(hex.slice(0, 2), 16)\n const g = parseInt(hex.slice(2, 4), 16)\n const b = parseInt(hex.slice(4, 6), 16)\n return `rgba(${r},${g},${b},${Math.round((alpha / 255) * 1000) / 1000})`\n}\n\n/** 判断颜色是否完全透明(含空值、transparent、none、alpha=0) */\nexport function isTransparentColor(color) {\n if (color === '' || color === null || color === undefined) {\n return true\n }\n if (typeof color !== 'string') {\n return false\n }\n const value = color.trim().toLowerCase()\n if (value === 'transparent' || value === 'none') {\n return true\n }\n if (/^rgba\\([^)]*,\\s*0(?:\\.0+)?\\s*\\)$/.test(value)) {\n return true\n }\n if (/^#([0-9a-f]{6})00$/.test(value)) {\n return true\n }\n return false\n}\n","/**\n * Fabric 渐变 → Leafer 渐变。\n * Fabric: { type, colorStops: [{ offset, color }], coords: { x1,y1,x2,y2,r1,r2 } }\n * Leafer: { type, stops: [{ offset, color }], from: {type,x,y}, to: {type,x,y} }\n *\n * 两边都兼容:如果传入的已经是 Leafer 结构(from/to/stops),直接沿用。\n */\n\nimport { normalizeColor } from './colors.js'\n\nfunction hasNumber(value) {\n return value !== undefined && value !== null && Number.isFinite(Number(value))\n}\n\n/** 判断一个 fill 值是不是渐变对象 */\nexport function isGradient(value) {\n return !!value && typeof value === 'object' && !Array.isArray(value)\n}\n\nexport function convertGradient(gradient, ctx) {\n const sourceStops = gradient.colorStops || gradient.stops || []\n const stops = sourceStops.map((item) => ({\n offset: Number(item.offset) || 0,\n color: normalizeColor(item.color)\n }))\n\n const coords = gradient.coords || {}\n const from = gradient.from || {}\n const to = gradient.to || {}\n\n const paint = {\n // Fabric 只有 linear / radial 两种;Leafer 还支持 angular/conic\n type: gradient.type || 'linear',\n stops\n }\n\n // Fabric 的 coords 是相对对象包围盒的 0~1 比例,Leafer 用 percent 表达同一含义\n paint.from = {\n type: 'percent',\n x: hasNumber(from.x) ? Number(from.x) : (hasNumber(coords.x1) ? Number(coords.x1) : 0),\n y: hasNumber(from.y) ? Number(from.y) : (hasNumber(coords.y1) ? Number(coords.y1) : 0)\n }\n paint.to = {\n type: 'percent',\n x: hasNumber(to.x) ? Number(to.x) : (hasNumber(coords.x2) ? Number(coords.x2) : 1),\n y: hasNumber(to.y) ? Number(to.y) : (hasNumber(coords.y2) ? Number(coords.y2) : 0)\n }\n\n if (paint.type === 'radial') {\n // Fabric 径向渐变用 r2 表示半径;x2/y2 常常和圆心重合\n const radius = hasNumber(coords.r2)\n ? Number(coords.r2)\n : (hasNumber(gradient.r2) ? Number(gradient.r2) : 0.5)\n\n if (paint.from.x === paint.to.x && paint.from.y === paint.to.y) {\n paint.to = {\n type: 'percent',\n x: paint.from.x + Math.max(0.0001, radius),\n y: paint.from.y\n }\n }\n }\n\n // 记录原始结构,方便排查转换问题(不参与渲染)\n if (ctx && ctx.options && ctx.options.debug) {\n paint.__fabricGradient = gradient\n }\n\n return paint\n}\n","/**\n * 资源路径解析。\n * 转换器不知道平台的资源系统(OSS / 本地 fs / 相对路径),\n * 只把「逻辑路径」交给 options.resolveAsset,由调用方决定最终 URL。\n */\n\n/** data/blob/http/绝对路径直接透传,不经过平台资源系统 */\nconst ABSOLUTE = /^(data:|blob:|https?:\\/\\/|\\/fs\\/open|\\/)/i\n\nexport function resolveImageUrl(src, rsrc, ctx) {\n const raw = typeof src === 'string' && src\n ? src\n : (rsrc === undefined || rsrc === null ? '' : String(rsrc))\n\n if (!raw) {\n return undefined\n }\n if (ABSOLUTE.test(raw)) {\n return raw\n }\n\n // 统一成 image/xxx 这种平台约定的逻辑路径\n let path = raw.replace(/^\\.?\\//, '')\n if (!path.startsWith('image/')) {\n path = 'image/' + path\n }\n return ctx.resolveAsset(path, 'image')\n}\n","/**\n * Fabric 的 Pattern 填充 → Leafer 的图片 paint。\n * Fabric: { type: 'pattern', source, repeat, offsetX, offsetY, patternTransform }\n * Leafer: { type: 'image', url, mode, repeat, offset, scale, rotation }\n *\n * source 一般是导出时内联的 data URL,也兼容平台逻辑路径(走 resolveAsset)。\n */\n\nimport { resolveImageUrl } from './assets.js'\n\n/** 判断一个 fill / stroke 值是不是 Fabric 的 Pattern 对象 */\nexport function isPattern(value) {\n return !!value && typeof value === 'object' && !Array.isArray(value) &&\n (value.type === 'pattern' ||\n (typeof value.source === 'string' && value.source !== '' && value.repeat !== undefined))\n}\n\n/** patternTransform 是 [a, b, c, d, e, f] → 平移 / 缩放 / 旋转 */\nfunction decomposeTransform(transform) {\n const list = Array.isArray(transform) ? transform.map(Number) : []\n if (list.length < 6 || list.some((item) => !Number.isFinite(item))) {\n return undefined\n }\n const [a, b, c, d, e, f] = list\n if (a === 1 && b === 0 && c === 0 && d === 1 && e === 0 && f === 0) {\n return undefined\n }\n return {\n scaleX: Math.hypot(a, b),\n scaleY: Math.hypot(c, d),\n rotation: (Math.atan2(b, a) * 180) / Math.PI,\n offsetX: e,\n offsetY: f\n }\n}\n\n/** Fabric 的 repeat → Leafer 的 mode + repeat */\nfunction applyRepeat(paint, repeat) {\n if (repeat === 'repeat-x') {\n paint.mode = 'repeat'\n paint.repeat = 'x'\n } else if (repeat === 'repeat-y') {\n paint.mode = 'repeat'\n paint.repeat = 'y'\n } else if (repeat === 'no-repeat') {\n // 只画一张,位置和大小由 offset / scale 决定\n paint.mode = 'normal'\n } else {\n paint.mode = 'repeat'\n paint.repeat = true\n }\n}\n\n/** Fabric 的 Pattern → Leafer 的 IImagePaint */\nexport function convertPattern(pattern, ctx) {\n const url = resolveImageUrl(pattern.source, undefined, ctx)\n if (!url) {\n if (ctx && typeof ctx.warn === 'function') {\n ctx.warn('pattern 填充缺少 source,已当作透明')\n }\n return 'transparent'\n }\n\n const paint = { type: 'image', url }\n applyRepeat(paint, pattern.repeat)\n\n const offsetX = Number(pattern.offsetX) || 0\n const offsetY = Number(pattern.offsetY) || 0\n const transform = decomposeTransform(pattern.patternTransform)\n const x = offsetX + (transform ? transform.offsetX : 0)\n const y = offsetY + (transform ? transform.offsetY : 0)\n if (x || y) {\n paint.offset = { x, y }\n }\n if (transform) {\n if (transform.scaleX !== 1 || transform.scaleY !== 1) {\n paint.scale = { x: transform.scaleX, y: transform.scaleY }\n }\n if (transform.rotation) {\n paint.rotation = transform.rotation\n }\n }\n return paint\n}\n","/**\n * 外观属性:fill / stroke / 虚线 / 阴影 / 混合模式。\n * Fabric 的 fill 可能是颜色字符串,也可能是渐变对象;\n * 空值统一成 transparent,避免 Leafer 把 undefined 当成黑色。\n */\n\nimport { normalizeColor, isTransparentColor } from '../colors.js'\nimport { convertGradient, isGradient } from '../gradient.js'\nimport { convertPattern, isPattern } from '../pattern.js'\nimport { optionalNum } from '../nodes.js'\n\n/** 把 Fabric 的 fill 值转成 Leafer 的 paint 值 */\nexport function paintOf(value, ctx) {\n if (value === undefined || value === null || value === '') {\n return 'transparent'\n }\n if (isPattern(value)) {\n return convertPattern(value, ctx)\n }\n if (isGradient(value)) {\n return convertGradient(value, ctx)\n }\n return normalizeColor(value)\n}\n\n/** fill / stroke / 描边宽度 / 虚线 / 阴影,元素模块可以直接复用 */\nexport function applyPaint(node, object, ctx) {\n if (object.fill !== undefined && node.fill === undefined) {\n node.fill = paintOf(object.fill, ctx)\n }\n if (object.stroke !== undefined && object.stroke !== null && object.stroke !== '') {\n node.stroke = paintOf(object.stroke, ctx)\n const strokeWidth = optionalNum(object.strokeWidth)\n if (strokeWidth !== undefined) {\n node.strokeWidth = strokeWidth\n }\n // 平台全局开了 Fabric 的 strokeUniform(描边不随缩放变细), Leafer 用\n // strokeScaleFixed 表达同一语义: 833 的组缩到 0.04 倍后指示线仍是 1px,\n // 不会缩成看不见的 0.04px\n node.strokeScaleFixed = true\n if (Array.isArray(object.strokeDashArray) && object.strokeDashArray.length) {\n node.dashPattern = object.strokeDashArray\n }\n }\n if (object.shadow !== undefined) {\n const shadow = convertShadow(object.shadow)\n if (shadow) node.shadow = shadow\n }\n}\n\n/**\n * Fabric 的 backgroundColor 是图形底层的背景色,Leafer 没有同名属性。\n * 当 fill 透明时用它兜底,避免旧画面的背景色完全消失。\n */\nexport function applyBackgroundFallback(node, object, ctx) {\n if (!object.backgroundColor) {\n return\n }\n if (isTransparentColor(node.fill)) {\n node.fill = paintOf(object.backgroundColor, ctx)\n }\n}\n\n/** Fabric 阴影 → Leafer 阴影数组(Leafer 只认数组形式) */\nexport function convertShadow(shadow) {\n if (!shadow) {\n return undefined\n }\n const list = Array.isArray(shadow) ? shadow : [shadow]\n return list.filter(Boolean).map((item) => ({\n x: Number(item.offsetX !== undefined ? item.offsetX : (item.x || 0)),\n y: Number(item.offsetY !== undefined ? item.offsetY : (item.y || 0)),\n blur: Number(item.blur || 0),\n color: normalizeColor(item.color || 'rgba(0,0,0,0.5)'),\n spread: Number(item.spread || 0)\n }))\n}\n\n/** Fabric 的 globalCompositeOperation 直接映射成 Leafer 的 blendMode */\nexport function applyBlendMode(node, object) {\n const mode = object.globalCompositeOperation\n if (mode && mode !== 'source-over') {\n node.blendMode = mode\n }\n}\n\n/** 描边端点:Fabric butt/square/round → Leafer(butt 是默认值,不输出) */\nexport function strokeCapOf(value) {\n if (!value || value === 'butt') return undefined\n return value === 'square' ? 'square' : 'round'\n}\n\n/** 描边拐角:miter/round/bevel 两边一致 */\nexport function strokeJoinOf(value) {\n if (!value) return undefined\n return ['miter', 'round', 'bevel'].includes(value) ? value : undefined\n}\n","/**\n * 元数据透传:平台自定义字段原样带到 Leafer JSON 里。\n * 这些字段由平台启动时 UI.addAttr 注册,转换器只负责搬运,不解释含义。\n * 注意:这里不能 import leafer-ui,否则转换器就和引擎绑死了。\n */\n\nconst PASSTHROUGH_KEYS = [\n 'name',\n 'libName',\n 'param',\n 'originParam',\n 'noScaleWithParent',\n 'rsrc',\n 'config',\n 'template',\n 'script',\n 'props',\n 'keyboardEvent',\n 'dyn',\n 'action',\n 'ctxmenu',\n 'hasLocalValue',\n 'disabled'\n]\n\n/**\n * Fabric 类型 → 平台(leafer) 类型。\n * i-text 转成自定义元素 IText(文字铺满包围盒), 平台上它是独立图元类型 i-text,\n * 编辑器里对应\"拉伸文字\"工具。\n */\nconst TYPE_MAP = {\n 'i-text': 'i-text',\n itext: 'i-text'\n}\n\nexport function applyMeta(node, object, ctx) {\n // type 一定要写:平台运行态靠它区分业务类型(button/bar/chart…)\n node.type = TYPE_MAP[object.type] || object.type\n\n PASSTHROUGH_KEYS.forEach((key) => {\n if (object[key] !== undefined) {\n node[key] = object[key]\n }\n })\n\n // 运行态默认不可拖拽,编辑器再单独打开\n if (!ctx || !ctx.options || ctx.options.draggable !== true) {\n node.draggable = false\n }\n\n const strokeCap = object.strokeLineCap\n if (strokeCap && strokeCap !== 'butt') {\n node.strokeCap = strokeCap === 'square' ? 'square' : 'round'\n }\n const strokeJoin = object.strokeLineJoin\n if (strokeJoin && ['miter', 'round', 'bevel'].includes(strokeJoin)) {\n node.strokeJoin = strokeJoin\n }\n\n return node\n}\n","/**\n * 属性装配入口。\n * 元素模块只负责「这个类型有哪些几何字段」,公共属性统一在这里补,\n * 避免每个元素都复制一遍 rotation / scale / opacity 这些逻辑。\n */\n\nimport { applyTransform } from './transform.js'\nimport { applyPaint, applyBackgroundFallback, applyBlendMode } from './fill.js'\nimport { applyMeta } from './meta.js'\n\n/**\n * 内容由平台浮层(DOM)绘制的类型:画布上的节点只当锚点,不画填充和描边,\n * 否则图表 / 控件底下会多出一块底色和边框。\n */\nconst OVERLAY_TYPES = new Set(['chart', 'component'])\n\n/** 元素自身已经设置过 fill 的类型,不再做 backgroundColor 兜底 */\nconst NO_FILL_FALLBACK = new Set([\n 'text', 'i-text', 'textbox', 'group', 'lib', 'image', 'rubik-image',\n 'rubik-gif', 'button', 'bar', 'chart', 'component', 'line'\n])\n\n/**\n * 给节点补全公共属性。\n * 顺序有讲究:先变换(会影响 x/y),再外观,最后元数据。\n */\nexport function applyCommon(node, object, ctx) {\n applyTransform(node, object, ctx)\n if (!OVERLAY_TYPES.has(object.type)) {\n applyPaint(node, object, ctx)\n }\n\n if (!NO_FILL_FALLBACK.has(object.type)) {\n applyBackgroundFallback(node, object, ctx)\n }\n\n applyBlendMode(node, object)\n applyMeta(node, object, ctx)\n return node\n}\n","/** 矩形(Fabric rect)→ Leafer Rect */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\n/** Fabric 的 rx/ry 圆角 → Leafer 的 cornerRadius(数字或 [x, y]) */\nexport function cornerRadiusOf(object) {\n const rx = optionalNum(object.rx)\n const ry = optionalNum(object.ry)\n if (rx === undefined && ry === undefined) {\n return undefined\n }\n if (ry === undefined || ry === rx) {\n return rx !== undefined ? rx : ry\n }\n return [Math.max(0, rx || 0), Math.max(0, ry || 0)]\n}\n\nexport function convertRect(object, ctx, parent) {\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n const rect = node('Rect', {\n // Leafer 的 Rect 不给宽高时用默认的 100x100, Fabric 里缺宽高的图元\n // (脏数据 / 没画完的空框)要显式写 0, 否则转出来凭空多出一个 100 的框\n width: width === undefined ? 0 : width,\n height: height === undefined ? 0 : height,\n fill: paintOf(object.fill, ctx),\n cornerRadius: cornerRadiusOf(object)\n })\n place(rect, object, parent)\n return rect\n}\n","/** 椭圆(Fabric ellipse)→ Leafer Ellipse */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertEllipse(object, ctx, parent) {\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n const ellipse = node('Ellipse', {\n // 同 Rect: 不写宽高会落到 Leafer 的 100x100 默认尺寸\n width: width === undefined ? 0 : width,\n height: height === undefined ? 0 : height,\n fill: paintOf(object.fill, ctx)\n })\n place(ellipse, object, parent)\n return ellipse\n}\n","/**\n * 圆(Fabric circle)→ Leafer Ellipse。\n *\n * 注意:Fabric 的 circle 支持 startAngle/endAngle 画圆弧,\n * 标准 Leafer 的 Ellipse 不支持角度,这里只还原整圆。\n * 如果平台以后注册了自定义 Circle 元素,可以在 elements 包里覆盖这个转换器。\n */\n\nimport { node, num } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertCircle(object, ctx, parent) {\n const radius = num(object.radius)\n const circle = node('Ellipse', {\n width: radius * 2,\n height: radius * 2,\n fill: paintOf(object.fill, ctx)\n })\n place(circle, object, parent)\n\n if (object.startAngle !== undefined || object.endAngle !== undefined) {\n ctx.warn('fabric circle 的 startAngle/endAngle 圆弧暂不支持,已按整圆输出')\n }\n return circle\n}\n","/** 三角形(Fabric triangle)→ Leafer Polygon */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertTriangle(object, ctx, parent) {\n const width = optionalNum(object.width)\n const height = optionalNum(object.height)\n const w = width || 0\n const h = height || 0\n\n const triangle = node('Polygon', {\n // 不写宽高会落到 Leafer 的 100x100 默认尺寸\n width: w,\n height: h,\n // 顶点在正上方,底边贴底:和 Fabric 的三角形一致\n points: [w / 2, 0, w, h, 0, h],\n fill: paintOf(object.fill, ctx),\n closed: true\n })\n place(triangle, object, parent)\n return triangle\n}\n","/**\n * 折线(Fabric polyline)→ Leafer Line。\n * Fabric 的 points 是画布绝对坐标,geometry 会归一化成节点本地坐标(减包围盒左上角)。\n */\n\nimport { node } from '../nodes.js'\nimport { place, convertPoints, pathPlaceOrigin, pointsBounds } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertPolyline(object, ctx, parent) {\n // 同上: 不显式给宽高会落到 Leafer 的 100x100 默认值\n const bounds = pointsBounds(object.points)\n const line = node('Line', {\n width: bounds ? bounds.width : undefined,\n height: bounds ? bounds.height : undefined,\n points: convertPoints(object.points, {\n flipX: object.flipX === true,\n flipY: object.flipY === true\n }),\n // 节点原点是路径包围盒左上角,落点按 Fabric 的盒(含描边)反推\n around: 'top-left',\n fill: paintOf(object.fill, ctx),\n closed: false\n })\n place(line, { ...object, ...pathPlaceOrigin(object, bounds) }, parent)\n return line\n}\n","/**\n * 直线(Fabric line)→ Leafer Line。\n *\n * Fabric 的 x1/y1/x2/y2 和 polyline 的 points 一样是画布坐标,\n * geometry.convertPoints 会归一化成节点本地坐标(减包围盒左上角),\n * 再按 fabric 的 left/top 摆位,否则线会按绝对坐标再叠加一次位移跑到画布外。\n *\n * Fabric 的 line 只画描边(_render 里 strokeStyle = stroke || fillStyle,\n * 但没 stroke 时不调 _renderStroke),所以这里不输出 fill。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place, convertPoints, pointsBounds, pathPlaceOrigin } from '../geometry.js'\nimport { strokeCapOf, strokeJoinOf } from '../attributes/fill.js'\n\nexport function convertLine(object, ctx, parent) {\n const x1 = optionalNum(object.x1) || 0\n const y1 = optionalNum(object.y1) || 0\n const x2 = optionalNum(object.x2) || 0\n const y2 = optionalNum(object.y2) || 0\n\n const line = node('Line', {\n // Leafer 的 Line 宽度默认 100, 必须显式给, 否则选中框和属性面板尺寸都是错的\n width: Math.abs(x2 - x1),\n height: Math.abs(y2 - y1),\n points: convertPoints([{ x: x1, y: y1 }, { x: x2, y: y2 }], {\n flipX: object.flipX === true,\n flipY: object.flipY === true\n }),\n closed: false,\n // 节点原点是路径包围盒左上角,落点按 Fabric 的盒(含描边)反推\n around: 'top-left',\n // 端点: Fabric butt 对应 Leafer 的默认值, 不需要输出\n strokeCap: strokeCapOf(object.strokeLineCap),\n strokeJoin: strokeJoinOf(object.strokeLineJoin)\n })\n place(line, { ...object, ...pathPlaceOrigin(object, pointsBounds([{ x: x1, y: y1 }, { x: x2, y: y2 }])) }, parent)\n return line\n}\n","/** 多边形(Fabric polygon)→ Leafer Polygon,闭合路径;points 由 geometry 归一化成节点本地坐标 */\n\nimport { node } from '../nodes.js'\nimport { place, convertPoints, pathPlaceOrigin, pointsBounds } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertPolygon(object, ctx, parent) {\n // Leafer 的 Polygon 不传 width 时会用默认的 100x100, 节点尺寸就对不上了,\n // 组包围盒也会被这个假尺寸带偏, 所以按点集包围盒显式给宽高。\n const bounds = pointsBounds(object.points)\n const polygon = node('Polygon', {\n width: bounds ? bounds.width : undefined,\n height: bounds ? bounds.height : undefined,\n points: convertPoints(object.points, {\n flipX: object.flipX === true,\n flipY: object.flipY === true\n }),\n // 节点原点是路径包围盒左上角,落点按 Fabric 的盒(含描边)反推\n around: 'top-left',\n fill: paintOf(object.fill, ctx),\n closed: true\n })\n place(polygon, { ...object, ...pathPlaceOrigin(object, bounds) }, parent)\n return polygon\n}\n","/**\n * 路径(Fabric path)→ Leafer Path。\n * Fabric 的 path 是命令数组,Leafer 要 SVG path 字符串;\n * flipX/flipY 直接改写坐标,而不是用负 scale(否则描边会被镜像)。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place, convertPathData } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertPath(object, ctx, parent) {\n const path = node('Path', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n path: convertPathData(object.path, object),\n fill: paintOf(object.fill, ctx)\n })\n place(path, object, parent)\n return path\n}\n","/**\n * 文本属性:字体、对齐、换行、字距、装饰、背景。\n * 单位差异是这里最容易出错的地方,注释里逐个标了。\n */\n\nimport { normalizeColor } from '../colors.js'\nimport { convertShadow, paintOf } from './fill.js'\nimport { optionalNum, num } from '../nodes.js'\n\n/**\n * Fabric 的默认字体是 Times New Roman:没写 fontFamily 的文本在 Fabric 里就是按它\n * 量尺寸的。这里不补上,Leafer 会用自带默认字体,量出来的宽高和 Fabric 包围盒不一致。\n */\nexport const FABRIC_DEFAULT_FONT = 'Times New Roman'\n\n/**\n * Fabric wordWrap: 'word' | 'char' | undefined\n * Leafer textWrap: 'normal'(按词换行)| 'break'(按字符换行)| 'none'(不换行)\n */\nexport function convertWordWrap(wordWrap, splitByGrapheme) {\n // 只有显式按字符换行才换行: 空值 / none / word 一律转成不换行,\n // 与平台里 Fabric 文本的实际观感一致(默认值 word 不打断整行)\n if (splitByGrapheme || wordWrap === 'char') {\n return 'break'\n }\n return 'none'\n}\n\n/**\n * Fabric charSpacing 单位是 1/1000 em,Leafer letterSpacing 单位是像素。\n * 换算:charSpacing / 1000 * fontSize\n */\nexport function convertLetterSpacing(charSpacing, fontSize) {\n const spacing = optionalNum(charSpacing)\n if (spacing === undefined) {\n return undefined\n }\n return (spacing / 1000) * num(fontSize)\n}\n\n/** Fabric 的 underline / linethrough → Leafer 的 textDecoration 组合值 */\nexport function textDecorationOf(object) {\n if (object.underline && object.linethrough) return 'under-delete'\n if (object.underline) return 'underline'\n if (object.linethrough) return 'delete'\n return undefined\n}\n\n/**\n * Fabric 的 textAlign 比 Leafer 多出 justify-left / justify-center / justify-right\n * 这类值,Leafer 只认 left / center / right / justify 等。\n * 直接透传会让 Leafer 识别失败并回退到默认对齐,这里统一映射。\n */\nconst TEXT_ALIGN_MAP = {\n left: 'left',\n center: 'center',\n right: 'right',\n justify: 'justify',\n 'justify-left': 'left',\n 'justify-center': 'center',\n 'justify-right': 'right',\n 'justify-start': 'left',\n 'justify-end': 'right',\n 'justify-letter': 'justify-letter',\n both: 'both',\n 'both-letter': 'both-letter'\n}\n\nexport function convertTextAlign(textAlign) {\n if (!textAlign) return 'left'\n const value = String(textAlign).trim().toLowerCase()\n return TEXT_ALIGN_MAP[value] || 'left'\n}\n\n/**\n * Fabric 的 lineHeight 是相对字号的倍数(默认 1.16)。\n * Leafer 的 lineHeight 如果写成纯数字会被当成像素,倍数必须写成 percent 对象,\n * 否则文字高度会塌成 1.2px,选中框和实际文字完全对不上。\n * 兼容旧数据里直接写像素值(>= 10)的情况。\n */\nexport function convertLineHeight(lineHeight) {\n const value = optionalNum(lineHeight)\n if (value === undefined) {\n return undefined\n }\n if (value < 10) {\n return { type: 'percent', value }\n }\n return value\n}\n\n/** 组装 Text 节点除位置/变换外的全部属性 */\nexport function textProps(object, ctx) {\n const props = {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n text: object.text === undefined ? '' : String(object.text),\n fontSize: optionalNum(object.fontSize),\n fontFamily: object.fontFamily || FABRIC_DEFAULT_FONT,\n fontWeight: object.fontWeight,\n // 'normal' 是默认值,不输出,减小 JSON 体积\n fontStyle: object.fontStyle === 'normal' ? undefined : object.fontStyle,\n textAlign: convertTextAlign(object.textAlign),\n textWrap: convertWordWrap(object.wordWrap, object.splitByGrapheme),\n lineHeight: convertLineHeight(object.lineHeight),\n letterSpacing: convertLetterSpacing(object.charSpacing, object.fontSize),\n fill: object.fill ? paintOf(object.fill, ctx) : '#000000',\n shadow: object.shadow ? convertShadow(object.shadow) : undefined,\n textDecoration: textDecorationOf(object)\n }\n\n // Fabric 的 textBackgroundColor 是逐行背景;Leafer Text 没有同名能力,\n // 单行/标签场景用 boxStyle 兜底,至少保证背景不丢。\n const backgroundColor = object.backgroundColor || object.textBackgroundColor\n if (backgroundColor) {\n props.boxStyle = { fill: normalizeColor(backgroundColor) }\n }\n if (object.textBackgroundColor) {\n props.textBackgroundColor = normalizeColor(object.textBackgroundColor)\n }\n\n // 编辑器需要保留原始 Fabric 对象,运行态不需要\n if (ctx && ctx.options && ctx.options.mode === 'editor') {\n props.editable = true\n }\n\n return props\n}\n","/**\n * 文本转换。\n * - i-text:Fabric 里它的包围盒是\"排版尺寸 × scale\",编辑态拖角改的也是 scale,文字\n * 会跟着变形。Leafer 没有这种图元,交给自定义 IText:宽高就是权威的包围盒,文字被\n * 拉伸铺满它。转换时不带宽高(交给内容自适应),Fabric 的 scaleX/scaleY 原样留在\n * 节点上——否则图源参数把文本换长/换短后,盒子还是定义页那天的尺寸,文字会被横向\n * 压扁或拉长(Fabric 的 i-text 换文本会重新量尺寸,不会变形)。\n * - text / textbox:维持原来的 Leafer Text,尺寸和换行行为不变。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { textProps } from '../attributes/text.js'\n\nfunction textLines(object) {\n const content = object.text === undefined ? '' : String(object.text)\n return Math.max(1, content.split('\\n').length)\n}\n\n/**\n * Fabric 的 height 反推出的行高比例:单行文本的包围盒高度就是字形行高,多行按行数摊开。\n * 明显是画框尺寸(而不是字形行高)时返回 undefined,交给 Leafer 默认行高。\n * 正常字形行高就是 1.1 ~ 1.4,取一个窄区间,免得把画框高度当成行高\n */\nfunction ratioFromHeight(object) {\n const fontSize = optionalNum(object.fontSize)\n const height = optionalNum(object.height)\n if (!fontSize || !height) return undefined\n const ratio = Math.round((height / (fontSize * textLines(object))) * 1000) / 1000\n return ratio > 0.8 && ratio < 1.6 ? ratio : undefined\n}\n\n/** Fabric 没写 lineHeight 时估一个,让 Leafer 排出来的行高和 Fabric 一致 */\nfunction estimateLineHeight(object) {\n const ratio = ratioFromHeight(object)\n return ratio === undefined ? undefined : { type: 'percent', value: ratio }\n}\n\n/** 行高换算成像素(percent 按字号折,不加 lineHeight 时用 Leafer 默认的 1.16 倍) */\nfunction lineHeightPx(lineHeight, fontSize) {\n if (lineHeight === undefined) return fontSize * 1.16\n if (typeof lineHeight === 'number') return lineHeight\n if (lineHeight && lineHeight.type === 'percent') return fontSize * (Number(lineHeight.value) || 0)\n return undefined\n}\n\n/**\n * Fabric 的 height 是字形框,Leafer 的行盒高度由 lineHeight 决定。\n * 行盒比框高时(14 号字 + lineHeight 1.5 = 21,框只有 15.82),verticalAlign 看起来是反的:\n * top 不偏移、文字溢出到框底,bottom 反而上移。这种情况用框高反推行高,让行盒和框对齐。\n */\nfunction fitLineHeight(props, object) {\n if (props.textWrap !== 'none') return props.lineHeight\n const fontSize = optionalNum(object.fontSize)\n const height = optionalNum(object.height)\n const ratio = ratioFromHeight(object)\n if (!fontSize || !height || ratio === undefined) return props.lineHeight\n const current = lineHeightPx(props.lineHeight, fontSize)\n if (current === undefined || current * textLines(object) <= height + 0.5) return props.lineHeight\n return { type: 'percent', value: ratio }\n}\n\n/**\n * 文本行高按字号(1.0 倍)走: 行盒高度就等于字号, 框比行盒大时 verticalAlign 才有空间可移;\n * 框比行盒还小时仍用 fitLineHeight 压到框高。\n */\nfunction textLineHeight(props, object) {\n return fitLineHeight({ ...props, lineHeight: { type: 'percent', value: 1 } }, object)\n}\n\n/**\n * textbox 的行高: 单行直接等于字号(1.0 倍); 多行(有换行)按框高反推\n * height / 行数 / 字号, 让 N 行正好铺满 Fabric 记下的框, 不挤也不溢出。\n */\nfunction textboxLineHeight(object) {\n const fontSize = optionalNum(object.fontSize)\n const height = optionalNum(object.height)\n const lines = textLines(object)\n if (lines > 1 && fontSize && height) {\n const ratio = Math.round((height / (fontSize * lines)) * 1000) / 1000\n // 明显不是行高比值时(比如框被拉得极扁/极高)退回 1.0\n if (ratio > 0.8 && ratio < 2.5) {\n return { type: 'percent', value: ratio }\n }\n }\n return { type: 'percent', value: 1 }\n}\n\nfunction isIText(object) {\n return object.type === 'i-text' || object.type === 'itext'\n}\n\nexport function convertText(object, ctx, parent) {\n const props = textProps(object, ctx)\n const itext = isIText(object)\n // 只有 Fabric 的普通 text 才改垂直对齐和行高: 它从顶部往下排(originY 默认 top),\n // 固定 top 且行高按字号才和 Fabric 观感一致。textbox 是固定宽高的文本框,\n // 垂直对齐和行高都沿用 Fabric 自己写的值, 不要动。\n if (!itext && object.type === 'textbox') {\n props.lineHeight = textboxLineHeight(object)\n } else if (!itext) {\n props.verticalAlign = 'top'\n props.lineHeight = textLineHeight(props, object)\n }\n const text = itext\n ? node('IText', {\n ...props,\n lineHeight: props.lineHeight || estimateLineHeight(object)\n })\n : node('Text', props)\n // 不额外偏移: 早期为了\"视觉更接近\"整体上移过 2px, 但和 Fabric 的包围盒对不上,\n // 按 comparator 逐图元比对, 不带偏移时误差为 0\n place(text, object, parent)\n\n if (itext) {\n // i-text 的盒宽由文字自身决定(拉伸走节点 scaleX/scaleY), 见文件头注释\n delete text.width\n delete text.height\n } else if (optionalNum(object.width) === undefined) {\n // 没有宽度时交给 Leafer 自适应,避免被压成 0 宽\n delete text.width\n }\n return text\n}\n","/**\n * 图片(Fabric image / rubik-image / rubik-gif)→ Leafer Image。\n * 图片地址走 resolveAsset,转换器本身不拼平台 URL。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { resolveImageUrl } from '../assets.js'\n\nexport function convertImage(object, ctx, parent) {\n const image = node('Image', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: 'transparent',\n url: resolveImageUrl(object.src, object.rsrc, ctx)\n })\n place(image, object, parent)\n\n if (object.cropX || object.cropY) {\n // Fabric 的裁剪信息 Leafer 没有直接对应字段,先留警告\n ctx.warn('fabric image 的 cropX/cropY 暂未转换')\n }\n return image\n}\n","/**\n * lib(组件库实例)相关:参数替换 + 页面跳转动作清理。\n *\n * 平台把可复用组件存成 lib,实例上通过 param 覆盖文本/颜色等内容。\n * Fabric JSON 里用 `{key}` 占位,转换时替换成实例参数。\n */\n\n/** 深拷贝,避免转换过程改到原始 Fabric JSON(调用方可能还要用) */\nexport function cloneData(value) {\n if (value === null || value === undefined) {\n return value\n }\n return JSON.parse(JSON.stringify(value))\n}\n\n/** 统一 lib 路径:去掉 mmi/ 前缀、.json 后缀和开头斜杠 */\nexport function normalizeLibName(libName) {\n return String(libName || '')\n .replace(/\\\\/g, '/')\n .replace(/^\\/+/, '')\n .replace(/^\\.?\\//, '')\n .replace(/^mmi\\//, '')\n .replace(/\\.json$/i, '')\n}\n\n/** 递归把字符串里的 {key} 替换成 params[key] */\nexport function replaceDataParams(value, params) {\n if (typeof value === 'string') {\n let result = value\n Object.keys(params || {}).forEach((key) => {\n const replacement = params[key] === null || params[key] === undefined\n ? ''\n : String(params[key])\n result = result.split('{' + key + '}').join(replacement)\n })\n return result\n }\n if (Array.isArray(value)) {\n return value.map((item) => replaceDataParams(item, params))\n }\n if (value && typeof value === 'object') {\n Object.keys(value).forEach((key) => {\n value[key] = replaceDataParams(value[key], params)\n })\n }\n return value\n}\n\n/** 页面跳转动作:点整组就跳页,子元素上的同类动作要去掉,避免抢事件 */\nfunction isPageAction(action) {\n return !!action && (action.act === 'openPad' || action.act === 'openWindow') && !!action.pic\n}\n\nexport function getPageActionEvents(actionMap) {\n const events = new Set()\n Object.keys(actionMap || {}).forEach((eventName) => {\n if (isPageAction(actionMap[eventName])) {\n events.add(eventName)\n }\n })\n return events\n}\n\n/** 删除子元素上和父级重复的页面跳转动作 */\nexport function stripChildPageActions(object, parentPageActionEvents) {\n if (!object || !parentPageActionEvents || parentPageActionEvents.size === 0) {\n return object\n }\n\n if (object.action) {\n Object.keys(object.action).forEach((eventName) => {\n if (parentPageActionEvents.has(eventName) && isPageAction(object.action[eventName])) {\n delete object.action[eventName]\n }\n })\n if (Object.keys(object.action).length === 0) {\n delete object.action\n }\n }\n\n if (Array.isArray(object.objects)) {\n object.objects.forEach((child) => stripChildPageActions(child, parentPageActionEvents))\n }\n return object\n}\n\n/** lib 节点:Fabric 用 type=lib,Leafer 转换后额外用 tag=Lib 区分 */\nexport function isLibNode(node) {\n return !!node && (node.type === 'lib' || node.tag === 'Lib')\n}\n\n/** lib 保存时只保留引用,内部图元由页面定义在加载时补全 */\nexport function stripLibChildren(value) {\n if (!value || typeof value !== 'object') return value\n if (Array.isArray(value)) {\n value.forEach((item) => stripLibChildren(item))\n return value\n }\n if (isLibNode(value)) {\n delete value.children\n return value\n }\n if (Array.isArray(value.children)) {\n value.children.forEach((child) => stripLibChildren(child))\n }\n return value\n}\n\nfunction definitionParams(definition) {\n return {\n ...((definition && definition.header && definition.header.param) || {}),\n ...((definition && definition.param) || {})\n }\n}\n\nfunction libParams(definition, node) {\n return {\n ...definitionParams(definition),\n ...((node && node.originParam) || {}),\n ...((node && node.param) || {})\n }\n}\n\n// 实例没有存宽高时的兜底: 用定义页尺寸; 定义页也没有就不写(让 Leafer 按内部图元算),\n// 不要凭空写 100x100, 否则实例框和 Fabric 里看到的大小对不上。\nfunction libSize(definition) {\n const header = (definition && definition.header) || {}\n const width = Number(header.width)\n const height = Number(header.height)\n return {\n width: width > 0 ? width : undefined,\n height: height > 0 ? height : undefined\n }\n}\n\n// 同步扫一遍树, 找出还没有内部图元的 lib 引用。\n// 原来每个节点都 await 一次(上千个节点就是上千次微任务), 4~5ms 全花在调度上。\nfunction collectLibNodes(children, stack) {\n const pending = []\n const walk = (list, chain) => {\n for (let i = 0; i < list.length; i++) {\n const node = list[i]\n if (!node || typeof node !== 'object') continue\n if (isLibNode(node) && node.libName) {\n const name = String(node.libName)\n const missing = !Array.isArray(node.children) || !node.children.length\n if (missing && chain.indexOf(name) === -1) {\n pending.push({ node, name, stack: chain })\n continue\n }\n }\n if (Array.isArray(node.children)) walk(node.children, chain)\n }\n }\n walk(children, stack)\n return pending\n}\n\n// lib 会嵌套, 展开出来的定义里可能还有 lib, 所以循环到没有待展开节点为止\nasync function hydrateLibChildren(children, loadDefinition, stack) {\n let pending = collectLibNodes(children, stack)\n while (pending.length) {\n const definitions = await Promise.all(pending.map((item) => {\n // 缺失的 lib 定义不能阻断整页加载,保留空 lib 让用户看到问题位置\n return Promise.resolve(loadDefinition(item.name)).catch(() => null)\n }))\n let next = []\n definitions.forEach((definition, index) => {\n if (!definition) return\n const item = pending[index]\n const node = item.node\n const params = libParams(definition, node)\n const size = libSize(definition)\n const children = replaceDataParams(cloneData(definition.children || []), params)\n const box = rebaseChildren(children)\n const hydrated = {\n children,\n originParam: node.originParam || definitionParams(definition),\n param: node.param || {}\n }\n // 实例框取内容包围盒, 没有尺寸信息才退回定义页尺寸\n const width = box && box.width > 0 ? box.width : size.width\n const height = box && box.height > 0 ? box.height : size.height\n if (width !== undefined) hydrated.width = width\n if (height !== undefined) hydrated.height = height\n Object.assign(node, hydrated)\n next = next.concat(collectLibNodes(hydrated.children, item.stack.concat(item.name)))\n })\n pending = next\n }\n}\n\n/** 内容由平台浮层绘制的类型 */\nconst OVERLAY_TYPES = new Set(['chart', 'component'])\n\n/**\n * 图表 / 控件的内容是浮层(DOM)画出来的,锚点节点本身不该带填充和描边。\n * 旧文件里存过 fill / stroke,加载时统一清掉,免得底下多一块底框。\n */\nexport function stripOverlayPaint(value) {\n if (!value || typeof value !== 'object') return value\n if (Array.isArray(value)) {\n value.forEach((item) => stripOverlayPaint(item))\n return value\n }\n if (OVERLAY_TYPES.has(value.type)) {\n value.fill = 'transparent'\n delete value.stroke\n delete value.strokeWidth\n if (value.border) delete value.border\n }\n if (Array.isArray(value.children)) {\n value.children.forEach((item) => stripOverlayPaint(item))\n }\n return value\n}\n\n/**\n * 把 Leafer 文档里只有 libName 的 lib 引用补全成完整图元。\n * loadDefinition(libName) 由宿主提供,返回 Leafer document。\n */\nexport async function hydrateLeaferDocument(document, loadDefinition) {\n if (!document || !Array.isArray(document.children)) {\n return document\n }\n stripOverlayPaint(document.children)\n if (typeof loadDefinition !== 'function') {\n return document\n }\n await hydrateLibChildren(document.children, loadDefinition, [])\n return document\n}\n\n// lib 内部图元的坐标必须归到 0 起的局部坐标:\n// 平台给 Lib 定的包围盒是 (0,0,width,height), 子图元若还带着定义页的绝对坐标,\n// 就会整体偏到包围盒外面, 和 Fabric 的组(内容贴包围盒)不一致。\n// 原点(around)和 scale 都会让\"存下来的 x/y\"不等于视觉左上角, 必须一起算。\n\n/** around 是 Leafer 的围绕点, 决定 x/y 指的是盒子的哪一点 */\nfunction originFraction(around) {\n if (!around) return { x: 0, y: 0 }\n if (typeof around === 'object') {\n const x = Number(around.x)\n const y = Number(around.y)\n if (Number.isFinite(x) || Number.isFinite(y)) {\n return { x: Number.isFinite(x) ? x : 0, y: Number.isFinite(y) ? y : 0 }\n }\n return { x: 0, y: 0 }\n }\n const text = String(around)\n const center = text.indexOf('center') > -1\n return {\n x: text.indexOf('right') > -1 ? 1 : (center ? 0.5 : 0),\n y: text.indexOf('bottom') > -1 ? 1 : (center ? 0.5 : 0)\n }\n}\n\nfunction nodeSize(child) {\n const scaleX = Math.abs(Number(child.scaleX))\n const scaleY = Math.abs(Number(child.scaleY))\n const width = Number(child.width) * (Number.isFinite(scaleX) ? scaleX : 1)\n const height = Number(child.height) * (Number.isFinite(scaleY) ? scaleY : 1)\n // 文本等自适应尺寸在数据里可能没有 width/height, 不能参与坐标计算\n return {\n width: Number.isFinite(width) ? width : 0,\n height: Number.isFinite(height) ? height : 0\n }\n}\n\n/** 子图元并集的视觉包围盒(父级局部坐标, 已考虑 around 与 scale) */\nexport function contentBox(children, offsetX = 0, offsetY = 0) {\n let minX = Infinity\n let minY = Infinity\n let maxX = -Infinity\n let maxY = -Infinity\n const merge = (box) => {\n if (!box) return\n minX = Math.min(minX, box.x)\n minY = Math.min(minY, box.y)\n maxX = Math.max(maxX, box.x + box.width)\n maxY = Math.max(maxY, box.y + box.height)\n }\n ;(children || []).forEach((child) => {\n if (!child || typeof child !== 'object') return\n const x = Number.isFinite(Number(child.x)) ? Number(child.x) : 0\n const y = Number.isFinite(Number(child.y)) ? Number(child.y) : 0\n const origin = originFraction(child.around)\n const size = nodeSize(child)\n // 盒子左上角: x/y 是围绕点, 减去绕点占的比例\n const left = offsetX + x - size.width * origin.x\n const top = offsetY + y - size.height * origin.y\n if (size.width > 0 && size.height > 0) {\n merge({ x: left, y: top, width: size.width, height: size.height })\n return\n }\n if (Array.isArray(child.children) && child.children.length) {\n merge(contentBox(child.children, left, top))\n return\n }\n merge({ x: left, y: top, width: 0, height: 0 })\n })\n if (!Number.isFinite(minX)) return null\n return { x: minX, y: minY, width: maxX - minX, height: maxY - minY }\n}\n\n/** 把子图元平移到 0 起的局部坐标, 返回平移前的视觉包围盒 */\nexport function rebaseChildren(children) {\n const box = contentBox(children)\n if (!box) return null\n if (box.x || box.y) {\n // 平移围绕点即可整体挪动盒子, 不用管 around/scale\n ;(children || []).forEach((child) => {\n if (!child || typeof child !== 'object') return\n const x = Number.isFinite(Number(child.x)) ? Number(child.x) : 0\n const y = Number.isFinite(Number(child.y)) ? Number(child.y) : 0\n child.x = x - box.x\n child.y = y - box.y\n })\n }\n return box\n}\n\nexport function createLibGroupData(definition, libName, position) {\n if (!definition) return null\n const params = libParams(definition, null)\n const children = replaceDataParams(cloneData(definition.children || []), params)\n const box = rebaseChildren(children)\n const size = libSize(definition)\n const point = position || { x: 0, y: 0 }\n // 实例框就是内容包围盒, 落点即内容左上角\n const width = box && box.width > 0 ? box.width : size.width\n const height = box && box.height > 0 ? box.height : size.height\n return {\n tag: 'Lib',\n type: 'lib',\n libName: String(libName || ''),\n x: Number(point.x) || 0,\n y: Number(point.y) || 0,\n width,\n height,\n fill: 'transparent',\n originParam: definitionParams(definition),\n param: {},\n children\n }\n}\n","/**\n * 组(Fabric group)→ Leafer Group。\n * Fabric 子元素坐标相对组中心,geometry.place 会自动加父级宽高的一半;\n * 另外 Fabric 的组是按存下来的宽高定位/旋转的,Leafer 却按子元素现算包围盒,\n * 所以这里还要把围绕点钉回 Fabric 的组中心,见下面的注释。\n */\n\nimport { node, num, optionalNum } from '../nodes.js'\nimport { aroundFraction, aroundOf, nodeBox, place, unionBoxes } from '../geometry.js'\nimport { cloneData, getPageActionEvents, stripChildPageActions } from '../lib.js'\n\nexport function convertGroup(object, ctx, parent) {\n const group = node('Group', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: 'transparent'\n })\n place(group, object, parent)\n\n // 整组绑定了页面跳转时,子元素上的同类动作要去掉,否则子元素会先吃掉点击\n const pageActionEvents = getPageActionEvents(object.action)\n const pairs = []\n\n ;(object.objects || []).forEach((child) => {\n const source = pageActionEvents.size\n ? stripChildPageActions(cloneData(child), pageActionEvents)\n : child\n const converted = ctx.convert(source, group)\n if (converted) {\n pairs.push({ node: converted, source })\n }\n })\n\n if (pairs.length) {\n group.children = pairs.map((pair) => pair.node)\n group.around = anchorOf(object, unionBoxes(pairs.map((pair) => nodeBox(pair.node, pair.source))))\n }\n return group\n}\n\n/**\n * 组的围绕点百分比。\n *\n * Fabric 的组按\"存下来的宽高\"定位和旋转,Leafer 的 Group 包围盒却永远按子元素\n * 现算;子元素被拖过/转过之后两个尺寸就对不上,整组会绕错中心。所以用百分比把\n * 围绕点钉回 Fabric 的原点(place 用的就是这一点),位置和旋转基准都回到 Fabric。\n *\n * Leafer 的百分比是相对 boxBounds 的,而运行态会把组包围盒撑成\"子元素并集 ∪\n * 存下来的宽高\"(leaferCanvas/compat 里的补丁),这里按同一口径算,否则并集比存下来的\n * 宽高小时百分比会偏,转了角度的组就会错位。\n */\nfunction anchorOf(object, box) {\n const width = num(object.width)\n const height = num(object.height)\n const origin = aroundFraction(aroundOf(object))\n const left = Math.min(box.x, 0)\n const top = Math.min(box.y, 0)\n const right = Math.max(box.x + box.width, width)\n const bottom = Math.max(box.y + box.height, height)\n return {\n type: 'percent',\n x: right - left ? (origin.x * width - left) / (right - left) : 0.5,\n y: bottom - top ? (origin.y * height - top) / (bottom - top) : 0.5\n }\n}\n","/**\n * 组件实例(Fabric lib)→ Leafer Lib 自定义元素。\n * lib 本质是「带参数、内部图元按需水合的组」:先把 {key} 占位替换成实例参数,再按组转换。\n *\n * 定义页里取出来的图元坐标是页面坐标(左上角为原点),不像 Fabric 组的子图元那样是\n * 相对组中心的,所以这里不能按父组补半个宽高的偏移——补了会让同一个图源比「打开\n * leafer 文件」时整体右下偏半个实例尺寸。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { cloneData, rebaseChildren, replaceDataParams } from '../lib.js'\n\nexport function convertLib(object, ctx, parent) {\n const group = node('Lib', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n fill: 'transparent'\n })\n place(group, object, parent)\n\n // 实例参数优先于定义时的默认参数\n const params = { ...(object.originParam || {}), ...(object.param || {}) }\n const children = []\n\n ;(object.objects || []).forEach((child) => {\n const source = replaceDataParams(cloneData(child), params)\n const converted = ctx.convert(source, null)\n if (converted) {\n children.push(converted)\n }\n })\n\n if (children.length) {\n // 子图元归到 0 起的局部坐标: 平台给 Lib 的包围盒是 (0,0,width,height)\n rebaseChildren(children)\n group.children = children\n }\n return group\n}\n","/**\n * 按钮(Fabric 平台自定义 button)→ Leafer 自定义原子元素 Button。\n *\n * Button 的字、边框、按压效果都由 @rubik/fabric-to-leafer-elements 内部绘制,\n * 转换结果不能再是 Group + Box + Text + Line,否则编辑态会把它当成组合。\n */\n\nimport { node, optionalNum, num } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\nimport { normalizeColor } from '../colors.js'\nimport { FABRIC_DEFAULT_FONT } from '../attributes/text.js'\n\n// 与自定义 Button 的默认值保持一致\nconst DEFAULT_FILL = '#969696'\nconst DEFAULT_FONT_SIZE = 12\n\nexport function convertButton(object, ctx, parent) {\n // 某些 Fabric 画面里按钮的 width/height 会被存成 null,\n // 真正的尺寸在 buttonScaleBase* 上;优先用主尺寸,缺失时回退到基准尺寸。\n const baseWidth = optionalNum(object.buttonScaleBaseWidth)\n const baseHeight = optionalNum(object.buttonScaleBaseHeight)\n const width = optionalNum(object.width) || baseWidth || 0\n const height = optionalNum(object.height) || baseHeight || 0\n // Fabric 自定义 Button 用 scaleY 表示显示高度; 把 scaleY 烘焙进高度,\n // 避免 Leafer 的 scaleY 把文字一起拉变形。\n const scaleY = num(object.scaleY, 1)\n const displayHeight = height * (scaleY > 0 ? scaleY : 1)\n\n const backgroundFill = object.backgroundColor === undefined || object.backgroundColor === ''\n ? (object.fill === undefined || object.fill === '' ? DEFAULT_FILL : object.fill)\n : object.backgroundColor\n\n const button = node('Button', {\n width,\n height: displayHeight,\n text: object.text === undefined ? '' : String(object.text),\n fontSize: optionalNum(object.fontSize) || DEFAULT_FONT_SIZE,\n fontFamily: object.fontFamily || FABRIC_DEFAULT_FONT,\n fontWeight: object.fontWeight || 'normal',\n fontColor: normalizeColor(object.fontColor || '#000000'),\n fill: paintOf(backgroundFill, ctx),\n backgroundColor: paintOf(backgroundFill, ctx),\n stroke: object.stroke === undefined || object.stroke === null || object.stroke === ''\n ? undefined\n : normalizeColor(object.stroke),\n strokeWidth: optionalNum(object.strokeWidth),\n cornerRadius: optionalNum(object.rx) || optionalNum(object.ry),\n wordWrap: object.wordWrap || 'word',\n down: object.down === true,\n buttonScaleBaseWidth: baseWidth || width,\n buttonScaleBaseHeight: baseHeight || displayHeight\n })\n place(button, object, parent)\n return button\n}\n","/**\n * 进度条 / 滑动条(Fabric 平台自定义 bar)→ Leafer 自定义原子元素 Bar。\n *\n * Bar 内部由 @rubik/fabric-to-leafer-elements 自己绘制背景和填充,\n * 转换结果不能再是 Group + 子元素,否则编辑态会把它当成可解组的组合。\n *\n * fpct:0~1 的进度;fdir:方向(0 左→右,1 右→左);\n * fstyle:'rect' 直角 / 'circle' 圆角。\n */\n\nimport { node, optionalNum, num } from '../nodes.js'\nimport { place } from '../geometry.js'\nimport { paintOf } from '../attributes/fill.js'\n\nexport function convertBar(object, ctx, parent) {\n const width = optionalNum(object.width) || 0\n const height = optionalNum(object.height) || 0\n const direction = num(object.fdir, 0) % 5\n const fdir = direction < 0 ? direction + 5 : direction\n let percent = num(object.fpct, 0.6)\n // 和 Fabric Bar 一致:方向 4 是中心向外,允许 -1~1;其它方向只允许 0~1\n percent = Math.max(fdir === 4 ? -1 : 0, Math.min(1, percent))\n\n const bar = node('Bar', {\n width,\n height,\n fill: paintOf(object.fill, ctx),\n backgroundFill: paintOf(object.backgroundColor || 'transparent', ctx),\n stroke: object.stroke === undefined || object.stroke === null || object.stroke === ''\n ? undefined\n : paintOf(object.stroke, ctx),\n strokeWidth: optionalNum(object.strokeWidth),\n fpct: percent,\n fdir,\n fstyle: object.fstyle || 'rect'\n })\n place(bar, object, parent)\n return bar\n}\n","/**\n * chart / component → 画布上的锚点盒。\n *\n * 它们不是 Leafer 图形,平台用 DOM 浮层画真实内容(图表走 echarts,控件走 Vue 组件):\n * 浮层按节点的世界矩阵定位、按宽高定尺寸、跟随可见性/透明度,锚点盒就是它唯一的依据。\n * config / template / script / props 由 meta 的透传字段原样带走,浮层据此渲染。\n * 所以这里不是\"占位不渲染\",去掉它页面上的图表和控件会直接消失。\n *\n * 锚点盒自己什么也不画:图表 / 控件的内容是浮层画出来的,再给底色和边框只会多出一块框。\n */\n\nimport { node, optionalNum } from '../nodes.js'\nimport { place } from '../geometry.js'\n\nexport function convertPlaceholder(object, ctx, parent) {\n const box = node('Box', {\n width: optionalNum(object.width),\n height: optionalNum(object.height),\n hitFill: 'all',\n fill: 'transparent'\n })\n place(box, object, parent)\n return box\n}","/**\n * 元素分发表:Fabric 类型 → 转换函数。\n *\n * 加新元素只要两步:\n * 1. 新建 elements/xxx.js 导出 convertXxx(object, ctx, parent)\n * 2. 在下面的表里登记类型\n */\n\nimport { applyCommon } from '../attributes/index.js'\nimport { normalizeSizeSign } from '../geometry.js'\n\nimport { convertRect } from './rect.js'\nimport { convertEllipse } from './ellipse.js'\nimport { convertCircle } from './circle.js'\nimport { convertTriangle } from './triangle.js'\nimport { convertPolyline } from './polyline.js'\nimport { convertLine } from './line.js'\nimport { convertPolygon } from './polygon.js'\nimport { convertPath } from './path.js'\nimport { convertText } from './text.js'\nimport { convertImage } from './image.js'\nimport { convertGroup } from './group.js'\nimport { convertLib } from './lib.js'\nimport { convertButton } from './button.js'\nimport { convertBar } from './bar.js'\nimport { convertPlaceholder } from './placeholder.js'\n\nconst CONVERTERS = {\n rect: convertRect,\n ellipse: convertEllipse,\n circle: convertCircle,\n triangle: convertTriangle,\n polyline: convertPolyline,\n line: convertLine,\n polygon: convertPolygon,\n path: convertPath,\n text: convertText,\n 'i-text': convertText,\n textbox: convertText,\n image: convertImage,\n 'rubik-image': convertImage,\n 'rubik-gif': convertImage,\n group: convertGroup,\n lib: convertLib,\n button: convertButton,\n bar: convertBar,\n chart: convertPlaceholder,\n component: convertPlaceholder\n}\n\n/**\n * 转换单个 Fabric 对象。parent 用来算组内坐标偏移。\n * 返回 null 表示这个对象被跳过(未知类型或不可见),调用方过滤掉即可。\n */\nexport function convertObject(object, ctx, parent = null) {\n if (!object || typeof object !== 'object') {\n return null\n }\n\n const convert = CONVERTERS[object.type]\n if (!convert) {\n ctx.warn(`未知的 Fabric 对象类型:${object.type}`)\n return null\n }\n\n // Fabric 存下来的负宽高先换成正宽高(图形类把符号并进 scale), 否则 Leafer 会自己\n // 镜像 + 打警告, 而且和后面写入的 scaleX 抢次序\n const source = normalizeSizeSign(object)\n const result = convert(source, ctx, parent)\n if (!result) {\n return null\n }\n\n return applyCommon(result, source, ctx)\n}\n\n/** 判断某个 Fabric 类型是否已支持,测试和 CLI 可以用 */\nexport function isSupportedType(type) {\n return Object.prototype.hasOwnProperty.call(CONVERTERS, type)\n}\n","/**\n * 根文档组装:把转换出来的 children 和 Fabric 的 header / param 拼成\n * 平台约定的 Leafer 文档结构。\n */\n\nexport const DOCUMENT_VERSION = '4.4.0'\n\nexport function buildDocument(fabricJson, children) {\n const source = fabricJson || {}\n const header = source.header || {}\n const param = source.param || {}\n\n return {\n version: DOCUMENT_VERSION,\n engine: 'leafer',\n format: 'leafer',\n header: {\n ...header,\n // 画布级参数 = header 里的默认值 + 文件级 param 覆盖\n param: { ...(header.param || {}), ...param },\n background: source.background !== undefined ? source.background : header.background\n },\n param,\n keyboardEvent: source.keyboardEvent || [],\n children\n }\n}\n","/**\n * 转换主流程。\n *\n * Fabric JSON(objects 数组)→ Leafer JSON(children 数组)。\n * 这里只做遍历和组装,具体类型在 elements/,公共属性在 attributes/。\n */\n\nimport { createContext } from './context.js'\nimport { convertObject } from './elements/index.js'\nimport { buildDocument } from './document.js'\nimport { cloneData, normalizeLibName } from './lib.js'\n\n// 平台保存的 lib 只有 libName,没有内部 objects;转换前由调用方提供的\n// loadLib 把页面定义补进来。纯数据层不关心文件/URL 从哪来。\nasync function hydrateLibObject(object, loadLib, stack) {\n if (!object || typeof object !== 'object') return\n if (object.type === 'lib' && object.libName && (!Array.isArray(object.objects) || !object.objects.length)) {\n const name = normalizeLibName(object.libName)\n if (!name || stack.indexOf(name) > -1) return\n try {\n const page = await loadLib(name)\n if (page && Array.isArray(page.objects)) {\n object.objects = page.objects\n if (!object.originParam) {\n object.originParam = {\n ...((page.header && page.header.param) || {}),\n ...(page.param || {})\n }\n }\n await hydrateLibObjects(object.objects, loadLib, stack.concat(name))\n }\n } catch (error) {\n // lib 定义缺失时保留空组,不能阻断整页转换\n }\n } else if (Array.isArray(object.objects)) {\n await hydrateLibObjects(object.objects, loadLib, stack)\n }\n}\n\nasync function hydrateLibObjects(objects, loadLib, stack = []) {\n if (!Array.isArray(objects) || typeof loadLib !== 'function') return\n // 同层 lib 之间互不依赖,并行拉取/展开,减少首屏串行等待\n await Promise.all(objects.map((object) => hydrateLibObject(object, loadLib, stack)))\n}\n\n/** 只在确实存在待补全的 lib 引用时才深拷贝整份 Fabric JSON */\nfunction hasMissingLibObjects(objects) {\n if (!Array.isArray(objects)) return false\n return objects.some((object) => {\n if (!object || typeof object !== 'object') return false\n if (object.type === 'lib' && object.libName &&\n (!Array.isArray(object.objects) || !object.objects.length)) {\n return true\n }\n return Array.isArray(object.objects) && hasMissingLibObjects(object.objects)\n })\n}\n\nasync function prepareSource(fabricJson, options) {\n if (!fabricJson || !Array.isArray(fabricJson.objects) || typeof options.loadLib !== 'function') {\n return fabricJson\n }\n if (!hasMissingLibObjects(fabricJson.objects)) return fabricJson\n const source = cloneData(fabricJson)\n await hydrateLibObjects(source.objects, options.loadLib)\n return source\n}\n\nfunction run(fabricJson, options) {\n const ctx = createContext(options)\n\n // 注入递归转换函数:group/lib 用它转子元素\n ctx.convert = (object, parent) => convertObject(object, ctx, parent)\n\n const objects = fabricJson && Array.isArray(fabricJson.objects)\n ? fabricJson.objects\n : null\n\n if (!objects) {\n ctx.warn('无效的 Fabric JSON:缺少 objects 数组')\n return { document: buildDocument(fabricJson || {}, []), warnings: ctx.warnings }\n }\n\n const children = []\n objects.forEach((object) => {\n const converted = convertObject(object, ctx, null)\n if (converted) {\n children.push(converted)\n }\n })\n\n return {\n document: buildDocument(fabricJson, children),\n warnings: ctx.warnings\n }\n}\n\n/** 异步入口,保持和文档/调用方约定的 API 一致 */\nexport async function convert(fabricJson, options = {}) {\n const source = await prepareSource(fabricJson, options)\n return run(source, options)\n}\n\n/** 同步入口:不依赖异步资源时(Node / 单测 / CLI)直接用 */\nexport function convertSync(fabricJson, options = {}) {\n return run(fabricJson, options)\n}\n","/**\n * Leafer JSON → Fabric JSON(fabric-to-leafer 的反向转换)。\n *\n * 目标:把平台保存的 Leafer 文档还原成 Fabric 编辑器能打开的 JSON。\n * 约束:\n * - 纯 JSON 变换,不 import leafer-ui,Node / 浏览器都能跑;\n * - 能精确逆的(位置、尺寸、文本、元数据)精确逆;\n * - 不可逆的(点集翻转、烘焙静态背景图、自定义 around)按最接近的语义还原。\n *\n * 与正向的对应关系见各元素转换器:\n * - 位置:正向 place() 加了父级宽高的一半,反向减回去;旋转/翻转/缩放再逆\n * attributes/transform.js 的 applyPosition 补偿;\n * - 点集(line / polyline / polygon):正向把 scale 和翻转烘焙进 points,节点\n * scale 归 1,反向把 points 当本地坐标、按节点落点平移回 Fabric 的绝对坐标;\n * - 文本 / 按钮 / 进度条 / lib / 图表锚点:字段名基本一一对应。\n */\n\nimport { num } from './nodes.js'\nimport { aroundFraction } from './geometry.js'\nimport { isTransparentColor } from './colors.js'\n\n/** 平台自定义字段:正向 attributes/meta.js 原样搬过来的那些,反向原样搬回去 */\nconst META_KEYS = [\n 'name',\n 'libName',\n 'param',\n 'originParam',\n 'noScaleWithParent',\n 'rsrc',\n 'config',\n 'template',\n 'script',\n 'props',\n 'keyboardEvent',\n 'dyn',\n 'action',\n 'ctxmenu',\n 'hasLocalValue',\n 'disabled'\n]\n\n/** 数值保留 4 位小数,避免 1e-15 级浮点尾数写进 JSON */\nfunction round(value, digits = 4) {\n const number = Number(value)\n if (!Number.isFinite(number)) return 0\n const factor = Math.pow(10, digits)\n return Math.round(number * factor) / factor\n}\n\n/** Leafer 节点 tag + 正向透传的 type → Fabric 类型 */\nfunction fabricTypeOf(node, ctx) {\n const tag = node.tag\n const type = node.type\n switch (tag) {\n case 'Button': return 'button'\n case 'Bar': return 'bar'\n case 'Circle': return 'circle'\n case 'Lib': return 'lib'\n // Fabric 没有图层概念, 导出时把层当普通组展开, 所有图元仍在同一层\n case 'Layer': return 'group'\n case 'IText': return 'i-text'\n case 'Rect': return 'rect'\n case 'Ellipse': return type === 'circle' ? 'circle' : 'ellipse'\n case 'Text': return type === 'text' ? 'text' : 'textbox'\n case 'Image': return typeof type === 'string' && type ? type : 'image'\n case 'Group': return 'group'\n case 'Box': return type === 'chart' || type === 'component' ? type : 'component'\n // 正向把 line / polyline 都输出成 Leafer 的 Line,靠 type 区分\n case 'Line': return type === 'polyline' ? 'polyline' : 'line'\n // 正向把 polygon / triangle 都输出成 Leafer 的 Polygon\n case 'Polygon': return type === 'triangle' ? 'triangle' : 'polygon'\n case 'Path': return 'path'\n default:\n if (ctx && tag) {\n ctx.warnings.push(`未知的 Leafer 节点 tag: ${tag},已按 rect 输出`)\n }\n return 'rect'\n }\n}\n\n/** Leafer 渐变 paint → Fabric 渐变 */\nfunction gradientToFabric(paint) {\n const from = paint.from && typeof paint.from === 'object' ? paint.from : {}\n const to = paint.to && typeof paint.to === 'object' ? paint.to : {}\n const coords = {\n x1: round(num(from.x)),\n y1: round(num(from.y)),\n x2: round(num(to.x)),\n y2: round(num(to.y))\n }\n if (paint.type === 'radial') {\n // Fabric 径向渐变用 r2 表示半径,圆心是 (x1, y1)\n coords.r2 = round(Math.hypot(coords.x2 - coords.x1, coords.y2 - coords.y1)) || 0.5\n }\n return {\n type: paint.type === 'radial' ? 'radial' : 'linear',\n colorStops: (paint.stops || []).map((stop) => ({\n offset: round(num(stop.offset)),\n color: stop.color\n })),\n coords\n }\n}\n\n/** Leafer 图片 paint → Fabric Pattern */\nfunction patternToFabric(paint) {\n const repeat = paint.mode === 'normal'\n ? 'no-repeat'\n : (paint.repeat === 'x' ? 'repeat-x' : (paint.repeat === 'y' ? 'repeat-y' : 'repeat'))\n const pattern = { type: 'pattern', source: paint.url, repeat }\n const offsetX = paint.offset ? num(paint.offset.x) : 0\n const offsetY = paint.offset ? num(paint.offset.y) : 0\n if (offsetX || offsetY) {\n pattern.offsetX = round(offsetX)\n pattern.offsetY = round(offsetY)\n }\n const rotation = num(paint.rotation)\n const scaleX = paint.scale ? num(paint.scale.x, 1) : 1\n const scaleY = paint.scale ? num(paint.scale.y, 1) : 1\n if (rotation || scaleX !== 1 || scaleY !== 1) {\n const rad = rotation * Math.PI / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n pattern.patternTransform = [\n round(scaleX * cos),\n round(scaleX * sin),\n round(-scaleY * sin),\n round(scaleY * cos),\n round(offsetX),\n round(offsetY)\n ]\n }\n return pattern\n}\n\n/** Leafer paint(颜色 / 渐变 / 图片)→ Fabric fill 值;完全透明统一成空字符串 */\nfunction fabricPaint(value) {\n if (value === undefined || value === null || value === '') return ''\n if (typeof value === 'string') {\n return isTransparentColor(value) ? '' : value\n }\n if (Array.isArray(value.stops)) {\n return gradientToFabric(value)\n }\n if (value.type === 'image' && value.url) {\n return patternToFabric(value)\n }\n return value\n}\n\n/** Leafer 阴影数组 → Fabric shadow */\nfunction fabricShadow(value) {\n const list = Array.isArray(value) ? value : [value]\n return list.filter(Boolean).map((item) => ({\n offsetX: round(num(item.x)),\n offsetY: round(num(item.y)),\n blur: round(num(item.blur)),\n color: item.color || 'rgba(0,0,0,0.5)',\n spread: round(num(item.spread))\n }))\n}\n\n/** 填充 / 描边 / 阴影 / 混合模式:形状类的公共外观 */\nfunction applyFillStroke(object, node, options = {}) {\n if (options.fill !== false) {\n object.fill = fabricPaint(node.fill)\n }\n if (options.stroke !== false) {\n const stroke = fabricPaint(node.stroke)\n if (stroke !== '') {\n object.stroke = stroke\n if (node.strokeWidth !== undefined) {\n object.strokeWidth = round(num(node.strokeWidth))\n }\n if (Array.isArray(node.dashPattern) && node.dashPattern.length) {\n object.strokeDashArray = node.dashPattern.slice()\n }\n }\n }\n if (node.shadow !== undefined) {\n object.shadow = fabricShadow(node.shadow)\n }\n if (node.strokeCap) object.strokeLineCap = node.strokeCap\n if (node.strokeJoin) object.strokeLineJoin = node.strokeJoin\n if (node.blendMode) object.globalCompositeOperation = node.blendMode\n}\n\n/** 文本字段:Leafer 的 textWrap / lineHeight / letterSpacing 等还原成 Fabric 写法 */\nfunction applyTextProps(object, node) {\n object.text = node.text === undefined ? '' : String(node.text)\n if (node.fontSize !== undefined) object.fontSize = round(num(node.fontSize))\n if (node.fontFamily !== undefined) object.fontFamily = node.fontFamily\n if (node.fontWeight !== undefined && node.fontWeight !== 'normal') {\n object.fontWeight = node.fontWeight\n }\n if (node.fontStyle && node.fontStyle !== 'normal') {\n object.fontStyle = node.fontStyle\n }\n if (node.textAlign && node.textAlign !== 'left') {\n object.textAlign = node.textAlign\n }\n if (node.textWrap === 'normal') {\n object.wordWrap = 'word'\n } else if (node.textWrap === 'break') {\n object.wordWrap = 'char'\n object.splitByGrapheme = true\n }\n if (node.lineHeight !== undefined) {\n object.lineHeight = node.lineHeight && typeof node.lineHeight === 'object'\n ? round(num(node.lineHeight.value))\n : round(num(node.lineHeight))\n }\n if (node.letterSpacing !== undefined) {\n const fontSize = num(node.fontSize)\n if (fontSize) {\n object.charSpacing = round(num(node.letterSpacing) / fontSize * 1000, 3)\n }\n }\n if (node.textDecoration) {\n const decoration = String(node.textDecoration)\n if (decoration.indexOf('under') > -1) object.underline = true\n if (decoration.indexOf('delete') > -1) object.linethrough = true\n }\n // 正向给文字兜了 #000000,这里还原成同色,避免重新转换时默认色发生变化\n const fill = fabricPaint(node.fill)\n object.fill = fill === '' ? '#000000' : fill\n if (node.shadow !== undefined) {\n object.shadow = fabricShadow(node.shadow)\n }\n const boxStyle = node.boxStyle\n if (boxStyle && boxStyle.fill) {\n object.backgroundColor = fabricPaint(boxStyle.fill)\n }\n if (node.textBackgroundColor) {\n object.backgroundColor = fabricPaint(node.textBackgroundColor)\n }\n}\n\n/** 平台自定义字段原样搬回 */\nfunction applyMeta(object, node) {\n META_KEYS.forEach((key) => {\n if (node[key] !== undefined) {\n object[key] = node[key]\n }\n })\n}\n\n/** 按钮字段(对应 elements/button.js 的 toJSON) */\nfunction applyButtonProps(object, node) {\n object.text = node.text === undefined ? '' : String(node.text)\n object.fontSize = round(num(node.fontSize, 12))\n if (node.fontFamily !== undefined) object.fontFamily = node.fontFamily\n if (node.fontWeight && node.fontWeight !== 'normal') object.fontWeight = node.fontWeight\n object.fontColor = node.fontColor || '#000000'\n\n const background = fabricPaint(node.backgroundColor !== undefined ? node.backgroundColor : node.fill)\n if (background !== '') object.backgroundColor = background\n const fill = fabricPaint(node.fill)\n if (fill !== '') object.fill = fill\n\n const stroke = fabricPaint(node.stroke)\n if (stroke !== '') {\n object.stroke = stroke\n if (node.strokeWidth !== undefined) object.strokeWidth = round(num(node.strokeWidth))\n }\n if (node.cornerRadius !== undefined && node.cornerRadius !== null) {\n if (Array.isArray(node.cornerRadius)) {\n object.rx = round(num(node.cornerRadius[0]))\n object.ry = round(num(node.cornerRadius[1]))\n } else {\n object.rx = round(num(node.cornerRadius))\n object.ry = round(num(node.cornerRadius))\n }\n }\n if (node.buttonScaleBaseWidth !== undefined) {\n object.buttonScaleBaseWidth = round(num(node.buttonScaleBaseWidth))\n }\n if (node.buttonScaleBaseHeight !== undefined) {\n object.buttonScaleBaseHeight = round(num(node.buttonScaleBaseHeight))\n }\n if (node.wordWrap !== undefined) object.wordWrap = node.wordWrap\n if (node.down === true) object.down = true\n}\n\n/** 进度条字段(对应 elements/bar.js 的 toJSON) */\nfunction applyBarProps(object, node) {\n object.fill = fabricPaint(node.fill)\n const background = fabricPaint(node.backgroundFill)\n if (background !== '') object.backgroundColor = background\n const stroke = fabricPaint(node.stroke)\n if (stroke !== '') {\n object.stroke = stroke\n object.strokeWidth = node.strokeWidth === undefined ? 1 : round(num(node.strokeWidth))\n }\n object.fpct = round(num(node.fpct, 0.6))\n object.fdir = num(node.fdir, 0)\n object.fstyle = node.fstyle || 'rect'\n}\n\n/** 点集(line / polyline / polygon):Leafer 本地 points → Fabric 绝对坐标 */\nfunction applyPointShape(object, node) {\n const points = Array.isArray(node.points) ? node.points : []\n const left = num(object.left)\n const top = num(object.top)\n const absolute = points.map((value, index) => (\n round(index % 2 === 0 ? num(value) + left : num(value) + top)\n ))\n if (object.type === 'line') {\n if (absolute.length >= 4) {\n object.x1 = absolute[0]\n object.y1 = absolute[1]\n object.x2 = absolute[2]\n object.y2 = absolute[3]\n }\n } else {\n object.points = []\n for (let i = 0; i + 1 < absolute.length; i += 2) {\n object.points.push({ x: absolute[i], y: absolute[i + 1] })\n }\n }\n}\n\n/**\n * 变换逆运算。\n *\n * 正向:place() 先按父级宽高补半宽,再 applyPosition() 按 Fabric 的原点、\n * 旋转、翻转、缩放反推 Leafer 的围绕点。这里把两步一起逆回来。\n *\n * 点集元素不同:正向把 scale / 翻转烘焙进 points、节点 scale 归 1,落点是\n * pathPlaceOrigin() 按描边宽度反推的,所以反向单独用 stroke/2 还原。\n */\nfunction applyTransform(object, node, parent) {\n const tag = node.tag\n const type = object.type\n const width = Math.abs(num(node.width))\n const height = Math.abs(num(node.height))\n const parentWidth = parent ? num(parent.width) : 0\n const parentHeight = parent ? num(parent.height) : 0\n\n // 正向 line / polyline / polygon 的落点走 pathPlaceOrigin(不含 triangle)\n const pointsPlaced = (tag === 'Line' || tag === 'Polygon') && type !== 'triangle'\n const rotation = num(node.rotation)\n let scaleX = node.scaleX === undefined ? 1 : num(node.scaleX, 1)\n let scaleY = node.scaleY === undefined ? 1 : num(node.scaleY, 1)\n\n // 正向 button 的 scaleY 烘焙进了高度;点集的 scale 烘焙进了 points\n if (tag === 'Button') scaleY = 1\n if (pointsPlaced) {\n scaleX = 1\n scaleY = 1\n }\n\n // 围绕点比例:组可能是 percent 对象,其它是九宫格字符串\n const fraction = aroundFraction(node.around, width, height)\n const originX = fraction.x < 0.25 ? 'left' : (fraction.x > 0.75 ? 'right' : 'center')\n const originY = fraction.y < 0.25 ? 'top' : (fraction.y > 0.75 ? 'bottom' : 'center')\n\n let x = num(node.x) - parentWidth / 2\n let y = num(node.y) - parentHeight / 2\n\n if (pointsPlaced) {\n // 正向 pathPlaceOrigin:left' = left + R·(stroke/2, stroke/2)\n const stroke = Math.abs(num(node.strokeWidth))\n const rad = rotation * Math.PI / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n x -= ((cos - sin) * stroke) / 2\n y -= ((sin + cos) * stroke) / 2\n } else {\n const single = scaleX > 0 && scaleY > 0 && !rotation\n if (!single) {\n const rad = rotation * Math.PI / 180\n const cos = Math.cos(rad)\n const sin = Math.sin(rad)\n const rotate = (dx, dy) => [cos * dx - sin * dy, sin * dx + cos * dy]\n const [centerX, centerY] = rotate(\n (0.5 - fraction.x) * Math.abs(scaleX) * width,\n (0.5 - fraction.y) * Math.abs(scaleY) * height\n )\n const [shiftX, shiftY] = rotate(\n scaleX * (fraction.x * width - width / 2),\n scaleY * (fraction.y * height - height / 2)\n )\n x -= centerX + shiftX\n y -= centerY + shiftY\n }\n }\n\n object.left = round(x)\n object.top = round(y)\n if (rotation) object.angle = round(rotation)\n if (originX !== 'left') object.originX = originX\n if (originY !== 'top') object.originY = originY\n\n if (!pointsPlaced) {\n if (type === 'path') {\n // path 的翻转已烘焙进路径数据,负 scale 原样保留(Fabric 里同样表示镜像)\n if (scaleX !== 1) object.scaleX = round(scaleX)\n if (scaleY !== 1) object.scaleY = round(scaleY)\n } else {\n // 其余类型的负 scale 来自 Fabric 的 flipX / flipY,还原成翻转标记\n if (scaleX < 0) {\n object.flipX = true\n scaleX = -scaleX\n }\n if (scaleY < 0) {\n object.flipY = true\n scaleY = -scaleY\n }\n if (scaleX !== 1) object.scaleX = round(scaleX)\n if (scaleY !== 1) object.scaleY = round(scaleY)\n }\n }\n\n if (node.skewX) object.skewX = num(node.skewX)\n if (node.skewY) object.skewY = num(node.skewY)\n if (node.opacity !== undefined && num(node.opacity) !== 1) {\n object.opacity = num(node.opacity)\n }\n if (node.visible === false) object.visible = false\n}\n\nfunction convertChildren(node, ctx) {\n return (node.children || [])\n .map((child) => convertNode(child, ctx, node))\n .filter(Boolean)\n}\n\n/** 单个 Leafer 节点 → Fabric 对象 */\nfunction convertNode(node, ctx, parent) {\n if (!node || typeof node !== 'object') return null\n const tag = node.tag\n const type = fabricTypeOf(node, ctx)\n const object = { type }\n applyTransform(object, node, parent)\n applyMeta(object, node)\n\n const width = Math.abs(num(node.width))\n const height = Math.abs(num(node.height))\n\n switch (tag) {\n case 'Rect': {\n object.width = round(width)\n object.height = round(height)\n const radius = node.cornerRadius\n if (radius !== undefined && radius !== null) {\n if (Array.isArray(radius)) {\n object.rx = round(num(radius[0]))\n object.ry = round(num(radius[1]))\n } else {\n object.rx = round(num(radius))\n object.ry = round(num(radius))\n }\n }\n applyFillStroke(object, node)\n break\n }\n case 'Ellipse': {\n if (type === 'circle') {\n object.radius = round(width / 2)\n object.width = round(width)\n object.height = round(height)\n } else {\n object.width = round(width)\n object.height = round(height)\n }\n applyFillStroke(object, node)\n break\n }\n case 'Circle': {\n // 自定义 Circle(elements 包)内部是圆弧 Path,角度单位是弧度\n object.width = round(width)\n object.height = round(height)\n object.radius = round(width / 2)\n if (node.startAngle !== undefined) {\n object.startAngle = round(num(node.startAngle) * 180 / Math.PI)\n }\n if (node.endAngle !== undefined) {\n object.endAngle = round(num(node.endAngle) * 180 / Math.PI)\n }\n applyFillStroke(object, node)\n break\n }\n case 'IText':\n case 'Text': {\n applyTextProps(object, node)\n if (node.width !== undefined) object.width = round(width)\n if (node.height !== undefined) object.height = round(height)\n break\n }\n case 'Image': {\n object.width = round(width)\n object.height = round(height)\n object.src = node.url === undefined ? '' : node.url\n break\n }\n // 层就是恒等变换的组, Fabric 没有层概念, 导出时按组展开\n case 'Group':\n case 'Layer': {\n if (node.width !== undefined) object.width = round(width)\n if (node.height !== undefined) object.height = round(height)\n object.objects = convertChildren(node, ctx)\n break\n }\n case 'Lib': {\n if (node.width !== undefined) object.width = round(width)\n if (node.height !== undefined) object.height = round(height)\n object.libName = node.libName || ''\n object.param = node.param || {}\n if (node.originParam !== undefined) object.originParam = node.originParam\n if (Array.isArray(node.children) && node.children.length) {\n object.objects = convertChildren(node, ctx)\n }\n break\n }\n case 'Box': {\n object.width = round(width)\n object.height = round(height)\n break\n }\n case 'Button': {\n object.width = round(width)\n object.height = round(height)\n applyButtonProps(object, node)\n break\n }\n case 'Bar': {\n object.width = round(width)\n object.height = round(height)\n applyBarProps(object, node)\n break\n }\n case 'Line': {\n object.width = round(width)\n object.height = round(height)\n applyPointShape(object, node)\n applyFillStroke(object, node, { fill: type === 'polyline' })\n break\n }\n case 'Polygon': {\n object.width = round(width)\n object.height = round(height)\n if (type === 'triangle') {\n applyFillStroke(object, node)\n break\n }\n applyPointShape(object, node)\n applyFillStroke(object, node)\n break\n }\n case 'Path': {\n object.width = round(width)\n object.height = round(height)\n object.path = node.path === undefined ? '' : node.path\n applyFillStroke(object, node)\n break\n }\n default: {\n object.width = round(width)\n object.height = round(height)\n applyFillStroke(object, node)\n break\n }\n }\n\n return object\n}\n\n/**\n * Leafer 文档 → Fabric 文档。\n *\n * @param {object} leaferDocument 形如 { header, param, keyboardEvent, children }\n * @param {object} [options]\n * @param {string} [options.version] 写入根节点的 Fabric 版本号(平台文件里一般是 5.x)\n * @returns {{ document: object, warnings: string[] }}\n */\nexport function leaferToFabric(leaferDocument, options = {}) {\n const warnings = []\n const ctx = { warnings, options }\n const source = leaferDocument || {}\n const header = { ...(source.header || {}) }\n const background = header.background\n delete header.background\n if (header.backgroundImage !== undefined) {\n warnings.push('Leafer header.backgroundImage 是烘焙静态图,Fabric 没有对应字段,已省略')\n delete header.backgroundImage\n }\n\n const document = {\n header,\n param: source.param || {},\n keyboardEvent: source.keyboardEvent || [],\n objects: (source.children || []).map((node) => convertNode(node, ctx, null)).filter(Boolean)\n }\n // 平台真实文件把背景色放在根上(button.json / DCS 页面都是),这里保持一致\n if (background !== undefined) {\n document.background = background\n }\n if (options.version) {\n document.version = options.version\n }\n\n return { document, warnings }\n}"],"mappings":"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","names":["node","node","alpha","node","node","node","node","children","OVERLAY_TYPES","originFraction","convert","node","applyMeta","applyTransform"]}
|