schematex 0.8.0 → 0.8.2

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 (89) hide show
  1. package/dist/ai/ai-sdk.cjs +9 -9
  2. package/dist/ai/ai-sdk.d.cts +3 -3
  3. package/dist/ai/ai-sdk.d.ts +3 -3
  4. package/dist/ai/ai-sdk.js +4 -4
  5. package/dist/ai/index.cjs +15 -15
  6. package/dist/ai/index.d.cts +3 -3
  7. package/dist/ai/index.d.ts +3 -3
  8. package/dist/ai/index.js +4 -4
  9. package/dist/{api-BnJAPCwC.d.cts → api-BDMaX1cT.d.cts} +1 -1
  10. package/dist/{api-DAZJGq9r.d.ts → api-OED2jUVj.d.ts} +1 -1
  11. package/dist/browser.cjs +10 -10
  12. package/dist/browser.d.cts +3 -3
  13. package/dist/browser.d.ts +3 -3
  14. package/dist/browser.js +4 -4
  15. package/dist/{chunk-2YBBDPOW.cjs → chunk-AJJYWXZB.cjs} +2 -2
  16. package/dist/chunk-AJJYWXZB.cjs.map +1 -0
  17. package/dist/{chunk-TXMT4XLE.js → chunk-FLDHD4RM.js} +141 -7
  18. package/dist/chunk-FLDHD4RM.js.map +1 -0
  19. package/dist/{chunk-WNGOG4CI.js → chunk-GDZNTILD.js} +5 -3
  20. package/dist/chunk-GDZNTILD.js.map +1 -0
  21. package/dist/{chunk-RKN6QJ7K.cjs → chunk-HWNVSNDJ.cjs} +143 -9
  22. package/dist/chunk-HWNVSNDJ.cjs.map +1 -0
  23. package/dist/{chunk-6DVK5M2J.js → chunk-KF3DFASA.js} +2 -2
  24. package/dist/chunk-KF3DFASA.js.map +1 -0
  25. package/dist/{chunk-KUITLG4N.cjs → chunk-LENRV7ZJ.cjs} +5 -3
  26. package/dist/chunk-LENRV7ZJ.cjs.map +1 -0
  27. package/dist/{chunk-XI5QP7LM.js → chunk-LM5X7ZNR.js} +973 -95
  28. package/dist/chunk-LM5X7ZNR.js.map +1 -0
  29. package/dist/{chunk-3CSST5GZ.cjs → chunk-UGB42BGK.cjs} +975 -96
  30. package/dist/chunk-UGB42BGK.cjs.map +1 -0
  31. package/dist/{diagnostics-B-jOt6Ua.d.cts → diagnostics-hObcaaFC.d.cts} +1 -1
  32. package/dist/{diagnostics-B-jOt6Ua.d.ts → diagnostics-hObcaaFC.d.ts} +1 -1
  33. package/dist/diagrams/blockdiagram/index.d.cts +1 -1
  34. package/dist/diagrams/blockdiagram/index.d.ts +1 -1
  35. package/dist/diagrams/circuit/index.d.cts +1 -1
  36. package/dist/diagrams/circuit/index.d.ts +1 -1
  37. package/dist/diagrams/ecomap/index.d.cts +1 -1
  38. package/dist/diagrams/ecomap/index.d.ts +1 -1
  39. package/dist/diagrams/entity/index.cjs +5 -5
  40. package/dist/diagrams/entity/index.d.cts +1 -1
  41. package/dist/diagrams/entity/index.d.ts +1 -1
  42. package/dist/diagrams/entity/index.js +1 -1
  43. package/dist/diagrams/fishbone/index.d.cts +1 -1
  44. package/dist/diagrams/fishbone/index.d.ts +1 -1
  45. package/dist/diagrams/flowchart/index.d.cts +2 -2
  46. package/dist/diagrams/flowchart/index.d.ts +2 -2
  47. package/dist/diagrams/genogram/index.d.cts +1 -1
  48. package/dist/diagrams/genogram/index.d.ts +1 -1
  49. package/dist/diagrams/ladder/index.d.cts +1 -1
  50. package/dist/diagrams/ladder/index.d.ts +1 -1
  51. package/dist/diagrams/logic/index.d.cts +1 -1
  52. package/dist/diagrams/logic/index.d.ts +1 -1
  53. package/dist/diagrams/orgchart/index.d.cts +1 -1
  54. package/dist/diagrams/orgchart/index.d.ts +1 -1
  55. package/dist/diagrams/pedigree/index.d.cts +1 -1
  56. package/dist/diagrams/pedigree/index.d.ts +1 -1
  57. package/dist/diagrams/phylo/index.d.cts +1 -1
  58. package/dist/diagrams/phylo/index.d.ts +1 -1
  59. package/dist/diagrams/sld/index.cjs +7 -7
  60. package/dist/diagrams/sld/index.d.cts +1 -1
  61. package/dist/diagrams/sld/index.d.ts +1 -1
  62. package/dist/diagrams/sld/index.js +1 -1
  63. package/dist/diagrams/sociogram/index.d.cts +1 -1
  64. package/dist/diagrams/sociogram/index.d.ts +1 -1
  65. package/dist/diagrams/timing/index.d.cts +1 -1
  66. package/dist/diagrams/timing/index.d.ts +1 -1
  67. package/dist/diagrams/venn/index.d.cts +1 -1
  68. package/dist/diagrams/venn/index.d.ts +1 -1
  69. package/dist/{index-D-MAB6CH.d.cts → index-B0YO7rx8.d.cts} +1 -1
  70. package/dist/{index-8MaUFTMN.d.ts → index-u3KZBdas.d.ts} +1 -1
  71. package/dist/index.cjs +41 -37
  72. package/dist/index.d.cts +7 -5
  73. package/dist/index.d.ts +7 -5
  74. package/dist/index.js +5 -5
  75. package/dist/react.cjs +4 -4
  76. package/dist/react.d.cts +2 -2
  77. package/dist/react.d.ts +2 -2
  78. package/dist/react.js +3 -3
  79. package/dist/{tools-CV1JZ75-.d.cts → tools-CVgUmiGP.d.cts} +2 -2
  80. package/dist/{tools-CcPysgAD.d.ts → tools-CbBjmZVr.d.ts} +2 -2
  81. package/package.json +1 -1
  82. package/dist/chunk-2YBBDPOW.cjs.map +0 -1
  83. package/dist/chunk-3CSST5GZ.cjs.map +0 -1
  84. package/dist/chunk-6DVK5M2J.js.map +0 -1
  85. package/dist/chunk-KUITLG4N.cjs.map +0 -1
  86. package/dist/chunk-RKN6QJ7K.cjs.map +0 -1
  87. package/dist/chunk-TXMT4XLE.js.map +0 -1
  88. package/dist/chunk-WNGOG4CI.js.map +0 -1
  89. package/dist/chunk-XI5QP7LM.js.map +0 -1
@@ -4,8 +4,8 @@ var chunkQ2YRJHFB_cjs = require('./chunk-Q2YRJHFB.cjs');
4
4
  var chunkJIJWGHRN_cjs = require('./chunk-JIJWGHRN.cjs');
5
5
  var chunk6L46VIXI_cjs = require('./chunk-6L46VIXI.cjs');
6
6
  var chunkJIUC4DRS_cjs = require('./chunk-JIUC4DRS.cjs');
7
- var chunk2YBBDPOW_cjs = require('./chunk-2YBBDPOW.cjs');
8
- var chunkKUITLG4N_cjs = require('./chunk-KUITLG4N.cjs');
7
+ var chunkAJJYWXZB_cjs = require('./chunk-AJJYWXZB.cjs');
8
+ var chunkLENRV7ZJ_cjs = require('./chunk-LENRV7ZJ.cjs');
9
9
  var chunkT5KHNJ67_cjs = require('./chunk-T5KHNJ67.cjs');
10
10
  var chunkYMFYPB5Y_cjs = require('./chunk-YMFYPB5Y.cjs');
11
11
  var chunkDR3DDDQY_cjs = require('./chunk-DR3DDDQY.cjs');
