figma-coder-mcp 0.2.2 → 0.4.0

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.
Files changed (4) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +164 -152
  3. package/dist/bin.js +4299 -154
  4. package/package.json +5 -1
package/dist/bin.js CHANGED
@@ -295,7 +295,8 @@ var require_client = __commonJS({
295
295
  async renderImages(fileKey, nodeIds, format = "svg", requestAuth, scale = 1) {
296
296
  const auth = this.resolveAuth(requestAuth);
297
297
  const ids = nodeIds.map(url_1.normalizeNodeId).join(",");
298
- const data = await this.get(`/images/${fileKey}?ids=${encodeURIComponent(ids)}&format=${format}&scale=${scale}`, auth);
298
+ const svgOpts = format === "svg" ? "&svg_outline_text=true&svg_simplify_stroke=true" : "";
299
+ const data = await this.get(`/images/${fileKey}?ids=${encodeURIComponent(ids)}&format=${format}&scale=${scale}${svgOpts}`, auth);
299
300
  if (data.err) {
300
301
  throw new errors_1.FigmaApiError(`Figma image render error: ${data.err}`, 502);
301
302
  }
@@ -361,8 +362,9 @@ var require_style_ir = __commonJS({
361
362
  "../packages/figma-core/dist/converter/style-ir.js"(exports) {
362
363
  "use strict";
363
364
  Object.defineProperty(exports, "__esModule", { value: true });
364
- exports.StyleIr = void 0;
365
+ exports.StyleIr = exports.IMAGE_FILL_TOKEN = void 0;
365
366
  var color_1 = require_color();
367
+ exports.IMAGE_FILL_TOKEN = "__FIGMA_IMAGE__";
366
368
  var ALIGN_MAIN = {
367
369
  MIN: "flex-start",
368
370
  CENTER: "center",
@@ -375,7 +377,7 @@ var require_style_ir = __commonJS({
375
377
  MAX: "flex-end",
376
378
  BASELINE: "baseline"
377
379
  };
378
- var StyleIr = class {
380
+ var StyleIr = class _StyleIr {
379
381
  /** Convert a Figma node subtree into the Style IR tree. */
380
382
  convert(root) {
381
383
  return this.walk(root, void 0);
@@ -392,10 +394,22 @@ var require_style_ir = __commonJS({
392
394
  this.applyEffects(node, css);
393
395
  }
394
396
  this.applyOpacity(node, css);
397
+ this.applyBlend(node, css);
395
398
  const isText = node.type === "TEXT";
396
399
  if (isText)
397
400
  this.applyText(node, css);
398
401
  const tag = isText ? "p" : "div";
402
+ if (asset?.kind === "vector") {
403
+ return {
404
+ id: node.id,
405
+ name: node.name,
406
+ figmaType: node.type,
407
+ tag,
408
+ css,
409
+ asset,
410
+ children: []
411
+ };
412
+ }
399
413
  const visibleChildren = (node.children ?? []).filter((c) => c.visible !== false);
400
414
  const maskChild = visibleChildren.find((c) => c.isMask);
401
415
  if (maskChild) {
@@ -405,17 +419,82 @@ var require_style_ir = __commonJS({
405
419
  this.applyRadius(maskChild, css);
406
420
  }
407
421
  const children = visibleChildren.map((c) => this.walk(c, node));
422
+ const runs = isText ? this.textRuns(node) : void 0;
408
423
  return {
409
424
  id: node.id,
410
425
  name: node.name,
411
426
  figmaType: node.type,
412
427
  tag,
413
428
  ...isText ? { text: node.characters ?? "" } : {},
429
+ ...runs ? { runs } : {},
414
430
  css,
415
431
  ...asset ? { asset } : {},
416
432
  children
417
433
  };
418
434
  }
435
+ /**
436
+ * Split a text node into styled runs when it has per-character overrides
437
+ * (a bold word, a colored span). Returns undefined for plain single-style
438
+ * text (the common case) so the renderer emits one string. `css` per run holds
439
+ * ONLY the overridden props; the <p> base style supplies the rest.
440
+ */
441
+ textRuns(node) {
442
+ const chars = node.characters ?? "";
443
+ const overrides = node.characterStyleOverrides;
444
+ const table = node.styleOverrideTable;
445
+ if (!chars || !overrides?.length || !table)
446
+ return void 0;
447
+ if (!overrides.some((id) => id && table[String(id)]))
448
+ return void 0;
449
+ const raw = [];
450
+ let curId = -1;
451
+ for (let i = 0; i < chars.length; i++) {
452
+ const id = overrides[i] ?? 0;
453
+ if (id !== curId || raw.length === 0) {
454
+ raw.push({ id, text: "" });
455
+ curId = id;
456
+ }
457
+ raw[raw.length - 1].text += chars[i];
458
+ }
459
+ if (raw.length <= 1)
460
+ return void 0;
461
+ return raw.map((r) => ({
462
+ text: r.text,
463
+ css: r.id && table[String(r.id)] ? this.overrideCss(table[String(r.id)]) : {}
464
+ }));
465
+ }
466
+ /** Map an override style entry (partial TypeStyle + optional fills) to CSS. */
467
+ overrideCss(o) {
468
+ const css = {};
469
+ if (o.fontWeight)
470
+ css["font-weight"] = String(o.fontWeight);
471
+ if (o.fontSize)
472
+ css["font-size"] = (0, color_1.px)(o.fontSize);
473
+ if (o.fontFamily)
474
+ css["font-family"] = `'${o.fontFamily}', sans-serif`;
475
+ if (o.italic)
476
+ css["font-style"] = "italic";
477
+ if (o.letterSpacing)
478
+ css["letter-spacing"] = (0, color_1.px)(o.letterSpacing);
479
+ if (o.lineHeightPx)
480
+ css["line-height"] = (0, color_1.px)(o.lineHeightPx);
481
+ else if (o.lineHeightPercentFontSize) {
482
+ css["line-height"] = String(Number((o.lineHeightPercentFontSize / 100).toFixed(3)));
483
+ }
484
+ if (o.textDecoration === "UNDERLINE")
485
+ css["text-decoration"] = "underline";
486
+ if (o.textDecoration === "STRIKETHROUGH")
487
+ css["text-decoration"] = "line-through";
488
+ if (o.textCase === "UPPER")
489
+ css["text-transform"] = "uppercase";
490
+ if (o.textCase === "LOWER")
491
+ css["text-transform"] = "lowercase";
492
+ const fills = this.visiblePaints(o.fills);
493
+ const p = fills[fills.length - 1];
494
+ if (p?.type === "SOLID" && p.color)
495
+ css.color = (0, color_1.figmaColorToCss)(p.color, p.opacity ?? 1);
496
+ return css;
497
+ }
419
498
  // ---- layout -------------------------------------------------------------
420
499
  applyLayout(node, parent, css) {
421
500
  const auto = node.layoutMode === "HORIZONTAL" || node.layoutMode === "VERTICAL";
@@ -457,8 +536,60 @@ var require_style_ir = __commonJS({
457
536
  const box = node.absoluteBoundingBox;
458
537
  if (!box)
459
538
  return;
460
- css.width = (0, color_1.px)(box.width);
461
- css.height = (0, color_1.px)(box.height);
539
+ this.applyAxisSize(node, parent, css, "H", box.width);
540
+ this.applyAxisSize(node, parent, css, "V", box.height);
541
+ if (node.minWidth != null)
542
+ css["min-width"] = (0, color_1.px)(node.minWidth);
543
+ if (node.maxWidth != null)
544
+ css["max-width"] = (0, color_1.px)(node.maxWidth);
545
+ if (node.minHeight != null)
546
+ css["min-height"] = (0, color_1.px)(node.minHeight);
547
+ if (node.maxHeight != null)
548
+ css["max-height"] = (0, color_1.px)(node.maxHeight);
549
+ }
550
+ /**
551
+ * Size one axis. Inside an auto-layout parent we honor Figma's sizing intent —
552
+ * FILL → grow (flex-1) or stretch the cross axis, HUG → let content size it,
553
+ * FIXED → px — instead of freezing every box to its pixel dimensions. Outside
554
+ * auto-layout (absolute children, root) we keep the exact px.
555
+ */
556
+ applyAxisSize(node, parent, css, axis, boxDim) {
557
+ const dim = axis === "H" ? "width" : "height";
558
+ const parentMainHorizontal = parent?.layoutMode === "HORIZONTAL";
559
+ const parentAuto = parentMainHorizontal || parent?.layoutMode === "VERTICAL";
560
+ const sizing = this.axisSizing(node, axis, parentMainHorizontal);
561
+ if (!parentAuto || !sizing) {
562
+ css[dim] = (0, color_1.px)(boxDim);
563
+ return;
564
+ }
565
+ const isMainAxis = axis === "H" === parentMainHorizontal;
566
+ if (sizing === "FILL") {
567
+ if (isMainAxis)
568
+ css.flex = "1 1 0%";
569
+ else
570
+ css["align-self"] = "stretch";
571
+ return;
572
+ }
573
+ if (sizing === "HUG") {
574
+ const hasContent = (node.children?.length ?? 0) > 0 || node.type === "TEXT";
575
+ if (!hasContent)
576
+ css[dim] = (0, color_1.px)(boxDim);
577
+ return;
578
+ }
579
+ css[dim] = (0, color_1.px)(boxDim);
580
+ }
581
+ /** Resolve a node's sizing mode on an axis, falling back from the modern
582
+ * layoutSizing* fields to the legacy layoutGrow/layoutAlign. */
583
+ axisSizing(node, axis, parentMainHorizontal) {
584
+ const explicit = axis === "H" ? node.layoutSizingHorizontal : node.layoutSizingVertical;
585
+ if (explicit)
586
+ return explicit;
587
+ const isMainAxis = axis === "H" === parentMainHorizontal;
588
+ if (isMainAxis && node.layoutGrow === 1)
589
+ return "FILL";
590
+ if (!isMainAxis && node.layoutAlign === "STRETCH")
591
+ return "FILL";
592
+ return void 0;
462
593
  }
463
594
  // ---- paints -------------------------------------------------------------
464
595
  visiblePaints(paints) {
@@ -472,22 +603,109 @@ var require_style_ir = __commonJS({
472
603
  const fills = this.visiblePaints(node.fills);
473
604
  if (!fills.length)
474
605
  return;
475
- const paint = fills[fills.length - 1];
476
- if (paint.type === "SOLID" && paint.color) {
477
- css["background-color"] = (0, color_1.figmaColorToCss)(paint.color, paint.opacity ?? 1);
478
- } else if (paint.type === "GRADIENT_LINEAR") {
479
- const grad = this.linearGradient(paint);
480
- if (grad)
481
- css["background-image"] = grad;
482
- } else if (paint.type === "IMAGE") {
606
+ if (fills.length === 1) {
607
+ const only = fills[0];
608
+ if (only.type === "SOLID" && only.color) {
609
+ css["background-color"] = (0, color_1.figmaColorToCss)(only.color, only.opacity ?? 1);
610
+ return;
611
+ }
612
+ if (only.type === "IMAGE" && asset?.kind === "image") {
613
+ css["background-image"] = `url(${exports.IMAGE_FILL_TOKEN})`;
614
+ this.applyImageSizing(only, css);
615
+ return;
616
+ }
617
+ }
618
+ const layers = [];
619
+ let hasImage = false;
620
+ for (let i = fills.length - 1; i >= 0; i--) {
621
+ const paint = fills[i];
622
+ if (paint.type === "IMAGE") {
623
+ if (asset?.kind !== "image")
624
+ continue;
625
+ layers.push(`url(${exports.IMAGE_FILL_TOKEN})`);
626
+ hasImage = true;
627
+ continue;
628
+ }
629
+ const layer = this.paintToLayer(paint);
630
+ if (layer)
631
+ layers.push(layer);
632
+ }
633
+ if (!layers.length)
634
+ return;
635
+ css["background-image"] = layers.join(", ");
636
+ if (hasImage) {
483
637
  css["background-size"] = "cover";
484
638
  css["background-position"] = "center";
485
639
  }
486
640
  }
487
- linearGradient(paint) {
641
+ /**
642
+ * Translate a Figma IMAGE paint's fit (scaleMode + crop transform) into CSS
643
+ * background sizing. Previously we always emitted cover/center, which only
644
+ * matches FILL-without-crop; FIT/TILE/STRETCH and cropped fills rendered the
645
+ * wrong region/scale.
646
+ */
647
+ applyImageSizing(paint, css) {
648
+ const pct = (n) => `${Number(n.toFixed(3))}%`;
649
+ const m = paint.imageTransform;
650
+ if (m && m.length >= 2 && m[0].length >= 3) {
651
+ const sx = m[0][0];
652
+ const sy = m[1][1];
653
+ const tx = m[0][2];
654
+ const ty = m[1][2];
655
+ if (sx > 0 && sy > 0 && sx < 1 && sy < 1) {
656
+ css["background-size"] = `${pct(100 / sx)} ${pct(100 / sy)}`;
657
+ css["background-position"] = `${pct(tx / (1 - sx) * 100)} ${pct(ty / (1 - sy) * 100)}`;
658
+ css["background-repeat"] = "no-repeat";
659
+ return;
660
+ }
661
+ }
662
+ switch (paint.scaleMode) {
663
+ case "FIT":
664
+ css["background-size"] = "contain";
665
+ css["background-position"] = "center";
666
+ css["background-repeat"] = "no-repeat";
667
+ break;
668
+ case "STRETCH":
669
+ css["background-size"] = "100% 100%";
670
+ break;
671
+ case "TILE":
672
+ css["background-repeat"] = "repeat";
673
+ break;
674
+ case "FILL":
675
+ default:
676
+ css["background-size"] = "cover";
677
+ css["background-position"] = "center";
678
+ break;
679
+ }
680
+ }
681
+ /** A single Figma paint as one CSS `background-image` layer (or null if it
682
+ * carries no renderable color, e.g. an image handled separately). */
683
+ paintToLayer(paint) {
684
+ if (paint.type === "SOLID" && paint.color) {
685
+ const c = (0, color_1.figmaColorToCss)(paint.color, paint.opacity ?? 1);
686
+ return `linear-gradient(${c}, ${c})`;
687
+ }
688
+ if (paint.type === "GRADIENT_LINEAR")
689
+ return this.linearGradient(paint);
690
+ if (paint.type === "GRADIENT_RADIAL")
691
+ return this.radialGradient(paint);
692
+ if (paint.type === "GRADIENT_ANGULAR")
693
+ return this.angularGradient(paint);
694
+ if (paint.type === "GRADIENT_DIAMOND")
695
+ return this.radialGradient(paint);
696
+ return null;
697
+ }
698
+ /** Comma-joined `color pos%` stops shared by every gradient kind. */
699
+ gradientStops(paint) {
488
700
  const stops = paint.gradientStops ?? [];
489
701
  if (stops.length < 2)
490
702
  return null;
703
+ return stops.map((s) => `${(0, color_1.figmaColorToCss)(s.color, paint.opacity ?? 1)} ${Math.round(s.position * 100)}%`).join(", ");
704
+ }
705
+ linearGradient(paint) {
706
+ const stopStr = this.gradientStops(paint);
707
+ if (!stopStr)
708
+ return null;
491
709
  let angle = 180;
492
710
  const handles = paint.gradientHandlePositions;
493
711
  if (handles && handles.length >= 2) {
@@ -495,19 +713,101 @@ var require_style_ir = __commonJS({
495
713
  const dy = handles[1].y - handles[0].y;
496
714
  angle = Math.round(Math.atan2(dy, dx) * 180 / Math.PI + 90);
497
715
  }
498
- const stopStr = stops.map((s) => `${(0, color_1.figmaColorToCss)(s.color, paint.opacity ?? 1)} ${Math.round(s.position * 100)}%`).join(", ");
499
716
  return `linear-gradient(${angle}deg, ${stopStr})`;
500
717
  }
718
+ /**
719
+ * Radial gradient. Figma's handles are normalized box coordinates: [0] is the
720
+ * center, [1] the end of one radius, [2] the end of the perpendicular radius.
721
+ * We map the center to a percentage position and each radius to a percentage
722
+ * of the box (an axis-aligned ellipse — CSS can't rotate a radial gradient, so
723
+ * a rotated Figma radial is approximated). Falls back to a centered circle.
724
+ */
725
+ radialGradient(paint) {
726
+ const stopStr = this.gradientStops(paint);
727
+ if (!stopStr)
728
+ return null;
729
+ const h = paint.gradientHandlePositions;
730
+ if (!h || h.length < 3) {
731
+ return `radial-gradient(circle at center, ${stopStr})`;
732
+ }
733
+ const pct = (n) => `${Number((n * 100).toFixed(2))}%`;
734
+ const cx = h[0].x;
735
+ const cy = h[0].y;
736
+ const rx = Math.hypot(h[1].x - cx, h[1].y - cy);
737
+ const ry = Math.hypot(h[2].x - cx, h[2].y - cy);
738
+ return `radial-gradient(ellipse ${pct(rx)} ${pct(ry)} at ${pct(cx)} ${pct(cy)}, ${stopStr})`;
739
+ }
740
+ /**
741
+ * Angular (conic) gradient. Handle [0] is the center and [0]->[1] sets the
742
+ * start angle. CSS conic accepts percentage stops, matching Figma's 0..1.
743
+ */
744
+ angularGradient(paint) {
745
+ const stopStr = this.gradientStops(paint);
746
+ if (!stopStr)
747
+ return null;
748
+ let angle = 0;
749
+ let cx = 0.5;
750
+ let cy = 0.5;
751
+ const h = paint.gradientHandlePositions;
752
+ if (h && h.length >= 2) {
753
+ cx = h[0].x;
754
+ cy = h[0].y;
755
+ angle = Math.round(Math.atan2(h[1].y - cy, h[1].x - cx) * 180 / Math.PI + 90);
756
+ }
757
+ const pct = (n) => `${Number((n * 100).toFixed(2))}%`;
758
+ return `conic-gradient(from ${angle}deg at ${pct(cx)} ${pct(cy)}, ${stopStr})`;
759
+ }
501
760
  applyStroke(node, css) {
502
761
  const strokes = this.visiblePaints(node.strokes);
503
- if (!strokes.length || !node.strokeWeight)
762
+ if (!strokes.length)
504
763
  return;
505
764
  const paint = strokes[strokes.length - 1];
506
- if (paint.type === "SOLID" && paint.color) {
507
- css.border = `${(0, color_1.px)(node.strokeWeight)} solid ${(0, color_1.figmaColorToCss)(paint.color, paint.opacity ?? 1)}`;
765
+ if (paint.type !== "SOLID" || !paint.color)
766
+ return;
767
+ const color = (0, color_1.figmaColorToCss)(paint.color, paint.opacity ?? 1);
768
+ if (node.type === "LINE") {
769
+ if (!node.strokeWeight)
770
+ return;
771
+ const box = node.absoluteBoundingBox;
772
+ const vertical = !!box && box.height > box.width;
773
+ css[vertical ? "border-left" : "border-top"] = `${(0, color_1.px)(node.strokeWeight)} solid ${color}`;
774
+ return;
775
+ }
776
+ const ind = node.individualStrokeWeights;
777
+ if (ind && (ind.top !== ind.right || ind.right !== ind.bottom || ind.bottom !== ind.left)) {
778
+ const side = (w2, name) => {
779
+ if (w2 > 0)
780
+ css[`border-${name}`] = `${(0, color_1.px)(w2)} solid ${color}`;
781
+ };
782
+ side(ind.top, "top");
783
+ side(ind.right, "right");
784
+ side(ind.bottom, "bottom");
785
+ side(ind.left, "left");
786
+ return;
787
+ }
788
+ if (!node.strokeWeight)
789
+ return;
790
+ const w = (0, color_1.px)(node.strokeWeight);
791
+ switch (node.strokeAlign) {
792
+ case "OUTSIDE":
793
+ css.outline = `${w} solid ${color}`;
794
+ css["outline-offset"] = "0px";
795
+ break;
796
+ case "CENTER":
797
+ css.outline = `${w} solid ${color}`;
798
+ css["outline-offset"] = `${(0, color_1.px)(-(node.strokeWeight / 2))}`;
799
+ break;
800
+ case "INSIDE":
801
+ default:
802
+ css.border = `${w} solid ${color}`;
803
+ break;
508
804
  }
509
805
  }
510
806
  applyRadius(node, css) {
807
+ if (node.type === "ELLIPSE") {
808
+ css["border-radius"] = "50%";
809
+ return;
810
+ }
511
811
  if (node.rectangleCornerRadii) {
512
812
  const [tl, tr, br, bl] = node.rectangleCornerRadii;
513
813
  if (tl || tr || br || bl) {
@@ -561,6 +861,9 @@ var require_style_ir = __commonJS({
561
861
  css["font-weight"] = String(s.fontWeight);
562
862
  if (s.lineHeightPx)
563
863
  css["line-height"] = (0, color_1.px)(s.lineHeightPx);
864
+ else if (s.lineHeightPercentFontSize) {
865
+ css["line-height"] = String(Number((s.lineHeightPercentFontSize / 100).toFixed(3)));
866
+ }
564
867
  if (s.letterSpacing)
565
868
  css["letter-spacing"] = (0, color_1.px)(s.letterSpacing);
566
869
  if (s.italic)
@@ -581,25 +884,451 @@ var require_style_ir = __commonJS({
581
884
  css["white-space"] = "pre";
582
885
  else if (s.textAutoResize === "HEIGHT")
583
886
  css["white-space"] = "pre-wrap";
887
+ if (s.textAlignVertical === "CENTER" || s.textAlignVertical === "BOTTOM") {
888
+ css.display = "flex";
889
+ css["flex-direction"] = "column";
890
+ css["justify-content"] = s.textAlignVertical === "CENTER" ? "center" : "flex-end";
891
+ }
584
892
  }
585
893
  const fills = this.visiblePaints(node.fills);
586
894
  const paint = fills[fills.length - 1];
587
895
  if (paint?.type === "SOLID" && paint.color) {
588
896
  css.color = (0, color_1.figmaColorToCss)(paint.color, paint.opacity ?? 1);
897
+ } else if (paint) {
898
+ const layer = this.paintToLayer(paint);
899
+ if (layer) {
900
+ css["background-image"] = layer;
901
+ css["-webkit-background-clip"] = "text";
902
+ css["background-clip"] = "text";
903
+ css.color = "transparent";
904
+ }
589
905
  }
590
906
  }
907
+ /** Map a Figma layer blend mode to CSS `mix-blend-mode` (no-op for NORMAL). */
908
+ applyBlend(node, css) {
909
+ const bm = node.blendMode;
910
+ if (!bm || bm === "NORMAL" || bm === "PASS_THROUGH")
911
+ return;
912
+ const css_ = bm.toLowerCase().replace(/_/g, "-");
913
+ const allowed = /* @__PURE__ */ new Set([
914
+ "multiply",
915
+ "screen",
916
+ "overlay",
917
+ "darken",
918
+ "lighten",
919
+ "color-dodge",
920
+ "color-burn",
921
+ "hard-light",
922
+ "soft-light",
923
+ "difference",
924
+ "exclusion",
925
+ "hue",
926
+ "saturation",
927
+ "color",
928
+ "luminosity"
929
+ ]);
930
+ if (allowed.has(css_))
931
+ css["mix-blend-mode"] = css_;
932
+ }
591
933
  // ---- assets -------------------------------------------------------------
592
934
  detectAsset(node) {
935
+ const imagePaint = [...this.visiblePaints(node.fills)].reverse().find((p) => p.type === "IMAGE" && p.imageRef);
593
936
  const vectorTypes = ["VECTOR", "STAR", "LINE", "ELLIPSE", "REGULAR_POLYGON", "BOOLEAN_OPERATION"];
594
- if (vectorTypes.includes(node.type))
937
+ if (vectorTypes.includes(node.type)) {
938
+ if (node.type === "ELLIPSE" && imagePaint) {
939
+ return { kind: "image", imageRef: imagePaint.imageRef };
940
+ }
941
+ if (this.isCssRenderableVector(node))
942
+ return void 0;
595
943
  return { kind: "vector" };
596
- const imagePaint = [...this.visiblePaints(node.fills)].reverse().find((p) => p.type === "IMAGE" && p.imageRef);
944
+ }
597
945
  if (imagePaint)
598
946
  return { kind: "image", imageRef: imagePaint.imageRef };
947
+ if (this.isVectorOnlyContainer(node))
948
+ return { kind: "vector" };
599
949
  return void 0;
600
950
  }
951
+ /**
952
+ * Whether a vector-typed node is faithfully renderable with CSS, so it can
953
+ * skip server-side rasterization.
954
+ *
955
+ * - ELLIPSE / LINE encode their geometry in the node type, so CSS always
956
+ * reproduces them (circle/oval via border-radius:50%, line via a border).
957
+ * - VECTOR / BOOLEAN_OPERATION have arbitrary geometry the IR can't see, so
958
+ * they only qualify with a positive "rounded rectangle" signal (corner
959
+ * radius or a background blur — i.e. a panel) plus at least one paint we can
960
+ * render (a solid/gradient fill or a stroke-only outline).
961
+ *
962
+ * A rotated node never qualifies: the IR emits no transform, so the baked
963
+ * raster (which already carries the rotation) is the faithful fallback.
964
+ */
965
+ isCssRenderableVector(node) {
966
+ if (this.hasRotation(node))
967
+ return false;
968
+ const fills = this.visiblePaints(node.fills);
969
+ if (fills.some((p) => p.type === "IMAGE"))
970
+ return false;
971
+ if (node.type === "ELLIPSE" || node.type === "LINE")
972
+ return true;
973
+ if (node.type === "VECTOR" || node.type === "BOOLEAN_OPERATION") {
974
+ const hasPaintableFill = fills.some((p) => p.type === "SOLID" || p.type === "GRADIENT_LINEAR");
975
+ if (!hasPaintableFill)
976
+ return false;
977
+ const hasRadius = (node.cornerRadius ?? 0) > 0 || (node.rectangleCornerRadii?.some((r) => r > 0) ?? false);
978
+ const hasBackgroundBlur = (node.effects ?? []).some((e) => e.type === "BACKGROUND_BLUR" && e.visible !== false);
979
+ return hasRadius || hasBackgroundBlur;
980
+ }
981
+ return false;
982
+ }
983
+ /**
984
+ * Whether a container should collapse into a single rendered SVG: its entire
985
+ * visible subtree is vector paths (no text, no image fills, no plain boxes)
986
+ * AND at least one of those paths actually needs rasterizing (a subtree of
987
+ * only CSS-renderable shapes is cheaper kept as elements).
988
+ */
989
+ isVectorOnlyContainer(node) {
990
+ if (!_StyleIr.CONTAINER_TYPES.includes(node.type))
991
+ return false;
992
+ if (!node.absoluteBoundingBox)
993
+ return false;
994
+ const isAutoLayout = node.layoutMode === "HORIZONTAL" || node.layoutMode === "VERTICAL";
995
+ const childCount = (node.children ?? []).filter((c) => c.visible !== false).length;
996
+ if (isAutoLayout && childCount < _StyleIr.SVG_COLLAPSE_AUTOLAYOUT_THRESHOLD)
997
+ return false;
998
+ const scan = this.collapseScan(node);
999
+ return scan.pure && scan.hasRaster;
1000
+ }
1001
+ /**
1002
+ * Classify a subtree for the collapse decision. `pure` is true only when every
1003
+ * visible node is a vector shape; `hasRaster` is true when at least one of
1004
+ * them would hit /v1/images (i.e. isn't reproducible as a CSS box).
1005
+ */
1006
+ collapseScan(node) {
1007
+ const NOT_PURE = { pure: false, hasRaster: false };
1008
+ if (node.visible === false)
1009
+ return { pure: true, hasRaster: false };
1010
+ if (node.type === "TEXT")
1011
+ return NOT_PURE;
1012
+ const hasImageFill = this.visiblePaints(node.fills).some((p) => p.type === "IMAGE" && p.imageRef);
1013
+ if (hasImageFill)
1014
+ return NOT_PURE;
1015
+ const vectorTypes = ["VECTOR", "STAR", "LINE", "ELLIPSE", "REGULAR_POLYGON", "BOOLEAN_OPERATION"];
1016
+ if (vectorTypes.includes(node.type)) {
1017
+ return { pure: true, hasRaster: !this.isCssRenderableVector(node) };
1018
+ }
1019
+ if (_StyleIr.CONTAINER_TYPES.includes(node.type)) {
1020
+ const kids = (node.children ?? []).filter((c) => c.visible !== false);
1021
+ if (!kids.length)
1022
+ return NOT_PURE;
1023
+ let hasRaster = false;
1024
+ for (const kid of kids) {
1025
+ const r = this.collapseScan(kid);
1026
+ if (!r.pure)
1027
+ return NOT_PURE;
1028
+ hasRaster = hasRaster || r.hasRaster;
1029
+ }
1030
+ return { pure: true, hasRaster };
1031
+ }
1032
+ return NOT_PURE;
1033
+ }
1034
+ /** True when the node is rotated beyond a tiny floating-point tolerance
1035
+ * (~0.5°). Figma reports rotation in radians; axis-aligned nodes carry
1036
+ * values like 8.7e-8 that must read as "not rotated". */
1037
+ hasRotation(node) {
1038
+ return typeof node.rotation === "number" && Math.abs(node.rotation) > 0.01;
1039
+ }
601
1040
  };
602
1041
  exports.StyleIr = StyleIr;
1042
+ StyleIr.CONTAINER_TYPES = ["GROUP", "FRAME", "INSTANCE", "COMPONENT"];
1043
+ StyleIr.SVG_COLLAPSE_AUTOLAYOUT_THRESHOLD = 10;
1044
+ }
1045
+ });
1046
+
1047
+ // ../packages/figma-core/dist/converter/tailwind-colors.js
1048
+ var require_tailwind_colors = __commonJS({
1049
+ "../packages/figma-core/dist/converter/tailwind-colors.js"(exports) {
1050
+ "use strict";
1051
+ Object.defineProperty(exports, "__esModule", { value: true });
1052
+ exports.nearestTailwindColor = nearestTailwindColor;
1053
+ var PALETTE = {
1054
+ black: "#000000",
1055
+ white: "#ffffff",
1056
+ "slate-50": "#f8fafc",
1057
+ "slate-100": "#f1f5f9",
1058
+ "slate-200": "#e2e8f0",
1059
+ "slate-300": "#cbd5e1",
1060
+ "slate-400": "#94a3b8",
1061
+ "slate-500": "#64748b",
1062
+ "slate-600": "#475569",
1063
+ "slate-700": "#334155",
1064
+ "slate-800": "#1e293b",
1065
+ "slate-900": "#0f172a",
1066
+ "slate-950": "#020617",
1067
+ "gray-50": "#f9fafb",
1068
+ "gray-100": "#f3f4f6",
1069
+ "gray-200": "#e5e7eb",
1070
+ "gray-300": "#d1d5db",
1071
+ "gray-400": "#9ca3af",
1072
+ "gray-500": "#6b7280",
1073
+ "gray-600": "#4b5563",
1074
+ "gray-700": "#374151",
1075
+ "gray-800": "#1f2937",
1076
+ "gray-900": "#111827",
1077
+ "gray-950": "#030712",
1078
+ "zinc-50": "#fafafa",
1079
+ "zinc-100": "#f4f4f5",
1080
+ "zinc-200": "#e4e4e7",
1081
+ "zinc-300": "#d4d4d8",
1082
+ "zinc-400": "#a1a1aa",
1083
+ "zinc-500": "#71717a",
1084
+ "zinc-600": "#52525b",
1085
+ "zinc-700": "#3f3f46",
1086
+ "zinc-800": "#27272a",
1087
+ "zinc-900": "#18181b",
1088
+ "zinc-950": "#09090b",
1089
+ "neutral-50": "#fafafa",
1090
+ "neutral-100": "#f5f5f5",
1091
+ "neutral-200": "#e5e5e5",
1092
+ "neutral-300": "#d4d4d4",
1093
+ "neutral-400": "#a3a3a3",
1094
+ "neutral-500": "#737373",
1095
+ "neutral-600": "#525252",
1096
+ "neutral-700": "#404040",
1097
+ "neutral-800": "#262626",
1098
+ "neutral-900": "#171717",
1099
+ "neutral-950": "#0a0a0a",
1100
+ "stone-50": "#fafaf9",
1101
+ "stone-100": "#f5f5f4",
1102
+ "stone-200": "#e7e5e4",
1103
+ "stone-300": "#d6d3d1",
1104
+ "stone-400": "#a8a29e",
1105
+ "stone-500": "#78716c",
1106
+ "stone-600": "#57534e",
1107
+ "stone-700": "#44403c",
1108
+ "stone-800": "#292524",
1109
+ "stone-900": "#1c1917",
1110
+ "stone-950": "#0c0a09",
1111
+ "red-50": "#fef2f2",
1112
+ "red-100": "#fee2e2",
1113
+ "red-200": "#fecaca",
1114
+ "red-300": "#fca5a5",
1115
+ "red-400": "#f87171",
1116
+ "red-500": "#ef4444",
1117
+ "red-600": "#dc2626",
1118
+ "red-700": "#b91c1c",
1119
+ "red-800": "#991b1b",
1120
+ "red-900": "#7f1d1d",
1121
+ "red-950": "#450a0a",
1122
+ "orange-50": "#fff7ed",
1123
+ "orange-100": "#ffedd5",
1124
+ "orange-200": "#fed7aa",
1125
+ "orange-300": "#fdba74",
1126
+ "orange-400": "#fb923c",
1127
+ "orange-500": "#f97316",
1128
+ "orange-600": "#ea580c",
1129
+ "orange-700": "#c2410c",
1130
+ "orange-800": "#9a3412",
1131
+ "orange-900": "#7c2d12",
1132
+ "orange-950": "#431407",
1133
+ "amber-50": "#fffbeb",
1134
+ "amber-100": "#fef3c7",
1135
+ "amber-200": "#fde68a",
1136
+ "amber-300": "#fcd34d",
1137
+ "amber-400": "#fbbf24",
1138
+ "amber-500": "#f59e0b",
1139
+ "amber-600": "#d97706",
1140
+ "amber-700": "#b45309",
1141
+ "amber-800": "#92400e",
1142
+ "amber-900": "#78350f",
1143
+ "amber-950": "#451a03",
1144
+ "yellow-50": "#fefce8",
1145
+ "yellow-100": "#fef9c3",
1146
+ "yellow-200": "#fef08a",
1147
+ "yellow-300": "#fde047",
1148
+ "yellow-400": "#facc15",
1149
+ "yellow-500": "#eab308",
1150
+ "yellow-600": "#ca8a04",
1151
+ "yellow-700": "#a16207",
1152
+ "yellow-800": "#854d0e",
1153
+ "yellow-900": "#713f12",
1154
+ "yellow-950": "#422006",
1155
+ "lime-50": "#f7fee7",
1156
+ "lime-100": "#ecfccb",
1157
+ "lime-200": "#d9f99d",
1158
+ "lime-300": "#bef264",
1159
+ "lime-400": "#a3e635",
1160
+ "lime-500": "#84cc16",
1161
+ "lime-600": "#65a30d",
1162
+ "lime-700": "#4d7c0f",
1163
+ "lime-800": "#3f6212",
1164
+ "lime-900": "#365314",
1165
+ "lime-950": "#1a2e05",
1166
+ "green-50": "#f0fdf4",
1167
+ "green-100": "#dcfce7",
1168
+ "green-200": "#bbf7d0",
1169
+ "green-300": "#86efac",
1170
+ "green-400": "#4ade80",
1171
+ "green-500": "#22c55e",
1172
+ "green-600": "#16a34a",
1173
+ "green-700": "#15803d",
1174
+ "green-800": "#166534",
1175
+ "green-900": "#14532d",
1176
+ "green-950": "#052e16",
1177
+ "emerald-50": "#ecfdf5",
1178
+ "emerald-100": "#d1fae5",
1179
+ "emerald-200": "#a7f3d0",
1180
+ "emerald-300": "#6ee7b7",
1181
+ "emerald-400": "#34d399",
1182
+ "emerald-500": "#10b981",
1183
+ "emerald-600": "#059669",
1184
+ "emerald-700": "#047857",
1185
+ "emerald-800": "#065f46",
1186
+ "emerald-900": "#064e3b",
1187
+ "emerald-950": "#022c22",
1188
+ "teal-50": "#f0fdfa",
1189
+ "teal-100": "#ccfbf1",
1190
+ "teal-200": "#99f6e4",
1191
+ "teal-300": "#5eead4",
1192
+ "teal-400": "#2dd4bf",
1193
+ "teal-500": "#14b8a6",
1194
+ "teal-600": "#0d9488",
1195
+ "teal-700": "#0f766e",
1196
+ "teal-800": "#115e59",
1197
+ "teal-900": "#134e4a",
1198
+ "teal-950": "#042f2e",
1199
+ "cyan-50": "#ecfeff",
1200
+ "cyan-100": "#cffafe",
1201
+ "cyan-200": "#a5f3fc",
1202
+ "cyan-300": "#67e8f9",
1203
+ "cyan-400": "#22d3ee",
1204
+ "cyan-500": "#06b6d4",
1205
+ "cyan-600": "#0891b2",
1206
+ "cyan-700": "#0e7490",
1207
+ "cyan-800": "#155e75",
1208
+ "cyan-900": "#164e63",
1209
+ "cyan-950": "#083344",
1210
+ "sky-50": "#f0f9ff",
1211
+ "sky-100": "#e0f2fe",
1212
+ "sky-200": "#bae6fd",
1213
+ "sky-300": "#7dd3fc",
1214
+ "sky-400": "#38bdf8",
1215
+ "sky-500": "#0ea5e9",
1216
+ "sky-600": "#0284c7",
1217
+ "sky-700": "#0369a1",
1218
+ "sky-800": "#075985",
1219
+ "sky-900": "#0c4a6e",
1220
+ "sky-950": "#082f49",
1221
+ "blue-50": "#eff6ff",
1222
+ "blue-100": "#dbeafe",
1223
+ "blue-200": "#bfdbfe",
1224
+ "blue-300": "#93c5fd",
1225
+ "blue-400": "#60a5fa",
1226
+ "blue-500": "#3b82f6",
1227
+ "blue-600": "#2563eb",
1228
+ "blue-700": "#1d4ed8",
1229
+ "blue-800": "#1e40af",
1230
+ "blue-900": "#1e3a8a",
1231
+ "blue-950": "#172554",
1232
+ "indigo-50": "#eef2ff",
1233
+ "indigo-100": "#e0e7ff",
1234
+ "indigo-200": "#c7d2fe",
1235
+ "indigo-300": "#a5b4fc",
1236
+ "indigo-400": "#818cf8",
1237
+ "indigo-500": "#6366f1",
1238
+ "indigo-600": "#4f46e5",
1239
+ "indigo-700": "#4338ca",
1240
+ "indigo-800": "#3730a3",
1241
+ "indigo-900": "#312e81",
1242
+ "indigo-950": "#1e1b4b",
1243
+ "violet-50": "#f5f3ff",
1244
+ "violet-100": "#ede9fe",
1245
+ "violet-200": "#ddd6fe",
1246
+ "violet-300": "#c4b5fd",
1247
+ "violet-400": "#a78bfa",
1248
+ "violet-500": "#8b5cf6",
1249
+ "violet-600": "#7c3aed",
1250
+ "violet-700": "#6d28d9",
1251
+ "violet-800": "#5b21b6",
1252
+ "violet-900": "#4c1d95",
1253
+ "violet-950": "#2e1065",
1254
+ "purple-50": "#faf5ff",
1255
+ "purple-100": "#f3e8ff",
1256
+ "purple-200": "#e9d5ff",
1257
+ "purple-300": "#d8b4fe",
1258
+ "purple-400": "#c084fc",
1259
+ "purple-500": "#a855f7",
1260
+ "purple-600": "#9333ea",
1261
+ "purple-700": "#7e22ce",
1262
+ "purple-800": "#6b21a8",
1263
+ "purple-900": "#581c87",
1264
+ "purple-950": "#3b0764",
1265
+ "fuchsia-50": "#fdf4ff",
1266
+ "fuchsia-100": "#fae8ff",
1267
+ "fuchsia-200": "#f5d0fe",
1268
+ "fuchsia-300": "#f0abfc",
1269
+ "fuchsia-400": "#e879f9",
1270
+ "fuchsia-500": "#d946ef",
1271
+ "fuchsia-600": "#c026d3",
1272
+ "fuchsia-700": "#a21caf",
1273
+ "fuchsia-800": "#86198f",
1274
+ "fuchsia-900": "#701a75",
1275
+ "fuchsia-950": "#4a044e",
1276
+ "pink-50": "#fdf2f8",
1277
+ "pink-100": "#fce7f3",
1278
+ "pink-200": "#fbcfe8",
1279
+ "pink-300": "#f9a8d4",
1280
+ "pink-400": "#f472b6",
1281
+ "pink-500": "#ec4899",
1282
+ "pink-600": "#db2777",
1283
+ "pink-700": "#be185d",
1284
+ "pink-800": "#9d174d",
1285
+ "pink-900": "#831843",
1286
+ "pink-950": "#500724",
1287
+ "rose-50": "#fff1f2",
1288
+ "rose-100": "#ffe4e6",
1289
+ "rose-200": "#fecdd3",
1290
+ "rose-300": "#fda4af",
1291
+ "rose-400": "#fb7185",
1292
+ "rose-500": "#f43f5e",
1293
+ "rose-600": "#e11d48",
1294
+ "rose-700": "#be123c",
1295
+ "rose-800": "#9f1239",
1296
+ "rose-900": "#881337",
1297
+ "rose-950": "#4c0519"
1298
+ };
1299
+ var RGB = Object.entries(PALETTE).map(([name, hex]) => ({ name, r: parseInt(hex.slice(1, 3), 16), g: parseInt(hex.slice(3, 5), 16), b: parseInt(hex.slice(5, 7), 16) }));
1300
+ function parseOpaqueRgb(value) {
1301
+ const v = value.trim().toLowerCase();
1302
+ let m = /^#([0-9a-f]{6})$/.exec(v);
1303
+ if (m)
1304
+ return { r: parseInt(m[1].slice(0, 2), 16), g: parseInt(m[1].slice(2, 4), 16), b: parseInt(m[1].slice(4, 6), 16) };
1305
+ m = /^#([0-9a-f]{3})$/.exec(v);
1306
+ if (m)
1307
+ return { r: parseInt(m[1][0] + m[1][0], 16), g: parseInt(m[1][1] + m[1][1], 16), b: parseInt(m[1][2] + m[1][2], 16) };
1308
+ m = /^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?\)$/.exec(v);
1309
+ if (m) {
1310
+ const a = m[4] === void 0 ? 1 : parseFloat(m[4]);
1311
+ if (a < 1)
1312
+ return null;
1313
+ return { r: +m[1], g: +m[2], b: +m[3] };
1314
+ }
1315
+ return null;
1316
+ }
1317
+ function nearestTailwindColor(value) {
1318
+ const c = parseOpaqueRgb(value);
1319
+ if (!c)
1320
+ return null;
1321
+ let best = null;
1322
+ let bestD = Infinity;
1323
+ for (const p of RGB) {
1324
+ const d = Math.max(Math.abs(p.r - c.r), Math.abs(p.g - c.g), Math.abs(p.b - c.b));
1325
+ if (d < bestD) {
1326
+ bestD = d;
1327
+ best = p.name;
1328
+ }
1329
+ }
1330
+ return bestD <= 2 ? best : null;
1331
+ }
603
1332
  }
604
1333
  });
605
1334
 
@@ -609,9 +1338,115 @@ var require_tailwind_mapper = __commonJS({
609
1338
  "use strict";
610
1339
  Object.defineProperty(exports, "__esModule", { value: true });
611
1340
  exports.cssToTailwind = cssToTailwind;
1341
+ var tailwind_colors_1 = require_tailwind_colors();
612
1342
  function arb(value) {
613
1343
  return value.replace(/\s+/g, "_");
614
1344
  }
1345
+ var SPACING = [
1346
+ ["0", 0],
1347
+ ["px", 1],
1348
+ ["0.5", 2],
1349
+ ["1", 4],
1350
+ ["1.5", 6],
1351
+ ["2", 8],
1352
+ ["2.5", 10],
1353
+ ["3", 12],
1354
+ ["3.5", 14],
1355
+ ["4", 16],
1356
+ ["5", 20],
1357
+ ["6", 24],
1358
+ ["7", 28],
1359
+ ["8", 32],
1360
+ ["9", 36],
1361
+ ["10", 40],
1362
+ ["11", 44],
1363
+ ["12", 48],
1364
+ ["14", 56],
1365
+ ["16", 64],
1366
+ ["20", 80],
1367
+ ["24", 96],
1368
+ ["28", 112],
1369
+ ["32", 128],
1370
+ ["36", 144],
1371
+ ["40", 160],
1372
+ ["44", 176],
1373
+ ["48", 192],
1374
+ ["52", 208],
1375
+ ["56", 224],
1376
+ ["60", 240],
1377
+ ["64", 256],
1378
+ ["72", 288],
1379
+ ["80", 320],
1380
+ ["96", 384]
1381
+ ];
1382
+ var RADIUS = [
1383
+ ["-none", 0],
1384
+ ["-sm", 2],
1385
+ ["", 4],
1386
+ ["-md", 6],
1387
+ ["-lg", 8],
1388
+ ["-xl", 12],
1389
+ ["-2xl", 16],
1390
+ ["-3xl", 24],
1391
+ ["-full", 9999]
1392
+ ];
1393
+ var FONT_SIZE = [
1394
+ ["xs", 12],
1395
+ ["sm", 14],
1396
+ ["base", 16],
1397
+ ["lg", 18],
1398
+ ["xl", 20],
1399
+ ["2xl", 24],
1400
+ ["3xl", 30],
1401
+ ["4xl", 36],
1402
+ ["5xl", 48],
1403
+ ["6xl", 60],
1404
+ ["7xl", 72],
1405
+ ["8xl", 96],
1406
+ ["9xl", 128]
1407
+ ];
1408
+ var FONT_WEIGHT = {
1409
+ "100": "thin",
1410
+ "200": "extralight",
1411
+ "300": "light",
1412
+ "400": "normal",
1413
+ "500": "medium",
1414
+ "600": "semibold",
1415
+ "700": "bold",
1416
+ "800": "extrabold",
1417
+ "900": "black"
1418
+ };
1419
+ function pxNum(value) {
1420
+ const m = /^(-?\d*\.?\d+)px$/.exec(value.trim());
1421
+ return m ? parseFloat(m[1]) : null;
1422
+ }
1423
+ function nearest(n, scale) {
1424
+ let best = null;
1425
+ let bestPx = 0;
1426
+ let bestD = Infinity;
1427
+ for (const [tok, px] of scale) {
1428
+ const d = Math.abs(px - n);
1429
+ if (d < bestD) {
1430
+ bestD = d;
1431
+ best = tok;
1432
+ bestPx = px;
1433
+ }
1434
+ }
1435
+ if (best === null)
1436
+ return null;
1437
+ return bestD <= 0.5 ? best : null;
1438
+ }
1439
+ function spacingClass(prefix, value, round) {
1440
+ if (round) {
1441
+ const n = pxNum(value);
1442
+ if (n !== null && n >= 0) {
1443
+ const tok = nearest(n, SPACING);
1444
+ if (tok !== null)
1445
+ return `${prefix}-${tok}`;
1446
+ }
1447
+ }
1448
+ return `${prefix}-[${arb(value)}]`;
1449
+ }
615
1450
  var JUSTIFY = {
616
1451
  "flex-start": "justify-start",
617
1452
  center: "justify-center",
@@ -630,7 +1465,8 @@ var require_tailwind_mapper = __commonJS({
630
1465
  right: "text-right",
631
1466
  justify: "text-justify"
632
1467
  };
633
- function cssToTailwind(css) {
1468
+ function cssToTailwind(css, opts = {}) {
1469
+ const round = opts.round ?? false;
634
1470
  const classes = [];
635
1471
  const leftover = {};
636
1472
  const push = (c) => {
@@ -663,16 +1499,16 @@ var require_tailwind_mapper = __commonJS({
663
1499
  ITEMS[value] ? push(ITEMS[value]) : leftover[prop] = value;
664
1500
  break;
665
1501
  case "gap":
666
- push(`gap-[${arb(value)}]`);
1502
+ push(spacingClass("gap", value, round));
667
1503
  break;
668
1504
  case "padding":
669
- applyPadding(value, push, leftover);
1505
+ applyPadding(value, push, leftover, round);
670
1506
  break;
671
1507
  case "width":
672
- push(`w-[${arb(value)}]`);
1508
+ push(spacingClass("w", value, round));
673
1509
  break;
674
1510
  case "height":
675
- push(`h-[${arb(value)}]`);
1511
+ push(spacingClass("h", value, round));
676
1512
  break;
677
1513
  case "position":
678
1514
  if (value === "absolute")
@@ -683,10 +1519,10 @@ var require_tailwind_mapper = __commonJS({
683
1519
  leftover[prop] = value;
684
1520
  break;
685
1521
  case "left":
686
- push(`left-[${arb(value)}]`);
1522
+ push(spacingClass("left", value, round));
687
1523
  break;
688
1524
  case "top":
689
- push(`top-[${arb(value)}]`);
1525
+ push(spacingClass("top", value, round));
690
1526
  break;
691
1527
  case "overflow":
692
1528
  if (value === "hidden")
@@ -694,9 +1530,11 @@ var require_tailwind_mapper = __commonJS({
694
1530
  else
695
1531
  leftover[prop] = value;
696
1532
  break;
697
- case "background-color":
698
- push(`bg-[${arb(value)}]`);
1533
+ case "background-color": {
1534
+ const c = round ? (0, tailwind_colors_1.nearestTailwindColor)(value) : null;
1535
+ push(c ? `bg-${c}` : `bg-[${arb(value)}]`);
699
1536
  break;
1537
+ }
700
1538
  case "background-image":
701
1539
  push(`bg-[${arb(value)}]`);
702
1540
  break;
@@ -710,10 +1548,17 @@ var require_tailwind_mapper = __commonJS({
710
1548
  leftover[prop] = value;
711
1549
  break;
712
1550
  case "border":
713
- applyBorder(value, push, leftover);
1551
+ applyBorder(value, push, leftover, round);
714
1552
  break;
715
1553
  case "border-radius":
716
- value.includes(" ") ? leftover[prop] = value : push(`rounded-[${arb(value)}]`);
1554
+ if (value.includes(" ")) {
1555
+ leftover[prop] = value;
1556
+ } else if (round && value === "50%") {
1557
+ push("rounded-full");
1558
+ } else {
1559
+ const tok = round ? snapRadius(value) : null;
1560
+ push(tok !== null ? `rounded${tok}` : `rounded-[${arb(value)}]`);
1561
+ }
717
1562
  break;
718
1563
  case "box-shadow":
719
1564
  push(`shadow-[${arb(value)}]`);
@@ -728,14 +1573,18 @@ var require_tailwind_mapper = __commonJS({
728
1573
  applyBlur(value, "backdrop-blur", push, leftover, prop);
729
1574
  break;
730
1575
  // text
731
- case "color":
732
- push(`text-[${arb(value)}]`);
1576
+ case "color": {
1577
+ const c = round ? (0, tailwind_colors_1.nearestTailwindColor)(value) : null;
1578
+ push(c ? `text-${c}` : `text-[${arb(value)}]`);
733
1579
  break;
734
- case "font-size":
735
- push(`text-[${arb(value)}]`);
1580
+ }
1581
+ case "font-size": {
1582
+ const tok = round ? nearest(pxNum(value) ?? -1, FONT_SIZE) : null;
1583
+ push(tok ? `text-${tok}` : `text-[${arb(value)}]`);
736
1584
  break;
1585
+ }
737
1586
  case "font-weight":
738
- push(`font-[${arb(value)}]`);
1587
+ push(round && FONT_WEIGHT[value] ? `font-${FONT_WEIGHT[value]}` : `font-[${arb(value)}]`);
739
1588
  break;
740
1589
  case "line-height":
741
1590
  push(`leading-[${arb(value)}]`);
@@ -768,26 +1617,42 @@ var require_tailwind_mapper = __commonJS({
768
1617
  }
769
1618
  return { classes, leftover };
770
1619
  }
771
- function applyPadding(value, push, leftover) {
1620
+ function snapRadius(value) {
1621
+ const n = pxNum(value);
1622
+ if (n === null || n < 0)
1623
+ return null;
1624
+ return nearest(n, RADIUS);
1625
+ }
1626
+ function applyPadding(value, push, leftover, round) {
772
1627
  const parts = value.split(/\s+/);
773
1628
  if (parts.length === 4) {
774
1629
  const [t, r, b, l] = parts;
775
- push(`pt-[${arb(t)}]`);
776
- push(`pr-[${arb(r)}]`);
777
- push(`pb-[${arb(b)}]`);
778
- push(`pl-[${arb(l)}]`);
1630
+ if (round && t === r && r === b && b === l) {
1631
+ push(spacingClass("p", t, round));
1632
+ } else if (round && t === b && l === r) {
1633
+ push(spacingClass("py", t, round));
1634
+ push(spacingClass("px", r, round));
1635
+ } else {
1636
+ push(spacingClass("pt", t, round));
1637
+ push(spacingClass("pr", r, round));
1638
+ push(spacingClass("pb", b, round));
1639
+ push(spacingClass("pl", l, round));
1640
+ }
779
1641
  } else if (parts.length === 1) {
780
- push(`p-[${arb(parts[0])}]`);
1642
+ push(spacingClass("p", parts[0], round));
781
1643
  } else {
782
1644
  leftover.padding = value;
783
1645
  }
784
1646
  }
785
- function applyBorder(value, push, leftover) {
1647
+ var BORDER_WIDTH = { "0px": "border-0", "1px": "border", "2px": "border-2", "4px": "border-4", "8px": "border-8" };
1648
+ function applyBorder(value, push, leftover, round) {
786
1649
  const m = value.match(/^(\S+)\s+solid\s+(.+)$/);
787
1650
  if (m) {
788
- push(`border-[${arb(m[1])}]`);
1651
+ const widthTok = round ? BORDER_WIDTH[m[1]] : void 0;
1652
+ push(widthTok ?? `border-[${arb(m[1])}]`);
789
1653
  push("border-solid");
790
- push(`border-[${arb(m[2])}]`);
1654
+ const c = round ? (0, tailwind_colors_1.nearestTailwindColor)(m[2]) : null;
1655
+ push(c ? `border-${c}` : `border-[${arb(m[2])}]`);
791
1656
  } else {
792
1657
  leftover.border = value;
793
1658
  }
@@ -808,6 +1673,7 @@ var require_html_renderer = __commonJS({
808
1673
  "use strict";
809
1674
  Object.defineProperty(exports, "__esModule", { value: true });
810
1675
  exports.HtmlRenderer = void 0;
1676
+ var style_ir_1 = require_style_ir();
811
1677
  var tailwind_mapper_1 = require_tailwind_mapper();
812
1678
  function escapeHtml(s) {
813
1679
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
@@ -815,14 +1681,19 @@ var require_html_renderer = __commonJS({
815
1681
  function styleString(css) {
816
1682
  return Object.entries(css).map(([k, v]) => `${k}: ${v}`).join("; ");
817
1683
  }
1684
+ function svgPlaceholder(markup) {
1685
+ return `data:image/svg+xml,${encodeURIComponent(markup)}`;
1686
+ }
1687
+ var IMAGE_PLACEHOLDER = svgPlaceholder("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid slice'><rect width='100' height='100' fill='#e5e7eb'/><circle cx='35' cy='34' r='9' fill='#c4cad3'/><path d='M16 78l22-26 15 15 16-16 17 27z' fill='#c4cad3'/></svg>");
1688
+ var VECTOR_PLACEHOLDER = svgPlaceholder("<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' preserveAspectRatio='xMidYMid meet'><rect width='24' height='24' rx='4' fill='#eef0f3'/><path d='M7 14l3.5-4 2.5 3 2-2.5L18 14z' fill='#b9c0cb'/><circle cx='9' cy='8.5' r='1.6' fill='#b9c0cb'/></svg>");
818
1689
  var HtmlRenderer = class _HtmlRenderer {
819
1690
  /** Render the Style IR tree into an HTML fragment string. */
820
1691
  renderFragment(node, opts = {}) {
821
- return this.render(node, opts.mode ?? "tailwind", 0);
1692
+ return this.render(node, opts.mode ?? "tailwind", 0, opts.round ?? true);
822
1693
  }
823
1694
  /** Render a standalone, previewable HTML document (Tailwind Play CDN). */
824
1695
  renderDocument(node, opts = {}) {
825
- const body = this.render(node, opts.mode ?? "tailwind", 2);
1696
+ const body = this.render(node, opts.mode ?? "tailwind", 2, opts.round ?? true);
826
1697
  return this.wrapDocument(body, node.name || "Figma Export", this.fontLinks(node));
827
1698
  }
828
1699
  /** Wrap an arbitrary HTML fragment (e.g. LLM output) into a previewable document. */
@@ -867,21 +1738,30 @@ ${bodyHtml}
867
1738
  }
868
1739
  return links.join("\n");
869
1740
  }
870
- render(node, mode, depth) {
1741
+ render(node, mode, depth, round) {
871
1742
  const indent = " ".repeat(depth);
872
- const isVectorAsset = node.asset?.kind === "vector" && !!node.assetSrc;
873
- const isImageAsset = node.asset?.kind === "image" && !!node.assetSrc;
1743
+ const isVectorAsset = node.asset?.kind === "vector";
1744
+ const isImageAsset = node.asset?.kind === "image";
874
1745
  const extraStyle = {};
1746
+ let baseCss = node.css;
875
1747
  if (isImageAsset) {
876
- extraStyle["background-image"] = `url(${node.assetSrc})`;
1748
+ const imageUrl = node.assetSrc ? `url(${node.assetSrc})` : `url(${IMAGE_PLACEHOLDER})`;
1749
+ const stack = node.css["background-image"];
1750
+ extraStyle["background-image"] = stack ? stack.split(`url(${style_ir_1.IMAGE_FILL_TOKEN})`).join(imageUrl) : imageUrl;
1751
+ if (!node.assetSrc) {
1752
+ extraStyle["background-size"] = "cover";
1753
+ extraStyle["background-position"] = "center";
1754
+ }
1755
+ const { ["background-image"]: _omit, ...rest } = node.css;
1756
+ baseCss = rest;
877
1757
  }
878
1758
  const attrs = [];
879
1759
  if (mode === "inline") {
880
- const css = { ...node.css, ...extraStyle };
1760
+ const css = { ...baseCss, ...extraStyle };
881
1761
  if (Object.keys(css).length)
882
1762
  attrs.push(`style="${escapeHtml(styleString(css))}"`);
883
1763
  } else {
884
- const { classes, leftover } = (0, tailwind_mapper_1.cssToTailwind)(node.css);
1764
+ const { classes, leftover } = (0, tailwind_mapper_1.cssToTailwind)(baseCss, { round });
885
1765
  const style = { ...leftover, ...extraStyle };
886
1766
  if (classes.length)
887
1767
  attrs.push(`class="${classes.join(" ")}"`);
@@ -891,7 +1771,15 @@ ${bodyHtml}
891
1771
  attrs.push(`data-figma-name="${escapeHtml(node.name)}"`);
892
1772
  const attrStr = attrs.length ? " " + attrs.join(" ") : "";
893
1773
  if (isVectorAsset) {
894
- return `${indent}<img${attrStr} src="${node.assetSrc}" alt="${escapeHtml(node.name)}" />`;
1774
+ const src = node.assetSrc ?? VECTOR_PLACEHOLDER;
1775
+ return `${indent}<img${attrStr} src="${src}" alt="${escapeHtml(node.name)}" />`;
1776
+ }
1777
+ if (node.runs && node.runs.length) {
1778
+ const spans = node.runs.map((r) => {
1779
+ const s = Object.keys(r.css).length ? ` style="${escapeHtml(styleString(r.css))}"` : "";
1780
+ return `<span${s}>${escapeHtml(r.text)}</span>`;
1781
+ }).join("");
1782
+ return `${indent}<${node.tag}${attrStr}>${spans}</${node.tag}>`;
895
1783
  }
896
1784
  if (node.text !== void 0) {
897
1785
  return `${indent}<${node.tag}${attrStr}>${escapeHtml(node.text)}</${node.tag}>`;
@@ -899,7 +1787,7 @@ ${bodyHtml}
899
1787
  if (!node.children.length) {
900
1788
  return `${indent}<${node.tag}${attrStr}></${node.tag}>`;
901
1789
  }
902
- const childHtml = node.children.map((c) => this.render(c, mode, depth + 1)).join("\n");
1790
+ const childHtml = node.children.map((c) => this.render(c, mode, depth + 1, round)).join("\n");
903
1791
  return `${indent}<${node.tag}${attrStr}>
904
1792
  ${childHtml}
905
1793
  ${indent}</${node.tag}>`;
@@ -931,45 +1819,213 @@ ${indent}</${node.tag}>`;
931
1819
  }
932
1820
  });
933
1821
 
1822
+ // ../packages/figma-core/dist/converter/compact-design.js
1823
+ var require_compact_design = __commonJS({
1824
+ "../packages/figma-core/dist/converter/compact-design.js"(exports) {
1825
+ "use strict";
1826
+ Object.defineProperty(exports, "__esModule", { value: true });
1827
+ exports.toCompactDesign = toCompactDesign2;
1828
+ exports.stableStringify = stableStringify;
1829
+ var MIN_TEMPLATE_NODES = 3;
1830
+ var POSITIONAL_KEYS = /* @__PURE__ */ new Set(["left", "top", "width", "height"]);
1831
+ function toCompactDesign2(root) {
1832
+ const styles = {};
1833
+ const styleIds = /* @__PURE__ */ new Map();
1834
+ let styleSeq = 0;
1835
+ const styleRef = (css) => {
1836
+ if (!css || Object.keys(css).length === 0)
1837
+ return void 0;
1838
+ const key = stableStringify(css);
1839
+ let id = styleIds.get(key);
1840
+ if (!id) {
1841
+ id = `s${++styleSeq}`;
1842
+ styleIds.set(key, id);
1843
+ styles[id] = css;
1844
+ }
1845
+ return id;
1846
+ };
1847
+ const hashCount = /* @__PURE__ */ new Map();
1848
+ const build = (node) => {
1849
+ const children = node.children.map(build);
1850
+ const compact = { tag: node.tag };
1851
+ if (node.name)
1852
+ compact.name = node.name;
1853
+ if (node.figmaType && node.figmaType !== "FRAME")
1854
+ compact.type = node.figmaType;
1855
+ const box = {};
1856
+ const rest = {};
1857
+ for (const [k, v] of Object.entries(node.css)) {
1858
+ if (POSITIONAL_KEYS.has(k))
1859
+ box[k] = v;
1860
+ else
1861
+ rest[k] = v;
1862
+ }
1863
+ if (Object.keys(box).length)
1864
+ compact.box = box;
1865
+ const sref = styleRef(rest);
1866
+ if (sref)
1867
+ compact.style = sref;
1868
+ if (node.text !== void 0)
1869
+ compact.text = node.text;
1870
+ if (node.asset)
1871
+ compact.asset = { kind: node.asset.kind };
1872
+ if (children.length)
1873
+ compact.children = children.map((c) => c.compact);
1874
+ const hash = stableStringify({
1875
+ t: compact.tag,
1876
+ ty: compact.type,
1877
+ b: compact.box,
1878
+ s: compact.style,
1879
+ x: compact.text,
1880
+ a: compact.asset?.kind,
1881
+ c: children.map((c) => c.hash)
1882
+ });
1883
+ hashCount.set(hash, (hashCount.get(hash) ?? 0) + 1);
1884
+ const size = 1 + children.reduce((n, c) => n + c.size, 0);
1885
+ return { compact, children, hash, size };
1886
+ };
1887
+ const built = build(root);
1888
+ const elements = {};
1889
+ const elementIds = /* @__PURE__ */ new Map();
1890
+ let elemSeq = 0;
1891
+ const templatize = (b) => {
1892
+ if (b.compact.children) {
1893
+ b.compact.children = b.children.map(templatize);
1894
+ }
1895
+ if (b.size >= MIN_TEMPLATE_NODES && (hashCount.get(b.hash) ?? 0) >= 2) {
1896
+ let id = elementIds.get(b.hash);
1897
+ if (!id) {
1898
+ id = `e${++elemSeq}`;
1899
+ elementIds.set(b.hash, id);
1900
+ elements[id] = b.compact;
1901
+ }
1902
+ return { ref: id };
1903
+ }
1904
+ return b.compact;
1905
+ };
1906
+ const rootCompact = templatize(built);
1907
+ return { name: root.name, globalVars: { styles }, elements, root: rootCompact };
1908
+ }
1909
+ function stableStringify(value) {
1910
+ return JSON.stringify(value, (_k, v) => v && typeof v === "object" && !Array.isArray(v) ? Object.keys(v).sort().reduce((acc, k) => {
1911
+ acc[k] = v[k];
1912
+ return acc;
1913
+ }, {}) : v);
1914
+ }
1915
+ }
1916
+ });
1917
+
934
1918
  // ../packages/figma-core/dist/assets/asset-resolver.js
935
1919
  var require_asset_resolver = __commonJS({
936
1920
  "../packages/figma-core/dist/assets/asset-resolver.js"(exports) {
937
1921
  "use strict";
938
1922
  Object.defineProperty(exports, "__esModule", { value: true });
939
1923
  exports.AssetResolver = void 0;
1924
+ var errors_1 = require_errors();
940
1925
  var AssetResolver = class {
941
1926
  constructor(figma, cache, logger) {
942
1927
  this.figma = figma;
943
1928
  this.cache = cache;
944
1929
  this.logger = logger;
945
1930
  this.fetchConcurrency = 8;
1931
+ this.renderBatchSize = 20;
1932
+ this.renderMaxAttempts = 4;
1933
+ this.renderMaxBackoffMs = 4e3;
946
1934
  }
947
1935
  async resolve(root, fileKey, auth, scale = 2) {
948
1936
  const vectors = [];
949
1937
  const images = [];
950
1938
  this.collect(root, vectors, images);
951
1939
  if (!vectors.length && !images.length) {
952
- return { vectors: 0, images: 0, embedded: 0, fromCache: 0 };
1940
+ return {
1941
+ vectors: 0,
1942
+ images: 0,
1943
+ embedded: 0,
1944
+ fromCache: 0,
1945
+ unresolvedVectors: 0,
1946
+ unresolvedImages: 0,
1947
+ rateLimited: false
1948
+ };
953
1949
  }
954
1950
  let fromCache = 0;
955
1951
  fromCache += await this.fillFromCache(vectors, fileKey, "svg", 1);
956
1952
  fromCache += await this.fillImageFillsFromCache(images, fileKey);
957
1953
  const vMissing = vectors.filter((n) => !n.assetSrc);
958
- let svgUrls = {};
959
- if (vMissing.length) {
960
- try {
961
- svgUrls = await this.figma.renderImages(fileKey, vMissing.map((n) => n.id), "svg", auth);
962
- await this.retryMissing(vMissing, svgUrls, fileKey, "svg", auth, 1);
963
- } catch (err) {
964
- this.logger.warn(`Vector render failed (keeping cached vectors + image fills): ${err.message}`);
965
- }
966
- }
1954
+ const { urls: svgUrls, rateLimited } = vMissing.length ? await this.renderVectors(vMissing.map((n) => n.id), fileKey, auth) : { urls: {}, rateLimited: false };
967
1955
  const iMissing = images.filter((n) => !n.assetSrc && n.asset?.imageRef);
968
1956
  let embedded = 0;
969
1957
  embedded += await this.embed(vMissing, svgUrls, "image/svg+xml", fileKey, "svg", 1);
970
1958
  embedded += await this.embedImageFills(iMissing, fileKey, auth);
1959
+ const unresolvedVectors = vectors.filter((n) => !n.assetSrc).length;
1960
+ const unresolvedImages = images.filter((n) => !n.assetSrc).length;
971
1961
  this.logger.log(`Assets: ${vectors.length} vectors, ${images.length} image fills, ${fromCache} from cache, ${embedded} newly embedded`);
972
- return { vectors: vectors.length, images: images.length, embedded, fromCache };
1962
+ if (unresolvedVectors || unresolvedImages) {
1963
+ this.logger.warn(`Assets unresolved: ${unresolvedVectors}/${vectors.length} vectors, ${unresolvedImages}/${images.length} image fills` + (rateLimited ? " (Figma render endpoint rate-limited; they fall back to placeholders)" : ""));
1964
+ }
1965
+ return {
1966
+ vectors: vectors.length,
1967
+ images: images.length,
1968
+ embedded,
1969
+ fromCache,
1970
+ unresolvedVectors,
1971
+ unresolvedImages,
1972
+ rateLimited
1973
+ };
1974
+ }
1975
+ /**
1976
+ * Render vector node ids via /v1/images in small batches. Each batch is
1977
+ * retried with capped exponential backoff on a 429 and isolated so an
1978
+ * exhausted batch leaves only its own ids unresolved. Returns the merged
1979
+ * id -> url map and whether any batch was rate-limited.
1980
+ */
1981
+ async renderVectors(ids, fileKey, auth) {
1982
+ const urls = {};
1983
+ let rateLimited = false;
1984
+ for (let i = 0; i < ids.length; i += this.renderBatchSize) {
1985
+ const batch = ids.slice(i, i + this.renderBatchSize);
1986
+ try {
1987
+ const rendered = await this.withRenderRetry(() => this.figma.renderImages(fileKey, batch, "svg", auth), (was429) => {
1988
+ if (was429)
1989
+ rateLimited = true;
1990
+ });
1991
+ for (const [id, url] of Object.entries(rendered)) {
1992
+ if (url)
1993
+ urls[id] = url;
1994
+ }
1995
+ } catch (err) {
1996
+ if (err instanceof errors_1.FigmaApiError && err.status === 429)
1997
+ rateLimited = true;
1998
+ this.logger.warn(`Vector render batch [${i}, ${i + batch.length}) failed after retries: ${err.message}`);
1999
+ }
2000
+ }
2001
+ return { urls, rateLimited };
2002
+ }
2003
+ /**
2004
+ * Run a render call, retrying on a Figma 429 with capped exponential backoff.
2005
+ * The backoff is deliberately capped (`renderMaxBackoffMs`) so a multi-hour
2006
+ * `Retry-After` can never block the request — we exhaust a few quick attempts
2007
+ * and then surface the failure instead of waiting.
2008
+ */
2009
+ async withRenderRetry(fn, onRateLimit) {
2010
+ let lastErr;
2011
+ for (let attempt = 0; attempt < this.renderMaxAttempts; attempt++) {
2012
+ try {
2013
+ return await fn();
2014
+ } catch (err) {
2015
+ lastErr = err;
2016
+ const is429 = err instanceof errors_1.FigmaApiError && err.status === 429;
2017
+ if (!is429 || attempt === this.renderMaxAttempts - 1)
2018
+ throw err;
2019
+ onRateLimit(true);
2020
+ const backoff = Math.min(this.renderMaxBackoffMs, 500 * 2 ** attempt);
2021
+ this.logger.warn(`Figma render rate-limited; retrying in ${backoff}ms (attempt ${attempt + 1}/${this.renderMaxAttempts})`);
2022
+ await this.sleep(backoff);
2023
+ }
2024
+ }
2025
+ throw lastErr;
2026
+ }
2027
+ sleep(ms) {
2028
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
973
2029
  }
974
2030
  assetKey(fileKey, id, format, scale) {
975
2031
  return `asset:${fileKey}:${id}:${format}:${scale}`;
@@ -1057,22 +2113,6 @@ var require_asset_resolver = __commonJS({
1057
2113
  for (const child of node.children)
1058
2114
  this.collect(child, vectors, images);
1059
2115
  }
1060
- async retryMissing(nodes, urlMap, fileKey, format, auth, scale) {
1061
- const missing = nodes.filter((n) => !urlMap[n.id]).map((n) => n.id);
1062
- if (!missing.length)
1063
- return;
1064
- try {
1065
- const retry = await this.figma.renderImages(fileKey, missing, format, auth, scale);
1066
- for (const [id, url] of Object.entries(retry)) {
1067
- if (url)
1068
- urlMap[id] = url;
1069
- }
1070
- const stillMissing = missing.filter((id) => !urlMap[id]).length;
1071
- this.logger.log(`Retried ${missing.length} missing ${format} assets; ${stillMissing} still unrendered`);
1072
- } catch (err) {
1073
- this.logger.warn(`Asset retry (${format}) failed: ${err.message}`);
1074
- }
1075
- }
1076
2116
  async embed(nodes, urlMap, mime, fileKey, format, scale) {
1077
2117
  let count = 0;
1078
2118
  for (let i = 0; i < nodes.length; i += this.fetchConcurrency) {
@@ -1255,20 +2295,20 @@ var require_strip_assets = __commonJS({
1255
2295
  Object.defineProperty(exports, "__esModule", { value: true });
1256
2296
  exports.stripHeavyAssets = stripHeavyAssets;
1257
2297
  function stripHeavyAssets(html) {
1258
- const map = /* @__PURE__ */ new Map();
2298
+ const map2 = /* @__PURE__ */ new Map();
1259
2299
  let n = 0;
1260
2300
  const placeholderFor = (original) => {
1261
- let ph = map.get(original);
2301
+ let ph = map2.get(original);
1262
2302
  if (!ph) {
1263
2303
  ph = `__F2H_ASSET_${n++}__`;
1264
- map.set(original, ph);
2304
+ map2.set(original, ph);
1265
2305
  }
1266
2306
  return ph;
1267
2307
  };
1268
2308
  const stripped = html.replace(/(<svg\b[^>]*>)([\s\S]*?)(<\/svg>)/gi, (_m, open, inner, close) => inner.trim() ? `${open}${placeholderFor(inner)}${close}` : `${open}${inner}${close}`).replace(/data:[^"')\s>]+/gi, (uri) => placeholderFor(uri));
1269
2309
  const restore = (s) => {
1270
2310
  let out = s;
1271
- for (const [original, ph] of map)
2311
+ for (const [original, ph] of map2)
1272
2312
  out = out.split(ph).join(original);
1273
2313
  return out;
1274
2314
  };
@@ -1580,16 +2620,22 @@ var require_convert = __commonJS({
1580
2620
  const node = await this.client.fetchNode(target2.fileKey, target2.nodeId, auth);
1581
2621
  const ir = this.styleIr.convert(node);
1582
2622
  let assetWarning;
1583
- if (options.assets !== false) {
2623
+ if (options.assets === true) {
1584
2624
  try {
1585
- await this.assets.resolve(ir, target2.fileKey, auth, options.assetScale ?? 2);
2625
+ const r = await this.assets.resolve(ir, target2.fileKey, auth, options.assetScale ?? 2);
2626
+ const unresolved = r.unresolvedVectors + r.unresolvedImages;
2627
+ if (unresolved > 0) {
2628
+ assetWarning = `${unresolved} asset(s) could not be rendered (${r.unresolvedVectors} vectors, ${r.unresolvedImages} image fills) and fall back to placeholders` + (r.rateLimited ? ". Figma\u2019s render endpoint is rate-limited \u2014 retry later for full fidelity." : ".");
2629
+ this.logger.warn(assetWarning);
2630
+ }
1586
2631
  } catch (err) {
1587
2632
  assetWarning = `Assets not fully resolved: ${err.message}`;
1588
2633
  this.logger.warn(assetWarning);
1589
2634
  }
1590
2635
  }
1591
2636
  const mode = options.mode ?? "tailwind";
1592
- let fragment = this.renderer.renderFragment(ir, { mode });
2637
+ const round = options.round ?? true;
2638
+ let fragment = this.renderer.renderFragment(ir, { mode, round });
1593
2639
  let usedLlm = false;
1594
2640
  if (options.llm && this.restructure?.enabled) {
1595
2641
  fragment = await this.restructure.restructure(fragment);
@@ -1695,7 +2741,7 @@ var require_dist = __commonJS({
1695
2741
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports2, p)) __createBinding(exports2, m, p);
1696
2742
  };
1697
2743
  Object.defineProperty(exports, "__esModule", { value: true });
1698
- exports.createFigmaCore = exports.countNodes = exports.FigmaConverter = exports.stripHeavyAssets = exports.stripCodeFence = exports.runAgent = exports.RefineAgent = exports.LlmRestructure = exports.ollamaConfigFromEnv = exports.OllamaClient = exports.AssetResolver = exports.px = exports.figmaColorToCss = exports.cssToTailwind = exports.HtmlRenderer = exports.StyleIr = exports.resolveFigmaTarget = exports.normalizeNodeId = exports.parseFigmaUrl = exports.FigmaClient = exports.NoopLogger = exports.ConsoleLogger = exports.DiskCache = exports.MemoryCache = exports.FigmaInputError = exports.FigmaApiError = void 0;
2744
+ exports.createFigmaCore = exports.countNodes = exports.FigmaConverter = exports.stripHeavyAssets = exports.stripCodeFence = exports.runAgent = exports.RefineAgent = exports.LlmRestructure = exports.ollamaConfigFromEnv = exports.OllamaClient = exports.AssetResolver = exports.stableStringify = exports.toCompactDesign = exports.px = exports.figmaColorToCss = exports.cssToTailwind = exports.HtmlRenderer = exports.IMAGE_FILL_TOKEN = exports.StyleIr = exports.resolveFigmaTarget = exports.normalizeNodeId = exports.parseFigmaUrl = exports.FigmaClient = exports.NoopLogger = exports.ConsoleLogger = exports.DiskCache = exports.MemoryCache = exports.FigmaInputError = exports.FigmaApiError = void 0;
1699
2745
  var errors_1 = require_errors();
1700
2746
  Object.defineProperty(exports, "FigmaApiError", { enumerable: true, get: function() {
1701
2747
  return errors_1.FigmaApiError;
@@ -1735,6 +2781,9 @@ var require_dist = __commonJS({
1735
2781
  Object.defineProperty(exports, "StyleIr", { enumerable: true, get: function() {
1736
2782
  return style_ir_1.StyleIr;
1737
2783
  } });
2784
+ Object.defineProperty(exports, "IMAGE_FILL_TOKEN", { enumerable: true, get: function() {
2785
+ return style_ir_1.IMAGE_FILL_TOKEN;
2786
+ } });
1738
2787
  var html_renderer_1 = require_html_renderer();
1739
2788
  Object.defineProperty(exports, "HtmlRenderer", { enumerable: true, get: function() {
1740
2789
  return html_renderer_1.HtmlRenderer;
@@ -1750,6 +2799,13 @@ var require_dist = __commonJS({
1750
2799
  Object.defineProperty(exports, "px", { enumerable: true, get: function() {
1751
2800
  return color_1.px;
1752
2801
  } });
2802
+ var compact_design_1 = require_compact_design();
2803
+ Object.defineProperty(exports, "toCompactDesign", { enumerable: true, get: function() {
2804
+ return compact_design_1.toCompactDesign;
2805
+ } });
2806
+ Object.defineProperty(exports, "stableStringify", { enumerable: true, get: function() {
2807
+ return compact_design_1.stableStringify;
2808
+ } });
1753
2809
  var asset_resolver_1 = require_asset_resolver();
1754
2810
  Object.defineProperty(exports, "AssetResolver", { enumerable: true, get: function() {
1755
2811
  return asset_resolver_1.AssetResolver;
@@ -1801,62 +2857,3122 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
1801
2857
  import { z } from "zod";
1802
2858
 
1803
2859
  // src/tools.ts
1804
- var import_core = __toESM(require_dist(), 1);
1805
2860
  import { promises as fs2 } from "fs";
1806
2861
  import * as path2 from "path";
1807
2862
 
1808
- // src/settings.ts
1809
- import { promises as fs } from "fs";
1810
- import * as os from "os";
1811
- import * as path from "path";
1812
- var DIR = path.join(os.homedir(), ".figma-mcp");
1813
- var FILE = path.join(DIR, "settings.json");
1814
- function settingsPath() {
1815
- return FILE;
2863
+ // ../node_modules/js-yaml/dist/js-yaml.mjs
2864
+ function getDefaultExportFromCjs(x) {
2865
+ return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
1816
2866
  }
1817
- async function loadSettings() {
1818
- try {
1819
- const raw = await fs.readFile(FILE, "utf8");
1820
- const parsed = JSON.parse(raw);
1821
- if (!parsed.env || typeof parsed.env !== "object") parsed.env = {};
1822
- return parsed;
1823
- } catch {
1824
- return { env: {} };
2867
+ var jsYaml = {};
2868
+ var loader = {};
2869
+ var common = {};
2870
+ var hasRequiredCommon;
2871
+ function requireCommon() {
2872
+ if (hasRequiredCommon) return common;
2873
+ hasRequiredCommon = 1;
2874
+ function isNothing(subject) {
2875
+ return typeof subject === "undefined" || subject === null;
2876
+ }
2877
+ function isObject(subject) {
2878
+ return typeof subject === "object" && subject !== null;
2879
+ }
2880
+ function toArray(sequence) {
2881
+ if (Array.isArray(sequence)) return sequence;
2882
+ else if (isNothing(sequence)) return [];
2883
+ return [sequence];
2884
+ }
2885
+ function extend(target2, source) {
2886
+ if (source) {
2887
+ const sourceKeys = Object.keys(source);
2888
+ for (let index = 0, length = sourceKeys.length; index < length; index += 1) {
2889
+ const key = sourceKeys[index];
2890
+ target2[key] = source[key];
2891
+ }
2892
+ }
2893
+ return target2;
2894
+ }
2895
+ function repeat(string, count) {
2896
+ let result = "";
2897
+ for (let cycle = 0; cycle < count; cycle += 1) {
2898
+ result += string;
2899
+ }
2900
+ return result;
2901
+ }
2902
+ function isNegativeZero(number) {
2903
+ return number === 0 && Number.NEGATIVE_INFINITY === 1 / number;
1825
2904
  }
2905
+ common.isNothing = isNothing;
2906
+ common.isObject = isObject;
2907
+ common.toArray = toArray;
2908
+ common.repeat = repeat;
2909
+ common.isNegativeZero = isNegativeZero;
2910
+ common.extend = extend;
2911
+ return common;
1826
2912
  }
1827
- async function saveSettings(patch) {
1828
- const current = await loadSettings();
1829
- const next = {
1830
- ...current,
1831
- ...patch,
1832
- env: { ...current.env ?? {}, ...patch.env ?? {} }
2913
+ var exception;
2914
+ var hasRequiredException;
2915
+ function requireException() {
2916
+ if (hasRequiredException) return exception;
2917
+ hasRequiredException = 1;
2918
+ function formatError(exception2, compact) {
2919
+ let where = "";
2920
+ const message = exception2.reason || "(unknown reason)";
2921
+ if (!exception2.mark) return message;
2922
+ if (exception2.mark.name) {
2923
+ where += 'in "' + exception2.mark.name + '" ';
2924
+ }
2925
+ where += "(" + (exception2.mark.line + 1) + ":" + (exception2.mark.column + 1) + ")";
2926
+ if (!compact && exception2.mark.snippet) {
2927
+ where += "\n\n" + exception2.mark.snippet;
2928
+ }
2929
+ return message + " " + where;
2930
+ }
2931
+ function YAMLException2(reason, mark) {
2932
+ Error.call(this);
2933
+ this.name = "YAMLException";
2934
+ this.reason = reason;
2935
+ this.mark = mark;
2936
+ this.message = formatError(this, false);
2937
+ if (Error.captureStackTrace) {
2938
+ Error.captureStackTrace(this, this.constructor);
2939
+ } else {
2940
+ this.stack = new Error().stack || "";
2941
+ }
2942
+ }
2943
+ YAMLException2.prototype = Object.create(Error.prototype);
2944
+ YAMLException2.prototype.constructor = YAMLException2;
2945
+ YAMLException2.prototype.toString = function toString(compact) {
2946
+ return this.name + ": " + formatError(this, compact);
1833
2947
  };
1834
- await fs.mkdir(DIR, { recursive: true });
1835
- await fs.writeFile(FILE, JSON.stringify(next, null, 2), { mode: 384 });
1836
- return next;
2948
+ exception = YAMLException2;
2949
+ return exception;
1837
2950
  }
1838
- async function clearSettings() {
1839
- try {
1840
- await fs.unlink(FILE);
1841
- } catch {
2951
+ var snippet;
2952
+ var hasRequiredSnippet;
2953
+ function requireSnippet() {
2954
+ if (hasRequiredSnippet) return snippet;
2955
+ hasRequiredSnippet = 1;
2956
+ const common2 = requireCommon();
2957
+ function getLine(buffer, lineStart, lineEnd, position, maxLineLength) {
2958
+ let head = "";
2959
+ let tail = "";
2960
+ const maxHalfLength = Math.floor(maxLineLength / 2) - 1;
2961
+ if (position - lineStart > maxHalfLength) {
2962
+ head = " ... ";
2963
+ lineStart = position - maxHalfLength + head.length;
2964
+ }
2965
+ if (lineEnd - position > maxHalfLength) {
2966
+ tail = " ...";
2967
+ lineEnd = position + maxHalfLength - tail.length;
2968
+ }
2969
+ return {
2970
+ str: head + buffer.slice(lineStart, lineEnd).replace(/\t/g, "\u2192") + tail,
2971
+ pos: position - lineStart + head.length
2972
+ // relative position
2973
+ };
1842
2974
  }
1843
- }
1844
-
1845
- // src/refresh.ts
1846
- var SKEW_MS = 6e4;
1847
- async function ensureFreshApiToken(apiUrl, force = false) {
1848
- const settings = await loadSettings();
1849
- const apiToken = settings.env?.FIGMA_MCP_TOKEN;
1850
- if (!apiToken || !settings.refreshToken) return;
1851
- if (!force) {
1852
- if (!settings.apiTokenExpiresAt) return;
1853
- if (Date.now() < settings.apiTokenExpiresAt - SKEW_MS) return;
2975
+ function padStart(string, max) {
2976
+ return common2.repeat(" ", max - string.length) + string;
1854
2977
  }
1855
- const base = apiUrl.replace(/\/+$/, "");
1856
- try {
1857
- const res = await fetch(`${base}/auth/figma/cli-refresh`, {
1858
- method: "POST",
1859
- headers: { "Content-Type": "application/json" },
2978
+ function makeSnippet(mark, options) {
2979
+ options = Object.create(options || null);
2980
+ if (!mark.buffer) return null;
2981
+ if (!options.maxLength) options.maxLength = 79;
2982
+ if (typeof options.indent !== "number") options.indent = 1;
2983
+ if (typeof options.linesBefore !== "number") options.linesBefore = 3;
2984
+ if (typeof options.linesAfter !== "number") options.linesAfter = 2;
2985
+ const re = /\r?\n|\r|\0/g;
2986
+ const lineStarts = [0];
2987
+ const lineEnds = [];
2988
+ let match;
2989
+ let foundLineNo = -1;
2990
+ while (match = re.exec(mark.buffer)) {
2991
+ lineEnds.push(match.index);
2992
+ lineStarts.push(match.index + match[0].length);
2993
+ if (mark.position <= match.index && foundLineNo < 0) {
2994
+ foundLineNo = lineStarts.length - 2;
2995
+ }
2996
+ }
2997
+ if (foundLineNo < 0) foundLineNo = lineStarts.length - 1;
2998
+ let result = "";
2999
+ const lineNoLength = Math.min(mark.line + options.linesAfter, lineEnds.length).toString().length;
3000
+ const maxLineLength = options.maxLength - (options.indent + lineNoLength + 3);
3001
+ for (let i = 1; i <= options.linesBefore; i++) {
3002
+ if (foundLineNo - i < 0) break;
3003
+ const line2 = getLine(
3004
+ mark.buffer,
3005
+ lineStarts[foundLineNo - i],
3006
+ lineEnds[foundLineNo - i],
3007
+ mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo - i]),
3008
+ maxLineLength
3009
+ );
3010
+ result = common2.repeat(" ", options.indent) + padStart((mark.line - i + 1).toString(), lineNoLength) + " | " + line2.str + "\n" + result;
3011
+ }
3012
+ const line = getLine(mark.buffer, lineStarts[foundLineNo], lineEnds[foundLineNo], mark.position, maxLineLength);
3013
+ result += common2.repeat(" ", options.indent) + padStart((mark.line + 1).toString(), lineNoLength) + " | " + line.str + "\n";
3014
+ result += common2.repeat("-", options.indent + lineNoLength + 3 + line.pos) + "^\n";
3015
+ for (let i = 1; i <= options.linesAfter; i++) {
3016
+ if (foundLineNo + i >= lineEnds.length) break;
3017
+ const line2 = getLine(
3018
+ mark.buffer,
3019
+ lineStarts[foundLineNo + i],
3020
+ lineEnds[foundLineNo + i],
3021
+ mark.position - (lineStarts[foundLineNo] - lineStarts[foundLineNo + i]),
3022
+ maxLineLength
3023
+ );
3024
+ result += common2.repeat(" ", options.indent) + padStart((mark.line + i + 1).toString(), lineNoLength) + " | " + line2.str + "\n";
3025
+ }
3026
+ return result.replace(/\n$/, "");
3027
+ }
3028
+ snippet = makeSnippet;
3029
+ return snippet;
3030
+ }
3031
+ var type;
3032
+ var hasRequiredType;
3033
+ function requireType() {
3034
+ if (hasRequiredType) return type;
3035
+ hasRequiredType = 1;
3036
+ const YAMLException2 = requireException();
3037
+ const TYPE_CONSTRUCTOR_OPTIONS = [
3038
+ "kind",
3039
+ "multi",
3040
+ "resolve",
3041
+ "construct",
3042
+ "instanceOf",
3043
+ "predicate",
3044
+ "represent",
3045
+ "representName",
3046
+ "defaultStyle",
3047
+ "styleAliases"
3048
+ ];
3049
+ const YAML_NODE_KINDS = [
3050
+ "scalar",
3051
+ "sequence",
3052
+ "mapping"
3053
+ ];
3054
+ function compileStyleAliases(map2) {
3055
+ const result = {};
3056
+ if (map2 !== null) {
3057
+ Object.keys(map2).forEach(function(style) {
3058
+ map2[style].forEach(function(alias) {
3059
+ result[String(alias)] = style;
3060
+ });
3061
+ });
3062
+ }
3063
+ return result;
3064
+ }
3065
+ function Type2(tag, options) {
3066
+ options = options || {};
3067
+ Object.keys(options).forEach(function(name) {
3068
+ if (TYPE_CONSTRUCTOR_OPTIONS.indexOf(name) === -1) {
3069
+ throw new YAMLException2('Unknown option "' + name + '" is met in definition of "' + tag + '" YAML type.');
3070
+ }
3071
+ });
3072
+ this.options = options;
3073
+ this.tag = tag;
3074
+ this.kind = options["kind"] || null;
3075
+ this.resolve = options["resolve"] || function() {
3076
+ return true;
3077
+ };
3078
+ this.construct = options["construct"] || function(data) {
3079
+ return data;
3080
+ };
3081
+ this.instanceOf = options["instanceOf"] || null;
3082
+ this.predicate = options["predicate"] || null;
3083
+ this.represent = options["represent"] || null;
3084
+ this.representName = options["representName"] || null;
3085
+ this.defaultStyle = options["defaultStyle"] || null;
3086
+ this.multi = options["multi"] || false;
3087
+ this.styleAliases = compileStyleAliases(options["styleAliases"] || null);
3088
+ if (YAML_NODE_KINDS.indexOf(this.kind) === -1) {
3089
+ throw new YAMLException2('Unknown kind "' + this.kind + '" is specified for "' + tag + '" YAML type.');
3090
+ }
3091
+ }
3092
+ type = Type2;
3093
+ return type;
3094
+ }
3095
+ var schema;
3096
+ var hasRequiredSchema;
3097
+ function requireSchema() {
3098
+ if (hasRequiredSchema) return schema;
3099
+ hasRequiredSchema = 1;
3100
+ const YAMLException2 = requireException();
3101
+ const Type2 = requireType();
3102
+ function compileList(schema2, name) {
3103
+ const result = [];
3104
+ schema2[name].forEach(function(currentType) {
3105
+ let newIndex = result.length;
3106
+ result.forEach(function(previousType, previousIndex) {
3107
+ if (previousType.tag === currentType.tag && previousType.kind === currentType.kind && previousType.multi === currentType.multi) {
3108
+ newIndex = previousIndex;
3109
+ }
3110
+ });
3111
+ result[newIndex] = currentType;
3112
+ });
3113
+ return result;
3114
+ }
3115
+ function compileMap() {
3116
+ const result = {
3117
+ scalar: {},
3118
+ sequence: {},
3119
+ mapping: {},
3120
+ fallback: {},
3121
+ multi: {
3122
+ scalar: [],
3123
+ sequence: [],
3124
+ mapping: [],
3125
+ fallback: []
3126
+ }
3127
+ };
3128
+ function collectType(type2) {
3129
+ if (type2.multi) {
3130
+ result.multi[type2.kind].push(type2);
3131
+ result.multi["fallback"].push(type2);
3132
+ } else {
3133
+ result[type2.kind][type2.tag] = result["fallback"][type2.tag] = type2;
3134
+ }
3135
+ }
3136
+ for (let index = 0, length = arguments.length; index < length; index += 1) {
3137
+ arguments[index].forEach(collectType);
3138
+ }
3139
+ return result;
3140
+ }
3141
+ function Schema2(definition) {
3142
+ return this.extend(definition);
3143
+ }
3144
+ Schema2.prototype.extend = function extend(definition) {
3145
+ let implicit = [];
3146
+ let explicit = [];
3147
+ if (definition instanceof Type2) {
3148
+ explicit.push(definition);
3149
+ } else if (Array.isArray(definition)) {
3150
+ explicit = explicit.concat(definition);
3151
+ } else if (definition && (Array.isArray(definition.implicit) || Array.isArray(definition.explicit))) {
3152
+ if (definition.implicit) implicit = implicit.concat(definition.implicit);
3153
+ if (definition.explicit) explicit = explicit.concat(definition.explicit);
3154
+ } else {
3155
+ throw new YAMLException2("Schema.extend argument should be a Type, [ Type ], or a schema definition ({ implicit: [...], explicit: [...] })");
3156
+ }
3157
+ implicit.forEach(function(type2) {
3158
+ if (!(type2 instanceof Type2)) {
3159
+ throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object.");
3160
+ }
3161
+ if (type2.loadKind && type2.loadKind !== "scalar") {
3162
+ throw new YAMLException2("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");
3163
+ }
3164
+ if (type2.multi) {
3165
+ throw new YAMLException2("There is a multi type in the implicit list of a schema. Multi tags can only be listed as explicit.");
3166
+ }
3167
+ });
3168
+ explicit.forEach(function(type2) {
3169
+ if (!(type2 instanceof Type2)) {
3170
+ throw new YAMLException2("Specified list of YAML types (or a single Type object) contains a non-Type object.");
3171
+ }
3172
+ });
3173
+ const result = Object.create(Schema2.prototype);
3174
+ result.implicit = (this.implicit || []).concat(implicit);
3175
+ result.explicit = (this.explicit || []).concat(explicit);
3176
+ result.compiledImplicit = compileList(result, "implicit");
3177
+ result.compiledExplicit = compileList(result, "explicit");
3178
+ result.compiledTypeMap = compileMap(result.compiledImplicit, result.compiledExplicit);
3179
+ return result;
3180
+ };
3181
+ schema = Schema2;
3182
+ return schema;
3183
+ }
3184
+ var str;
3185
+ var hasRequiredStr;
3186
+ function requireStr() {
3187
+ if (hasRequiredStr) return str;
3188
+ hasRequiredStr = 1;
3189
+ const Type2 = requireType();
3190
+ str = new Type2("tag:yaml.org,2002:str", {
3191
+ kind: "scalar",
3192
+ construct: function(data) {
3193
+ return data !== null ? data : "";
3194
+ }
3195
+ });
3196
+ return str;
3197
+ }
3198
+ var seq;
3199
+ var hasRequiredSeq;
3200
+ function requireSeq() {
3201
+ if (hasRequiredSeq) return seq;
3202
+ hasRequiredSeq = 1;
3203
+ const Type2 = requireType();
3204
+ seq = new Type2("tag:yaml.org,2002:seq", {
3205
+ kind: "sequence",
3206
+ construct: function(data) {
3207
+ return data !== null ? data : [];
3208
+ }
3209
+ });
3210
+ return seq;
3211
+ }
3212
+ var map;
3213
+ var hasRequiredMap;
3214
+ function requireMap() {
3215
+ if (hasRequiredMap) return map;
3216
+ hasRequiredMap = 1;
3217
+ const Type2 = requireType();
3218
+ map = new Type2("tag:yaml.org,2002:map", {
3219
+ kind: "mapping",
3220
+ construct: function(data) {
3221
+ return data !== null ? data : {};
3222
+ }
3223
+ });
3224
+ return map;
3225
+ }
3226
+ var failsafe;
3227
+ var hasRequiredFailsafe;
3228
+ function requireFailsafe() {
3229
+ if (hasRequiredFailsafe) return failsafe;
3230
+ hasRequiredFailsafe = 1;
3231
+ const Schema2 = requireSchema();
3232
+ failsafe = new Schema2({
3233
+ explicit: [
3234
+ requireStr(),
3235
+ requireSeq(),
3236
+ requireMap()
3237
+ ]
3238
+ });
3239
+ return failsafe;
3240
+ }
3241
+ var _null;
3242
+ var hasRequired_null;
3243
+ function require_null() {
3244
+ if (hasRequired_null) return _null;
3245
+ hasRequired_null = 1;
3246
+ const Type2 = requireType();
3247
+ function resolveYamlNull(data) {
3248
+ if (data === null) return true;
3249
+ const max = data.length;
3250
+ return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL");
3251
+ }
3252
+ function constructYamlNull() {
3253
+ return null;
3254
+ }
3255
+ function isNull(object) {
3256
+ return object === null;
3257
+ }
3258
+ _null = new Type2("tag:yaml.org,2002:null", {
3259
+ kind: "scalar",
3260
+ resolve: resolveYamlNull,
3261
+ construct: constructYamlNull,
3262
+ predicate: isNull,
3263
+ represent: {
3264
+ canonical: function() {
3265
+ return "~";
3266
+ },
3267
+ lowercase: function() {
3268
+ return "null";
3269
+ },
3270
+ uppercase: function() {
3271
+ return "NULL";
3272
+ },
3273
+ camelcase: function() {
3274
+ return "Null";
3275
+ },
3276
+ empty: function() {
3277
+ return "";
3278
+ }
3279
+ },
3280
+ defaultStyle: "lowercase"
3281
+ });
3282
+ return _null;
3283
+ }
3284
+ var bool;
3285
+ var hasRequiredBool;
3286
+ function requireBool() {
3287
+ if (hasRequiredBool) return bool;
3288
+ hasRequiredBool = 1;
3289
+ const Type2 = requireType();
3290
+ function resolveYamlBoolean(data) {
3291
+ if (data === null) return false;
3292
+ const max = data.length;
3293
+ return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE");
3294
+ }
3295
+ function constructYamlBoolean(data) {
3296
+ return data === "true" || data === "True" || data === "TRUE";
3297
+ }
3298
+ function isBoolean(object) {
3299
+ return Object.prototype.toString.call(object) === "[object Boolean]";
3300
+ }
3301
+ bool = new Type2("tag:yaml.org,2002:bool", {
3302
+ kind: "scalar",
3303
+ resolve: resolveYamlBoolean,
3304
+ construct: constructYamlBoolean,
3305
+ predicate: isBoolean,
3306
+ represent: {
3307
+ lowercase: function(object) {
3308
+ return object ? "true" : "false";
3309
+ },
3310
+ uppercase: function(object) {
3311
+ return object ? "TRUE" : "FALSE";
3312
+ },
3313
+ camelcase: function(object) {
3314
+ return object ? "True" : "False";
3315
+ }
3316
+ },
3317
+ defaultStyle: "lowercase"
3318
+ });
3319
+ return bool;
3320
+ }
3321
+ var int;
3322
+ var hasRequiredInt;
3323
+ function requireInt() {
3324
+ if (hasRequiredInt) return int;
3325
+ hasRequiredInt = 1;
3326
+ const common2 = requireCommon();
3327
+ const Type2 = requireType();
3328
+ function isHexCode(c) {
3329
+ return c >= 48 && c <= 57 || c >= 65 && c <= 70 || c >= 97 && c <= 102;
3330
+ }
3331
+ function isOctCode(c) {
3332
+ return c >= 48 && c <= 55;
3333
+ }
3334
+ function isDecCode(c) {
3335
+ return c >= 48 && c <= 57;
3336
+ }
3337
+ function resolveYamlInteger(data) {
3338
+ if (data === null) return false;
3339
+ const max = data.length;
3340
+ let index = 0;
3341
+ let hasDigits = false;
3342
+ if (!max) return false;
3343
+ let ch = data[index];
3344
+ if (ch === "-" || ch === "+") {
3345
+ ch = data[++index];
3346
+ }
3347
+ if (ch === "0") {
3348
+ if (index + 1 === max) return true;
3349
+ ch = data[++index];
3350
+ if (ch === "b") {
3351
+ index++;
3352
+ for (; index < max; index++) {
3353
+ ch = data[index];
3354
+ if (ch !== "0" && ch !== "1") return false;
3355
+ hasDigits = true;
3356
+ }
3357
+ return hasDigits && isFinite(parseYamlInteger(data));
3358
+ }
3359
+ if (ch === "x") {
3360
+ index++;
3361
+ for (; index < max; index++) {
3362
+ if (!isHexCode(data.charCodeAt(index))) return false;
3363
+ hasDigits = true;
3364
+ }
3365
+ return hasDigits && isFinite(parseYamlInteger(data));
3366
+ }
3367
+ if (ch === "o") {
3368
+ index++;
3369
+ for (; index < max; index++) {
3370
+ if (!isOctCode(data.charCodeAt(index))) return false;
3371
+ hasDigits = true;
3372
+ }
3373
+ return hasDigits && isFinite(parseYamlInteger(data));
3374
+ }
3375
+ }
3376
+ for (; index < max; index++) {
3377
+ if (!isDecCode(data.charCodeAt(index))) {
3378
+ return false;
3379
+ }
3380
+ hasDigits = true;
3381
+ }
3382
+ if (!hasDigits) return false;
3383
+ return isFinite(parseYamlInteger(data));
3384
+ }
3385
+ function parseYamlInteger(data) {
3386
+ let value = data;
3387
+ let sign = 1;
3388
+ let ch = value[0];
3389
+ if (ch === "-" || ch === "+") {
3390
+ if (ch === "-") sign = -1;
3391
+ value = value.slice(1);
3392
+ ch = value[0];
3393
+ }
3394
+ if (value === "0") return 0;
3395
+ if (ch === "0") {
3396
+ if (value[1] === "b") return sign * parseInt(value.slice(2), 2);
3397
+ if (value[1] === "x") return sign * parseInt(value.slice(2), 16);
3398
+ if (value[1] === "o") return sign * parseInt(value.slice(2), 8);
3399
+ }
3400
+ return sign * parseInt(value, 10);
3401
+ }
3402
+ function constructYamlInteger(data) {
3403
+ return parseYamlInteger(data);
3404
+ }
3405
+ function isInteger(object) {
3406
+ return Object.prototype.toString.call(object) === "[object Number]" && (object % 1 === 0 && !common2.isNegativeZero(object));
3407
+ }
3408
+ int = new Type2("tag:yaml.org,2002:int", {
3409
+ kind: "scalar",
3410
+ resolve: resolveYamlInteger,
3411
+ construct: constructYamlInteger,
3412
+ predicate: isInteger,
3413
+ represent: {
3414
+ binary: function(obj) {
3415
+ return obj >= 0 ? "0b" + obj.toString(2) : "-0b" + obj.toString(2).slice(1);
3416
+ },
3417
+ octal: function(obj) {
3418
+ return obj >= 0 ? "0o" + obj.toString(8) : "-0o" + obj.toString(8).slice(1);
3419
+ },
3420
+ decimal: function(obj) {
3421
+ return obj.toString(10);
3422
+ },
3423
+ hexadecimal: function(obj) {
3424
+ return obj >= 0 ? "0x" + obj.toString(16).toUpperCase() : "-0x" + obj.toString(16).toUpperCase().slice(1);
3425
+ }
3426
+ },
3427
+ defaultStyle: "decimal",
3428
+ styleAliases: {
3429
+ binary: [2, "bin"],
3430
+ octal: [8, "oct"],
3431
+ decimal: [10, "dec"],
3432
+ hexadecimal: [16, "hex"]
3433
+ }
3434
+ });
3435
+ return int;
3436
+ }
3437
+ var float;
3438
+ var hasRequiredFloat;
3439
+ function requireFloat() {
3440
+ if (hasRequiredFloat) return float;
3441
+ hasRequiredFloat = 1;
3442
+ const common2 = requireCommon();
3443
+ const Type2 = requireType();
3444
+ const YAML_FLOAT_PATTERN = new RegExp(
3445
+ // 2.5e4, 2.5 and integers
3446
+ "^(?:[-+]?(?:[0-9]+)(?:\\.[0-9]*)?(?:[eE][-+]?[0-9]+)?|\\.[0-9]+(?:[eE][-+]?[0-9]+)?|[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"
3447
+ );
3448
+ const YAML_FLOAT_SPECIAL_PATTERN = new RegExp(
3449
+ "^(?:[-+]?\\.(?:inf|Inf|INF)|\\.(?:nan|NaN|NAN))$"
3450
+ );
3451
+ function resolveYamlFloat(data) {
3452
+ if (data === null) return false;
3453
+ if (!YAML_FLOAT_PATTERN.test(data)) {
3454
+ return false;
3455
+ }
3456
+ if (isFinite(parseFloat(data, 10))) {
3457
+ return true;
3458
+ }
3459
+ return YAML_FLOAT_SPECIAL_PATTERN.test(data);
3460
+ }
3461
+ function constructYamlFloat(data) {
3462
+ let value = data.toLowerCase();
3463
+ const sign = value[0] === "-" ? -1 : 1;
3464
+ if ("+-".indexOf(value[0]) >= 0) {
3465
+ value = value.slice(1);
3466
+ }
3467
+ if (value === ".inf") {
3468
+ return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
3469
+ } else if (value === ".nan") {
3470
+ return NaN;
3471
+ }
3472
+ return sign * parseFloat(value, 10);
3473
+ }
3474
+ const SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
3475
+ function representYamlFloat(object, style) {
3476
+ if (isNaN(object)) {
3477
+ switch (style) {
3478
+ case "lowercase":
3479
+ return ".nan";
3480
+ case "uppercase":
3481
+ return ".NAN";
3482
+ case "camelcase":
3483
+ return ".NaN";
3484
+ }
3485
+ } else if (Number.POSITIVE_INFINITY === object) {
3486
+ switch (style) {
3487
+ case "lowercase":
3488
+ return ".inf";
3489
+ case "uppercase":
3490
+ return ".INF";
3491
+ case "camelcase":
3492
+ return ".Inf";
3493
+ }
3494
+ } else if (Number.NEGATIVE_INFINITY === object) {
3495
+ switch (style) {
3496
+ case "lowercase":
3497
+ return "-.inf";
3498
+ case "uppercase":
3499
+ return "-.INF";
3500
+ case "camelcase":
3501
+ return "-.Inf";
3502
+ }
3503
+ } else if (common2.isNegativeZero(object)) {
3504
+ return "-0.0";
3505
+ }
3506
+ const res = object.toString(10);
3507
+ return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res;
3508
+ }
3509
+ function isFloat(object) {
3510
+ return Object.prototype.toString.call(object) === "[object Number]" && (object % 1 !== 0 || common2.isNegativeZero(object));
3511
+ }
3512
+ float = new Type2("tag:yaml.org,2002:float", {
3513
+ kind: "scalar",
3514
+ resolve: resolveYamlFloat,
3515
+ construct: constructYamlFloat,
3516
+ predicate: isFloat,
3517
+ represent: representYamlFloat,
3518
+ defaultStyle: "lowercase"
3519
+ });
3520
+ return float;
3521
+ }
3522
+ var json;
3523
+ var hasRequiredJson;
3524
+ function requireJson() {
3525
+ if (hasRequiredJson) return json;
3526
+ hasRequiredJson = 1;
3527
+ json = requireFailsafe().extend({
3528
+ implicit: [
3529
+ require_null(),
3530
+ requireBool(),
3531
+ requireInt(),
3532
+ requireFloat()
3533
+ ]
3534
+ });
3535
+ return json;
3536
+ }
3537
+ var core;
3538
+ var hasRequiredCore;
3539
+ function requireCore() {
3540
+ if (hasRequiredCore) return core;
3541
+ hasRequiredCore = 1;
3542
+ core = requireJson();
3543
+ return core;
3544
+ }
3545
+ var timestamp;
3546
+ var hasRequiredTimestamp;
3547
+ function requireTimestamp() {
3548
+ if (hasRequiredTimestamp) return timestamp;
3549
+ hasRequiredTimestamp = 1;
3550
+ const Type2 = requireType();
3551
+ const YAML_DATE_REGEXP = new RegExp(
3552
+ "^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$"
3553
+ );
3554
+ const YAML_TIMESTAMP_REGEXP = new RegExp(
3555
+ "^([0-9][0-9][0-9][0-9])-([0-9][0-9]?)-([0-9][0-9]?)(?:[Tt]|[ \\t]+)([0-9][0-9]?):([0-9][0-9]):([0-9][0-9])(?:\\.([0-9]*))?(?:[ \\t]*(Z|([-+])([0-9][0-9]?)(?::([0-9][0-9]))?))?$"
3556
+ );
3557
+ function resolveYamlTimestamp(data) {
3558
+ if (data === null) return false;
3559
+ if (YAML_DATE_REGEXP.exec(data) !== null) return true;
3560
+ if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
3561
+ return false;
3562
+ }
3563
+ function constructYamlTimestamp(data) {
3564
+ let fraction = 0;
3565
+ let delta = null;
3566
+ let match = YAML_DATE_REGEXP.exec(data);
3567
+ if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
3568
+ if (match === null) throw new Error("Date resolve error");
3569
+ const year = +match[1];
3570
+ const month = +match[2] - 1;
3571
+ const day = +match[3];
3572
+ if (!match[4]) {
3573
+ return new Date(Date.UTC(year, month, day));
3574
+ }
3575
+ const hour = +match[4];
3576
+ const minute = +match[5];
3577
+ const second = +match[6];
3578
+ if (match[7]) {
3579
+ fraction = match[7].slice(0, 3);
3580
+ while (fraction.length < 3) {
3581
+ fraction += "0";
3582
+ }
3583
+ fraction = +fraction;
3584
+ }
3585
+ if (match[9]) {
3586
+ const tzHour = +match[10];
3587
+ const tzMinute = +(match[11] || 0);
3588
+ delta = (tzHour * 60 + tzMinute) * 6e4;
3589
+ if (match[9] === "-") delta = -delta;
3590
+ }
3591
+ const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
3592
+ if (delta) date.setTime(date.getTime() - delta);
3593
+ return date;
3594
+ }
3595
+ function representYamlTimestamp(object) {
3596
+ return object.toISOString();
3597
+ }
3598
+ timestamp = new Type2("tag:yaml.org,2002:timestamp", {
3599
+ kind: "scalar",
3600
+ resolve: resolveYamlTimestamp,
3601
+ construct: constructYamlTimestamp,
3602
+ instanceOf: Date,
3603
+ represent: representYamlTimestamp
3604
+ });
3605
+ return timestamp;
3606
+ }
3607
+ var merge;
3608
+ var hasRequiredMerge;
3609
+ function requireMerge() {
3610
+ if (hasRequiredMerge) return merge;
3611
+ hasRequiredMerge = 1;
3612
+ const Type2 = requireType();
3613
+ function resolveYamlMerge(data) {
3614
+ return data === "<<" || data === null;
3615
+ }
3616
+ merge = new Type2("tag:yaml.org,2002:merge", {
3617
+ kind: "scalar",
3618
+ resolve: resolveYamlMerge
3619
+ });
3620
+ return merge;
3621
+ }
3622
+ var binary;
3623
+ var hasRequiredBinary;
3624
+ function requireBinary() {
3625
+ if (hasRequiredBinary) return binary;
3626
+ hasRequiredBinary = 1;
3627
+ const Type2 = requireType();
3628
+ const BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";
3629
+ function resolveYamlBinary(data) {
3630
+ if (data === null) return false;
3631
+ let bitlen = 0;
3632
+ const max = data.length;
3633
+ const map2 = BASE64_MAP;
3634
+ for (let idx = 0; idx < max; idx++) {
3635
+ const code = map2.indexOf(data.charAt(idx));
3636
+ if (code > 64) continue;
3637
+ if (code < 0) return false;
3638
+ bitlen += 6;
3639
+ }
3640
+ return bitlen % 8 === 0;
3641
+ }
3642
+ function constructYamlBinary(data) {
3643
+ const input = data.replace(/[\r\n=]/g, "");
3644
+ const max = input.length;
3645
+ const map2 = BASE64_MAP;
3646
+ let bits = 0;
3647
+ const result = [];
3648
+ for (let idx = 0; idx < max; idx++) {
3649
+ if (idx % 4 === 0 && idx) {
3650
+ result.push(bits >> 16 & 255);
3651
+ result.push(bits >> 8 & 255);
3652
+ result.push(bits & 255);
3653
+ }
3654
+ bits = bits << 6 | map2.indexOf(input.charAt(idx));
3655
+ }
3656
+ const tailbits = max % 4 * 6;
3657
+ if (tailbits === 0) {
3658
+ result.push(bits >> 16 & 255);
3659
+ result.push(bits >> 8 & 255);
3660
+ result.push(bits & 255);
3661
+ } else if (tailbits === 18) {
3662
+ result.push(bits >> 10 & 255);
3663
+ result.push(bits >> 2 & 255);
3664
+ } else if (tailbits === 12) {
3665
+ result.push(bits >> 4 & 255);
3666
+ }
3667
+ return new Uint8Array(result);
3668
+ }
3669
+ function representYamlBinary(object) {
3670
+ let result = "";
3671
+ let bits = 0;
3672
+ const max = object.length;
3673
+ const map2 = BASE64_MAP;
3674
+ for (let idx = 0; idx < max; idx++) {
3675
+ if (idx % 3 === 0 && idx) {
3676
+ result += map2[bits >> 18 & 63];
3677
+ result += map2[bits >> 12 & 63];
3678
+ result += map2[bits >> 6 & 63];
3679
+ result += map2[bits & 63];
3680
+ }
3681
+ bits = (bits << 8) + object[idx];
3682
+ }
3683
+ const tail = max % 3;
3684
+ if (tail === 0) {
3685
+ result += map2[bits >> 18 & 63];
3686
+ result += map2[bits >> 12 & 63];
3687
+ result += map2[bits >> 6 & 63];
3688
+ result += map2[bits & 63];
3689
+ } else if (tail === 2) {
3690
+ result += map2[bits >> 10 & 63];
3691
+ result += map2[bits >> 4 & 63];
3692
+ result += map2[bits << 2 & 63];
3693
+ result += map2[64];
3694
+ } else if (tail === 1) {
3695
+ result += map2[bits >> 2 & 63];
3696
+ result += map2[bits << 4 & 63];
3697
+ result += map2[64];
3698
+ result += map2[64];
3699
+ }
3700
+ return result;
3701
+ }
3702
+ function isBinary(obj) {
3703
+ return Object.prototype.toString.call(obj) === "[object Uint8Array]";
3704
+ }
3705
+ binary = new Type2("tag:yaml.org,2002:binary", {
3706
+ kind: "scalar",
3707
+ resolve: resolveYamlBinary,
3708
+ construct: constructYamlBinary,
3709
+ predicate: isBinary,
3710
+ represent: representYamlBinary
3711
+ });
3712
+ return binary;
3713
+ }
3714
+ var omap;
3715
+ var hasRequiredOmap;
3716
+ function requireOmap() {
3717
+ if (hasRequiredOmap) return omap;
3718
+ hasRequiredOmap = 1;
3719
+ const Type2 = requireType();
3720
+ const _hasOwnProperty = Object.prototype.hasOwnProperty;
3721
+ const _toString = Object.prototype.toString;
3722
+ function resolveYamlOmap(data) {
3723
+ if (data === null) return true;
3724
+ const objectKeys = [];
3725
+ const object = data;
3726
+ for (let index = 0, length = object.length; index < length; index += 1) {
3727
+ const pair = object[index];
3728
+ let pairHasKey = false;
3729
+ if (_toString.call(pair) !== "[object Object]") return false;
3730
+ let pairKey;
3731
+ for (pairKey in pair) {
3732
+ if (_hasOwnProperty.call(pair, pairKey)) {
3733
+ if (!pairHasKey) pairHasKey = true;
3734
+ else return false;
3735
+ }
3736
+ }
3737
+ if (!pairHasKey) return false;
3738
+ if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
3739
+ else return false;
3740
+ }
3741
+ return true;
3742
+ }
3743
+ function constructYamlOmap(data) {
3744
+ return data !== null ? data : [];
3745
+ }
3746
+ omap = new Type2("tag:yaml.org,2002:omap", {
3747
+ kind: "sequence",
3748
+ resolve: resolveYamlOmap,
3749
+ construct: constructYamlOmap
3750
+ });
3751
+ return omap;
3752
+ }
3753
+ var pairs;
3754
+ var hasRequiredPairs;
3755
+ function requirePairs() {
3756
+ if (hasRequiredPairs) return pairs;
3757
+ hasRequiredPairs = 1;
3758
+ const Type2 = requireType();
3759
+ const _toString = Object.prototype.toString;
3760
+ function resolveYamlPairs(data) {
3761
+ if (data === null) return true;
3762
+ const object = data;
3763
+ const result = new Array(object.length);
3764
+ for (let index = 0, length = object.length; index < length; index += 1) {
3765
+ const pair = object[index];
3766
+ if (_toString.call(pair) !== "[object Object]") return false;
3767
+ const keys = Object.keys(pair);
3768
+ if (keys.length !== 1) return false;
3769
+ result[index] = [keys[0], pair[keys[0]]];
3770
+ }
3771
+ return true;
3772
+ }
3773
+ function constructYamlPairs(data) {
3774
+ if (data === null) return [];
3775
+ const object = data;
3776
+ const result = new Array(object.length);
3777
+ for (let index = 0, length = object.length; index < length; index += 1) {
3778
+ const pair = object[index];
3779
+ const keys = Object.keys(pair);
3780
+ result[index] = [keys[0], pair[keys[0]]];
3781
+ }
3782
+ return result;
3783
+ }
3784
+ pairs = new Type2("tag:yaml.org,2002:pairs", {
3785
+ kind: "sequence",
3786
+ resolve: resolveYamlPairs,
3787
+ construct: constructYamlPairs
3788
+ });
3789
+ return pairs;
3790
+ }
3791
+ var set;
3792
+ var hasRequiredSet;
3793
+ function requireSet() {
3794
+ if (hasRequiredSet) return set;
3795
+ hasRequiredSet = 1;
3796
+ const Type2 = requireType();
3797
+ const _hasOwnProperty = Object.prototype.hasOwnProperty;
3798
+ function resolveYamlSet(data) {
3799
+ if (data === null) return true;
3800
+ const object = data;
3801
+ for (const key in object) {
3802
+ if (_hasOwnProperty.call(object, key)) {
3803
+ if (object[key] !== null) return false;
3804
+ }
3805
+ }
3806
+ return true;
3807
+ }
3808
+ function constructYamlSet(data) {
3809
+ return data !== null ? data : {};
3810
+ }
3811
+ set = new Type2("tag:yaml.org,2002:set", {
3812
+ kind: "mapping",
3813
+ resolve: resolveYamlSet,
3814
+ construct: constructYamlSet
3815
+ });
3816
+ return set;
3817
+ }
3818
+ var _default;
3819
+ var hasRequired_default;
3820
+ function require_default() {
3821
+ if (hasRequired_default) return _default;
3822
+ hasRequired_default = 1;
3823
+ _default = requireCore().extend({
3824
+ implicit: [
3825
+ requireTimestamp(),
3826
+ requireMerge()
3827
+ ],
3828
+ explicit: [
3829
+ requireBinary(),
3830
+ requireOmap(),
3831
+ requirePairs(),
3832
+ requireSet()
3833
+ ]
3834
+ });
3835
+ return _default;
3836
+ }
3837
+ var hasRequiredLoader;
3838
+ function requireLoader() {
3839
+ if (hasRequiredLoader) return loader;
3840
+ hasRequiredLoader = 1;
3841
+ const common2 = requireCommon();
3842
+ const YAMLException2 = requireException();
3843
+ const makeSnippet = requireSnippet();
3844
+ const DEFAULT_SCHEMA2 = require_default();
3845
+ const _hasOwnProperty = Object.prototype.hasOwnProperty;
3846
+ const CONTEXT_FLOW_IN = 1;
3847
+ const CONTEXT_FLOW_OUT = 2;
3848
+ const CONTEXT_BLOCK_IN = 3;
3849
+ const CONTEXT_BLOCK_OUT = 4;
3850
+ const CHOMPING_CLIP = 1;
3851
+ const CHOMPING_STRIP = 2;
3852
+ const CHOMPING_KEEP = 3;
3853
+ const PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
3854
+ const PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
3855
+ const PATTERN_FLOW_INDICATORS = /[,\[\]{}]/;
3856
+ const PATTERN_TAG_HANDLE = /^(?:!|!!|![0-9A-Za-z-]+!)$/;
3857
+ const PATTERN_TAG_URI = /^(?:!|[^,\[\]{}])(?:%[0-9a-f]{2}|[0-9a-z\-#;/?:@&=+$,_.!~*'()\[\]])*$/i;
3858
+ function _class(obj) {
3859
+ return Object.prototype.toString.call(obj);
3860
+ }
3861
+ function isEol(c) {
3862
+ return c === 10 || c === 13;
3863
+ }
3864
+ function isWhiteSpace(c) {
3865
+ return c === 9 || c === 32;
3866
+ }
3867
+ function isWsOrEol(c) {
3868
+ return c === 9 || c === 32 || c === 10 || c === 13;
3869
+ }
3870
+ function isFlowIndicator(c) {
3871
+ return c === 44 || c === 91 || c === 93 || c === 123 || c === 125;
3872
+ }
3873
+ function fromHexCode(c) {
3874
+ if (c >= 48 && c <= 57) {
3875
+ return c - 48;
3876
+ }
3877
+ const lc = c | 32;
3878
+ if (lc >= 97 && lc <= 102) {
3879
+ return lc - 97 + 10;
3880
+ }
3881
+ return -1;
3882
+ }
3883
+ function escapedHexLen(c) {
3884
+ if (c === 120) {
3885
+ return 2;
3886
+ }
3887
+ if (c === 117) {
3888
+ return 4;
3889
+ }
3890
+ if (c === 85) {
3891
+ return 8;
3892
+ }
3893
+ return 0;
3894
+ }
3895
+ function fromDecimalCode(c) {
3896
+ if (c >= 48 && c <= 57) {
3897
+ return c - 48;
3898
+ }
3899
+ return -1;
3900
+ }
3901
+ function simpleEscapeSequence(c) {
3902
+ switch (c) {
3903
+ case 48:
3904
+ return "\0";
3905
+ case 97:
3906
+ return "\x07";
3907
+ case 98:
3908
+ return "\b";
3909
+ case 116:
3910
+ return " ";
3911
+ case 9:
3912
+ return " ";
3913
+ case 110:
3914
+ return "\n";
3915
+ case 118:
3916
+ return "\v";
3917
+ case 102:
3918
+ return "\f";
3919
+ case 114:
3920
+ return "\r";
3921
+ case 101:
3922
+ return "\x1B";
3923
+ case 32:
3924
+ return " ";
3925
+ case 34:
3926
+ return '"';
3927
+ case 47:
3928
+ return "/";
3929
+ case 92:
3930
+ return "\\";
3931
+ case 78:
3932
+ return "\x85";
3933
+ case 95:
3934
+ return "\xA0";
3935
+ case 76:
3936
+ return "\u2028";
3937
+ case 80:
3938
+ return "\u2029";
3939
+ default:
3940
+ return "";
3941
+ }
3942
+ }
3943
+ function charFromCodepoint(c) {
3944
+ if (c <= 65535) {
3945
+ return String.fromCharCode(c);
3946
+ }
3947
+ return String.fromCharCode(
3948
+ (c - 65536 >> 10) + 55296,
3949
+ (c - 65536 & 1023) + 56320
3950
+ );
3951
+ }
3952
+ function setProperty(object, key, value) {
3953
+ if (key === "__proto__") {
3954
+ Object.defineProperty(object, key, {
3955
+ configurable: true,
3956
+ enumerable: true,
3957
+ writable: true,
3958
+ value
3959
+ });
3960
+ } else {
3961
+ object[key] = value;
3962
+ }
3963
+ }
3964
+ const simpleEscapeCheck = new Array(256);
3965
+ const simpleEscapeMap = new Array(256);
3966
+ for (let i = 0; i < 256; i++) {
3967
+ simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
3968
+ simpleEscapeMap[i] = simpleEscapeSequence(i);
3969
+ }
3970
+ function State(input, options) {
3971
+ this.input = input;
3972
+ this.filename = options["filename"] || null;
3973
+ this.schema = options["schema"] || DEFAULT_SCHEMA2;
3974
+ this.onWarning = options["onWarning"] || null;
3975
+ this.legacy = options["legacy"] || false;
3976
+ this.json = options["json"] || false;
3977
+ this.listener = options["listener"] || null;
3978
+ this.maxDepth = typeof options["maxDepth"] === "number" ? options["maxDepth"] : 100;
3979
+ this.maxTotalMergeKeys = typeof options["maxTotalMergeKeys"] === "number" ? options["maxTotalMergeKeys"] : 1e4;
3980
+ this.implicitTypes = this.schema.compiledImplicit;
3981
+ this.typeMap = this.schema.compiledTypeMap;
3982
+ this.length = input.length;
3983
+ this.position = 0;
3984
+ this.line = 0;
3985
+ this.lineStart = 0;
3986
+ this.lineIndent = 0;
3987
+ this.depth = 0;
3988
+ this.totalMergeKeys = 0;
3989
+ this.firstTabInLine = -1;
3990
+ this.documents = [];
3991
+ this.anchorMapTransactions = [];
3992
+ }
3993
+ function generateError(state, message) {
3994
+ const mark = {
3995
+ name: state.filename,
3996
+ buffer: state.input.slice(0, -1),
3997
+ // omit trailing \0
3998
+ position: state.position,
3999
+ line: state.line,
4000
+ column: state.position - state.lineStart
4001
+ };
4002
+ mark.snippet = makeSnippet(mark);
4003
+ return new YAMLException2(message, mark);
4004
+ }
4005
+ function throwError(state, message) {
4006
+ throw generateError(state, message);
4007
+ }
4008
+ function throwWarning(state, message) {
4009
+ if (state.onWarning) {
4010
+ state.onWarning.call(null, generateError(state, message));
4011
+ }
4012
+ }
4013
+ function storeAnchor(state, name, value) {
4014
+ const transactions = state.anchorMapTransactions;
4015
+ if (transactions.length !== 0) {
4016
+ const transaction = transactions[transactions.length - 1];
4017
+ if (!_hasOwnProperty.call(transaction, name)) {
4018
+ transaction[name] = {
4019
+ existed: _hasOwnProperty.call(state.anchorMap, name),
4020
+ value: state.anchorMap[name]
4021
+ };
4022
+ }
4023
+ }
4024
+ state.anchorMap[name] = value;
4025
+ }
4026
+ function beginAnchorTransaction(state) {
4027
+ state.anchorMapTransactions.push(/* @__PURE__ */ Object.create(null));
4028
+ }
4029
+ function commitAnchorTransaction(state) {
4030
+ const transaction = state.anchorMapTransactions.pop();
4031
+ const transactions = state.anchorMapTransactions;
4032
+ if (transactions.length === 0) return;
4033
+ const parent = transactions[transactions.length - 1];
4034
+ const names = Object.keys(transaction);
4035
+ for (let index = 0, length = names.length; index < length; index += 1) {
4036
+ const name = names[index];
4037
+ if (!_hasOwnProperty.call(parent, name)) {
4038
+ parent[name] = transaction[name];
4039
+ }
4040
+ }
4041
+ }
4042
+ function rollbackAnchorTransaction(state) {
4043
+ const transaction = state.anchorMapTransactions.pop();
4044
+ const names = Object.keys(transaction);
4045
+ for (let index = names.length - 1; index >= 0; index -= 1) {
4046
+ const entry = transaction[names[index]];
4047
+ if (entry.existed) {
4048
+ state.anchorMap[names[index]] = entry.value;
4049
+ } else {
4050
+ delete state.anchorMap[names[index]];
4051
+ }
4052
+ }
4053
+ }
4054
+ function snapshotState(state) {
4055
+ return {
4056
+ position: state.position,
4057
+ line: state.line,
4058
+ lineStart: state.lineStart,
4059
+ lineIndent: state.lineIndent,
4060
+ firstTabInLine: state.firstTabInLine,
4061
+ tag: state.tag,
4062
+ anchor: state.anchor,
4063
+ kind: state.kind,
4064
+ result: state.result
4065
+ };
4066
+ }
4067
+ function restoreState(state, snapshot) {
4068
+ state.position = snapshot.position;
4069
+ state.line = snapshot.line;
4070
+ state.lineStart = snapshot.lineStart;
4071
+ state.lineIndent = snapshot.lineIndent;
4072
+ state.firstTabInLine = snapshot.firstTabInLine;
4073
+ state.tag = snapshot.tag;
4074
+ state.anchor = snapshot.anchor;
4075
+ state.kind = snapshot.kind;
4076
+ state.result = snapshot.result;
4077
+ }
4078
+ const directiveHandlers = {
4079
+ YAML: function handleYamlDirective(state, name, args) {
4080
+ if (state.version !== null) {
4081
+ throwError(state, "duplication of %YAML directive");
4082
+ }
4083
+ if (args.length !== 1) {
4084
+ throwError(state, "YAML directive accepts exactly one argument");
4085
+ }
4086
+ const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
4087
+ if (match === null) {
4088
+ throwError(state, "ill-formed argument of the YAML directive");
4089
+ }
4090
+ const major = parseInt(match[1], 10);
4091
+ const minor = parseInt(match[2], 10);
4092
+ if (major !== 1) {
4093
+ throwError(state, "unacceptable YAML version of the document");
4094
+ }
4095
+ state.version = args[0];
4096
+ state.checkLineBreaks = minor < 2;
4097
+ if (minor !== 1 && minor !== 2) {
4098
+ throwWarning(state, "unsupported YAML version of the document");
4099
+ }
4100
+ },
4101
+ TAG: function handleTagDirective(state, name, args) {
4102
+ let prefix;
4103
+ if (args.length !== 2) {
4104
+ throwError(state, "TAG directive accepts exactly two arguments");
4105
+ }
4106
+ const handle = args[0];
4107
+ prefix = args[1];
4108
+ if (!PATTERN_TAG_HANDLE.test(handle)) {
4109
+ throwError(state, "ill-formed tag handle (first argument) of the TAG directive");
4110
+ }
4111
+ if (_hasOwnProperty.call(state.tagMap, handle)) {
4112
+ throwError(state, 'there is a previously declared suffix for "' + handle + '" tag handle');
4113
+ }
4114
+ if (!PATTERN_TAG_URI.test(prefix)) {
4115
+ throwError(state, "ill-formed tag prefix (second argument) of the TAG directive");
4116
+ }
4117
+ try {
4118
+ prefix = decodeURIComponent(prefix);
4119
+ } catch (err) {
4120
+ throwError(state, "tag prefix is malformed: " + prefix);
4121
+ }
4122
+ state.tagMap[handle] = prefix;
4123
+ }
4124
+ };
4125
+ function captureSegment(state, start, end, checkJson) {
4126
+ if (start < end) {
4127
+ const _result = state.input.slice(start, end);
4128
+ if (checkJson) {
4129
+ for (let _position = 0, _length = _result.length; _position < _length; _position += 1) {
4130
+ const _character = _result.charCodeAt(_position);
4131
+ if (!(_character === 9 || _character >= 32 && _character <= 1114111)) {
4132
+ throwError(state, "expected valid JSON character");
4133
+ }
4134
+ }
4135
+ } else if (PATTERN_NON_PRINTABLE.test(_result)) {
4136
+ throwError(state, "the stream contains non-printable characters");
4137
+ }
4138
+ state.result += _result;
4139
+ }
4140
+ }
4141
+ function mergeMappings(state, destination, source, overridableKeys) {
4142
+ if (!common2.isObject(source)) {
4143
+ throwError(state, "cannot merge mappings; the provided source object is unacceptable");
4144
+ }
4145
+ const sourceKeys = Object.keys(source);
4146
+ for (let index = 0, quantity = sourceKeys.length; index < quantity; index += 1) {
4147
+ const key = sourceKeys[index];
4148
+ if (state.maxTotalMergeKeys !== -1 && ++state.totalMergeKeys > state.maxTotalMergeKeys) {
4149
+ throwError(state, "merge keys exceeded maxTotalMergeKeys (" + state.maxTotalMergeKeys + ")");
4150
+ }
4151
+ if (!_hasOwnProperty.call(destination, key)) {
4152
+ setProperty(destination, key, source[key]);
4153
+ overridableKeys[key] = true;
4154
+ }
4155
+ }
4156
+ }
4157
+ function storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, startLine, startLineStart, startPos) {
4158
+ if (Array.isArray(keyNode)) {
4159
+ keyNode = Array.prototype.slice.call(keyNode);
4160
+ for (let index = 0, quantity = keyNode.length; index < quantity; index += 1) {
4161
+ if (Array.isArray(keyNode[index])) {
4162
+ throwError(state, "nested arrays are not supported inside keys");
4163
+ }
4164
+ if (typeof keyNode === "object" && _class(keyNode[index]) === "[object Object]") {
4165
+ keyNode[index] = "[object Object]";
4166
+ }
4167
+ }
4168
+ }
4169
+ if (typeof keyNode === "object" && _class(keyNode) === "[object Object]") {
4170
+ keyNode = "[object Object]";
4171
+ }
4172
+ keyNode = String(keyNode);
4173
+ if (_result === null) {
4174
+ _result = {};
4175
+ }
4176
+ if (keyTag === "tag:yaml.org,2002:merge") {
4177
+ if (Array.isArray(valueNode)) {
4178
+ for (let index = 0, quantity = valueNode.length; index < quantity; index += 1) {
4179
+ mergeMappings(state, _result, valueNode[index], overridableKeys);
4180
+ }
4181
+ } else {
4182
+ mergeMappings(state, _result, valueNode, overridableKeys);
4183
+ }
4184
+ } else {
4185
+ if (!state.json && !_hasOwnProperty.call(overridableKeys, keyNode) && _hasOwnProperty.call(_result, keyNode)) {
4186
+ state.line = startLine || state.line;
4187
+ state.lineStart = startLineStart || state.lineStart;
4188
+ state.position = startPos || state.position;
4189
+ throwError(state, "duplicated mapping key");
4190
+ }
4191
+ setProperty(_result, keyNode, valueNode);
4192
+ delete overridableKeys[keyNode];
4193
+ }
4194
+ return _result;
4195
+ }
4196
+ function readLineBreak(state) {
4197
+ const ch = state.input.charCodeAt(state.position);
4198
+ if (ch === 10) {
4199
+ state.position++;
4200
+ } else if (ch === 13) {
4201
+ state.position++;
4202
+ if (state.input.charCodeAt(state.position) === 10) {
4203
+ state.position++;
4204
+ }
4205
+ } else {
4206
+ throwError(state, "a line break is expected");
4207
+ }
4208
+ state.line += 1;
4209
+ state.lineStart = state.position;
4210
+ state.firstTabInLine = -1;
4211
+ }
4212
+ function skipSeparationSpace(state, allowComments, checkIndent) {
4213
+ let lineBreaks = 0;
4214
+ let ch = state.input.charCodeAt(state.position);
4215
+ while (ch !== 0) {
4216
+ while (isWhiteSpace(ch)) {
4217
+ if (ch === 9 && state.firstTabInLine === -1) {
4218
+ state.firstTabInLine = state.position;
4219
+ }
4220
+ ch = state.input.charCodeAt(++state.position);
4221
+ }
4222
+ if (allowComments && ch === 35) {
4223
+ do {
4224
+ ch = state.input.charCodeAt(++state.position);
4225
+ } while (ch !== 10 && ch !== 13 && ch !== 0);
4226
+ }
4227
+ if (isEol(ch)) {
4228
+ readLineBreak(state);
4229
+ ch = state.input.charCodeAt(state.position);
4230
+ lineBreaks++;
4231
+ state.lineIndent = 0;
4232
+ while (ch === 32) {
4233
+ state.lineIndent++;
4234
+ ch = state.input.charCodeAt(++state.position);
4235
+ }
4236
+ } else {
4237
+ break;
4238
+ }
4239
+ }
4240
+ if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
4241
+ throwWarning(state, "deficient indentation");
4242
+ }
4243
+ return lineBreaks;
4244
+ }
4245
+ function testDocumentSeparator(state) {
4246
+ let _position = state.position;
4247
+ let ch = state.input.charCodeAt(_position);
4248
+ if ((ch === 45 || ch === 46) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) {
4249
+ _position += 3;
4250
+ ch = state.input.charCodeAt(_position);
4251
+ if (ch === 0 || isWsOrEol(ch)) {
4252
+ return true;
4253
+ }
4254
+ }
4255
+ return false;
4256
+ }
4257
+ function writeFoldedLines(state, count) {
4258
+ if (count === 1) {
4259
+ state.result += " ";
4260
+ } else if (count > 1) {
4261
+ state.result += common2.repeat("\n", count - 1);
4262
+ }
4263
+ }
4264
+ function readPlainScalar(state, nodeIndent, withinFlowCollection) {
4265
+ let captureStart;
4266
+ let captureEnd;
4267
+ let hasPendingContent;
4268
+ let _line;
4269
+ let _lineStart;
4270
+ let _lineIndent;
4271
+ const _kind = state.kind;
4272
+ const _result = state.result;
4273
+ let ch = state.input.charCodeAt(state.position);
4274
+ if (isWsOrEol(ch) || isFlowIndicator(ch) || ch === 35 || ch === 38 || ch === 42 || ch === 33 || ch === 124 || ch === 62 || ch === 39 || ch === 34 || ch === 37 || ch === 64 || ch === 96) {
4275
+ return false;
4276
+ }
4277
+ if (ch === 63 || ch === 45) {
4278
+ const following = state.input.charCodeAt(state.position + 1);
4279
+ if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
4280
+ return false;
4281
+ }
4282
+ }
4283
+ state.kind = "scalar";
4284
+ state.result = "";
4285
+ captureStart = captureEnd = state.position;
4286
+ hasPendingContent = false;
4287
+ while (ch !== 0) {
4288
+ if (ch === 58) {
4289
+ const following = state.input.charCodeAt(state.position + 1);
4290
+ if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
4291
+ break;
4292
+ }
4293
+ } else if (ch === 35) {
4294
+ const preceding = state.input.charCodeAt(state.position - 1);
4295
+ if (isWsOrEol(preceding)) {
4296
+ break;
4297
+ }
4298
+ } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && isFlowIndicator(ch)) {
4299
+ break;
4300
+ } else if (isEol(ch)) {
4301
+ _line = state.line;
4302
+ _lineStart = state.lineStart;
4303
+ _lineIndent = state.lineIndent;
4304
+ skipSeparationSpace(state, false, -1);
4305
+ if (state.lineIndent >= nodeIndent) {
4306
+ hasPendingContent = true;
4307
+ ch = state.input.charCodeAt(state.position);
4308
+ continue;
4309
+ } else {
4310
+ state.position = captureEnd;
4311
+ state.line = _line;
4312
+ state.lineStart = _lineStart;
4313
+ state.lineIndent = _lineIndent;
4314
+ break;
4315
+ }
4316
+ }
4317
+ if (hasPendingContent) {
4318
+ captureSegment(state, captureStart, captureEnd, false);
4319
+ writeFoldedLines(state, state.line - _line);
4320
+ captureStart = captureEnd = state.position;
4321
+ hasPendingContent = false;
4322
+ }
4323
+ if (!isWhiteSpace(ch)) {
4324
+ captureEnd = state.position + 1;
4325
+ }
4326
+ ch = state.input.charCodeAt(++state.position);
4327
+ }
4328
+ captureSegment(state, captureStart, captureEnd, false);
4329
+ if (state.result) {
4330
+ return true;
4331
+ }
4332
+ state.kind = _kind;
4333
+ state.result = _result;
4334
+ return false;
4335
+ }
4336
+ function readSingleQuotedScalar(state, nodeIndent) {
4337
+ let captureStart;
4338
+ let captureEnd;
4339
+ let ch = state.input.charCodeAt(state.position);
4340
+ if (ch !== 39) {
4341
+ return false;
4342
+ }
4343
+ state.kind = "scalar";
4344
+ state.result = "";
4345
+ state.position++;
4346
+ captureStart = captureEnd = state.position;
4347
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
4348
+ if (ch === 39) {
4349
+ captureSegment(state, captureStart, state.position, true);
4350
+ ch = state.input.charCodeAt(++state.position);
4351
+ if (ch === 39) {
4352
+ captureStart = state.position;
4353
+ state.position++;
4354
+ captureEnd = state.position;
4355
+ } else {
4356
+ return true;
4357
+ }
4358
+ } else if (isEol(ch)) {
4359
+ captureSegment(state, captureStart, captureEnd, true);
4360
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
4361
+ captureStart = captureEnd = state.position;
4362
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
4363
+ throwError(state, "unexpected end of the document within a single quoted scalar");
4364
+ } else {
4365
+ state.position++;
4366
+ if (!isWhiteSpace(ch)) {
4367
+ captureEnd = state.position;
4368
+ }
4369
+ }
4370
+ }
4371
+ throwError(state, "unexpected end of the stream within a single quoted scalar");
4372
+ }
4373
+ function readDoubleQuotedScalar(state, nodeIndent) {
4374
+ let captureStart;
4375
+ let captureEnd;
4376
+ let tmp;
4377
+ let ch = state.input.charCodeAt(state.position);
4378
+ if (ch !== 34) {
4379
+ return false;
4380
+ }
4381
+ state.kind = "scalar";
4382
+ state.result = "";
4383
+ state.position++;
4384
+ captureStart = captureEnd = state.position;
4385
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
4386
+ if (ch === 34) {
4387
+ captureSegment(state, captureStart, state.position, true);
4388
+ state.position++;
4389
+ return true;
4390
+ } else if (ch === 92) {
4391
+ captureSegment(state, captureStart, state.position, true);
4392
+ ch = state.input.charCodeAt(++state.position);
4393
+ if (isEol(ch)) {
4394
+ skipSeparationSpace(state, false, nodeIndent);
4395
+ } else if (ch < 256 && simpleEscapeCheck[ch]) {
4396
+ state.result += simpleEscapeMap[ch];
4397
+ state.position++;
4398
+ } else if ((tmp = escapedHexLen(ch)) > 0) {
4399
+ let hexLength = tmp;
4400
+ let hexResult = 0;
4401
+ for (; hexLength > 0; hexLength--) {
4402
+ ch = state.input.charCodeAt(++state.position);
4403
+ if ((tmp = fromHexCode(ch)) >= 0) {
4404
+ hexResult = (hexResult << 4) + tmp;
4405
+ } else {
4406
+ throwError(state, "expected hexadecimal character");
4407
+ }
4408
+ }
4409
+ state.result += charFromCodepoint(hexResult);
4410
+ state.position++;
4411
+ } else {
4412
+ throwError(state, "unknown escape sequence");
4413
+ }
4414
+ captureStart = captureEnd = state.position;
4415
+ } else if (isEol(ch)) {
4416
+ captureSegment(state, captureStart, captureEnd, true);
4417
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
4418
+ captureStart = captureEnd = state.position;
4419
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
4420
+ throwError(state, "unexpected end of the document within a double quoted scalar");
4421
+ } else {
4422
+ state.position++;
4423
+ if (!isWhiteSpace(ch)) {
4424
+ captureEnd = state.position;
4425
+ }
4426
+ }
4427
+ }
4428
+ throwError(state, "unexpected end of the stream within a double quoted scalar");
4429
+ }
4430
+ function readFlowCollection(state, nodeIndent) {
4431
+ let readNext = true;
4432
+ let _line;
4433
+ let _lineStart;
4434
+ let _pos;
4435
+ const _tag = state.tag;
4436
+ let _result;
4437
+ const _anchor = state.anchor;
4438
+ let terminator;
4439
+ let isPair;
4440
+ let isExplicitPair;
4441
+ let isMapping;
4442
+ const overridableKeys = /* @__PURE__ */ Object.create(null);
4443
+ let keyNode;
4444
+ let keyTag;
4445
+ let valueNode;
4446
+ let ch = state.input.charCodeAt(state.position);
4447
+ if (ch === 91) {
4448
+ terminator = 93;
4449
+ isMapping = false;
4450
+ _result = [];
4451
+ } else if (ch === 123) {
4452
+ terminator = 125;
4453
+ isMapping = true;
4454
+ _result = {};
4455
+ } else {
4456
+ return false;
4457
+ }
4458
+ if (state.anchor !== null) {
4459
+ storeAnchor(state, state.anchor, _result);
4460
+ }
4461
+ ch = state.input.charCodeAt(++state.position);
4462
+ while (ch !== 0) {
4463
+ skipSeparationSpace(state, true, nodeIndent);
4464
+ ch = state.input.charCodeAt(state.position);
4465
+ if (ch === terminator) {
4466
+ state.position++;
4467
+ state.tag = _tag;
4468
+ state.anchor = _anchor;
4469
+ state.kind = isMapping ? "mapping" : "sequence";
4470
+ state.result = _result;
4471
+ return true;
4472
+ } else if (!readNext) {
4473
+ throwError(state, "missed comma between flow collection entries");
4474
+ } else if (ch === 44) {
4475
+ throwError(state, "expected the node content, but found ','");
4476
+ }
4477
+ keyTag = keyNode = valueNode = null;
4478
+ isPair = isExplicitPair = false;
4479
+ if (ch === 63) {
4480
+ const following = state.input.charCodeAt(state.position + 1);
4481
+ if (isWsOrEol(following)) {
4482
+ isPair = isExplicitPair = true;
4483
+ state.position++;
4484
+ skipSeparationSpace(state, true, nodeIndent);
4485
+ }
4486
+ }
4487
+ _line = state.line;
4488
+ _lineStart = state.lineStart;
4489
+ _pos = state.position;
4490
+ composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
4491
+ keyTag = state.tag;
4492
+ keyNode = state.result;
4493
+ skipSeparationSpace(state, true, nodeIndent);
4494
+ ch = state.input.charCodeAt(state.position);
4495
+ if ((isExplicitPair || state.line === _line) && ch === 58) {
4496
+ isPair = true;
4497
+ ch = state.input.charCodeAt(++state.position);
4498
+ skipSeparationSpace(state, true, nodeIndent);
4499
+ composeNode(state, nodeIndent, CONTEXT_FLOW_IN, false, true);
4500
+ valueNode = state.result;
4501
+ }
4502
+ if (isMapping) {
4503
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos);
4504
+ } else if (isPair) {
4505
+ _result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode, _line, _lineStart, _pos));
4506
+ } else {
4507
+ _result.push(keyNode);
4508
+ }
4509
+ skipSeparationSpace(state, true, nodeIndent);
4510
+ ch = state.input.charCodeAt(state.position);
4511
+ if (ch === 44) {
4512
+ readNext = true;
4513
+ ch = state.input.charCodeAt(++state.position);
4514
+ } else {
4515
+ readNext = false;
4516
+ }
4517
+ }
4518
+ throwError(state, "unexpected end of the stream within a flow collection");
4519
+ }
4520
+ function readBlockScalar(state, nodeIndent) {
4521
+ let folding;
4522
+ let chomping = CHOMPING_CLIP;
4523
+ let didReadContent = false;
4524
+ let detectedIndent = false;
4525
+ let textIndent = nodeIndent;
4526
+ let emptyLines = 0;
4527
+ let atMoreIndented = false;
4528
+ let tmp;
4529
+ let ch = state.input.charCodeAt(state.position);
4530
+ if (ch === 124) {
4531
+ folding = false;
4532
+ } else if (ch === 62) {
4533
+ folding = true;
4534
+ } else {
4535
+ return false;
4536
+ }
4537
+ state.kind = "scalar";
4538
+ state.result = "";
4539
+ while (ch !== 0) {
4540
+ ch = state.input.charCodeAt(++state.position);
4541
+ if (ch === 43 || ch === 45) {
4542
+ if (CHOMPING_CLIP === chomping) {
4543
+ chomping = ch === 43 ? CHOMPING_KEEP : CHOMPING_STRIP;
4544
+ } else {
4545
+ throwError(state, "repeat of a chomping mode identifier");
4546
+ }
4547
+ } else if ((tmp = fromDecimalCode(ch)) >= 0) {
4548
+ if (tmp === 0) {
4549
+ throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one");
4550
+ } else if (!detectedIndent) {
4551
+ textIndent = nodeIndent + tmp - 1;
4552
+ detectedIndent = true;
4553
+ } else {
4554
+ throwError(state, "repeat of an indentation width identifier");
4555
+ }
4556
+ } else {
4557
+ break;
4558
+ }
4559
+ }
4560
+ if (isWhiteSpace(ch)) {
4561
+ do {
4562
+ ch = state.input.charCodeAt(++state.position);
4563
+ } while (isWhiteSpace(ch));
4564
+ if (ch === 35) {
4565
+ do {
4566
+ ch = state.input.charCodeAt(++state.position);
4567
+ } while (!isEol(ch) && ch !== 0);
4568
+ }
4569
+ }
4570
+ while (ch !== 0) {
4571
+ readLineBreak(state);
4572
+ state.lineIndent = 0;
4573
+ ch = state.input.charCodeAt(state.position);
4574
+ while ((!detectedIndent || state.lineIndent < textIndent) && ch === 32) {
4575
+ state.lineIndent++;
4576
+ ch = state.input.charCodeAt(++state.position);
4577
+ }
4578
+ if (!detectedIndent && state.lineIndent > textIndent) {
4579
+ textIndent = state.lineIndent;
4580
+ }
4581
+ if (isEol(ch)) {
4582
+ emptyLines++;
4583
+ continue;
4584
+ }
4585
+ if (!detectedIndent && textIndent === 0) {
4586
+ throwError(state, "missing indentation for block scalar");
4587
+ }
4588
+ if (state.lineIndent < textIndent) {
4589
+ if (chomping === CHOMPING_KEEP) {
4590
+ state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
4591
+ } else if (chomping === CHOMPING_CLIP) {
4592
+ if (didReadContent) {
4593
+ state.result += "\n";
4594
+ }
4595
+ }
4596
+ break;
4597
+ }
4598
+ if (folding) {
4599
+ if (isWhiteSpace(ch)) {
4600
+ atMoreIndented = true;
4601
+ state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
4602
+ } else if (atMoreIndented) {
4603
+ atMoreIndented = false;
4604
+ state.result += common2.repeat("\n", emptyLines + 1);
4605
+ } else if (emptyLines === 0) {
4606
+ if (didReadContent) {
4607
+ state.result += " ";
4608
+ }
4609
+ } else {
4610
+ state.result += common2.repeat("\n", emptyLines);
4611
+ }
4612
+ } else {
4613
+ state.result += common2.repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
4614
+ }
4615
+ didReadContent = true;
4616
+ detectedIndent = true;
4617
+ emptyLines = 0;
4618
+ const captureStart = state.position;
4619
+ while (!isEol(ch) && ch !== 0) {
4620
+ ch = state.input.charCodeAt(++state.position);
4621
+ }
4622
+ captureSegment(state, captureStart, state.position, false);
4623
+ }
4624
+ return true;
4625
+ }
4626
+ function readBlockSequence(state, nodeIndent) {
4627
+ const _tag = state.tag;
4628
+ const _anchor = state.anchor;
4629
+ const _result = [];
4630
+ let detected = false;
4631
+ if (state.firstTabInLine !== -1) return false;
4632
+ if (state.anchor !== null) {
4633
+ storeAnchor(state, state.anchor, _result);
4634
+ }
4635
+ let ch = state.input.charCodeAt(state.position);
4636
+ while (ch !== 0) {
4637
+ if (state.firstTabInLine !== -1) {
4638
+ state.position = state.firstTabInLine;
4639
+ throwError(state, "tab characters must not be used in indentation");
4640
+ }
4641
+ if (ch !== 45) {
4642
+ break;
4643
+ }
4644
+ const following = state.input.charCodeAt(state.position + 1);
4645
+ if (!isWsOrEol(following)) {
4646
+ break;
4647
+ }
4648
+ detected = true;
4649
+ state.position++;
4650
+ if (skipSeparationSpace(state, true, -1)) {
4651
+ if (state.lineIndent <= nodeIndent) {
4652
+ _result.push(null);
4653
+ ch = state.input.charCodeAt(state.position);
4654
+ continue;
4655
+ }
4656
+ }
4657
+ const _line = state.line;
4658
+ composeNode(state, nodeIndent, CONTEXT_BLOCK_IN, false, true);
4659
+ _result.push(state.result);
4660
+ skipSeparationSpace(state, true, -1);
4661
+ ch = state.input.charCodeAt(state.position);
4662
+ if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
4663
+ throwError(state, "bad indentation of a sequence entry");
4664
+ } else if (state.lineIndent < nodeIndent) {
4665
+ break;
4666
+ }
4667
+ }
4668
+ if (detected) {
4669
+ state.tag = _tag;
4670
+ state.anchor = _anchor;
4671
+ state.kind = "sequence";
4672
+ state.result = _result;
4673
+ return true;
4674
+ }
4675
+ return false;
4676
+ }
4677
+ function readBlockMapping(state, nodeIndent, flowIndent) {
4678
+ let allowCompact;
4679
+ let _keyLine;
4680
+ let _keyLineStart;
4681
+ let _keyPos;
4682
+ const _tag = state.tag;
4683
+ const _anchor = state.anchor;
4684
+ const _result = {};
4685
+ const overridableKeys = /* @__PURE__ */ Object.create(null);
4686
+ let keyTag = null;
4687
+ let keyNode = null;
4688
+ let valueNode = null;
4689
+ let atExplicitKey = false;
4690
+ let detected = false;
4691
+ if (state.firstTabInLine !== -1) return false;
4692
+ if (state.anchor !== null) {
4693
+ storeAnchor(state, state.anchor, _result);
4694
+ }
4695
+ let ch = state.input.charCodeAt(state.position);
4696
+ while (ch !== 0) {
4697
+ if (!atExplicitKey && state.firstTabInLine !== -1) {
4698
+ state.position = state.firstTabInLine;
4699
+ throwError(state, "tab characters must not be used in indentation");
4700
+ }
4701
+ const following = state.input.charCodeAt(state.position + 1);
4702
+ const _line = state.line;
4703
+ if ((ch === 63 || ch === 58) && isWsOrEol(following)) {
4704
+ if (ch === 63) {
4705
+ if (atExplicitKey) {
4706
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
4707
+ keyTag = keyNode = valueNode = null;
4708
+ }
4709
+ detected = true;
4710
+ atExplicitKey = true;
4711
+ allowCompact = true;
4712
+ } else if (atExplicitKey) {
4713
+ atExplicitKey = false;
4714
+ allowCompact = true;
4715
+ } else {
4716
+ throwError(state, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line");
4717
+ }
4718
+ state.position += 1;
4719
+ ch = following;
4720
+ } else {
4721
+ _keyLine = state.line;
4722
+ _keyLineStart = state.lineStart;
4723
+ _keyPos = state.position;
4724
+ if (!composeNode(state, flowIndent, CONTEXT_FLOW_OUT, false, true)) {
4725
+ break;
4726
+ }
4727
+ if (state.line === _line) {
4728
+ ch = state.input.charCodeAt(state.position);
4729
+ while (isWhiteSpace(ch)) {
4730
+ ch = state.input.charCodeAt(++state.position);
4731
+ }
4732
+ if (ch === 58) {
4733
+ ch = state.input.charCodeAt(++state.position);
4734
+ if (!isWsOrEol(ch)) {
4735
+ throwError(state, "a whitespace character is expected after the key-value separator within a block mapping");
4736
+ }
4737
+ if (atExplicitKey) {
4738
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
4739
+ keyTag = keyNode = valueNode = null;
4740
+ }
4741
+ detected = true;
4742
+ atExplicitKey = false;
4743
+ allowCompact = false;
4744
+ keyTag = state.tag;
4745
+ keyNode = state.result;
4746
+ } else if (detected) {
4747
+ throwError(state, "can not read an implicit mapping pair; a colon is missed");
4748
+ } else {
4749
+ state.tag = _tag;
4750
+ state.anchor = _anchor;
4751
+ return true;
4752
+ }
4753
+ } else if (detected) {
4754
+ throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key");
4755
+ } else {
4756
+ state.tag = _tag;
4757
+ state.anchor = _anchor;
4758
+ return true;
4759
+ }
4760
+ }
4761
+ if (state.line === _line || state.lineIndent > nodeIndent) {
4762
+ if (atExplicitKey) {
4763
+ _keyLine = state.line;
4764
+ _keyLineStart = state.lineStart;
4765
+ _keyPos = state.position;
4766
+ }
4767
+ if (composeNode(state, nodeIndent, CONTEXT_BLOCK_OUT, true, allowCompact)) {
4768
+ if (atExplicitKey) {
4769
+ keyNode = state.result;
4770
+ } else {
4771
+ valueNode = state.result;
4772
+ }
4773
+ }
4774
+ if (!atExplicitKey) {
4775
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, valueNode, _keyLine, _keyLineStart, _keyPos);
4776
+ keyTag = keyNode = valueNode = null;
4777
+ }
4778
+ skipSeparationSpace(state, true, -1);
4779
+ ch = state.input.charCodeAt(state.position);
4780
+ }
4781
+ if ((state.line === _line || state.lineIndent > nodeIndent) && ch !== 0) {
4782
+ throwError(state, "bad indentation of a mapping entry");
4783
+ } else if (state.lineIndent < nodeIndent) {
4784
+ break;
4785
+ }
4786
+ }
4787
+ if (atExplicitKey) {
4788
+ storeMappingPair(state, _result, overridableKeys, keyTag, keyNode, null, _keyLine, _keyLineStart, _keyPos);
4789
+ }
4790
+ if (detected) {
4791
+ state.tag = _tag;
4792
+ state.anchor = _anchor;
4793
+ state.kind = "mapping";
4794
+ state.result = _result;
4795
+ }
4796
+ return detected;
4797
+ }
4798
+ function readTagProperty(state) {
4799
+ let isVerbatim = false;
4800
+ let isNamed = false;
4801
+ let tagHandle;
4802
+ let tagName;
4803
+ let ch = state.input.charCodeAt(state.position);
4804
+ if (ch !== 33) return false;
4805
+ if (state.tag !== null) {
4806
+ throwError(state, "duplication of a tag property");
4807
+ }
4808
+ ch = state.input.charCodeAt(++state.position);
4809
+ if (ch === 60) {
4810
+ isVerbatim = true;
4811
+ ch = state.input.charCodeAt(++state.position);
4812
+ } else if (ch === 33) {
4813
+ isNamed = true;
4814
+ tagHandle = "!!";
4815
+ ch = state.input.charCodeAt(++state.position);
4816
+ } else {
4817
+ tagHandle = "!";
4818
+ }
4819
+ let _position = state.position;
4820
+ if (isVerbatim) {
4821
+ do {
4822
+ ch = state.input.charCodeAt(++state.position);
4823
+ } while (ch !== 0 && ch !== 62);
4824
+ if (state.position < state.length) {
4825
+ tagName = state.input.slice(_position, state.position);
4826
+ ch = state.input.charCodeAt(++state.position);
4827
+ } else {
4828
+ throwError(state, "unexpected end of the stream within a verbatim tag");
4829
+ }
4830
+ } else {
4831
+ while (ch !== 0 && !isWsOrEol(ch)) {
4832
+ if (ch === 33) {
4833
+ if (!isNamed) {
4834
+ tagHandle = state.input.slice(_position - 1, state.position + 1);
4835
+ if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
4836
+ throwError(state, "named tag handle cannot contain such characters");
4837
+ }
4838
+ isNamed = true;
4839
+ _position = state.position + 1;
4840
+ } else {
4841
+ throwError(state, "tag suffix cannot contain exclamation marks");
4842
+ }
4843
+ }
4844
+ ch = state.input.charCodeAt(++state.position);
4845
+ }
4846
+ tagName = state.input.slice(_position, state.position);
4847
+ if (PATTERN_FLOW_INDICATORS.test(tagName)) {
4848
+ throwError(state, "tag suffix cannot contain flow indicator characters");
4849
+ }
4850
+ }
4851
+ if (tagName && !PATTERN_TAG_URI.test(tagName)) {
4852
+ throwError(state, "tag name cannot contain such characters: " + tagName);
4853
+ }
4854
+ try {
4855
+ tagName = decodeURIComponent(tagName);
4856
+ } catch (err) {
4857
+ throwError(state, "tag name is malformed: " + tagName);
4858
+ }
4859
+ if (isVerbatim) {
4860
+ state.tag = tagName;
4861
+ } else if (_hasOwnProperty.call(state.tagMap, tagHandle)) {
4862
+ state.tag = state.tagMap[tagHandle] + tagName;
4863
+ } else if (tagHandle === "!") {
4864
+ state.tag = "!" + tagName;
4865
+ } else if (tagHandle === "!!") {
4866
+ state.tag = "tag:yaml.org,2002:" + tagName;
4867
+ } else {
4868
+ throwError(state, 'undeclared tag handle "' + tagHandle + '"');
4869
+ }
4870
+ return true;
4871
+ }
4872
+ function readAnchorProperty(state) {
4873
+ let ch = state.input.charCodeAt(state.position);
4874
+ if (ch !== 38) return false;
4875
+ if (state.anchor !== null) {
4876
+ throwError(state, "duplication of an anchor property");
4877
+ }
4878
+ ch = state.input.charCodeAt(++state.position);
4879
+ const _position = state.position;
4880
+ while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
4881
+ ch = state.input.charCodeAt(++state.position);
4882
+ }
4883
+ if (state.position === _position) {
4884
+ throwError(state, "name of an anchor node must contain at least one character");
4885
+ }
4886
+ state.anchor = state.input.slice(_position, state.position);
4887
+ return true;
4888
+ }
4889
+ function readAlias(state) {
4890
+ let ch = state.input.charCodeAt(state.position);
4891
+ if (ch !== 42) return false;
4892
+ ch = state.input.charCodeAt(++state.position);
4893
+ const _position = state.position;
4894
+ while (ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)) {
4895
+ ch = state.input.charCodeAt(++state.position);
4896
+ }
4897
+ if (state.position === _position) {
4898
+ throwError(state, "name of an alias node must contain at least one character");
4899
+ }
4900
+ const alias = state.input.slice(_position, state.position);
4901
+ if (!_hasOwnProperty.call(state.anchorMap, alias)) {
4902
+ throwError(state, 'unidentified alias "' + alias + '"');
4903
+ }
4904
+ state.result = state.anchorMap[alias];
4905
+ skipSeparationSpace(state, true, -1);
4906
+ return true;
4907
+ }
4908
+ function tryReadBlockMappingFromProperty(state, propertyStart, nodeIndent, flowIndent) {
4909
+ const fallbackState = snapshotState(state);
4910
+ beginAnchorTransaction(state);
4911
+ restoreState(state, propertyStart);
4912
+ state.tag = null;
4913
+ state.anchor = null;
4914
+ state.kind = null;
4915
+ state.result = null;
4916
+ if (readBlockMapping(state, nodeIndent, flowIndent) && state.kind === "mapping") {
4917
+ commitAnchorTransaction(state);
4918
+ return true;
4919
+ }
4920
+ rollbackAnchorTransaction(state);
4921
+ restoreState(state, fallbackState);
4922
+ return false;
4923
+ }
4924
+ function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
4925
+ let allowBlockScalars;
4926
+ let allowBlockCollections;
4927
+ let indentStatus = 1;
4928
+ let atNewLine = false;
4929
+ let hasContent = false;
4930
+ let propertyStart = null;
4931
+ let type2;
4932
+ let flowIndent;
4933
+ let blockIndent;
4934
+ if (state.depth >= state.maxDepth) {
4935
+ throwError(state, "nesting exceeded maxDepth (" + state.maxDepth + ")");
4936
+ }
4937
+ state.depth += 1;
4938
+ if (state.listener !== null) {
4939
+ state.listener("open", state);
4940
+ }
4941
+ state.tag = null;
4942
+ state.anchor = null;
4943
+ state.kind = null;
4944
+ state.result = null;
4945
+ const allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext;
4946
+ if (allowToSeek) {
4947
+ if (skipSeparationSpace(state, true, -1)) {
4948
+ atNewLine = true;
4949
+ if (state.lineIndent > parentIndent) {
4950
+ indentStatus = 1;
4951
+ } else if (state.lineIndent === parentIndent) {
4952
+ indentStatus = 0;
4953
+ } else if (state.lineIndent < parentIndent) {
4954
+ indentStatus = -1;
4955
+ }
4956
+ }
4957
+ }
4958
+ if (indentStatus === 1) {
4959
+ while (true) {
4960
+ const ch = state.input.charCodeAt(state.position);
4961
+ const propertyState = snapshotState(state);
4962
+ if (atNewLine && (ch === 33 && state.tag !== null || ch === 38 && state.anchor !== null)) {
4963
+ break;
4964
+ }
4965
+ if (!readTagProperty(state) && !readAnchorProperty(state)) {
4966
+ break;
4967
+ }
4968
+ if (propertyStart === null) {
4969
+ propertyStart = propertyState;
4970
+ }
4971
+ if (skipSeparationSpace(state, true, -1)) {
4972
+ atNewLine = true;
4973
+ allowBlockCollections = allowBlockStyles;
4974
+ if (state.lineIndent > parentIndent) {
4975
+ indentStatus = 1;
4976
+ } else if (state.lineIndent === parentIndent) {
4977
+ indentStatus = 0;
4978
+ } else if (state.lineIndent < parentIndent) {
4979
+ indentStatus = -1;
4980
+ }
4981
+ } else {
4982
+ allowBlockCollections = false;
4983
+ }
4984
+ }
4985
+ }
4986
+ if (allowBlockCollections) {
4987
+ allowBlockCollections = atNewLine || allowCompact;
4988
+ }
4989
+ if (indentStatus === 1 || CONTEXT_BLOCK_OUT === nodeContext) {
4990
+ if (CONTEXT_FLOW_IN === nodeContext || CONTEXT_FLOW_OUT === nodeContext) {
4991
+ flowIndent = parentIndent;
4992
+ } else {
4993
+ flowIndent = parentIndent + 1;
4994
+ }
4995
+ blockIndent = state.position - state.lineStart;
4996
+ if (indentStatus === 1) {
4997
+ if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) {
4998
+ hasContent = true;
4999
+ } else {
5000
+ const ch = state.input.charCodeAt(state.position);
5001
+ if (propertyStart !== null && allowBlockStyles && !allowBlockCollections && ch !== 124 && ch !== 62 && tryReadBlockMappingFromProperty(
5002
+ state,
5003
+ propertyStart,
5004
+ propertyStart.position - propertyStart.lineStart,
5005
+ flowIndent
5006
+ )) {
5007
+ hasContent = true;
5008
+ } else if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) {
5009
+ hasContent = true;
5010
+ } else if (readAlias(state)) {
5011
+ hasContent = true;
5012
+ if (state.tag !== null || state.anchor !== null) {
5013
+ throwError(state, "alias node should not have any properties");
5014
+ }
5015
+ } else if (readPlainScalar(state, flowIndent, CONTEXT_FLOW_IN === nodeContext)) {
5016
+ hasContent = true;
5017
+ if (state.tag === null) {
5018
+ state.tag = "?";
5019
+ }
5020
+ }
5021
+ if (state.anchor !== null) {
5022
+ storeAnchor(state, state.anchor, state.result);
5023
+ }
5024
+ }
5025
+ } else if (indentStatus === 0) {
5026
+ hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
5027
+ }
5028
+ }
5029
+ if (state.tag === null) {
5030
+ if (state.anchor !== null) {
5031
+ storeAnchor(state, state.anchor, state.result);
5032
+ }
5033
+ } else if (state.tag === "?") {
5034
+ if (state.result !== null && state.kind !== "scalar") {
5035
+ throwError(state, 'unacceptable node kind for !<?> tag; it should be "scalar", not "' + state.kind + '"');
5036
+ }
5037
+ for (let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex += 1) {
5038
+ type2 = state.implicitTypes[typeIndex];
5039
+ if (type2.resolve(state.result)) {
5040
+ state.result = type2.construct(state.result);
5041
+ state.tag = type2.tag;
5042
+ if (state.anchor !== null) {
5043
+ storeAnchor(state, state.anchor, state.result);
5044
+ }
5045
+ break;
5046
+ }
5047
+ }
5048
+ } else if (state.tag !== "!") {
5049
+ if (_hasOwnProperty.call(state.typeMap[state.kind || "fallback"], state.tag)) {
5050
+ type2 = state.typeMap[state.kind || "fallback"][state.tag];
5051
+ } else {
5052
+ type2 = null;
5053
+ const typeList = state.typeMap.multi[state.kind || "fallback"];
5054
+ for (let typeIndex = 0, typeQuantity = typeList.length; typeIndex < typeQuantity; typeIndex += 1) {
5055
+ if (state.tag.slice(0, typeList[typeIndex].tag.length) === typeList[typeIndex].tag) {
5056
+ type2 = typeList[typeIndex];
5057
+ break;
5058
+ }
5059
+ }
5060
+ }
5061
+ if (!type2) {
5062
+ throwError(state, "unknown tag !<" + state.tag + ">");
5063
+ }
5064
+ if (state.result !== null && type2.kind !== state.kind) {
5065
+ throwError(state, "unacceptable node kind for !<" + state.tag + '> tag; it should be "' + type2.kind + '", not "' + state.kind + '"');
5066
+ }
5067
+ if (!type2.resolve(state.result, state.tag)) {
5068
+ throwError(state, "cannot resolve a node with !<" + state.tag + "> explicit tag");
5069
+ } else {
5070
+ state.result = type2.construct(state.result, state.tag);
5071
+ if (state.anchor !== null) {
5072
+ storeAnchor(state, state.anchor, state.result);
5073
+ }
5074
+ }
5075
+ }
5076
+ if (state.listener !== null) {
5077
+ state.listener("close", state);
5078
+ }
5079
+ state.depth -= 1;
5080
+ return state.tag !== null || state.anchor !== null || hasContent;
5081
+ }
5082
+ function readDocument(state) {
5083
+ const documentStart = state.position;
5084
+ let hasDirectives = false;
5085
+ let ch;
5086
+ state.version = null;
5087
+ state.checkLineBreaks = state.legacy;
5088
+ state.tagMap = /* @__PURE__ */ Object.create(null);
5089
+ state.anchorMap = /* @__PURE__ */ Object.create(null);
5090
+ while ((ch = state.input.charCodeAt(state.position)) !== 0) {
5091
+ skipSeparationSpace(state, true, -1);
5092
+ ch = state.input.charCodeAt(state.position);
5093
+ if (state.lineIndent > 0 || ch !== 37) {
5094
+ break;
5095
+ }
5096
+ hasDirectives = true;
5097
+ ch = state.input.charCodeAt(++state.position);
5098
+ let _position = state.position;
5099
+ while (ch !== 0 && !isWsOrEol(ch)) {
5100
+ ch = state.input.charCodeAt(++state.position);
5101
+ }
5102
+ const directiveName = state.input.slice(_position, state.position);
5103
+ const directiveArgs = [];
5104
+ if (directiveName.length < 1) {
5105
+ throwError(state, "directive name must not be less than one character in length");
5106
+ }
5107
+ while (ch !== 0) {
5108
+ while (isWhiteSpace(ch)) {
5109
+ ch = state.input.charCodeAt(++state.position);
5110
+ }
5111
+ if (ch === 35) {
5112
+ do {
5113
+ ch = state.input.charCodeAt(++state.position);
5114
+ } while (ch !== 0 && !isEol(ch));
5115
+ break;
5116
+ }
5117
+ if (isEol(ch)) break;
5118
+ _position = state.position;
5119
+ while (ch !== 0 && !isWsOrEol(ch)) {
5120
+ ch = state.input.charCodeAt(++state.position);
5121
+ }
5122
+ directiveArgs.push(state.input.slice(_position, state.position));
5123
+ }
5124
+ if (ch !== 0) readLineBreak(state);
5125
+ if (_hasOwnProperty.call(directiveHandlers, directiveName)) {
5126
+ directiveHandlers[directiveName](state, directiveName, directiveArgs);
5127
+ } else {
5128
+ throwWarning(state, 'unknown document directive "' + directiveName + '"');
5129
+ }
5130
+ }
5131
+ skipSeparationSpace(state, true, -1);
5132
+ if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 45 && state.input.charCodeAt(state.position + 1) === 45 && state.input.charCodeAt(state.position + 2) === 45) {
5133
+ state.position += 3;
5134
+ skipSeparationSpace(state, true, -1);
5135
+ } else if (hasDirectives) {
5136
+ throwError(state, "directives end mark is expected");
5137
+ }
5138
+ composeNode(state, state.lineIndent - 1, CONTEXT_BLOCK_OUT, false, true);
5139
+ skipSeparationSpace(state, true, -1);
5140
+ if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
5141
+ throwWarning(state, "non-ASCII line breaks are interpreted as content");
5142
+ }
5143
+ state.documents.push(state.result);
5144
+ if (state.position === state.lineStart && testDocumentSeparator(state)) {
5145
+ if (state.input.charCodeAt(state.position) === 46) {
5146
+ state.position += 3;
5147
+ skipSeparationSpace(state, true, -1);
5148
+ }
5149
+ return;
5150
+ }
5151
+ if (state.position < state.length - 1) {
5152
+ throwError(state, "end of the stream or a document separator is expected");
5153
+ }
5154
+ }
5155
+ function loadDocuments(input, options) {
5156
+ input = String(input);
5157
+ options = options || {};
5158
+ if (input.length !== 0) {
5159
+ if (input.charCodeAt(input.length - 1) !== 10 && input.charCodeAt(input.length - 1) !== 13) {
5160
+ input += "\n";
5161
+ }
5162
+ if (input.charCodeAt(0) === 65279) {
5163
+ input = input.slice(1);
5164
+ }
5165
+ }
5166
+ const state = new State(input, options);
5167
+ const nullpos = input.indexOf("\0");
5168
+ if (nullpos !== -1) {
5169
+ state.position = nullpos;
5170
+ throwError(state, "null byte is not allowed in input");
5171
+ }
5172
+ state.input += "\0";
5173
+ while (state.input.charCodeAt(state.position) === 32) {
5174
+ state.lineIndent += 1;
5175
+ state.position += 1;
5176
+ }
5177
+ while (state.position < state.length - 1) {
5178
+ readDocument(state);
5179
+ }
5180
+ return state.documents;
5181
+ }
5182
+ function loadAll2(input, iterator, options) {
5183
+ if (iterator !== null && typeof iterator === "object" && typeof options === "undefined") {
5184
+ options = iterator;
5185
+ iterator = null;
5186
+ }
5187
+ const documents = loadDocuments(input, options);
5188
+ if (typeof iterator !== "function") {
5189
+ return documents;
5190
+ }
5191
+ for (let index = 0, length = documents.length; index < length; index += 1) {
5192
+ iterator(documents[index]);
5193
+ }
5194
+ }
5195
+ function load2(input, options) {
5196
+ const documents = loadDocuments(input, options);
5197
+ if (documents.length === 0) {
5198
+ return void 0;
5199
+ } else if (documents.length === 1) {
5200
+ return documents[0];
5201
+ }
5202
+ throw new YAMLException2("expected a single document in the stream, but found more");
5203
+ }
5204
+ loader.loadAll = loadAll2;
5205
+ loader.load = load2;
5206
+ return loader;
5207
+ }
5208
+ var dumper = {};
5209
+ var hasRequiredDumper;
5210
+ function requireDumper() {
5211
+ if (hasRequiredDumper) return dumper;
5212
+ hasRequiredDumper = 1;
5213
+ const common2 = requireCommon();
5214
+ const YAMLException2 = requireException();
5215
+ const DEFAULT_SCHEMA2 = require_default();
5216
+ const _toString = Object.prototype.toString;
5217
+ const _hasOwnProperty = Object.prototype.hasOwnProperty;
5218
+ const CHAR_BOM = 65279;
5219
+ const CHAR_TAB = 9;
5220
+ const CHAR_LINE_FEED = 10;
5221
+ const CHAR_CARRIAGE_RETURN = 13;
5222
+ const CHAR_SPACE = 32;
5223
+ const CHAR_EXCLAMATION = 33;
5224
+ const CHAR_DOUBLE_QUOTE = 34;
5225
+ const CHAR_SHARP = 35;
5226
+ const CHAR_PERCENT = 37;
5227
+ const CHAR_AMPERSAND = 38;
5228
+ const CHAR_SINGLE_QUOTE = 39;
5229
+ const CHAR_ASTERISK = 42;
5230
+ const CHAR_COMMA = 44;
5231
+ const CHAR_MINUS = 45;
5232
+ const CHAR_COLON = 58;
5233
+ const CHAR_EQUALS = 61;
5234
+ const CHAR_GREATER_THAN = 62;
5235
+ const CHAR_QUESTION = 63;
5236
+ const CHAR_COMMERCIAL_AT = 64;
5237
+ const CHAR_LEFT_SQUARE_BRACKET = 91;
5238
+ const CHAR_RIGHT_SQUARE_BRACKET = 93;
5239
+ const CHAR_GRAVE_ACCENT = 96;
5240
+ const CHAR_LEFT_CURLY_BRACKET = 123;
5241
+ const CHAR_VERTICAL_LINE = 124;
5242
+ const CHAR_RIGHT_CURLY_BRACKET = 125;
5243
+ const ESCAPE_SEQUENCES = {};
5244
+ ESCAPE_SEQUENCES[0] = "\\0";
5245
+ ESCAPE_SEQUENCES[7] = "\\a";
5246
+ ESCAPE_SEQUENCES[8] = "\\b";
5247
+ ESCAPE_SEQUENCES[9] = "\\t";
5248
+ ESCAPE_SEQUENCES[10] = "\\n";
5249
+ ESCAPE_SEQUENCES[11] = "\\v";
5250
+ ESCAPE_SEQUENCES[12] = "\\f";
5251
+ ESCAPE_SEQUENCES[13] = "\\r";
5252
+ ESCAPE_SEQUENCES[27] = "\\e";
5253
+ ESCAPE_SEQUENCES[34] = '\\"';
5254
+ ESCAPE_SEQUENCES[92] = "\\\\";
5255
+ ESCAPE_SEQUENCES[133] = "\\N";
5256
+ ESCAPE_SEQUENCES[160] = "\\_";
5257
+ ESCAPE_SEQUENCES[8232] = "\\L";
5258
+ ESCAPE_SEQUENCES[8233] = "\\P";
5259
+ const DEPRECATED_BOOLEANS_SYNTAX = [
5260
+ "y",
5261
+ "Y",
5262
+ "yes",
5263
+ "Yes",
5264
+ "YES",
5265
+ "on",
5266
+ "On",
5267
+ "ON",
5268
+ "n",
5269
+ "N",
5270
+ "no",
5271
+ "No",
5272
+ "NO",
5273
+ "off",
5274
+ "Off",
5275
+ "OFF"
5276
+ ];
5277
+ const DEPRECATED_BASE60_SYNTAX = /^[-+]?[0-9_]+(?::[0-9_]+)+(?:\.[0-9_]*)?$/;
5278
+ function compileStyleMap(schema2, map2) {
5279
+ if (map2 === null) return {};
5280
+ const result = {};
5281
+ const keys = Object.keys(map2);
5282
+ for (let index = 0, length = keys.length; index < length; index += 1) {
5283
+ let tag = keys[index];
5284
+ let style = String(map2[tag]);
5285
+ if (tag.slice(0, 2) === "!!") {
5286
+ tag = "tag:yaml.org,2002:" + tag.slice(2);
5287
+ }
5288
+ const type2 = schema2.compiledTypeMap["fallback"][tag];
5289
+ if (type2 && _hasOwnProperty.call(type2.styleAliases, style)) {
5290
+ style = type2.styleAliases[style];
5291
+ }
5292
+ result[tag] = style;
5293
+ }
5294
+ return result;
5295
+ }
5296
+ function encodeHex(character) {
5297
+ let handle;
5298
+ let length;
5299
+ const string = character.toString(16).toUpperCase();
5300
+ if (character <= 255) {
5301
+ handle = "x";
5302
+ length = 2;
5303
+ } else if (character <= 65535) {
5304
+ handle = "u";
5305
+ length = 4;
5306
+ } else if (character <= 4294967295) {
5307
+ handle = "U";
5308
+ length = 8;
5309
+ } else {
5310
+ throw new YAMLException2("code point within a string may not be greater than 0xFFFFFFFF");
5311
+ }
5312
+ return "\\" + handle + common2.repeat("0", length - string.length) + string;
5313
+ }
5314
+ const QUOTING_TYPE_SINGLE = 1;
5315
+ const QUOTING_TYPE_DOUBLE = 2;
5316
+ function State(options) {
5317
+ this.schema = options["schema"] || DEFAULT_SCHEMA2;
5318
+ this.indent = Math.max(1, options["indent"] || 2);
5319
+ this.noArrayIndent = options["noArrayIndent"] || false;
5320
+ this.skipInvalid = options["skipInvalid"] || false;
5321
+ this.flowLevel = common2.isNothing(options["flowLevel"]) ? -1 : options["flowLevel"];
5322
+ this.styleMap = compileStyleMap(this.schema, options["styles"] || null);
5323
+ this.sortKeys = options["sortKeys"] || false;
5324
+ this.lineWidth = options["lineWidth"] || 80;
5325
+ this.noRefs = options["noRefs"] || false;
5326
+ this.noCompatMode = options["noCompatMode"] || false;
5327
+ this.condenseFlow = options["condenseFlow"] || false;
5328
+ this.quotingType = options["quotingType"] === '"' ? QUOTING_TYPE_DOUBLE : QUOTING_TYPE_SINGLE;
5329
+ this.forceQuotes = options["forceQuotes"] || false;
5330
+ this.replacer = typeof options["replacer"] === "function" ? options["replacer"] : null;
5331
+ this.implicitTypes = this.schema.compiledImplicit;
5332
+ this.explicitTypes = this.schema.compiledExplicit;
5333
+ this.tag = null;
5334
+ this.result = "";
5335
+ this.duplicates = [];
5336
+ this.usedDuplicates = null;
5337
+ }
5338
+ function indentString(string, spaces) {
5339
+ const ind = common2.repeat(" ", spaces);
5340
+ let position = 0;
5341
+ let result = "";
5342
+ const length = string.length;
5343
+ while (position < length) {
5344
+ let line;
5345
+ const next = string.indexOf("\n", position);
5346
+ if (next === -1) {
5347
+ line = string.slice(position);
5348
+ position = length;
5349
+ } else {
5350
+ line = string.slice(position, next + 1);
5351
+ position = next + 1;
5352
+ }
5353
+ if (line.length && line !== "\n") result += ind;
5354
+ result += line;
5355
+ }
5356
+ return result;
5357
+ }
5358
+ function generateNextLine(state, level) {
5359
+ return "\n" + common2.repeat(" ", state.indent * level);
5360
+ }
5361
+ function testImplicitResolving(state, str2) {
5362
+ for (let index = 0, length = state.implicitTypes.length; index < length; index += 1) {
5363
+ const type2 = state.implicitTypes[index];
5364
+ if (type2.resolve(str2)) {
5365
+ return true;
5366
+ }
5367
+ }
5368
+ return false;
5369
+ }
5370
+ function isWhitespace(c) {
5371
+ return c === CHAR_SPACE || c === CHAR_TAB;
5372
+ }
5373
+ function isPrintable(c) {
5374
+ return c >= 32 && c <= 126 || c >= 161 && c <= 55295 && c !== 8232 && c !== 8233 || c >= 57344 && c <= 65533 && c !== CHAR_BOM || c >= 65536 && c <= 1114111;
5375
+ }
5376
+ function isNsCharOrWhitespace(c) {
5377
+ return isPrintable(c) && c !== CHAR_BOM && // - b-char
5378
+ c !== CHAR_CARRIAGE_RETURN && c !== CHAR_LINE_FEED;
5379
+ }
5380
+ function isPlainSafe(c, prev, inblock) {
5381
+ const cIsNsCharOrWhitespace = isNsCharOrWhitespace(c);
5382
+ const cIsNsChar = cIsNsCharOrWhitespace && !isWhitespace(c);
5383
+ return (
5384
+ // ns-plain-safe
5385
+ (inblock ? cIsNsCharOrWhitespace : cIsNsCharOrWhitespace && // - c-flow-indicator
5386
+ c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET) && // ns-plain-char
5387
+ c !== CHAR_SHARP && // false on '#'
5388
+ !(prev === CHAR_COLON && !cIsNsChar) || // false on ': '
5389
+ isNsCharOrWhitespace(prev) && !isWhitespace(prev) && c === CHAR_SHARP || // change to true on '[^ ]#'
5390
+ prev === CHAR_COLON && cIsNsChar
5391
+ );
5392
+ }
5393
+ function isPlainSafeFirst(c) {
5394
+ return isPrintable(c) && c !== CHAR_BOM && !isWhitespace(c) && // - s-white
5395
+ // - (c-indicator ::=
5396
+ // “-” | “?” | “:” | “,” | “[” | “]” | “{” | “}”
5397
+ c !== CHAR_MINUS && c !== CHAR_QUESTION && c !== CHAR_COLON && c !== CHAR_COMMA && c !== CHAR_LEFT_SQUARE_BRACKET && c !== CHAR_RIGHT_SQUARE_BRACKET && c !== CHAR_LEFT_CURLY_BRACKET && c !== CHAR_RIGHT_CURLY_BRACKET && // | “#” | “&” | “*” | “!” | “|” | “=” | “>” | “'” | “"”
5398
+ c !== CHAR_SHARP && c !== CHAR_AMPERSAND && c !== CHAR_ASTERISK && c !== CHAR_EXCLAMATION && c !== CHAR_VERTICAL_LINE && c !== CHAR_EQUALS && c !== CHAR_GREATER_THAN && c !== CHAR_SINGLE_QUOTE && c !== CHAR_DOUBLE_QUOTE && // | “%” | “@” | “`”)
5399
+ c !== CHAR_PERCENT && c !== CHAR_COMMERCIAL_AT && c !== CHAR_GRAVE_ACCENT;
5400
+ }
5401
+ function isPlainSafeLast(c) {
5402
+ return !isWhitespace(c) && c !== CHAR_COLON;
5403
+ }
5404
+ function codePointAt(string, pos) {
5405
+ const first = string.charCodeAt(pos);
5406
+ let second;
5407
+ if (first >= 55296 && first <= 56319 && pos + 1 < string.length) {
5408
+ second = string.charCodeAt(pos + 1);
5409
+ if (second >= 56320 && second <= 57343) {
5410
+ return (first - 55296) * 1024 + second - 56320 + 65536;
5411
+ }
5412
+ }
5413
+ return first;
5414
+ }
5415
+ function needIndentIndicator(string) {
5416
+ const leadingSpaceRe = /^\n* /;
5417
+ return leadingSpaceRe.test(string);
5418
+ }
5419
+ const STYLE_PLAIN = 1;
5420
+ const STYLE_SINGLE = 2;
5421
+ const STYLE_LITERAL = 3;
5422
+ const STYLE_FOLDED = 4;
5423
+ const STYLE_DOUBLE = 5;
5424
+ function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType, quotingType, forceQuotes, inblock) {
5425
+ let i;
5426
+ let char = 0;
5427
+ let prevChar = null;
5428
+ let hasLineBreak = false;
5429
+ let hasFoldableLine = false;
5430
+ const shouldTrackWidth = lineWidth !== -1;
5431
+ let previousLineBreak = -1;
5432
+ let plain = isPlainSafeFirst(codePointAt(string, 0)) && isPlainSafeLast(codePointAt(string, string.length - 1));
5433
+ if (singleLineOnly || forceQuotes) {
5434
+ for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
5435
+ char = codePointAt(string, i);
5436
+ if (!isPrintable(char)) {
5437
+ return STYLE_DOUBLE;
5438
+ }
5439
+ plain = plain && isPlainSafe(char, prevChar, inblock);
5440
+ prevChar = char;
5441
+ }
5442
+ } else {
5443
+ for (i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
5444
+ char = codePointAt(string, i);
5445
+ if (char === CHAR_LINE_FEED) {
5446
+ hasLineBreak = true;
5447
+ if (shouldTrackWidth) {
5448
+ hasFoldableLine = hasFoldableLine || // Foldable line = too long, and not more-indented.
5449
+ i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
5450
+ previousLineBreak = i;
5451
+ }
5452
+ } else if (!isPrintable(char)) {
5453
+ return STYLE_DOUBLE;
5454
+ }
5455
+ plain = plain && isPlainSafe(char, prevChar, inblock);
5456
+ prevChar = char;
5457
+ }
5458
+ hasFoldableLine = hasFoldableLine || shouldTrackWidth && (i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ");
5459
+ }
5460
+ if (!hasLineBreak && !hasFoldableLine) {
5461
+ if (plain && !forceQuotes && !testAmbiguousType(string)) {
5462
+ return STYLE_PLAIN;
5463
+ }
5464
+ return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
5465
+ }
5466
+ if (indentPerLevel > 9 && needIndentIndicator(string)) {
5467
+ return STYLE_DOUBLE;
5468
+ }
5469
+ if (!forceQuotes) {
5470
+ return hasFoldableLine ? STYLE_FOLDED : STYLE_LITERAL;
5471
+ }
5472
+ return quotingType === QUOTING_TYPE_DOUBLE ? STYLE_DOUBLE : STYLE_SINGLE;
5473
+ }
5474
+ function writeScalar(state, string, level, iskey, inblock) {
5475
+ state.dump = (function() {
5476
+ if (string.length === 0) {
5477
+ return state.quotingType === QUOTING_TYPE_DOUBLE ? '""' : "''";
5478
+ }
5479
+ if (!state.noCompatMode) {
5480
+ if (DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1 || DEPRECATED_BASE60_SYNTAX.test(string)) {
5481
+ return state.quotingType === QUOTING_TYPE_DOUBLE ? '"' + string + '"' : "'" + string + "'";
5482
+ }
5483
+ }
5484
+ const indent = state.indent * Math.max(1, level);
5485
+ const lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
5486
+ const singleLineOnly = iskey || // No block styles in flow mode.
5487
+ state.flowLevel > -1 && level >= state.flowLevel;
5488
+ function testAmbiguity(string2) {
5489
+ return testImplicitResolving(state, string2);
5490
+ }
5491
+ switch (chooseScalarStyle(
5492
+ string,
5493
+ singleLineOnly,
5494
+ state.indent,
5495
+ lineWidth,
5496
+ testAmbiguity,
5497
+ state.quotingType,
5498
+ state.forceQuotes && !iskey,
5499
+ inblock
5500
+ )) {
5501
+ case STYLE_PLAIN:
5502
+ return string;
5503
+ case STYLE_SINGLE:
5504
+ return "'" + string.replace(/'/g, "''") + "'";
5505
+ case STYLE_LITERAL:
5506
+ return "|" + blockHeader(string, state.indent) + dropEndingNewline(indentString(string, indent));
5507
+ case STYLE_FOLDED:
5508
+ return ">" + blockHeader(string, state.indent) + dropEndingNewline(indentString(foldString(string, lineWidth), indent));
5509
+ case STYLE_DOUBLE:
5510
+ return '"' + escapeString(string) + '"';
5511
+ default:
5512
+ throw new YAMLException2("impossible error: invalid scalar style");
5513
+ }
5514
+ })();
5515
+ }
5516
+ function blockHeader(string, indentPerLevel) {
5517
+ const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : "";
5518
+ const clip = string[string.length - 1] === "\n";
5519
+ const keep = clip && (string[string.length - 2] === "\n" || string === "\n");
5520
+ const chomp = keep ? "+" : clip ? "" : "-";
5521
+ return indentIndicator + chomp + "\n";
5522
+ }
5523
+ function dropEndingNewline(string) {
5524
+ return string[string.length - 1] === "\n" ? string.slice(0, -1) : string;
5525
+ }
5526
+ function foldString(string, width) {
5527
+ const lineRe = /(\n+)([^\n]*)/g;
5528
+ let result = (function() {
5529
+ let nextLF = string.indexOf("\n");
5530
+ nextLF = nextLF !== -1 ? nextLF : string.length;
5531
+ lineRe.lastIndex = nextLF;
5532
+ return foldLine(string.slice(0, nextLF), width);
5533
+ })();
5534
+ let prevMoreIndented = string[0] === "\n" || string[0] === " ";
5535
+ let moreIndented;
5536
+ let match;
5537
+ while (match = lineRe.exec(string)) {
5538
+ const prefix = match[1];
5539
+ const line = match[2];
5540
+ moreIndented = line[0] === " ";
5541
+ result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
5542
+ prevMoreIndented = moreIndented;
5543
+ }
5544
+ return result;
5545
+ }
5546
+ function foldLine(line, width) {
5547
+ if (line === "" || line[0] === " ") return line;
5548
+ const breakRe = / [^ ]/g;
5549
+ let match;
5550
+ let start = 0;
5551
+ let end;
5552
+ let curr = 0;
5553
+ let next = 0;
5554
+ let result = "";
5555
+ while (match = breakRe.exec(line)) {
5556
+ next = match.index;
5557
+ if (next - start > width) {
5558
+ end = curr > start ? curr : next;
5559
+ result += "\n" + line.slice(start, end);
5560
+ start = end + 1;
5561
+ }
5562
+ curr = next;
5563
+ }
5564
+ result += "\n";
5565
+ if (line.length - start > width && curr > start) {
5566
+ result += line.slice(start, curr) + "\n" + line.slice(curr + 1);
5567
+ } else {
5568
+ result += line.slice(start);
5569
+ }
5570
+ return result.slice(1);
5571
+ }
5572
+ function escapeString(string) {
5573
+ let result = "";
5574
+ let char = 0;
5575
+ for (let i = 0; i < string.length; char >= 65536 ? i += 2 : i++) {
5576
+ char = codePointAt(string, i);
5577
+ const escapeSeq = ESCAPE_SEQUENCES[char];
5578
+ if (!escapeSeq && isPrintable(char)) {
5579
+ result += string[i];
5580
+ if (char >= 65536) result += string[i + 1];
5581
+ } else {
5582
+ result += escapeSeq || encodeHex(char);
5583
+ }
5584
+ }
5585
+ return result;
5586
+ }
5587
+ function writeFlowSequence(state, level, object) {
5588
+ let _result = "";
5589
+ const _tag = state.tag;
5590
+ for (let index = 0, length = object.length; index < length; index += 1) {
5591
+ let value = object[index];
5592
+ if (state.replacer) {
5593
+ value = state.replacer.call(object, String(index), value);
5594
+ }
5595
+ if (writeNode(state, level, value, false, false) || typeof value === "undefined" && writeNode(state, level, null, false, false)) {
5596
+ if (_result !== "") _result += "," + (!state.condenseFlow ? " " : "");
5597
+ _result += state.dump;
5598
+ }
5599
+ }
5600
+ state.tag = _tag;
5601
+ state.dump = "[" + _result + "]";
5602
+ }
5603
+ function writeBlockSequence(state, level, object, compact) {
5604
+ let _result = "";
5605
+ const _tag = state.tag;
5606
+ for (let index = 0, length = object.length; index < length; index += 1) {
5607
+ let value = object[index];
5608
+ if (state.replacer) {
5609
+ value = state.replacer.call(object, String(index), value);
5610
+ }
5611
+ if (writeNode(state, level + 1, value, true, true, false, true) || typeof value === "undefined" && writeNode(state, level + 1, null, true, true, false, true)) {
5612
+ if (!compact || _result !== "") {
5613
+ _result += generateNextLine(state, level);
5614
+ }
5615
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
5616
+ _result += "-";
5617
+ } else {
5618
+ _result += "- ";
5619
+ }
5620
+ _result += state.dump;
5621
+ }
5622
+ }
5623
+ state.tag = _tag;
5624
+ state.dump = _result || "[]";
5625
+ }
5626
+ function writeFlowMapping(state, level, object) {
5627
+ let _result = "";
5628
+ const _tag = state.tag;
5629
+ const objectKeyList = Object.keys(object);
5630
+ for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
5631
+ let pairBuffer = "";
5632
+ if (_result !== "") pairBuffer += ", ";
5633
+ if (state.condenseFlow) pairBuffer += '"';
5634
+ const objectKey = objectKeyList[index];
5635
+ let objectValue = object[objectKey];
5636
+ if (state.replacer) {
5637
+ objectValue = state.replacer.call(object, objectKey, objectValue);
5638
+ }
5639
+ if (!writeNode(state, level, objectKey, false, false)) {
5640
+ continue;
5641
+ }
5642
+ if (state.dump.length > 1024) pairBuffer += "? ";
5643
+ pairBuffer += state.dump + (state.condenseFlow ? '"' : "") + ":" + (state.condenseFlow ? "" : " ");
5644
+ if (!writeNode(state, level, objectValue, false, false)) {
5645
+ continue;
5646
+ }
5647
+ pairBuffer += state.dump;
5648
+ _result += pairBuffer;
5649
+ }
5650
+ state.tag = _tag;
5651
+ state.dump = "{" + _result + "}";
5652
+ }
5653
+ function writeBlockMapping(state, level, object, compact) {
5654
+ let _result = "";
5655
+ const _tag = state.tag;
5656
+ const objectKeyList = Object.keys(object);
5657
+ if (state.sortKeys === true) {
5658
+ objectKeyList.sort();
5659
+ } else if (typeof state.sortKeys === "function") {
5660
+ objectKeyList.sort(state.sortKeys);
5661
+ } else if (state.sortKeys) {
5662
+ throw new YAMLException2("sortKeys must be a boolean or a function");
5663
+ }
5664
+ for (let index = 0, length = objectKeyList.length; index < length; index += 1) {
5665
+ let pairBuffer = "";
5666
+ if (!compact || _result !== "") {
5667
+ pairBuffer += generateNextLine(state, level);
5668
+ }
5669
+ const objectKey = objectKeyList[index];
5670
+ let objectValue = object[objectKey];
5671
+ if (state.replacer) {
5672
+ objectValue = state.replacer.call(object, objectKey, objectValue);
5673
+ }
5674
+ if (!writeNode(state, level + 1, objectKey, true, true, true)) {
5675
+ continue;
5676
+ }
5677
+ const explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024;
5678
+ if (explicitPair) {
5679
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
5680
+ pairBuffer += "?";
5681
+ } else {
5682
+ pairBuffer += "? ";
5683
+ }
5684
+ }
5685
+ pairBuffer += state.dump;
5686
+ if (explicitPair) {
5687
+ pairBuffer += generateNextLine(state, level);
5688
+ }
5689
+ if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
5690
+ continue;
5691
+ }
5692
+ if (state.dump && CHAR_LINE_FEED === state.dump.charCodeAt(0)) {
5693
+ pairBuffer += ":";
5694
+ } else {
5695
+ pairBuffer += ": ";
5696
+ }
5697
+ pairBuffer += state.dump;
5698
+ _result += pairBuffer;
5699
+ }
5700
+ state.tag = _tag;
5701
+ state.dump = _result || "{}";
5702
+ }
5703
+ function detectType(state, object, explicit) {
5704
+ const typeList = explicit ? state.explicitTypes : state.implicitTypes;
5705
+ for (let index = 0, length = typeList.length; index < length; index += 1) {
5706
+ const type2 = typeList[index];
5707
+ if ((type2.instanceOf || type2.predicate) && (!type2.instanceOf || typeof object === "object" && object instanceof type2.instanceOf) && (!type2.predicate || type2.predicate(object))) {
5708
+ if (explicit) {
5709
+ if (type2.multi && type2.representName) {
5710
+ state.tag = type2.representName(object);
5711
+ } else {
5712
+ state.tag = type2.tag;
5713
+ }
5714
+ } else {
5715
+ state.tag = "?";
5716
+ }
5717
+ if (type2.represent) {
5718
+ const style = state.styleMap[type2.tag] || type2.defaultStyle;
5719
+ let _result;
5720
+ if (_toString.call(type2.represent) === "[object Function]") {
5721
+ _result = type2.represent(object, style);
5722
+ } else if (_hasOwnProperty.call(type2.represent, style)) {
5723
+ _result = type2.represent[style](object, style);
5724
+ } else {
5725
+ throw new YAMLException2("!<" + type2.tag + '> tag resolver accepts not "' + style + '" style');
5726
+ }
5727
+ state.dump = _result;
5728
+ }
5729
+ return true;
5730
+ }
5731
+ }
5732
+ return false;
5733
+ }
5734
+ function writeNode(state, level, object, block, compact, iskey, isblockseq) {
5735
+ state.tag = null;
5736
+ state.dump = object;
5737
+ if (!detectType(state, object, false)) {
5738
+ detectType(state, object, true);
5739
+ }
5740
+ const type2 = _toString.call(state.dump);
5741
+ const inblock = block;
5742
+ if (block) {
5743
+ block = state.flowLevel < 0 || state.flowLevel > level;
5744
+ }
5745
+ const objectOrArray = type2 === "[object Object]" || type2 === "[object Array]";
5746
+ let duplicateIndex;
5747
+ let duplicate;
5748
+ if (objectOrArray) {
5749
+ duplicateIndex = state.duplicates.indexOf(object);
5750
+ duplicate = duplicateIndex !== -1;
5751
+ }
5752
+ if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) {
5753
+ compact = false;
5754
+ }
5755
+ if (duplicate && state.usedDuplicates[duplicateIndex]) {
5756
+ state.dump = "*ref_" + duplicateIndex;
5757
+ } else {
5758
+ if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
5759
+ state.usedDuplicates[duplicateIndex] = true;
5760
+ }
5761
+ if (type2 === "[object Object]") {
5762
+ if (block && Object.keys(state.dump).length !== 0) {
5763
+ writeBlockMapping(state, level, state.dump, compact);
5764
+ if (duplicate) {
5765
+ state.dump = "&ref_" + duplicateIndex + state.dump;
5766
+ }
5767
+ } else {
5768
+ writeFlowMapping(state, level, state.dump);
5769
+ if (duplicate) {
5770
+ state.dump = "&ref_" + duplicateIndex + " " + state.dump;
5771
+ }
5772
+ }
5773
+ } else if (type2 === "[object Array]") {
5774
+ if (block && state.dump.length !== 0) {
5775
+ if (state.noArrayIndent && !isblockseq && level > 0) {
5776
+ writeBlockSequence(state, level - 1, state.dump, compact);
5777
+ } else {
5778
+ writeBlockSequence(state, level, state.dump, compact);
5779
+ }
5780
+ if (duplicate) {
5781
+ state.dump = "&ref_" + duplicateIndex + state.dump;
5782
+ }
5783
+ } else {
5784
+ writeFlowSequence(state, level, state.dump);
5785
+ if (duplicate) {
5786
+ state.dump = "&ref_" + duplicateIndex + " " + state.dump;
5787
+ }
5788
+ }
5789
+ } else if (type2 === "[object String]") {
5790
+ if (state.tag !== "?") {
5791
+ writeScalar(state, state.dump, level, iskey, inblock);
5792
+ }
5793
+ } else if (type2 === "[object Undefined]") {
5794
+ return false;
5795
+ } else {
5796
+ if (state.skipInvalid) return false;
5797
+ throw new YAMLException2("unacceptable kind of an object to dump " + type2);
5798
+ }
5799
+ if (state.tag !== null && state.tag !== "?") {
5800
+ let tagStr = encodeURI(
5801
+ state.tag[0] === "!" ? state.tag.slice(1) : state.tag
5802
+ ).replace(/!/g, "%21");
5803
+ if (state.tag[0] === "!") {
5804
+ tagStr = "!" + tagStr;
5805
+ } else if (tagStr.slice(0, 18) === "tag:yaml.org,2002:") {
5806
+ tagStr = "!!" + tagStr.slice(18);
5807
+ } else {
5808
+ tagStr = "!<" + tagStr + ">";
5809
+ }
5810
+ state.dump = tagStr + " " + state.dump;
5811
+ }
5812
+ }
5813
+ return true;
5814
+ }
5815
+ function getDuplicateReferences(object, state) {
5816
+ const objects = [];
5817
+ const duplicatesIndexes = [];
5818
+ inspectNode(object, objects, duplicatesIndexes);
5819
+ const length = duplicatesIndexes.length;
5820
+ for (let index = 0; index < length; index += 1) {
5821
+ state.duplicates.push(objects[duplicatesIndexes[index]]);
5822
+ }
5823
+ state.usedDuplicates = new Array(length);
5824
+ }
5825
+ function inspectNode(object, objects, duplicatesIndexes) {
5826
+ if (object !== null && typeof object === "object") {
5827
+ const index = objects.indexOf(object);
5828
+ if (index !== -1) {
5829
+ if (duplicatesIndexes.indexOf(index) === -1) {
5830
+ duplicatesIndexes.push(index);
5831
+ }
5832
+ } else {
5833
+ objects.push(object);
5834
+ if (Array.isArray(object)) {
5835
+ for (let i = 0, length = object.length; i < length; i += 1) {
5836
+ inspectNode(object[i], objects, duplicatesIndexes);
5837
+ }
5838
+ } else {
5839
+ const objectKeyList = Object.keys(object);
5840
+ for (let i = 0, length = objectKeyList.length; i < length; i += 1) {
5841
+ inspectNode(object[objectKeyList[i]], objects, duplicatesIndexes);
5842
+ }
5843
+ }
5844
+ }
5845
+ }
5846
+ }
5847
+ function dump2(input, options) {
5848
+ options = options || {};
5849
+ const state = new State(options);
5850
+ if (!state.noRefs) getDuplicateReferences(input, state);
5851
+ let value = input;
5852
+ if (state.replacer) {
5853
+ value = state.replacer.call({ "": value }, "", value);
5854
+ }
5855
+ if (writeNode(state, 0, value, true, true)) return state.dump + "\n";
5856
+ return "";
5857
+ }
5858
+ dumper.dump = dump2;
5859
+ return dumper;
5860
+ }
5861
+ var hasRequiredJsYaml;
5862
+ function requireJsYaml() {
5863
+ if (hasRequiredJsYaml) return jsYaml;
5864
+ hasRequiredJsYaml = 1;
5865
+ const loader2 = requireLoader();
5866
+ const dumper2 = requireDumper();
5867
+ function renamed(from, to) {
5868
+ return function() {
5869
+ throw new Error("Function yaml." + from + " is removed in js-yaml 4. Use yaml." + to + " instead, which is now safe by default.");
5870
+ };
5871
+ }
5872
+ jsYaml.Type = requireType();
5873
+ jsYaml.Schema = requireSchema();
5874
+ jsYaml.FAILSAFE_SCHEMA = requireFailsafe();
5875
+ jsYaml.JSON_SCHEMA = requireJson();
5876
+ jsYaml.CORE_SCHEMA = requireCore();
5877
+ jsYaml.DEFAULT_SCHEMA = require_default();
5878
+ jsYaml.load = loader2.load;
5879
+ jsYaml.loadAll = loader2.loadAll;
5880
+ jsYaml.dump = dumper2.dump;
5881
+ jsYaml.YAMLException = requireException();
5882
+ jsYaml.types = {
5883
+ binary: requireBinary(),
5884
+ float: requireFloat(),
5885
+ map: requireMap(),
5886
+ null: require_null(),
5887
+ pairs: requirePairs(),
5888
+ set: requireSet(),
5889
+ timestamp: requireTimestamp(),
5890
+ bool: requireBool(),
5891
+ int: requireInt(),
5892
+ merge: requireMerge(),
5893
+ omap: requireOmap(),
5894
+ seq: requireSeq(),
5895
+ str: requireStr()
5896
+ };
5897
+ jsYaml.safeLoad = renamed("safeLoad", "load");
5898
+ jsYaml.safeLoadAll = renamed("safeLoadAll", "loadAll");
5899
+ jsYaml.safeDump = renamed("safeDump", "dump");
5900
+ return jsYaml;
5901
+ }
5902
+ var jsYamlExports = requireJsYaml();
5903
+ var yaml = /* @__PURE__ */ getDefaultExportFromCjs(jsYamlExports);
5904
+ var {
5905
+ Type,
5906
+ Schema,
5907
+ FAILSAFE_SCHEMA,
5908
+ JSON_SCHEMA,
5909
+ CORE_SCHEMA,
5910
+ DEFAULT_SCHEMA,
5911
+ load,
5912
+ loadAll,
5913
+ dump,
5914
+ YAMLException,
5915
+ types,
5916
+ safeLoad,
5917
+ safeLoadAll,
5918
+ safeDump
5919
+ } = yaml;
5920
+
5921
+ // src/tools.ts
5922
+ var import_core = __toESM(require_dist(), 1);
5923
+
5924
+ // src/settings.ts
5925
+ import { promises as fs } from "fs";
5926
+ import * as os from "os";
5927
+ import * as path from "path";
5928
+ var DIR = path.join(os.homedir(), ".figma-mcp");
5929
+ var FILE = path.join(DIR, "settings.json");
5930
+ function settingsPath() {
5931
+ return FILE;
5932
+ }
5933
+ async function loadSettings() {
5934
+ try {
5935
+ const raw = await fs.readFile(FILE, "utf8");
5936
+ const parsed = JSON.parse(raw);
5937
+ if (!parsed.env || typeof parsed.env !== "object") parsed.env = {};
5938
+ return parsed;
5939
+ } catch {
5940
+ return { env: {} };
5941
+ }
5942
+ }
5943
+ async function saveSettings(patch) {
5944
+ const current = await loadSettings();
5945
+ const next = {
5946
+ ...current,
5947
+ ...patch,
5948
+ env: { ...current.env ?? {}, ...patch.env ?? {} }
5949
+ };
5950
+ await fs.mkdir(DIR, { recursive: true });
5951
+ await fs.writeFile(FILE, JSON.stringify(next, null, 2), { mode: 384 });
5952
+ return next;
5953
+ }
5954
+ async function clearSettings() {
5955
+ try {
5956
+ await fs.unlink(FILE);
5957
+ } catch {
5958
+ }
5959
+ }
5960
+
5961
+ // src/refresh.ts
5962
+ var SKEW_MS = 6e4;
5963
+ async function ensureFreshApiToken(apiUrl, force = false) {
5964
+ const settings = await loadSettings();
5965
+ const apiToken = settings.env?.FIGMA_MCP_TOKEN;
5966
+ if (!apiToken || !settings.refreshToken) return;
5967
+ if (!force) {
5968
+ if (!settings.apiTokenExpiresAt) return;
5969
+ if (Date.now() < settings.apiTokenExpiresAt - SKEW_MS) return;
5970
+ }
5971
+ const base = apiUrl.replace(/\/+$/, "");
5972
+ try {
5973
+ const res = await fetch(`${base}/auth/figma/cli-refresh`, {
5974
+ method: "POST",
5975
+ headers: { "Content-Type": "application/json" },
1860
5976
  body: JSON.stringify({ refresh_token: settings.refreshToken })
1861
5977
  });
1862
5978
  if (!res.ok) return;
@@ -1944,14 +6060,16 @@ function remoteExtractStyles(cfg, body) {
1944
6060
 
1945
6061
  // src/tools.ts
1946
6062
  var INLINE_LIMIT = 1e5;
1947
- var core;
6063
+ var core2;
1948
6064
  var corePat;
6065
+ var coreOverride;
1949
6066
  function getCore(pat) {
1950
- if (!core || corePat !== pat) {
1951
- core = (0, import_core.createFigmaCore)({ figmaToken: pat });
6067
+ if (coreOverride) return coreOverride;
6068
+ if (!core2 || corePat !== pat) {
6069
+ core2 = (0, import_core.createFigmaCore)({ figmaToken: pat });
1952
6070
  corePat = pat;
1953
6071
  }
1954
- return core;
6072
+ return core2;
1955
6073
  }
1956
6074
  function sanitize(s) {
1957
6075
  return (s || "figma").replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60) || "figma";
@@ -1976,6 +6094,7 @@ async function convertFigmaToHtml(args, overrides = {}) {
1976
6094
  document: args.document ?? true,
1977
6095
  assets: args.assets,
1978
6096
  assetScale: args.assetScale,
6097
+ round: args.round,
1979
6098
  llm: args.llm
1980
6099
  });
1981
6100
  result = { name: r.name, nodeCount: r.nodeCount, mode: r.mode, llm: r.llm, html: r.html };
@@ -1986,6 +6105,7 @@ async function convertFigmaToHtml(args, overrides = {}) {
1986
6105
  document: args.document ?? true,
1987
6106
  assets: args.assets,
1988
6107
  assetScale: args.assetScale,
6108
+ round: args.round,
1989
6109
  llm: args.llm
1990
6110
  });
1991
6111
  result = { name: r.name, nodeCount: r.nodeCount, mode: r.mode, llm: r.llm, html: r.html, previewUrl: r.previewUrl };
@@ -2013,23 +6133,35 @@ async function getFigmaData(args, overrides = {}) {
2013
6133
  } else {
2014
6134
  ir = await remoteExtractStyles(cfg, target(args));
2015
6135
  }
2016
- const json = JSON.stringify(ir, null, 2);
2017
6136
  const nodeCount = countIr(ir);
2018
- if (json.length <= INLINE_LIMIT) {
2019
- return [`Style IR for "${ir.name}" (${nodeCount} nodes, ${describeConfig(cfg)}):`, "", json].join("\n");
6137
+ const compact = (0, import_core.toCompactDesign)(ir);
6138
+ const format = args.format ?? "json";
6139
+ const serialized = format === "yaml" ? yaml.dump(compact, { lineWidth: -1, noRefs: true, skipInvalid: true }) : JSON.stringify(compact);
6140
+ const legend = [
6141
+ `Compact design format (${format}, token-optimized):`,
6142
+ "- `globalVars.styles`: id -> CSS declaration map. A node's full CSS = { ...globalVars.styles[node.style], ...node.box }.",
6143
+ "- `node.box`: per-node left/top/width/height (kept inline because unique).",
6144
+ "- `elements`: id -> a subtree that repeats; a node with `ref: e1` is an instance of elements.e1.",
6145
+ "- `root`: the node tree (each node: tag, optional type/name/text/asset/style/box/children)."
6146
+ ].join("\n");
6147
+ if (serialized.length <= INLINE_LIMIT) {
6148
+ return [
6149
+ `Compact design for "${compact.name}" (${nodeCount} nodes, ${describeConfig(cfg)}):`,
6150
+ legend,
6151
+ "",
6152
+ serialized
6153
+ ].join("\n");
2020
6154
  }
2021
- const filePath = await writeOut(cfg.outDir, `${sanitize(ir.name)}.ir.json`, json);
6155
+ const ext = format === "json" ? "json" : "yaml";
6156
+ const filePath = await writeOut(cfg.outDir, `${sanitize(compact.name)}.design.${ext}`, serialized);
2022
6157
  return [
2023
- `Style IR for "${ir.name}" is large (${nodeCount} nodes, ${(json.length / 1024).toFixed(1)} KB) \u2014 written to a file.`,
6158
+ `Compact design for "${compact.name}" is large (${nodeCount} nodes, ${(serialized.length / 1024).toFixed(1)} KB) \u2014 written to a file.`,
2024
6159
  `- file: ${filePath}`,
2025
- `- root: <${ir.tag}> figmaType=${ir.figmaType}, css keys=${Object.keys(ir.css || {}).length}`,
6160
+ `- ${Object.keys(compact.globalVars.styles).length} shared styles, ${Object.keys(compact.elements).length} repeated-subtree templates`,
2026
6161
  "",
2027
- "Top-level children:",
2028
- ...(ir.children || []).map(
2029
- (c, i) => ` ${i}. "${c.name}" <${c.tag}> ${c.figmaType} (${(c.children || []).length} children)`
2030
- ),
6162
+ legend,
2031
6163
  "",
2032
- "Read the file for the full tree (each node has exact `css`)."
6164
+ "Read the file for the full tree."
2033
6165
  ].join("\n");
2034
6166
  }
2035
6167
  function countIr(node) {
@@ -2059,8 +6191,11 @@ function buildServer() {
2059
6191
  "get_figma_data",
2060
6192
  {
2061
6193
  title: "Get Figma design data",
2062
- description: "Fetch the deterministic Style IR (exact CSS per node) for a Figma file or node, so an agent can reason about the design and generate code itself. Small trees are returned inline; large trees are written to a JSON file and summarised.",
2063
- inputSchema: targetShape
6194
+ description: 'Fetch a Figma file/node as a compact, token-efficient design tree for an agent to reason about and generate code from. Styles are deduped into globalVars.styles (nodes carry short `style` refs), per-node position/size is inline as `box`, and repeated subtrees are hoisted into `elements` ({ref}). Returned as minified JSON by default (most token-efficient; pass format:"yaml" for a more readable but larger form). Small results are returned inline; large ones are written to a file and summarised.',
6195
+ inputSchema: {
6196
+ ...targetShape,
6197
+ format: z.enum(["yaml", "json"]).optional().describe("Serialization. Default 'json' (minified, most compact); 'yaml' for readability.")
6198
+ }
2064
6199
  },
2065
6200
  safe((a) => getFigmaData(a))
2066
6201
  );
@@ -2075,6 +6210,9 @@ function buildServer() {
2075
6210
  document: z.boolean().optional().describe("Emit a full HTML document (default true) vs a fragment."),
2076
6211
  assets: z.boolean().optional().describe("Export & inline vectors/images as data URIs. Default false (placeholders shown instead)."),
2077
6212
  assetScale: z.number().min(1).max(4).optional().describe("Raster export scale (1-4). Default 2."),
6213
+ round: z.boolean().optional().describe(
6214
+ "Snap on-grid values to idiomatic Tailwind scale tokens (p-4, gap-6, rounded-lg, text-2xl); off-grid values stay exact. Default true. Set false for exact arbitrary values everywhere."
6215
+ ),
2078
6216
  llm: z.boolean().optional().describe("Run the LLM restructure pass (needs OLLAMA_* config). Default false."),
2079
6217
  outFile: z.string().optional().describe("Override the output file name (within the output dir).")
2080
6218
  }
@@ -2218,6 +6356,8 @@ Common flags (convert/data):
2218
6356
  --node <id> Node id ("1-23" or "1:23")
2219
6357
  --mode <m> tailwind | inline (convert)
2220
6358
  --assets Render & inline assets (convert; off by default, placeholders shown)
6359
+ --no-round Keep exact arbitrary values (default snaps on-grid values to Tailwind tokens)
6360
+ --format <f> data: json (default, most compact) | yaml (readable)
2221
6361
  --llm Run LLM restructure (convert; needs OLLAMA_* env)
2222
6362
  --out <file> Output file name (convert)
2223
6363
 
@@ -2239,6 +6379,8 @@ async function main() {
2239
6379
  ...targetFrom(positionals[1], flags),
2240
6380
  mode: flags.mode === "inline" ? "inline" : flags.mode === "tailwind" ? "tailwind" : void 0,
2241
6381
  assets: flags.assets ? true : flags["no-assets"] ? false : void 0,
6382
+ round: flags["no-round"] ? false : void 0,
6383
+ // default true (in core)
2242
6384
  llm: flags.llm === true,
2243
6385
  outFile: typeof flags.out === "string" ? flags.out : void 0
2244
6386
  });
@@ -2246,7 +6388,10 @@ async function main() {
2246
6388
  return;
2247
6389
  }
2248
6390
  case "data": {
2249
- const text = await getFigmaData(targetFrom(positionals[1], flags));
6391
+ const text = await getFigmaData({
6392
+ ...targetFrom(positionals[1], flags),
6393
+ format: flags.format === "yaml" ? "yaml" : "json"
6394
+ });
2250
6395
  console.log(text);
2251
6396
  return;
2252
6397
  }