@@ -144,8 +144,8 @@ function parseInfluence(src, title2) {
144
144
  const key = tok.slice(0, eq).toLowerCase();
145
145
  const value = tok.slice(eq + 1);
146
146
  if (key === "utility" || key === "payoff" || key === "value") {
147
- const num3 = Number(value);
148
- if (!Number.isNaN(num3)) utility = num3;
147
+ const num4 = Number(value);
148
+ if (!Number.isNaN(num4)) utility = num4;
149
149
  } else if (key === "kind") {
150
150
  const resolved = toKind(value.toLowerCase());
151
151
  if (!resolved) throw new DTreeParseError(`Unknown node kind "${value}"`, line2);
@@ -11644,8 +11644,8 @@ var SequenceLayout = class {
11644
11644
  }
11645
11645
  }
11646
11646
  const row = { message: m, y, x1, x2, self };
11647
- const num3 = this.nextNumber();
11648
- if (num3 !== void 0) row.number = num3;
11647
+ const num4 = this.nextNumber();
11648
+ if (num4 !== void 0) row.number = num4;
11649
11649
  if (self) {
11650
11650
  row.selfBottomY = y + SEQ_CONST.SELF_GAP;
11651
11651
  this.y = row.selfBottomY;
@@ -12413,7 +12413,7 @@ function parseMarking(body, lineNo, ast, placeIds) {
12413
12413
  if (!placeIds.has(id)) {
12414
12414
  throw new PetriParseError(`marking references unknown place "${id}"`, lineNo);
12415
12415
  }
12416
- const place = ast.places.find((pl) => pl.id === id);
12416
+ const place = ast.places.find((pl2) => pl2.id === id);
12417
12417
  if (place) place.tokens = n;
12418
12418
  }
12419
12419
  }
@@ -21563,7 +21563,7 @@ function classPeriod(P, states) {
21563
21563
  level.set(start, 0);
21564
21564
  const queue = [start];
21565
21565
  let g = 0;
21566
- const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
21566
+ const gcd2 = (a, b) => b === 0 ? a : gcd2(b, a % b);
21567
21567
  while (queue.length > 0) {
21568
21568
  const u = queue.shift();
21569
21569
  const lu = level.get(u);
@@ -21574,7 +21574,7 @@ function classPeriod(P, states) {
21574
21574
  queue.push(j);
21575
21575
  } else {
21576
21576
  const diff = lu + 1 - level.get(j);
21577
- g = gcd(g, Math.abs(diff));
21577
+ g = gcd2(g, Math.abs(diff));
21578
21578
  }
21579
21579
  }
21580
21580
  }
@@ -24361,9 +24361,9 @@ function nodePrefix(node) {
24361
24361
  const m = /^([A-Za-z]+)(-?\d+)?$/.exec(node.trim());
24362
24362
  if (!m) return node;
24363
24363
  const letters = m[1];
24364
- const num3 = m[2];
24365
- if (num3 === void 0 || num3 === "0" || num3 === "-0") return letters;
24366
- return `${letters}${num3}`;
24364
+ const num4 = m[2];
24365
+ if (num4 === void 0 || num4 === "0" || num4 === "-0") return letters;
24366
+ return `${letters}${num4}`;
24367
24367
  }
24368
24368
  function assignIcomCodes(ast) {
24369
24369
  const counters = { I: 0, C: 0, O: 0, M: 0 };
@@ -25648,6 +25648,560 @@ var threatmodel = {
25648
25648
  }
25649
25649
  };
25650
25650
 
25651
+ // src/diagrams/welding/types.ts
25652
+ var GROOVE_TYPES = /* @__PURE__ */ new Set([
25653
+ "square",
25654
+ "vgroove",
25655
+ "bevel",
25656
+ "ugroove",
25657
+ "jgroove",
25658
+ "flarev",
25659
+ "flarebevel"
25660
+ ]);
25661
+ var WELD_TYPE_NAMES = {
25662
+ fillet: "fillet weld",
25663
+ square: "square-groove weld",
25664
+ vgroove: "V-groove weld",
25665
+ bevel: "bevel-groove weld",
25666
+ ugroove: "U-groove weld",
25667
+ jgroove: "J-groove weld",
25668
+ flarev: "flare-V-groove weld",
25669
+ flarebevel: "flare-bevel-groove weld",
25670
+ plug: "plug weld",
25671
+ slot: "slot weld",
25672
+ spot: "spot weld",
25673
+ seam: "seam weld",
25674
+ back: "back weld",
25675
+ backing: "backing weld",
25676
+ surfacing: "surfacing weld",
25677
+ edge: "edge weld"
25678
+ };
25679
+ function validateWelding(ast) {
25680
+ const warnings = [];
25681
+ ast.joints.forEach((j, i) => {
25682
+ const id = j.label ? `joint "${j.label}"` : `joint ${i + 1}`;
25683
+ if (!j.arrow && !j.other) {
25684
+ warnings.push(`${id}: no weld declared (add arrow:, other:, or both:).`);
25685
+ }
25686
+ for (const [side, spec] of [
25687
+ ["arrow", j.arrow],
25688
+ ["other", j.other]
25689
+ ]) {
25690
+ if (!spec) continue;
25691
+ if (spec.type === "fillet" && spec.size === void 0) {
25692
+ warnings.push(`${id} ${side}: a fillet weld needs a leg size (size=\u2026).`);
25693
+ }
25694
+ if ((spec.type === "plug" || spec.type === "slot") && spec.size === void 0) {
25695
+ warnings.push(`${id} ${side}: a ${spec.type} weld needs a diameter (size=\u2026).`);
25696
+ }
25697
+ if (spec.type === "surfacing" && spec.throat === void 0) {
25698
+ warnings.push(`${id} ${side}: a surfacing weld needs a build-up height (throat=\u2026).`);
25699
+ }
25700
+ if (spec.angle !== void 0 && !GROOVE_TYPES.has(spec.type)) {
25701
+ warnings.push(`${id} ${side}: angle= only applies to groove welds, not a ${spec.type}.`);
25702
+ }
25703
+ if (spec.pitch !== void 0 && spec.length === void 0) {
25704
+ warnings.push(`${id} ${side}: pitch= needs a length= (an intermittent weld is length-pitch).`);
25705
+ }
25706
+ if (spec.angle !== void 0 && (spec.angle <= 0 || spec.angle >= 180)) {
25707
+ warnings.push(`${id} ${side}: groove angle ${spec.angle}\xB0 is out of range (0\u2013180).`);
25708
+ }
25709
+ }
25710
+ if (j.other?.type === "surfacing") {
25711
+ warnings.push(`${id}: a surfacing weld is arrow-side only.`);
25712
+ }
25713
+ });
25714
+ return warnings;
25715
+ }
25716
+
25717
+ // src/diagrams/welding/parser.ts
25718
+ var WELD_TYPES = /* @__PURE__ */ new Set([
25719
+ "fillet",
25720
+ "square",
25721
+ "vgroove",
25722
+ "bevel",
25723
+ "ugroove",
25724
+ "jgroove",
25725
+ "flarev",
25726
+ "flarebevel",
25727
+ "plug",
25728
+ "slot",
25729
+ "spot",
25730
+ "seam",
25731
+ "back",
25732
+ "backing",
25733
+ "surfacing",
25734
+ "edge"
25735
+ ]);
25736
+ var TYPE_ALIAS = {
25737
+ v: "vgroove",
25738
+ "v-groove": "vgroove",
25739
+ u: "ugroove",
25740
+ "u-groove": "ugroove",
25741
+ j: "jgroove",
25742
+ "j-groove": "jgroove",
25743
+ "flare-v": "flarev",
25744
+ "flare-bevel": "flarebevel",
25745
+ groove: "vgroove"
25746
+ };
25747
+ var CONTOURS = /* @__PURE__ */ new Set(["flush", "convex", "concave"]);
25748
+ var FINISHES = /* @__PURE__ */ new Set(["G", "M", "C", "R", "H", "U"]);
25749
+ function stripQuotes5(s) {
25750
+ const t = s.trim();
25751
+ const pairs = [['"', '"'], ["'", "'"], ["\u201C", "\u201D"], ["\u2018", "\u2019"]];
25752
+ for (const [a, b] of pairs) {
25753
+ if (t.startsWith(a) && t.endsWith(b) && t.length >= 2) return t.slice(1, -1);
25754
+ }
25755
+ return t;
25756
+ }
25757
+ function num3(v) {
25758
+ const n = Number(v);
25759
+ return Number.isFinite(n) ? n : void 0;
25760
+ }
25761
+ function parseWeldSpec(raw) {
25762
+ const tokens = raw.trim().split(/\s+/);
25763
+ if (tokens.length === 0) return void 0;
25764
+ const head = tokens[0].toLowerCase();
25765
+ const type = WELD_TYPES.has(head) ? head : TYPE_ALIAS[head];
25766
+ if (!type) return void 0;
25767
+ const spec = { type };
25768
+ for (let i = 1; i < tokens.length; i++) {
25769
+ const m = tokens[i].match(/^([a-zA-Z]+)\s*[=:]\s*(.+)$/);
25770
+ if (!m) continue;
25771
+ const key = m[1].toLowerCase();
25772
+ const val = m[2];
25773
+ switch (key) {
25774
+ case "size":
25775
+ case "leg":
25776
+ case "s":
25777
+ spec.size = num3(val);
25778
+ break;
25779
+ case "len":
25780
+ case "length":
25781
+ case "l":
25782
+ spec.length = num3(val);
25783
+ break;
25784
+ case "pitch":
25785
+ case "p":
25786
+ spec.pitch = num3(val);
25787
+ break;
25788
+ case "count":
25789
+ case "n":
25790
+ spec.count = num3(val);
25791
+ break;
25792
+ case "angle":
25793
+ case "a":
25794
+ case "deg":
25795
+ spec.angle = num3(val);
25796
+ break;
25797
+ case "root":
25798
+ case "gap":
25799
+ case "r":
25800
+ spec.root = num3(val);
25801
+ break;
25802
+ case "throat":
25803
+ case "e":
25804
+ case "t":
25805
+ spec.throat = num3(val);
25806
+ break;
25807
+ case "contour":
25808
+ case "c":
25809
+ if (CONTOURS.has(val.toLowerCase())) spec.contour = val.toLowerCase();
25810
+ break;
25811
+ case "finish":
25812
+ case "f": {
25813
+ const u = val.toUpperCase();
25814
+ if (FINISHES.has(u)) spec.finish = u;
25815
+ break;
25816
+ }
25817
+ }
25818
+ }
25819
+ return spec;
25820
+ }
25821
+ function emptyJoint() {
25822
+ return { around: false, field: false };
25823
+ }
25824
+ function stripComment13(line2) {
25825
+ const hash = line2.indexOf("#");
25826
+ if (hash >= 0 && (line2.slice(0, hash).match(/["'“‘]/g)?.length ?? 0) % 2 === 0) {
25827
+ return line2.slice(0, hash);
25828
+ }
25829
+ return line2;
25830
+ }
25831
+ var DIR_BOUNDARY = "(?:arrow|other|both|tail|label)\\s*[:=]|(?:around|all-?around|field|site)\\b";
25832
+ function parseJointBody(body, joint) {
25833
+ const dirRe = new RegExp(`\\b(arrow|other|both|tail|label)\\s*[:=]\\s*([\\s\\S]*?)(?=\\b(?:${DIR_BOUNDARY})|$)`, "gi");
25834
+ for (const m of body.matchAll(dirRe)) {
25835
+ const key = m[1].toLowerCase();
25836
+ const val = m[2].trim();
25837
+ if (key === "arrow") joint.arrow = parseWeldSpec(val);
25838
+ else if (key === "other") joint.other = parseWeldSpec(val);
25839
+ else if (key === "both") {
25840
+ const spec = parseWeldSpec(val);
25841
+ if (spec) {
25842
+ joint.arrow = spec;
25843
+ joint.other = { ...spec };
25844
+ }
25845
+ } else if (key === "tail") joint.tail = stripQuotes5(val);
25846
+ else if (key === "label") joint.label = stripQuotes5(val);
25847
+ }
25848
+ if (/\b(around|all-?around)\b/i.test(body)) joint.around = true;
25849
+ if (/\b(field|site)\b/i.test(body)) joint.field = true;
25850
+ }
25851
+ function parseWelding(text2) {
25852
+ const ast = { type: "welding", standard: "aws", joints: [], warnings: [] };
25853
+ const src = text2.split(/\r?\n/).map(stripComment13).join("\n");
25854
+ const headEnd = src.search(/\bjoint\b/i);
25855
+ const headerScope = headEnd >= 0 ? src.slice(0, headEnd) : src;
25856
+ const header = headerScope.match(/welding\b([^\n]*)/i);
25857
+ if (header) {
25858
+ const rest = header[1].trim();
25859
+ const std = rest.match(/standard\s*[:=]\s*([a-zA-Z-]+)/i);
25860
+ if (std) {
25861
+ const s = std[1].toLowerCase();
25862
+ if (s === "aws" || s === "iso-a" || s === "iso-b") ast.standard = s;
25863
+ else if (s === "iso") ast.standard = "iso-a";
25864
+ }
25865
+ const titleM = rest.replace(/standard\s*[:=]\s*[a-zA-Z-]+/i, "").trim();
25866
+ if (titleM) ast.title = stripQuotes5(titleM);
25867
+ }
25868
+ const jointRe = /\bjoint\b([^{]*)\{([\s\S]*?)\}/gi;
25869
+ for (const m of src.matchAll(jointRe)) {
25870
+ const joint = emptyJoint();
25871
+ const labelRaw = m[1].trim();
25872
+ if (labelRaw) joint.label = stripQuotes5(labelRaw);
25873
+ parseJointBody(m[2], joint);
25874
+ ast.joints.push(joint);
25875
+ }
25876
+ const opens = (src.match(/\{/g) ?? []).length;
25877
+ const closes = (src.match(/\}/g) ?? []).length;
25878
+ const tail = opens > closes ? src.match(/\bjoint\b([^{]*)\{([^}]*)$/i) : null;
25879
+ if (tail) {
25880
+ const joint = emptyJoint();
25881
+ const labelRaw = tail[1].trim();
25882
+ if (labelRaw) joint.label = stripQuotes5(labelRaw);
25883
+ parseJointBody(tail[2], joint);
25884
+ ast.joints.push(joint);
25885
+ }
25886
+ ast.warnings = validateWelding(ast);
25887
+ return ast;
25888
+ }
25889
+
25890
+ // src/diagrams/welding/layout.ts
25891
+ var PAD = 22;
25892
+ var BAND_H = 132;
25893
+ var REF_X0 = 150;
25894
+ var REF_LEN = 168;
25895
+ var SYMBOL_DX = 96;
25896
+ var REF_Y_OFFSET = 60;
25897
+ var CANVAS_W = 470;
25898
+ function layoutWelding(ast) {
25899
+ const titleH = ast.title ? 38 : 0;
25900
+ const nJoints = Math.max(1, ast.joints.length);
25901
+ const bandsBottom = titleH + nJoints * BAND_H;
25902
+ const warningsY = ast.warnings.length > 0 ? bandsBottom + 6 : 0;
25903
+ const warningsH = ast.warnings.length > 0 ? 20 + ast.warnings.length * 16 : 0;
25904
+ return {
25905
+ canvasWidth: CANVAS_W,
25906
+ canvasHeight: bandsBottom + warningsH + PAD,
25907
+ titleH,
25908
+ bandH: BAND_H,
25909
+ refX0: REF_X0,
25910
+ refX1: REF_X0 + REF_LEN,
25911
+ symbolX: REF_X0 + SYMBOL_DX,
25912
+ refYOffset: REF_Y_OFFSET,
25913
+ warningsY
25914
+ };
25915
+ }
25916
+
25917
+ // src/diagrams/welding/symbols.ts
25918
+ var W = 18;
25919
+ var H = 15;
25920
+ function pl(points, cls) {
25921
+ return chunk3WNW5Y7P_cjs.polygon({ points: points.map((p) => `${round9(p[0])},${round9(p[1])}`).join(" "), class: cls, fill: "none" });
25922
+ }
25923
+ function round9(n) {
25924
+ return Math.round(n * 100) / 100;
25925
+ }
25926
+ function weldGlyph(type, cx, y, dir, cls) {
25927
+ const x0 = cx - W / 2;
25928
+ const x1 = cx + W / 2;
25929
+ const yb = y + dir * H;
25930
+ switch (type) {
25931
+ case "fillet":
25932
+ return [pl([[x0, y], [x0, yb], [x1, y]], cls)];
25933
+ case "square":
25934
+ return [
25935
+ chunk3WNW5Y7P_cjs.line({ x1: cx - 3, y1: y, x2: cx - 3, y2: yb, class: cls }),
25936
+ chunk3WNW5Y7P_cjs.line({ x1: cx + 3, y1: y, x2: cx + 3, y2: yb, class: cls })
25937
+ ];
25938
+ case "vgroove":
25939
+ return [chunk3WNW5Y7P_cjs.path({ d: `M ${round9(x0)} ${round9(yb)} L ${round9(cx)} ${round9(y)} L ${round9(x1)} ${round9(yb)}`, class: cls, fill: "none" })];
25940
+ case "bevel":
25941
+ return [
25942
+ chunk3WNW5Y7P_cjs.line({ x1: cx - 4, y1: y, x2: cx - 4, y2: yb, class: cls }),
25943
+ chunk3WNW5Y7P_cjs.line({ x1: cx - 4, y1: y, x2: x1, y2: yb, class: cls })
25944
+ ];
25945
+ case "ugroove":
25946
+ return [
25947
+ chunk3WNW5Y7P_cjs.path({
25948
+ d: `M ${round9(x0)} ${round9(y)} L ${round9(x0)} ${round9(y + dir * H * 0.45)} Q ${round9(x0)} ${round9(yb)} ${round9(cx)} ${round9(yb)} Q ${round9(x1)} ${round9(yb)} ${round9(x1)} ${round9(y + dir * H * 0.45)} L ${round9(x1)} ${round9(y)}`,
25949
+ class: cls,
25950
+ fill: "none"
25951
+ })
25952
+ ];
25953
+ case "jgroove":
25954
+ return [
25955
+ chunk3WNW5Y7P_cjs.path({
25956
+ d: `M ${round9(cx - 4)} ${round9(y)} L ${round9(cx - 4)} ${round9(y + dir * H * 0.45)} Q ${round9(cx - 4)} ${round9(yb)} ${round9(x1)} ${round9(yb)}`,
25957
+ class: cls,
25958
+ fill: "none"
25959
+ })
25960
+ ];
25961
+ case "flarev":
25962
+ return [
25963
+ chunk3WNW5Y7P_cjs.path({ d: `M ${round9(x0)} ${round9(yb)} Q ${round9(cx - 2)} ${round9(yb)} ${round9(cx)} ${round9(y)}`, class: cls, fill: "none" }),
25964
+ chunk3WNW5Y7P_cjs.path({ d: `M ${round9(x1)} ${round9(yb)} Q ${round9(cx + 2)} ${round9(yb)} ${round9(cx)} ${round9(y)}`, class: cls, fill: "none" })
25965
+ ];
25966
+ case "flarebevel":
25967
+ return [
25968
+ chunk3WNW5Y7P_cjs.line({ x1: cx - 4, y1: y, x2: cx - 4, y2: yb, class: cls }),
25969
+ chunk3WNW5Y7P_cjs.path({ d: `M ${round9(cx - 4)} ${round9(y)} Q ${round9(x1)} ${round9(y)} ${round9(x1)} ${round9(yb)}`, class: cls, fill: "none" })
25970
+ ];
25971
+ case "plug":
25972
+ case "slot": {
25973
+ const ry = dir > 0 ? y : y - H * 0.7;
25974
+ return [chunk3WNW5Y7P_cjs.rect({ x: x0, y: ry, width: W, height: H * 0.7, class: cls, fill: "none" })];
25975
+ }
25976
+ case "spot":
25977
+ return [chunk3WNW5Y7P_cjs.circle({ cx, cy: y, r: W * 0.42, class: cls, fill: "none" })];
25978
+ case "seam":
25979
+ return [
25980
+ chunk3WNW5Y7P_cjs.circle({ cx, cy: y, r: W * 0.42, class: cls, fill: "none" }),
25981
+ chunk3WNW5Y7P_cjs.line({ x1: cx - W * 0.42, y1: y, x2: cx + W * 0.42, y2: y, class: cls })
25982
+ ];
25983
+ case "back":
25984
+ case "backing": {
25985
+ const rr = W * 0.45;
25986
+ const sweep = dir > 0 ? 1 : 0;
25987
+ return [chunk3WNW5Y7P_cjs.path({ d: `M ${round9(cx - rr)} ${round9(y)} A ${round9(rr)} ${round9(rr)} 0 0 ${sweep} ${round9(cx + rr)} ${round9(y)}`, class: cls, fill: "none" })];
25988
+ }
25989
+ case "surfacing": {
25990
+ const r6 = W / 4;
25991
+ const yy = y + dir * 3;
25992
+ const bump = (off) => chunk3WNW5Y7P_cjs.path({ d: `M ${round9(cx - W / 2)} ${round9(off)} a ${round9(r6)} ${round9(r6)} 0 0 ${dir > 0 ? 1 : 0} ${round9(W / 2)} 0 a ${round9(r6)} ${round9(r6)} 0 0 ${dir > 0 ? 1 : 0} ${round9(W / 2)} 0`, class: cls, fill: "none" });
25993
+ return [bump(y), bump(yy)];
25994
+ }
25995
+ case "edge":
25996
+ return [
25997
+ chunk3WNW5Y7P_cjs.line({ x1: cx - 3, y1: y, x2: cx - 3, y2: yb, class: cls }),
25998
+ chunk3WNW5Y7P_cjs.line({ x1: cx + 3, y1: y, x2: cx + 3, y2: yb, class: cls })
25999
+ ];
26000
+ }
26001
+ }
26002
+ function contourGlyph(contour, cx, y, dir, cls) {
26003
+ const yy = y + dir * (H + 5);
26004
+ const half = W / 2;
26005
+ if (contour === "flush") {
26006
+ return chunk3WNW5Y7P_cjs.line({ x1: cx - half, y1: yy, x2: cx + half, y2: yy, class: cls });
26007
+ }
26008
+ const bulge = contour === "convex" ? dir : -dir;
26009
+ return chunk3WNW5Y7P_cjs.path({
26010
+ d: `M ${round9(cx - half)} ${round9(yy)} Q ${round9(cx)} ${round9(yy + bulge * 5)} ${round9(cx + half)} ${round9(yy)}`,
26011
+ class: cls,
26012
+ fill: "none"
26013
+ });
26014
+ }
26015
+ var WELD_GLYPH_W = W;
26016
+ var WELD_GLYPH_H = H;
26017
+
26018
+ // src/diagrams/welding/renderer.ts
26019
+ var CSS = `
26020
+ .sx-welding { font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
26021
+ .sx-welding-title { font: 600 16px sans-serif; fill: #111; text-anchor: middle; }
26022
+ .sx-weld-ref { stroke: #1e3a5f; stroke-width: 1.6; fill: none; }
26023
+ .sx-weld-ref-dashed { stroke: #1e3a5f; stroke-width: 1.4; fill: none; stroke-dasharray: 5 3; }
26024
+ .sx-weld-leader { stroke: #1e3a5f; stroke-width: 1.6; fill: none; }
26025
+ .sx-weld-arrowhead { fill: #1e3a5f; }
26026
+ .sx-weld-glyph { stroke: #1d4ed8; stroke-width: 1.8; fill: none; stroke-linejoin: round; stroke-linecap: round; }
26027
+ .sx-weld-supp { stroke: #1d4ed8; stroke-width: 1.5; fill: none; }
26028
+ .sx-weld-allaround { stroke: #1e3a5f; stroke-width: 1.6; fill: none; }
26029
+ .sx-weld-flag { fill: #1e3a5f; stroke: #1e3a5f; stroke-width: 1; }
26030
+ .sx-weld-dim { font: 600 12px ui-monospace, Menlo, monospace; fill: #0f172a; }
26031
+ .sx-weld-angle { font: 600 11px ui-monospace, Menlo, monospace; fill: #475569; }
26032
+ .sx-weld-finish { font: 700 11px sans-serif; fill: #1d4ed8; text-anchor: middle; }
26033
+ .sx-weld-tailtext { font: 500 11px sans-serif; fill: #334155; text-anchor: end; dominant-baseline: central; }
26034
+ .sx-weld-label { font: 600 12.5px sans-serif; fill: #1f2937; text-anchor: middle; }
26035
+ .sx-weld-warn { font: 500 11.5px sans-serif; fill: #b45309; }
26036
+ .sx-weld-warn-head { font: 700 11.5px sans-serif; fill: #b45309; }
26037
+ `;
26038
+ function r23(n) {
26039
+ return Math.round(n * 100) / 100;
26040
+ }
26041
+ function sizeText(spec) {
26042
+ if (spec.size === void 0 && spec.throat === void 0) return "";
26043
+ const parts = [];
26044
+ if (spec.size !== void 0) parts.push(String(spec.size));
26045
+ if (spec.throat !== void 0) parts.push(`(${spec.throat})`);
26046
+ return parts.join(" ");
26047
+ }
26048
+ function lengthText(spec) {
26049
+ if (spec.length === void 0) return "";
26050
+ if (spec.pitch !== void 0) {
26051
+ return spec.count !== void 0 ? `${spec.count}\xD7${spec.length} (${spec.pitch})` : `${spec.length}-${spec.pitch}`;
26052
+ }
26053
+ return String(spec.length);
26054
+ }
26055
+ function renderSide(spec, symbolX, refY, dir) {
26056
+ const nodes = [];
26057
+ nodes.push(...weldGlyph(spec.type, symbolX, refY, dir, "sx-weld-glyph"));
26058
+ const midY = refY + dir * (WELD_GLYPH_H / 2);
26059
+ const leftX = symbolX - WELD_GLYPH_W / 2;
26060
+ const rightX = symbolX + WELD_GLYPH_W / 2;
26061
+ const sz = sizeText(spec);
26062
+ if (sz) {
26063
+ nodes.push(
26064
+ chunk3WNW5Y7P_cjs.text({ x: r23(leftX - 5), y: r23(midY), class: "sx-weld-dim", "text-anchor": "end", "dominant-baseline": "central" }, sz)
26065
+ );
26066
+ }
26067
+ const len = lengthText(spec);
26068
+ if (len) {
26069
+ nodes.push(
26070
+ chunk3WNW5Y7P_cjs.text({ x: r23(rightX + 5), y: r23(midY), class: "sx-weld-dim", "text-anchor": "start", "dominant-baseline": "central" }, len)
26071
+ );
26072
+ }
26073
+ if (spec.angle !== void 0) {
26074
+ nodes.push(
26075
+ chunk3WNW5Y7P_cjs.text({ x: r23(symbolX), y: r23(refY + dir * (WELD_GLYPH_H + 11)), class: "sx-weld-angle", "text-anchor": "middle" }, `${spec.angle}\xB0`)
26076
+ );
26077
+ }
26078
+ if (spec.root !== void 0) {
26079
+ nodes.push(
26080
+ chunk3WNW5Y7P_cjs.text({ x: r23(rightX + 5), y: r23(refY + dir * 5), class: "sx-weld-angle", "text-anchor": "start", "dominant-baseline": "central" }, `root ${spec.root}`)
26081
+ );
26082
+ }
26083
+ if (spec.contour) {
26084
+ nodes.push(contourGlyph(spec.contour, symbolX, refY, dir, "sx-weld-supp"));
26085
+ }
26086
+ if (spec.finish) {
26087
+ nodes.push(
26088
+ chunk3WNW5Y7P_cjs.text({ x: r23(symbolX), y: r23(refY + dir * (WELD_GLYPH_H + 13)), class: "sx-weld-finish" }, spec.finish)
26089
+ );
26090
+ }
26091
+ return nodes;
26092
+ }
26093
+ function renderJoint(joint, ast, bandTop, lay) {
26094
+ const refY = bandTop + lay.refYOffset;
26095
+ const { refX0, refX1, symbolX } = lay;
26096
+ const iso = ast.standard === "iso-a";
26097
+ const nodes = [];
26098
+ nodes.push(chunk3WNW5Y7P_cjs.line({ x1: refX0, y1: refY, x2: refX1, y2: refY, class: "sx-weld-ref" }));
26099
+ const symmetric = iso && joint.arrow && joint.other && joint.arrow.type === joint.other.type;
26100
+ if (iso && !symmetric) {
26101
+ nodes.push(chunk3WNW5Y7P_cjs.line({ x1: refX0, y1: refY - 6, x2: refX1, y2: refY - 6, class: "sx-weld-ref-dashed" }));
26102
+ }
26103
+ const lx = refX1 + 34;
26104
+ const ly = refY + 44;
26105
+ nodes.push(chunk3WNW5Y7P_cjs.line({ x1: refX1, y1: refY, x2: lx, y2: ly, class: "sx-weld-leader" }));
26106
+ const ah = 8;
26107
+ const angle = Math.atan2(ly - refY, lx - refX1);
26108
+ const a1 = angle + 2.7;
26109
+ const a2 = angle - 2.7;
26110
+ nodes.push(
26111
+ chunk3WNW5Y7P_cjs.polygon({
26112
+ points: `${r23(lx)},${r23(ly)} ${r23(lx + ah * Math.cos(a1))},${r23(ly + ah * Math.sin(a1))} ${r23(lx + ah * Math.cos(a2))},${r23(ly + ah * Math.sin(a2))}`,
26113
+ class: "sx-weld-arrowhead"
26114
+ })
26115
+ );
26116
+ if (joint.arrow) {
26117
+ nodes.push(...renderSide(joint.arrow, symbolX, refY, 1));
26118
+ }
26119
+ if (joint.other && !symmetric) {
26120
+ const oy = iso ? refY - 6 : refY;
26121
+ nodes.push(...renderSide(joint.other, symbolX, oy, -1));
26122
+ }
26123
+ if (joint.around) {
26124
+ nodes.push(chunk3WNW5Y7P_cjs.circle({ cx: refX1, cy: refY, r: 5, class: "sx-weld-allaround" }));
26125
+ }
26126
+ if (joint.field) {
26127
+ const fx = refX1;
26128
+ const fy = refY;
26129
+ nodes.push(chunk3WNW5Y7P_cjs.line({ x1: fx, y1: fy, x2: fx, y2: fy - 14, class: "sx-weld-flag" }));
26130
+ nodes.push(chunk3WNW5Y7P_cjs.polygon({ points: `${fx},${fy - 14} ${fx},${fy - 6} ${fx - 11},${fy - 10}`, class: "sx-weld-flag" }));
26131
+ }
26132
+ if (joint.tail) {
26133
+ nodes.push(chunk3WNW5Y7P_cjs.line({ x1: refX0, y1: refY, x2: refX0 - 12, y2: refY - 7, class: "sx-weld-ref" }));
26134
+ nodes.push(chunk3WNW5Y7P_cjs.line({ x1: refX0, y1: refY, x2: refX0 - 12, y2: refY + 7, class: "sx-weld-ref" }));
26135
+ nodes.push(chunk3WNW5Y7P_cjs.text({ x: refX0 - 16, y: refY, class: "sx-weld-tailtext" }, joint.tail));
26136
+ }
26137
+ if (joint.label) {
26138
+ nodes.push(chunk3WNW5Y7P_cjs.text({ x: symbolX, y: r23(bandTop + lay.bandH - 16), class: "sx-weld-label" }, joint.label));
26139
+ }
26140
+ const desc2 = describeJoint(joint);
26141
+ return chunk3WNW5Y7P_cjs.group({ class: "sx-weld-joint", "data-joint": joint.label ?? "" }, [chunk3WNW5Y7P_cjs.title(desc2), ...nodes]);
26142
+ }
26143
+ function describeJoint(j) {
26144
+ const sides = [];
26145
+ if (j.arrow) sides.push(`arrow side: ${WELD_TYPE_NAMES[j.arrow.type]}${j.arrow.size !== void 0 ? ` size ${j.arrow.size}` : ""}`);
26146
+ if (j.other) sides.push(`other side: ${WELD_TYPE_NAMES[j.other.type]}`);
26147
+ const extra = [j.around ? "all-around" : "", j.field ? "field weld" : "", j.tail ? `tail ${j.tail}` : ""].filter(Boolean);
26148
+ return `${j.label ? `${j.label} \u2014 ` : ""}${sides.join("; ")}${extra.length ? `; ${extra.join("; ")}` : ""}`;
26149
+ }
26150
+ function renderWeldingAST(ast) {
26151
+ const lay = layoutWelding(ast);
26152
+ const body = [];
26153
+ if (ast.title) {
26154
+ body.push(chunk3WNW5Y7P_cjs.text({ x: lay.canvasWidth / 2, y: 26, class: "sx-welding-title" }, ast.title));
26155
+ }
26156
+ ast.joints.forEach((joint, i) => {
26157
+ const bandTop = lay.titleH + i * lay.bandH;
26158
+ body.push(renderJoint(joint, ast, bandTop, lay));
26159
+ });
26160
+ if (ast.joints.length === 0) {
26161
+ body.push(
26162
+ chunk3WNW5Y7P_cjs.text({ x: lay.canvasWidth / 2, y: 70, class: "sx-weld-label" }, 'Add a joint, e.g. joint "plate" { arrow: fillet size=8 }')
26163
+ );
26164
+ }
26165
+ if (ast.warnings.length > 0) {
26166
+ body.push(chunk3WNW5Y7P_cjs.text({ x: 22, y: lay.warningsY + 14, class: "sx-weld-warn-head" }, "\u26A0 Validation:"));
26167
+ ast.warnings.forEach((w, i) => {
26168
+ body.push(chunk3WNW5Y7P_cjs.text({ x: 22, y: lay.warningsY + 32 + i * 16, class: "sx-weld-warn" }, w));
26169
+ });
26170
+ }
26171
+ return chunk3WNW5Y7P_cjs.svgRoot(
26172
+ {
26173
+ class: "sx-welding",
26174
+ "data-diagram-type": "welding",
26175
+ "data-standard": ast.standard,
26176
+ width: lay.canvasWidth,
26177
+ height: lay.canvasHeight,
26178
+ viewBox: `0 0 ${lay.canvasWidth} ${lay.canvasHeight}`,
26179
+ role: "graphics-document"
26180
+ },
26181
+ [
26182
+ chunk3WNW5Y7P_cjs.title(ast.title ? `Welding symbols \u2014 ${chunk3WNW5Y7P_cjs.escapeXml(ast.title)}` : "Welding symbols"),
26183
+ chunk3WNW5Y7P_cjs.desc(
26184
+ `Welding-symbol diagram (${ast.standard.toUpperCase()}) \u2014 ${ast.joints.length} joint(s): ${ast.joints.map(describeJoint).join(" \xB7 ")}`
26185
+ ),
26186
+ chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS)]),
26187
+ ...body
26188
+ ]
26189
+ );
26190
+ }
26191
+ function renderWelding(text2, _config) {
26192
+ return renderWeldingAST(parseWelding(text2));
26193
+ }
26194
+
26195
+ // src/diagrams/welding/index.ts
26196
+ var welding = {
26197
+ type: "welding",
26198
+ detect: (t) => /^\s*welding\b/i.test(t),
26199
+ parse: parseWelding,
26200
+ render(text2, config) {
26201
+ return renderWelding(text2);
26202
+ }
26203
+ };
26204
+
25651
26205
  // src/core/diagnostics.ts
25652
26206
  var ENGINE_BUG_NAMES = /* @__PURE__ */ new Set([
25653
26207
  "ReferenceError",
@@ -27008,7 +27562,7 @@ function newAST() {
27008
27562
  config: { ...DEFAULT_CONFIG }
27009
27563
  };
27010
27564
  }
27011
- function stripQuotes5(s) {
27565
+ function stripQuotes6(s) {
27012
27566
  const t = s.trim();
27013
27567
  if (t.startsWith('"') && t.endsWith('"') || t.startsWith("'") && t.endsWith("'")) {
27014
27568
  return t.slice(1, -1);
@@ -27044,7 +27598,7 @@ function parseAxis(raw) {
27044
27598
  function parseNumberList2(raw) {
27045
27599
  const t = raw.trim();
27046
27600
  const inner = t.startsWith("[") && t.endsWith("]") ? t.slice(1, -1) : t;
27047
- return inner.split(",").map((s) => stripQuotes5(s.trim())).filter((s) => s.length > 0);
27601
+ return inner.split(",").map((s) => stripQuotes6(s.trim())).filter((s) => s.length > 0);
27048
27602
  }
27049
27603
  function parseProperties2(raw, point) {
27050
27604
  let i = 0;
@@ -27217,6 +27771,41 @@ function parseQfdLine(line2, ast) {
27217
27771
  }
27218
27772
  return false;
27219
27773
  }
27774
+ function parseGenotype(token) {
27775
+ const t = token.trim();
27776
+ if (t.length === 0 || t.length % 2 !== 0) return null;
27777
+ const loci = [];
27778
+ for (let i = 0; i < t.length; i += 2) {
27779
+ const a = t[i];
27780
+ const b = t[i + 1];
27781
+ if (!/[A-Za-z]/.test(a) || !/[A-Za-z]/.test(b)) return null;
27782
+ if (a.toUpperCase() !== b.toUpperCase()) return null;
27783
+ loci.push({ letter: a.toUpperCase(), alleles: [a, b] });
27784
+ }
27785
+ return loci;
27786
+ }
27787
+ function parsePunnettLine(line2, st) {
27788
+ if (!st.punnett) return false;
27789
+ const crossMatch = line2.match(/^(?:cross|parents?)\s*:\s*(.+)$/i);
27790
+ if (crossMatch) {
27791
+ const parts = crossMatch[1].split(/\s*[x×*]\s*/i);
27792
+ if (parts.length === 2) {
27793
+ st.punnett.p1raw = parts[0].trim();
27794
+ st.punnett.p2raw = parts[1].trim();
27795
+ }
27796
+ return true;
27797
+ }
27798
+ const traitMatch = line2.match(/^trait\s+([A-Za-z])\s*:\s*(.+)$/i);
27799
+ if (traitMatch) {
27800
+ const letter = traitMatch[1].toUpperCase();
27801
+ const slash = traitMatch[2].split("/");
27802
+ const dominant = stripQuotes6(slash[0] ?? "");
27803
+ const recessive = slash[1] !== void 0 ? stripQuotes6(slash[1]) : void 0;
27804
+ st.punnett.traits[letter] = { dominant, recessive };
27805
+ return true;
27806
+ }
27807
+ return false;
27808
+ }
27220
27809
  function parseConfigLine(key, value, ast) {
27221
27810
  const k = key.trim().toLowerCase();
27222
27811
  const v = value.trim();
@@ -27244,7 +27833,7 @@ function parseHeader2(line2, ast) {
27244
27833
  ast.cols = Number(heatMatch[1]);
27245
27834
  ast.rows = Number(heatMatch[2]);
27246
27835
  const title2 = heatMatch[3].trim();
27247
- if (title2) ast.title = stripQuotes5(title2);
27836
+ if (title2) ast.title = stripQuotes6(title2);
27248
27837
  return void 0;
27249
27838
  }
27250
27839
  const corrMatch = rest.match(/^correlation\s*(?:(\d+)\s*x\s*(\d+))?\s*(.*)$/i);
@@ -27256,7 +27845,7 @@ function parseHeader2(line2, ast) {
27256
27845
  ast.rows = Number(corrMatch[2]);
27257
27846
  }
27258
27847
  const title2 = corrMatch[3].trim();
27259
- if (title2) ast.title = stripQuotes5(title2);
27848
+ if (title2) ast.title = stripQuotes6(title2);
27260
27849
  return void 0;
27261
27850
  }
27262
27851
  const sipocMatch = rest.match(/^sipoc\b\s*(.*)$/i);
@@ -27267,7 +27856,7 @@ function parseHeader2(line2, ast) {
27267
27856
  ast.rows = 0;
27268
27857
  ast.sipoc = emptySipoc();
27269
27858
  const title2 = sipocMatch[1].trim();
27270
- if (title2) ast.title = stripQuotes5(title2);
27859
+ if (title2) ast.title = stripQuotes6(title2);
27271
27860
  return void 0;
27272
27861
  }
27273
27862
  const qfdMatch = rest.match(/^qfd\b\s*(.*)$/i);
@@ -27276,7 +27865,16 @@ function parseHeader2(line2, ast) {
27276
27865
  ast.grid = "NxM";
27277
27866
  ast.qfd = emptyQfd();
27278
27867
  const title2 = qfdMatch[1].trim();
27279
- if (title2) ast.title = stripQuotes5(title2);
27868
+ if (title2) ast.title = stripQuotes6(title2);
27869
+ return void 0;
27870
+ }
27871
+ const punnettMatch = rest.match(/^punnett\b\s*(.*)$/i);
27872
+ if (punnettMatch) {
27873
+ ast.mode = "punnett";
27874
+ ast.grid = "NxM";
27875
+ ast.punnett = { genes: [], parent1: [], parent2: [] };
27876
+ const title2 = punnettMatch[1].trim();
27877
+ if (title2) ast.title = stripQuotes6(title2);
27280
27878
  return void 0;
27281
27879
  }
27282
27880
  const tokenMatch = rest.match(/^([a-zA-Z0-9_-]+)\s*(.*)$/);
@@ -27284,13 +27882,13 @@ function parseHeader2(line2, ast) {
27284
27882
  const tok = tokenMatch[1].toLowerCase();
27285
27883
  const remainder = tokenMatch[2].trim();
27286
27884
  if (TEMPLATE_NAMES.has(tok)) {
27287
- if (remainder) ast.title = stripQuotes5(remainder);
27885
+ if (remainder) ast.title = stripQuotes6(remainder);
27288
27886
  return tok;
27289
27887
  }
27290
27888
  if (rest.startsWith('"') || rest.startsWith("'")) {
27291
- ast.title = stripQuotes5(rest);
27889
+ ast.title = stripQuotes6(rest);
27292
27890
  } else if (rest.length > 0) {
27293
- ast.title = stripQuotes5(rest);
27891
+ ast.title = stripQuotes6(rest);
27294
27892
  }
27295
27893
  }
27296
27894
  return void 0;
@@ -27311,6 +27909,7 @@ function parseMatrix(text2) {
27311
27909
  }
27312
27910
  if (/^matrix\b/i.test(line2)) {
27313
27911
  templateName = parseHeader2(line2, st.ast);
27912
+ if (st.ast.mode === "punnett" && !st.punnett) st.punnett = { traits: {} };
27314
27913
  continue;
27315
27914
  }
27316
27915
  if (/^config\s*:/i.test(line2)) {
@@ -27326,11 +27925,12 @@ function parseMatrix(text2) {
27326
27925
  inConfig = false;
27327
27926
  }
27328
27927
  if (/^title\s*:/i.test(line2)) {
27329
- st.ast.title = stripQuotes5(line2.replace(/^title\s*:\s*/i, ""));
27928
+ st.ast.title = stripQuotes6(line2.replace(/^title\s*:\s*/i, ""));
27330
27929
  continue;
27331
27930
  }
27332
27931
  if (st.ast.mode === "sipoc" && parseSipocLine(line2, st.ast)) continue;
27333
27932
  if (st.ast.mode === "qfd" && parseQfdLine(line2, st.ast)) continue;
27933
+ if (st.ast.mode === "punnett" && parsePunnettLine(line2, st)) continue;
27334
27934
  if (/^x-axis\s*:/i.test(line2)) {
27335
27935
  st.ast.xAxis = parseAxis(line2.replace(/^x-axis\s*:\s*/i, ""));
27336
27936
  continue;
@@ -27413,7 +28013,7 @@ function parseMatrix(text2) {
27413
28013
  if (qShort) {
27414
28014
  const q = Number(qShort[1]);
27415
28015
  const labelRaw = qShort[2].trim();
27416
- const label = stripQuotes5(labelRaw);
28016
+ const label = stripQuotes6(labelRaw);
27417
28017
  const cell = quadrantToCell(q);
27418
28018
  st.ast.cellLabels.push({ col: cell.col, row: cell.row, label });
27419
28019
  continue;
@@ -27432,7 +28032,7 @@ function parseMatrix(text2) {
27432
28032
  if (st.ast.cols === 3 && st.ast.rows === 3 && st.ast.grid !== "NxM" && st.ast.mode !== "sipoc" && st.ast.mode !== "qfd") {
27433
28033
  st.ast.grid = "3x3";
27434
28034
  }
27435
- if (st.ast.mode === "heatmap" || st.ast.mode === "correlation" || st.ast.mode === "sipoc" || st.ast.mode === "qfd") {
28035
+ if (st.ast.mode === "heatmap" || st.ast.mode === "correlation" || st.ast.mode === "sipoc" || st.ast.mode === "qfd" || st.ast.mode === "punnett") {
27436
28036
  st.ast.grid = "NxM";
27437
28037
  }
27438
28038
  if (st.ast.mode === "sipoc" && st.ast.sipoc) {
@@ -27450,6 +28050,31 @@ function parseMatrix(text2) {
27450
28050
  st.ast.cols = st.ast.qfd.hows.length;
27451
28051
  st.ast.rows = st.ast.qfd.whats.length;
27452
28052
  }
28053
+ if (st.ast.mode === "punnett" && st.punnett && st.ast.punnett) {
28054
+ const sc = st.punnett;
28055
+ const loci1 = sc.p1raw ? parseGenotype(sc.p1raw) : null;
28056
+ const loci2 = sc.p2raw ? parseGenotype(sc.p2raw) : null;
28057
+ if (loci1 && loci2 && loci1.length > 0) {
28058
+ const genes = loci1.map((l) => {
28059
+ const t = sc.traits[l.letter];
28060
+ return {
28061
+ dominant: l.letter,
28062
+ recessive: l.letter.toLowerCase(),
28063
+ ...t?.dominant ? { dominantTrait: t.dominant } : {},
28064
+ ...t?.recessive ? { recessiveTrait: t.recessive } : {}
28065
+ };
28066
+ });
28067
+ const parent1 = loci1.map((l) => [l.alleles[0], l.alleles[1]]);
28068
+ const parent2 = genes.map((g) => {
28069
+ const found = loci2.find((l) => l.letter === g.dominant);
28070
+ return found ? [found.alleles[0], found.alleles[1]] : [g.dominant, g.recessive];
28071
+ });
28072
+ st.ast.punnett = { genes, parent1, parent2 };
28073
+ const dim = Math.pow(2, genes.length);
28074
+ st.ast.cols = dim;
28075
+ st.ast.rows = dim;
28076
+ }
28077
+ }
27453
28078
  return st.ast;
27454
28079
  }
27455
28080
  function findCommentStart(line2) {
@@ -27468,6 +28093,82 @@ function findCommentStart(line2) {
27468
28093
  }
27469
28094
 
27470
28095
  // src/diagrams/matrix/types.ts
28096
+ function gametesOf(parent) {
28097
+ let acc = [""];
28098
+ for (const pair of parent) {
28099
+ const a0 = pair[0] ?? "";
28100
+ const a1 = pair[1] ?? a0;
28101
+ const next = [];
28102
+ for (const g of acc) {
28103
+ next.push(g + a0);
28104
+ next.push(g + a1);
28105
+ }
28106
+ acc = next;
28107
+ }
28108
+ return acc;
28109
+ }
28110
+ function combineGametes(g1, g2, genes) {
28111
+ let genotype = "";
28112
+ let phenotypeKey = "";
28113
+ for (let i = 0; i < genes.length; i++) {
28114
+ const dom = genes[i].dominant;
28115
+ const rec = genes[i].recessive;
28116
+ const a = g1[i] ?? rec;
28117
+ const b = g2[i] ?? rec;
28118
+ const hasDom = a === dom || b === dom;
28119
+ const pair = a === dom ? [a, b] : b === dom ? [b, a] : [a, b];
28120
+ genotype += pair.join("");
28121
+ phenotypeKey += hasDom ? dom : rec;
28122
+ }
28123
+ return { genotype, phenotypeKey };
28124
+ }
28125
+ function phenotypeLabel(key, genes) {
28126
+ const parts = [];
28127
+ for (let i = 0; i < genes.length; i++) {
28128
+ const ch = key[i];
28129
+ const g = genes[i];
28130
+ if (ch === g.dominant) parts.push(g.dominantTrait ?? `${g.dominant}_`);
28131
+ else parts.push(g.recessiveTrait ?? `${g.recessive}${g.recessive}`);
28132
+ }
28133
+ return parts.join(", ");
28134
+ }
28135
+ function computePunnett(data) {
28136
+ const genes = data.genes;
28137
+ const gametes1 = gametesOf(data.parent1);
28138
+ const gametes2 = gametesOf(data.parent2);
28139
+ const grid = [];
28140
+ const genoCount = /* @__PURE__ */ new Map();
28141
+ const phenoCount = /* @__PURE__ */ new Map();
28142
+ for (const g2 of gametes2) {
28143
+ const row = [];
28144
+ for (const g1 of gametes1) {
28145
+ const cell = combineGametes(g1, g2, genes);
28146
+ row.push(cell);
28147
+ genoCount.set(cell.genotype, (genoCount.get(cell.genotype) ?? 0) + 1);
28148
+ phenoCount.set(cell.phenotypeKey, (phenoCount.get(cell.phenotypeKey) ?? 0) + 1);
28149
+ }
28150
+ grid.push(row);
28151
+ }
28152
+ const genotypeRatio = [...genoCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([genotype, count]) => ({ key: genotype, label: genotype, count }));
28153
+ const phenotypeRatio = [...phenoCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).map(([key, count]) => ({ key, label: phenotypeLabel(key, genes), count }));
28154
+ return { gametes1, gametes2, grid, genotypeRatio, phenotypeRatio };
28155
+ }
28156
+ function gcd(a, b) {
28157
+ return b === 0 ? a : gcd(b, a % b);
28158
+ }
28159
+ function reduceRatio(counts) {
28160
+ const divisor = counts.reduce((acc, c) => gcd(acc, c), 0) || 1;
28161
+ return counts.map((c) => c / divisor).join(":");
28162
+ }
28163
+ function punnettFooter(result) {
28164
+ const enumerate = result.genotypeRatio.length <= 4;
28165
+ return {
28166
+ phenotypeRatio: reduceRatio(result.phenotypeRatio.map((p) => p.count)),
28167
+ legend: result.phenotypeRatio,
28168
+ genotypeRatio: reduceRatio(result.genotypeRatio.map((e) => e.count)),
28169
+ genotypeDetail: enumerate ? result.genotypeRatio.map((e) => `${e.count} ${e.label}`).join(", ") : `${result.genotypeRatio.length} distinct genotypes`
28170
+ };
28171
+ }
27471
28172
  function computeQfdImportance(qfd) {
27472
28173
  const raw = qfd.hows.map(() => 0);
27473
28174
  for (const r6 of qfd.relationships) {
@@ -27485,7 +28186,7 @@ function computeQfdImportance(qfd) {
27485
28186
  }
27486
28187
 
27487
28188
  // src/diagrams/matrix/layout.ts
27488
- var CANVAS_W = 720;
28189
+ var CANVAS_W2 = 720;
27489
28190
  var CANVAS_H = 560;
27490
28191
  var PADDING_X = 110;
27491
28192
  var PADDING_Y = 90;
@@ -27544,21 +28245,21 @@ function resolveLabelCollisions(points, plot, mode) {
27544
28245
  }
27545
28246
  return;
27546
28247
  }
27547
- const PAD = 3;
28248
+ const PAD2 = 3;
27548
28249
  for (let iter = 0; iter < 30; iter++) {
27549
28250
  let moved = false;
27550
28251
  for (let i = 0; i < points.length; i++) {
27551
28252
  for (let j = i + 1; j < points.length; j++) {
27552
28253
  const a = points[i].label;
27553
28254
  const b = points[j].label;
27554
- const ax0 = a.lx - a.width / 2 - PAD;
27555
- const ax1 = a.lx + a.width / 2 + PAD;
27556
- const ay0 = a.ly - a.height / 2 - PAD;
27557
- const ay1 = a.ly + a.height / 2 + PAD;
27558
- const bx0 = b.lx - b.width / 2 - PAD;
27559
- const bx1 = b.lx + b.width / 2 + PAD;
27560
- const by0 = b.ly - b.height / 2 - PAD;
27561
- const by1 = b.ly + b.height / 2 + PAD;
28255
+ const ax0 = a.lx - a.width / 2 - PAD2;
28256
+ const ax1 = a.lx + a.width / 2 + PAD2;
28257
+ const ay0 = a.ly - a.height / 2 - PAD2;
28258
+ const ay1 = a.ly + a.height / 2 + PAD2;
28259
+ const bx0 = b.lx - b.width / 2 - PAD2;
28260
+ const bx1 = b.lx + b.width / 2 + PAD2;
28261
+ const by0 = b.ly - b.height / 2 - PAD2;
28262
+ const by1 = b.ly + b.height / 2 + PAD2;
27562
28263
  const overlapX = Math.min(ax1, bx1) - Math.max(ax0, bx0);
27563
28264
  const overlapY = Math.min(ay1, by1) - Math.max(ay0, by0);
27564
28265
  if (overlapX > 0 && overlapY > 0) {
@@ -27652,8 +28353,51 @@ function layoutQfd(ast) {
27652
28353
  footerH
27653
28354
  };
27654
28355
  }
28356
+ var PUNNETT_PAD = 24;
28357
+ function layoutPunnett(ast) {
28358
+ const pd = ast.punnett;
28359
+ const genes = pd?.genes ?? [];
28360
+ const g = Math.max(1, genes.length);
28361
+ const dim = Math.pow(2, g);
28362
+ const genoChars = g * 2;
28363
+ const cell = Math.max(52, genoChars * 11 + 18);
28364
+ const titleH = ast.title ? 40 : 0;
28365
+ const x0 = PUNNETT_PAD;
28366
+ const y0 = PUNNETT_PAD + titleH;
28367
+ const gridRight = x0 + cell + dim * cell;
28368
+ const gridBottom = y0 + cell + dim * cell;
28369
+ const result = pd && genes.length > 0 ? computePunnett(pd) : null;
28370
+ const phenoLines = result ? Math.max(1, result.phenotypeRatio.length) : 1;
28371
+ const footerY = gridBottom + 18;
28372
+ const footerH = 30 + phenoLines * 22 + 26;
28373
+ let footerW = 0;
28374
+ if (result) {
28375
+ const f = punnettFooter(result);
28376
+ const longest = Math.max(
28377
+ `Phenotype ratio ${f.phenotypeRatio}`.length,
28378
+ `Genotype ratio ${f.genotypeRatio} \u2014 ${f.genotypeDetail}`.length,
28379
+ ...f.legend.map((p) => `${p.count} \xD7 ${p.label}`.length + 4)
28380
+ );
28381
+ footerW = x0 + longest * 6.7 + PUNNETT_PAD;
28382
+ }
28383
+ const canvasWidth = Math.max(gridRight + PUNNETT_PAD, footerW, 360);
28384
+ const canvasHeight = footerY + footerH + PUNNETT_PAD;
28385
+ return {
28386
+ canvasWidth,
28387
+ canvasHeight,
28388
+ x0,
28389
+ y0,
28390
+ headerW: cell,
28391
+ headerH: cell,
28392
+ cellW: cell,
28393
+ cellH: cell,
28394
+ dim,
28395
+ footerY,
28396
+ footerH
28397
+ };
28398
+ }
27655
28399
  function layoutMatrix(ast) {
27656
- const canvasWidth = CANVAS_W;
28400
+ const canvasWidth = CANVAS_W2;
27657
28401
  const canvasHeight = CANVAS_H;
27658
28402
  const plot = {
27659
28403
  x0: PADDING_X,
@@ -27724,7 +28468,7 @@ var HEAT_RAMP = [
27724
28468
  "#ef4444",
27725
28469
  "#b91c1c"
27726
28470
  ];
27727
- var CSS = `
28471
+ var CSS2 = `
27728
28472
  .sx-matrix { font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
27729
28473
  .sx-matrix-title { font: 600 16px sans-serif; fill: #111; }
27730
28474
  .sx-matrix-grid { stroke: #e5e7eb; stroke-width: 1; fill: none; }
@@ -27780,6 +28524,18 @@ var CSS = `
27780
28524
  .sx-qfd-imp-value { font: 700 13px sans-serif; fill: #1e3a8a; text-anchor: middle; dominant-baseline: central; }
27781
28525
  .sx-qfd-imp-value-top { font: 800 14px sans-serif; fill: #dc2626; text-anchor: middle; dominant-baseline: central; }
27782
28526
  .sx-qfd-dir { font: 700 13px sans-serif; fill: #475569; text-anchor: middle; dominant-baseline: central; }
28527
+ .sx-punnett-corner { fill: #f1f5f9; stroke: #94a3b8; stroke-width: 1; }
28528
+ .sx-punnett-cornerline { stroke: #cbd5e1; stroke-width: 1; }
28529
+ .sx-punnett-corner-p1 { font: 600 11px sans-serif; fill: #1e3a8a; dominant-baseline: hanging; }
28530
+ .sx-punnett-corner-p2 { font: 600 11px sans-serif; fill: #1e3a8a; }
28531
+ .sx-punnett-header { fill: #e2e8f0; stroke: #94a3b8; stroke-width: 1; }
28532
+ .sx-punnett-gamete { font: 700 14px ui-monospace, "SF Mono", Menlo, monospace; fill: #0f172a; text-anchor: middle; dominant-baseline: central; }
28533
+ .sx-punnett-cell { stroke: #94a3b8; stroke-width: 1; }
28534
+ .sx-punnett-genotype { font: 700 15px ui-monospace, "SF Mono", Menlo, monospace; fill: #0f172a; text-anchor: middle; dominant-baseline: central; }
28535
+ .sx-punnett-footer-head { font: 700 13px sans-serif; fill: #111; }
28536
+ .sx-punnett-legend { font: 500 12.5px sans-serif; fill: #1f2937; dominant-baseline: central; }
28537
+ .sx-punnett-geno-ratio { font: 500 12px sans-serif; fill: #475569; }
28538
+ .sx-punnett-hint { font: 500 13px sans-serif; fill: #64748b; text-anchor: middle; }
27783
28539
  `.trim();
27784
28540
  function axisArrow() {
27785
28541
  return chunk3WNW5Y7P_cjs.el(
@@ -28439,8 +29195,8 @@ function renderPoints(ast, lay) {
28439
29195
  }
28440
29196
  return chunk3WNW5Y7P_cjs.group({ id: "sx-matrix-points" }, nodes);
28441
29197
  }
28442
- function renderOnePoint(pl, categories) {
28443
- const p = pl.point;
29198
+ function renderOnePoint(pl2, categories) {
29199
+ const p = pl2.point;
28444
29200
  const color = bubbleFill(p, categories);
28445
29201
  const shape = p.shape ?? "circle";
28446
29202
  let shapeEl;
@@ -28449,9 +29205,9 @@ function renderOnePoint(pl, categories) {
28449
29205
  const fillOpacity = p.size !== void 0 ? 0.45 : 0.75;
28450
29206
  if (shape === "circle") {
28451
29207
  shapeEl = chunk3WNW5Y7P_cjs.circle({
28452
- cx: pl.px,
28453
- cy: pl.py,
28454
- r: pl.r,
29208
+ cx: pl2.px,
29209
+ cy: pl2.py,
29210
+ r: pl2.r,
28455
29211
  fill: color,
28456
29212
  "fill-opacity": fillOpacity,
28457
29213
  stroke,
@@ -28460,10 +29216,10 @@ function renderOnePoint(pl, categories) {
28460
29216
  });
28461
29217
  } else if (shape === "square") {
28462
29218
  shapeEl = chunk3WNW5Y7P_cjs.rect({
28463
- x: pl.px - pl.r,
28464
- y: pl.py - pl.r,
28465
- width: pl.r * 2,
28466
- height: pl.r * 2,
29219
+ x: pl2.px - pl2.r,
29220
+ y: pl2.py - pl2.r,
29221
+ width: pl2.r * 2,
29222
+ height: pl2.r * 2,
28467
29223
  fill: color,
28468
29224
  "fill-opacity": fillOpacity,
28469
29225
  stroke,
@@ -28471,9 +29227,9 @@ function renderOnePoint(pl, categories) {
28471
29227
  class: "sx-matrix-bubble"
28472
29228
  });
28473
29229
  } else if (shape === "diamond") {
28474
- const r6 = pl.r;
29230
+ const r6 = pl2.r;
28475
29231
  shapeEl = chunk3WNW5Y7P_cjs.polygon({
28476
- points: `${pl.px},${pl.py - r6} ${pl.px + r6},${pl.py} ${pl.px},${pl.py + r6} ${pl.px - r6},${pl.py}`,
29232
+ points: `${pl2.px},${pl2.py - r6} ${pl2.px + r6},${pl2.py} ${pl2.px},${pl2.py + r6} ${pl2.px - r6},${pl2.py}`,
28477
29233
  fill: color,
28478
29234
  "fill-opacity": fillOpacity,
28479
29235
  stroke,
@@ -28481,9 +29237,9 @@ function renderOnePoint(pl, categories) {
28481
29237
  class: "sx-matrix-bubble"
28482
29238
  });
28483
29239
  } else {
28484
- const r6 = pl.r;
29240
+ const r6 = pl2.r;
28485
29241
  shapeEl = chunk3WNW5Y7P_cjs.polygon({
28486
- points: `${pl.px},${pl.py - r6} ${pl.px + r6},${pl.py + r6 * 0.8} ${pl.px - r6},${pl.py + r6 * 0.8}`,
29242
+ points: `${pl2.px},${pl2.py - r6} ${pl2.px + r6},${pl2.py + r6 * 0.8} ${pl2.px - r6},${pl2.py + r6 * 0.8}`,
28487
29243
  fill: color,
28488
29244
  "fill-opacity": fillOpacity,
28489
29245
  stroke,
@@ -28491,23 +29247,23 @@ function renderOnePoint(pl, categories) {
28491
29247
  class: "sx-matrix-bubble"
28492
29248
  });
28493
29249
  }
28494
- const leader = pl.label.external ? chunk3WNW5Y7P_cjs.line({
28495
- x1: pl.px,
28496
- y1: pl.py,
28497
- x2: pl.label.lx,
28498
- y2: pl.label.ly,
29250
+ const leader = pl2.label.external ? chunk3WNW5Y7P_cjs.line({
29251
+ x1: pl2.px,
29252
+ y1: pl2.py,
29253
+ x2: pl2.label.lx,
29254
+ y2: pl2.label.ly,
28499
29255
  class: "sx-matrix-leader"
28500
29256
  }) : "";
28501
29257
  const label = chunk3WNW5Y7P_cjs.text(
28502
- { x: pl.label.lx, y: pl.label.ly, class: "sx-matrix-label" },
28503
- pl.label.text
29258
+ { x: pl2.label.lx, y: pl2.label.ly, class: "sx-matrix-label" },
29259
+ pl2.label.text
28504
29260
  );
28505
29261
  let badge = "";
28506
29262
  if (p.offChart) {
28507
- const bx = pl.px;
28508
- const by = pl.py;
29263
+ const bx = pl2.px;
29264
+ const by = pl2.py;
28509
29265
  badge = chunk3WNW5Y7P_cjs.text(
28510
- { x: bx + pl.r + 4, y: by - pl.r - 2, class: "sx-matrix-offchart", "font-size": 14, "font-weight": 700 },
29266
+ { x: bx + pl2.r + 4, y: by - pl2.r - 2, class: "sx-matrix-offchart", "font-size": 14, "font-weight": 700 },
28511
29267
  "\u2197"
28512
29268
  );
28513
29269
  }
@@ -28662,7 +29418,7 @@ function renderSipocAST(ast) {
28662
29418
  chunk3WNW5Y7P_cjs.desc(
28663
29419
  `SIPOC scoping table \u2014 ${sipoc.suppliers.length} supplier(s), ${sipoc.inputs.length} input(s), ${sipoc.process.length} process step(s), ${sipoc.outputs.length} output(s), ${sipoc.customers.length} customer(s)`
28664
29420
  ),
28665
- chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS)]),
29421
+ chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS2)]),
28666
29422
  ...nodes
28667
29423
  ]
28668
29424
  );
@@ -28891,14 +29647,135 @@ function renderQfdAST(ast) {
28891
29647
  chunk3WNW5Y7P_cjs.desc(
28892
29648
  `QFD House of Quality \u2014 ${qfd.whats.length} customer requirement(s), ${qfd.hows.length} engineering characteristic(s), ${qfd.relationships.length} relationship(s); technical importance computed per column`
28893
29649
  ),
28894
- chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS)]),
29650
+ chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS2)]),
28895
29651
  ...nodes
28896
29652
  ]
28897
29653
  );
28898
29654
  }
29655
+ var PUNNETT_TINTS = ["#dbeafe", "#dcfce7", "#fef9c3", "#fed7aa", "#fae8ff", "#cffafe", "#fee2e2", "#e0e7ff"];
29656
+ var PUNNETT_STRONG = ["#2563eb", "#16a34a", "#ca8a04", "#ea580c", "#9333ea", "#0891b2", "#dc2626", "#4f46e5"];
29657
+ function genotypeText(parent, genes) {
29658
+ return parent.map((pair, i) => {
29659
+ const dom = genes[i]?.dominant;
29660
+ const [a, b] = [pair[0] ?? "", pair[1] ?? ""];
29661
+ return a === dom ? a + b : b === dom ? b + a : a + b;
29662
+ }).join("");
29663
+ }
29664
+ function renderPunnettAST(ast) {
29665
+ const pd = ast.punnett;
29666
+ const lay = layoutPunnett(ast);
29667
+ const svgWrap = (body, descText2) => chunk3WNW5Y7P_cjs.svgRoot(
29668
+ {
29669
+ class: "sx-matrix sx-punnett",
29670
+ "data-diagram-type": "matrix",
29671
+ "data-mode": "punnett",
29672
+ width: lay.canvasWidth,
29673
+ height: lay.canvasHeight,
29674
+ viewBox: `0 0 ${lay.canvasWidth} ${lay.canvasHeight}`,
29675
+ role: "graphics-document"
29676
+ },
29677
+ [
29678
+ chunk3WNW5Y7P_cjs.title(ast.title ? `Punnett square \u2014 ${chunk3WNW5Y7P_cjs.escapeXml(ast.title)}` : "Punnett square"),
29679
+ chunk3WNW5Y7P_cjs.desc(descText2),
29680
+ chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS2)]),
29681
+ ...body
29682
+ ]
29683
+ );
29684
+ if (!pd || pd.genes.length === 0) {
29685
+ return svgWrap(
29686
+ [
29687
+ chunk3WNW5Y7P_cjs.text(
29688
+ { x: lay.canvasWidth / 2, y: 44, class: "sx-matrix-title", "text-anchor": "middle" },
29689
+ ast.title ?? "Punnett square"
29690
+ ),
29691
+ chunk3WNW5Y7P_cjs.text({ x: lay.canvasWidth / 2, y: 84, class: "sx-punnett-hint" }, "Add a cross, e.g. cross: Bb x Bb")
29692
+ ],
29693
+ "Empty Punnett square \u2014 no cross specified"
29694
+ );
29695
+ }
29696
+ const result = computePunnett(pd);
29697
+ const phenoColor = /* @__PURE__ */ new Map();
29698
+ result.phenotypeRatio.forEach((p, i) => {
29699
+ phenoColor.set(p.key, {
29700
+ tint: PUNNETT_TINTS[i % PUNNETT_TINTS.length],
29701
+ strong: PUNNETT_STRONG[i % PUNNETT_STRONG.length]
29702
+ });
29703
+ });
29704
+ const nodes = [];
29705
+ if (ast.title) {
29706
+ nodes.push(
29707
+ chunk3WNW5Y7P_cjs.text(
29708
+ { x: lay.canvasWidth / 2, y: 24, class: "sx-matrix-title", "text-anchor": "middle" },
29709
+ ast.title
29710
+ )
29711
+ );
29712
+ }
29713
+ const gx0 = lay.x0 + lay.headerW;
29714
+ const gy0 = lay.y0 + lay.headerH;
29715
+ nodes.push(chunk3WNW5Y7P_cjs.rect({ x: lay.x0, y: lay.y0, width: lay.headerW, height: lay.headerH, class: "sx-punnett-corner" }));
29716
+ nodes.push(
29717
+ chunk3WNW5Y7P_cjs.line({ x1: lay.x0, y1: lay.y0, x2: lay.x0 + lay.headerW, y2: lay.y0 + lay.headerH, class: "sx-punnett-cornerline" })
29718
+ );
29719
+ nodes.push(
29720
+ chunk3WNW5Y7P_cjs.text(
29721
+ { x: lay.x0 + lay.headerW - 6, y: lay.y0 + 8, class: "sx-punnett-corner-p1", "text-anchor": "end" },
29722
+ genotypeText(pd.parent1, pd.genes)
29723
+ )
29724
+ );
29725
+ nodes.push(
29726
+ chunk3WNW5Y7P_cjs.text(
29727
+ { x: lay.x0 + 6, y: lay.y0 + lay.headerH - 8, class: "sx-punnett-corner-p2", "text-anchor": "start" },
29728
+ genotypeText(pd.parent2, pd.genes)
29729
+ )
29730
+ );
29731
+ result.gametes1.forEach((g, c) => {
29732
+ const cx = gx0 + c * lay.cellW;
29733
+ nodes.push(chunk3WNW5Y7P_cjs.rect({ x: cx, y: lay.y0, width: lay.cellW, height: lay.headerH, class: "sx-punnett-header" }));
29734
+ nodes.push(chunk3WNW5Y7P_cjs.text({ x: cx + lay.cellW / 2, y: lay.y0 + lay.headerH / 2, class: "sx-punnett-gamete" }, g));
29735
+ });
29736
+ result.gametes2.forEach((g, r6) => {
29737
+ const cy = gy0 + r6 * lay.cellH;
29738
+ nodes.push(chunk3WNW5Y7P_cjs.rect({ x: lay.x0, y: cy, width: lay.headerW, height: lay.cellH, class: "sx-punnett-header" }));
29739
+ nodes.push(chunk3WNW5Y7P_cjs.text({ x: lay.x0 + lay.headerW / 2, y: cy + lay.cellH / 2, class: "sx-punnett-gamete" }, g));
29740
+ });
29741
+ for (let r6 = 0; r6 < result.grid.length; r6++) {
29742
+ const row = result.grid[r6];
29743
+ for (let c = 0; c < row.length; c++) {
29744
+ const cell = row[c];
29745
+ const color = phenoColor.get(cell.phenotypeKey);
29746
+ const cx = gx0 + c * lay.cellW;
29747
+ const cy = gy0 + r6 * lay.cellH;
29748
+ nodes.push(chunk3WNW5Y7P_cjs.rect({ x: cx, y: cy, width: lay.cellW, height: lay.cellH, fill: color.tint, class: "sx-punnett-cell" }));
29749
+ nodes.push(chunk3WNW5Y7P_cjs.text({ x: cx + lay.cellW / 2, y: cy + lay.cellH / 2, class: "sx-punnett-genotype" }, cell.genotype));
29750
+ }
29751
+ }
29752
+ const footer = punnettFooter(result);
29753
+ let fy = lay.footerY + 18;
29754
+ nodes.push(
29755
+ chunk3WNW5Y7P_cjs.text({ x: lay.x0, y: fy, class: "sx-punnett-footer-head" }, `Phenotype ratio ${footer.phenotypeRatio}`)
29756
+ );
29757
+ fy += 22;
29758
+ for (const p of footer.legend) {
29759
+ const color = phenoColor.get(p.key);
29760
+ nodes.push(
29761
+ chunk3WNW5Y7P_cjs.rect({ x: lay.x0, y: fy - 8, width: 14, height: 14, fill: color.tint, stroke: color.strong, "stroke-width": 1.4 })
29762
+ );
29763
+ nodes.push(chunk3WNW5Y7P_cjs.text({ x: lay.x0 + 22, y: fy, class: "sx-punnett-legend" }, `${p.count} \xD7 ${p.label}`));
29764
+ fy += 22;
29765
+ }
29766
+ nodes.push(
29767
+ chunk3WNW5Y7P_cjs.text(
29768
+ { x: lay.x0, y: fy + 4, class: "sx-punnett-geno-ratio" },
29769
+ `Genotype ratio ${footer.genotypeRatio} \u2014 ${footer.genotypeDetail}`
29770
+ )
29771
+ );
29772
+ const descText = `Punnett square \u2014 ${pd.genes.length === 1 ? "monohybrid" : pd.genes.length === 2 ? "dihybrid" : `${pd.genes.length}-gene`} cross ${genotypeText(pd.parent1, pd.genes)} \xD7 ${genotypeText(pd.parent2, pd.genes)}; phenotype ratio ${footer.phenotypeRatio}`;
29773
+ return svgWrap(nodes, descText);
29774
+ }
28899
29775
  function renderMatrixAST(ast) {
28900
29776
  if (ast.mode === "sipoc") return renderSipocAST(ast);
28901
29777
  if (ast.mode === "qfd") return renderQfdAST(ast);
29778
+ if (ast.mode === "punnett") return renderPunnettAST(ast);
28902
29779
  const lay = layoutMatrix(ast);
28903
29780
  const needsLegendSpace = lay.categories.length > 0 || ast.mode === "correlation";
28904
29781
  const extraWidth = needsLegendSpace && lay.plot.x0 + lay.plot.w + 140 > lay.canvasWidth ? 160 : 0;
@@ -28932,7 +29809,7 @@ function renderMatrixAST(ast) {
28932
29809
  chunk3WNW5Y7P_cjs.desc(
28933
29810
  `Matrix diagram${ast.template ? ` (${ast.template} template)` : ""}, ${ast.mode} mode, ${ast.points.length} point(s)`
28934
29811
  ),
28935
- chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS), axisArrow()]),
29812
+ chunk3WNW5Y7P_cjs.defs([chunk3WNW5Y7P_cjs.el("style", {}, CSS2), axisArrow()]),
28936
29813
  ...body
28937
29814
  ]
28938
29815
  );
@@ -28964,7 +29841,7 @@ var ErdParseError = class extends Error {
28964
29841
  }
28965
29842
  lineNumber;
28966
29843
  };
28967
- function stripComment13(s) {
29844
+ function stripComment14(s) {
28968
29845
  let out = "";
28969
29846
  let inQuote = false;
28970
29847
  for (let i = 0; i < s.length; i++) {
@@ -29018,7 +29895,7 @@ function parseCardToken(raw, side) {
29018
29895
  }
29019
29896
  function lex(text2) {
29020
29897
  return text2.split(/\r?\n/).map((raw, i) => ({
29021
- text: stripComment13(raw).trim(),
29898
+ text: stripComment14(raw).trim(),
29022
29899
  lineNumber: i + 1
29023
29900
  })).filter((l) => l.text.length > 0);
29024
29901
  }
@@ -30145,7 +31022,7 @@ var BreadboardParseError = class extends Error {
30145
31022
  }
30146
31023
  lineNumber;
30147
31024
  };
30148
- function stripComment14(s) {
31025
+ function stripComment15(s) {
30149
31026
  let out = "";
30150
31027
  let inQuote = false;
30151
31028
  for (let i = 0; i < s.length; i++) {
@@ -30166,7 +31043,7 @@ function unquote8(v) {
30166
31043
  }
30167
31044
  function lex2(text2) {
30168
31045
  return text2.split(/\r?\n/).map((raw, i) => ({
30169
- text: stripComment14(raw).trimEnd().replace(/^\s+/, ""),
31046
+ text: stripComment15(raw).trimEnd().replace(/^\s+/, ""),
30170
31047
  lineNumber: i + 1
30171
31048
  })).filter((l) => l.text.length > 0);
30172
31049
  }
@@ -30507,9 +31384,9 @@ function resistorBands(value) {
30507
31384
  const s = String(value).replace(/[^\d.kKmMrRΩ]/g, "");
30508
31385
  const m = s.match(/^([\d.]+)\s*([kKmM]?)/);
30509
31386
  if (!m) return ["#92400e", "#92400e", "#1f2937", "#facc15"];
30510
- const num3 = parseFloat(m[1]);
31387
+ const num4 = parseFloat(m[1]);
30511
31388
  const mult = m[2] === "k" || m[2] === "K" ? 1e3 : m[2] === "m" || m[2] === "M" ? 1e6 : 1;
30512
- const ohms = Math.round(num3 * mult);
31389
+ const ohms = Math.round(num4 * mult);
30513
31390
  if (!Number.isFinite(ohms) || ohms <= 0) return ["#92400e", "#92400e", "#1f2937", "#facc15"];
30514
31391
  const str = String(ohms);
30515
31392
  if (str.length <= 1) return [BAND_COLORS["0"], BAND_COLORS[str[0]], BAND_COLORS["0"], "#facc15"];
@@ -32180,7 +33057,7 @@ function renderBpmnLayout(layout, _config) {
32180
33057
  out.push(chunk3WNW5Y7P_cjs.title(ast.title ?? "BPMN diagram"));
32181
33058
  out.push(chunk3WNW5Y7P_cjs.desc(`BPMN ${ast.direction} \u2014 ${ast.pools.length} pool(s), ${layout.objects.length} flow object(s).`));
32182
33059
  out.push(buildDefs());
32183
- for (const pl of layout.pools) out.push(renderPool(pl));
33060
+ for (const pl2 of layout.pools) out.push(renderPool(pl2));
32184
33061
  for (const lan of layout.lanes) {
32185
33062
  out.push(
32186
33063
  chunk3WNW5Y7P_cjs.group({ class: "schematex-bpmn-lane" }, [
@@ -32290,25 +33167,25 @@ function buildDefs() {
32290
33167
  )
32291
33168
  ]);
32292
33169
  }
32293
- function renderPool(pl) {
32294
- const labelCx = pl.labelX + pl.labelWidth / 2;
32295
- const labelCy = pl.labelY + pl.height / 2;
32296
- if (pl.pool.blackbox) {
33170
+ function renderPool(pl2) {
33171
+ const labelCx = pl2.labelX + pl2.labelWidth / 2;
33172
+ const labelCy = pl2.labelY + pl2.height / 2;
33173
+ if (pl2.pool.blackbox) {
32297
33174
  return chunk3WNW5Y7P_cjs.group({ class: "schematex-bpmn-pool blackbox" }, [
32298
33175
  chunk3WNW5Y7P_cjs.rect({
32299
- x: pl.x,
32300
- y: pl.y,
32301
- width: pl.width,
32302
- height: pl.height,
33176
+ x: pl2.x,
33177
+ y: pl2.y,
33178
+ width: pl2.width,
33179
+ height: pl2.height,
32303
33180
  fill: POOL_FILL,
32304
33181
  stroke: STROKE,
32305
33182
  "stroke-width": 1.5
32306
33183
  }),
32307
33184
  chunk3WNW5Y7P_cjs.rect({
32308
- x: pl.x,
32309
- y: pl.y,
32310
- width: pl.labelWidth,
32311
- height: pl.height,
33185
+ x: pl2.x,
33186
+ y: pl2.y,
33187
+ width: pl2.labelWidth,
33188
+ height: pl2.height,
32312
33189
  fill: LABEL_BAND_FILL,
32313
33190
  stroke: STROKE,
32314
33191
  "stroke-width": 1
@@ -32325,25 +33202,25 @@ function renderPool(pl) {
32325
33202
  "font-weight": "bold",
32326
33203
  fill: STROKE
32327
33204
  },
32328
- pl.pool.label
33205
+ pl2.pool.label
32329
33206
  )
32330
33207
  ]);
32331
33208
  }
32332
33209
  return chunk3WNW5Y7P_cjs.group({ class: "schematex-bpmn-pool" }, [
32333
33210
  chunk3WNW5Y7P_cjs.rect({
32334
- x: pl.x,
32335
- y: pl.y,
32336
- width: pl.width,
32337
- height: pl.height,
33211
+ x: pl2.x,
33212
+ y: pl2.y,
33213
+ width: pl2.width,
33214
+ height: pl2.height,
32338
33215
  fill: POOL_FILL,
32339
33216
  stroke: STROKE,
32340
33217
  "stroke-width": 1.5
32341
33218
  }),
32342
33219
  chunk3WNW5Y7P_cjs.rect({
32343
- x: pl.x,
32344
- y: pl.y,
32345
- width: pl.labelWidth,
32346
- height: pl.height,
33220
+ x: pl2.x,
33221
+ y: pl2.y,
33222
+ width: pl2.labelWidth,
33223
+ height: pl2.height,
32347
33224
  fill: LABEL_BAND_FILL,
32348
33225
  stroke: STROKE,
32349
33226
  "stroke-width": 1
@@ -32360,7 +33237,7 @@ function renderPool(pl) {
32360
33237
  "font-weight": "bold",
32361
33238
  fill: STROKE
32362
33239
  },
32363
- pl.pool.label
33240
+ pl2.pool.label
32364
33241
  )
32365
33242
  ]);
32366
33243
  }
@@ -35059,8 +35936,8 @@ var plugins = [
35059
35936
  chunkJIJWGHRN_cjs.circuit,
35060
35937
  chunk6L46VIXI_cjs.blockdiagram,
35061
35938
  chunkJIUC4DRS_cjs.ladder,
35062
- chunk2YBBDPOW_cjs.sld,
35063
- chunkKUITLG4N_cjs.entity,
35939
+ chunkAJJYWXZB_cjs.sld,
35940
+ chunkLENRV7ZJ_cjs.entity,
35064
35941
  chunkT5KHNJ67_cjs.fishbone,
35065
35942
  chunkYMFYPB5Y_cjs.venn,
35066
35943
  chunkDR3DDDQY_cjs.flowchart,
@@ -35092,7 +35969,8 @@ var plugins = [
35092
35969
  gitgraph,
35093
35970
  epc,
35094
35971
  idef0,
35095
- threatmodel
35972
+ threatmodel,
35973
+ welding
35096
35974
  ];
35097
35975
  function detectPlugin(text2, config) {
35098
35976
  if (config?.type) {
@@ -35270,5 +36148,6 @@ exports.threatmodel = threatmodel;
35270
36148
  exports.timeline = timeline;
35271
36149
  exports.umlclass = umlclass;
35272
36150
  exports.usecase = usecase;
35273
- //# sourceMappingURL=chunk-3CSST5GZ.cjs.map
35274
- //# sourceMappingURL=chunk-3CSST5GZ.cjs.map
36151
+ exports.welding = welding;
36152
+ //# sourceMappingURL=chunk-UGB42BGK.cjs.map
36153
+ //# sourceMappingURL=chunk-UGB42BGK.cjs.map