wt-huatu 1.3.4

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 (110) hide show
  1. package/Readme.md +223 -0
  2. package/component/HuatuComponentCache.js +89 -0
  3. package/component/HuatuComponentDef.js +249 -0
  4. package/component/HuatuComponentPlacement.js +172 -0
  5. package/component/HuatuComponentPort.js +58 -0
  6. package/component/IHuatuComponent.js +2 -0
  7. package/for-node/node-cli-funcs.js +36 -0
  8. package/geometry/AngDeg.js +68 -0
  9. package/geometry/Angle.js +77 -0
  10. package/geometry/Bezier.js +623 -0
  11. package/geometry/Circle.js +143 -0
  12. package/geometry/Ellipse.js +546 -0
  13. package/geometry/EllipticalArc.js +337 -0
  14. package/geometry/IGeometry.js +1 -0
  15. package/geometry/Intersection.js +601 -0
  16. package/geometry/Line.js +136 -0
  17. package/geometry/LineSeg.js +179 -0
  18. package/geometry/Point.js +88 -0
  19. package/geometry/PolyLine.js +97 -0
  20. package/geometry/Polygon.js +122 -0
  21. package/geometry/Rect.js +149 -0
  22. package/geometry/Ring.js +91 -0
  23. package/geometry/SegmentModel.js +206 -0
  24. package/geometry/Triangle.js +168 -0
  25. package/geometry/Vector.js +92 -0
  26. package/huatu/Huatu.js +4279 -0
  27. package/huatu/HuatuAngleMark.js +400 -0
  28. package/huatu/HuatuBlock.js +26 -0
  29. package/huatu/HuatuClipPath.js +29 -0
  30. package/huatu/HuatuCompDrawing.js +77 -0
  31. package/huatu/HuatuDimMark.js +579 -0
  32. package/huatu/HuatuDrawing.js +185 -0
  33. package/huatu/HuatuDrawingGroup.js +52 -0
  34. package/huatu/HuatuJob.js +347 -0
  35. package/huatu/HuatuLabel.js +311 -0
  36. package/huatu/HuatuLabelStyle.js +190 -0
  37. package/huatu/HuatuLayer.js +10 -0
  38. package/huatu/HuatuMarker.js +209 -0
  39. package/huatu/HuatuParser.js +435 -0
  40. package/huatu/HuatuPath.js +131 -0
  41. package/huatu/HuatuPathSeries.js +51 -0
  42. package/huatu/HuatuPattern.js +54 -0
  43. package/huatu/HuatuPoint.js +20 -0
  44. package/huatu/HuatuPointSeries.js +67 -0
  45. package/huatu/HuatuStyle.js +394 -0
  46. package/huatu/HuatuSymbol.js +81 -0
  47. package/huatu/HuatuSymbolArray.js +235 -0
  48. package/huatu/HuatuTransform.js +113 -0
  49. package/huatu/HuatuVar.js +17 -0
  50. package/huatu/HuatuYml.js +271 -0
  51. package/huatu/IHuatu.js +2 -0
  52. package/huatu/IHuatuYml.js +1 -0
  53. package/huatu/IndentParsingStack.js +82 -0
  54. package/index.d.ts +1747 -0
  55. package/index.js +247 -0
  56. package/math/Complex.js +72 -0
  57. package/math/Matrix.js +31 -0
  58. package/math/NumberRange.js +38 -0
  59. package/math/VarFuncs.js +24 -0
  60. package/math/WtMath.js +217 -0
  61. package/package.json +34 -0
  62. package/path/PathBezier2.js +75 -0
  63. package/path/PathBezier3.js +89 -0
  64. package/path/PathCircle.js +82 -0
  65. package/path/PathConfig.js +81 -0
  66. package/path/PathContinuousSegmentedPath.js +390 -0
  67. package/path/PathEllipse.js +99 -0
  68. package/path/PathEllipticalArc.js +111 -0
  69. package/path/PathGeneric.js +59 -0
  70. package/path/PathLine.js +75 -0
  71. package/path/PathLines.js +46 -0
  72. package/path/PathPolygon.js +142 -0
  73. package/path/PathPolyline.js +266 -0
  74. package/path/PathRect.js +125 -0
  75. package/path/PathRing.js +51 -0
  76. package/path/PathSegmentedPath.js +199 -0
  77. package/path/PathTriangle.js +90 -0
  78. package/presets/marker.js +37 -0
  79. package/presets/pattern.js +85 -0
  80. package/shape/SvgShapeArrowHead.js +92 -0
  81. package/shape/SvgShapeCircle.js +26 -0
  82. package/shape/SvgShapeCross.js +43 -0
  83. package/shape/SvgShapeEllipse.js +28 -0
  84. package/shape/SvgShapeGeneric.js +50 -0
  85. package/shape/SvgShapeHeart.js +40 -0
  86. package/shape/SvgShapeIsoscelesTriangle.js +52 -0
  87. package/shape/SvgShapePolygon.js +39 -0
  88. package/shape/SvgShapeRect.js +26 -0
  89. package/shape/SvgShapeRhombus.js +27 -0
  90. package/shape/SvgShapeStar.js +103 -0
  91. package/svg/ISvg.js +1 -0
  92. package/svg/SvgBBox.js +149 -0
  93. package/svg/SvgConstants.js +14 -0
  94. package/svg/SvgGradient.js +97 -0
  95. package/svg/SvgMarker.js +221 -0
  96. package/svg/SvgPattern.js +228 -0
  97. package/svg/SvgPoint.js +33 -0
  98. package/svg/SvgPointSet.js +41 -0
  99. package/templates/lines.js +35 -0
  100. package/tools/gen-id.js +2 -0
  101. package/tools/html.js +2 -0
  102. package/tools/katex.js +75 -0
  103. package/tools/rand-str.js +122 -0
  104. package/tools/regex.js +15 -0
  105. package/tools/utils.js +438 -0
  106. package/tools/webColor.js +700 -0
  107. package/wire/HuatuNet.js +22 -0
  108. package/wire/HuatuWire.js +415 -0
  109. package/wire/HuatuWireDrawing.js +17 -0
  110. package/wire/IHuatuWire.js +1 -0
@@ -0,0 +1,209 @@
1
+ import { SvgMarker } from "../svg/SvgMarker.js";
2
+ import { SvgShapeArrowHeadSimpleAngle, SvgShapeArrowHeadSolidTriangle, SvgShapeArrowHeadSolidTwoTriangle } from "../shape/SvgShapeArrowHead.js";
3
+ import { fitNumInRange } from "../tools/utils.js";
4
+ import { WtMath } from "../math/WtMath.js";
5
+ import { SvgShapeCircle } from "../shape/SvgShapeCircle.js";
6
+ import { SvgShapeEllipse } from "../shape/SvgShapeEllipse.js";
7
+ import { SvgShapeRect } from "../shape/SvgShapeRect.js";
8
+ import { SvgShapeCross, SvgShapePlus } from "../shape/SvgShapeCross.js";
9
+ import { SvgShapeRhombus } from "../shape/SvgShapeRhombus.js";
10
+ import { SvgShapeIsoscelesTriangle } from "../shape/SvgShapeIsoscelesTriangle.js";
11
+ import { SvgShapeStar5, SvgShapeStarUnified } from "../shape/SvgShapeStar.js";
12
+ import { SvgShapePolygon } from "../shape/SvgShapePolygon.js";
13
+ import { genHex } from "../tools/gen-id.js";
14
+ export class HuatuMarker {
15
+ // The possible marker types that user could use when designing the marker
16
+ static TYPES = {
17
+ arrowSolid: ["arrow-solid", "arrowsolid", "solidarrow", "arrow"],
18
+ arrowDouble: ["arrow-double", "arrowdouble", "doublearrow"],
19
+ arrowSimple: ["arrow-simple", "arrowsimple", "simple-arrow", "simplearrow"],
20
+ circle: ["circle", "circ", "dot"],
21
+ triangle: ["triangle", "tri"],
22
+ ellipse: ["ellipse", "ell"],
23
+ rhombus: ["rhombus", "rhom"],
24
+ square: ["square", "sqr"],
25
+ rectangle: ["rectangle", "rect"],
26
+ star5: ["star", "star5", "5-star", "5star", "wujiaoxing"],
27
+ starU: ["staru", "star-u", "star-unified", "unifiedstar", "unified-star"],
28
+ plus: ["plus", "jiahao"],
29
+ cross: ["cross", "chacha", "cha"],
30
+ polygon: ["polygon", "plg", "duobianxing", "dbx"]
31
+ };
32
+ name;
33
+ marker;
34
+ primaryColor;
35
+ secondaryColor;
36
+ refCount = 0;
37
+ alwaysInDef = true;
38
+ magicId;
39
+ constructor(name, marker) {
40
+ this.name = name;
41
+ this.marker = marker;
42
+ this.magicId = genHex(8);
43
+ }
44
+ buildHtmlForDef() {
45
+ return this.marker.buildMarkerSvg(this.buildId(), this.primaryColor, this.secondaryColor);
46
+ }
47
+ buildId() {
48
+ return `mkr-${this.magicId}`;
49
+ }
50
+ static getAllMarkerTypeWords() {
51
+ const res = [];
52
+ for (const key in HuatuMarker.TYPES) {
53
+ res.push(...HuatuMarker.TYPES[key]);
54
+ }
55
+ return res;
56
+ }
57
+ static buildMarkerFromParams(name, params) {
58
+ if (!params.type)
59
+ return `Marker Type not specified!`;
60
+ const type = params.type.toLowerCase();
61
+ let shape;
62
+ let orient = 0;
63
+ let refX = 0, refY = 0;
64
+ let hasStroke = false, hasFill = false;
65
+ let fill = {};
66
+ let stroke = {};
67
+ let openDeg = params.degOpen ?? 46;
68
+ let len = params.len ? params.len
69
+ : params.size ? params.size
70
+ : params.width ? params.width
71
+ : 5;
72
+ let radius = params.r ? params.r
73
+ : params.size ? params.size / 2
74
+ : params.width ? params.width / 2
75
+ : params.height ? params.height / 2
76
+ : 6;
77
+ let w = params.width ? params.width
78
+ : params.size ? params.size
79
+ : params.len ? params.len
80
+ : 6;
81
+ let h = params.height ? params.height
82
+ : params.size ? params.size
83
+ : params.len ? params.len
84
+ : 6;
85
+ let rx = params.rx ? params.rx
86
+ : params.r ? params.r
87
+ : params.width ? params.width / 2
88
+ : params.height ? params.height / 2
89
+ : 6;
90
+ let ry = params.ry ? params.ry
91
+ : params.r ? params.r
92
+ : params.height ? params.height / 2
93
+ : params.width ? params.width / 2
94
+ : 6;
95
+ let size = params.size ? params.size
96
+ : params.width ? params.width
97
+ : params.height ? params.height
98
+ : 6;
99
+ if (HuatuMarker.TYPES.arrowSolid.includes(type)) {
100
+ orient = "auto-start-reverse";
101
+ shape = new SvgShapeArrowHeadSolidTriangle(fitNumInRange(len, 1, 200), fitNumInRange(openDeg, 10, 160), params.makeSmooth ? 0.1 : undefined);
102
+ refX = -0.5 / Math.tan(shape.angHalf);
103
+ hasFill = true;
104
+ }
105
+ else if (HuatuMarker.TYPES.arrowDouble.includes(type)) {
106
+ orient = "auto-start-reverse";
107
+ let len2Ratio;
108
+ if (params.k && WtMath.isIn0and1(params.k))
109
+ len2Ratio = fitNumInRange(params.k, 0, 1);
110
+ shape = new SvgShapeArrowHeadSolidTwoTriangle(fitNumInRange(len, 1, 200), fitNumInRange(openDeg, 10, 160), len2Ratio, params.makeSmooth ? 0.1 : undefined);
111
+ refX = -0.5 / Math.tan(shape.angHalf);
112
+ hasFill = true;
113
+ }
114
+ else if (HuatuMarker.TYPES.arrowSimple.includes(type)) {
115
+ orient = "auto-start-reverse";
116
+ shape = new SvgShapeArrowHeadSimpleAngle(fitNumInRange(len, 1, 200), fitNumInRange(openDeg, 10, 160), params.closeArrow, params.makeSmooth);
117
+ refX = -0.5 / Math.tan(shape.angHalf) + 0.5 / Math.sin(shape.angHalf);
118
+ hasStroke = true;
119
+ }
120
+ else if (HuatuMarker.TYPES.circle.includes(type)) {
121
+ shape = new SvgShapeCircle(fitNumInRange(radius, 0.2, 100));
122
+ hasStroke = true;
123
+ hasFill = true;
124
+ }
125
+ else if (HuatuMarker.TYPES.triangle.includes(type)) {
126
+ const dir = params.direction && ["up", "down", "left", "right"].includes(params.direction) ? params.direction : "up";
127
+ shape = new SvgShapeIsoscelesTriangle(fitNumInRange(w, 2, 100), fitNumInRange(h, 2, 100), dir);
128
+ hasFill = true;
129
+ hasStroke = true;
130
+ }
131
+ else if (HuatuMarker.TYPES.ellipse.includes(type)) {
132
+ orient = "auto";
133
+ shape = new SvgShapeEllipse(fitNumInRange(rx, 0.2, 100), fitNumInRange(ry, 0.2, 100));
134
+ hasFill = true;
135
+ hasStroke = true;
136
+ }
137
+ else if (HuatuMarker.TYPES.rhombus.includes(type)) {
138
+ shape = new SvgShapeRhombus(fitNumInRange(w, 0.2, 100), fitNumInRange(h, 0.2, 100));
139
+ hasFill = true;
140
+ hasStroke = true;
141
+ }
142
+ else if (HuatuMarker.TYPES.square.includes(type)) {
143
+ w = fitNumInRange(w, 0.2, 100);
144
+ shape = new SvgShapeRect(w, w);
145
+ hasFill = true;
146
+ hasStroke = true;
147
+ }
148
+ else if (HuatuMarker.TYPES.rectangle.includes(type)) {
149
+ shape = new SvgShapeRect(fitNumInRange(w, 0.2, 100), fitNumInRange(h, 0.2, 100));
150
+ hasFill = true;
151
+ hasStroke = true;
152
+ }
153
+ else if (HuatuMarker.TYPES.star5.includes(type)) {
154
+ shape = new SvgShapeStar5(fitNumInRange(size, 0.4, 100) / 2, params.centerEmpty);
155
+ hasFill = true;
156
+ hasStroke = true;
157
+ }
158
+ else if (HuatuMarker.TYPES.starU.includes(type)) {
159
+ if (!params.n)
160
+ return `Star angle count N must be presented!`;
161
+ let rIn = params.rIn ? params.rIn : params.r ? params.r : 10;
162
+ let rOut = params.rOut ? params.rOut : rIn * 1.2;
163
+ if (rOut < rIn) {
164
+ let x = rIn;
165
+ rIn = rOut;
166
+ rOut = x;
167
+ }
168
+ else if (rOut === rIn) {
169
+ rOut = rIn * 1.2;
170
+ }
171
+ let degOffset = params.degOffset ?? 0;
172
+ let rCorner = params.rx ? params.rx : params.ry ? params.ry : undefined;
173
+ shape = new SvgShapeStarUnified(fitNumInRange(params.n, 3, 30), rIn, rOut, degOffset, rCorner);
174
+ hasFill = true;
175
+ hasStroke = true;
176
+ }
177
+ else if (HuatuMarker.TYPES.plus.includes(type)) {
178
+ shape = new SvgShapePlus(fitNumInRange(w, 0.2, 100));
179
+ hasStroke = true;
180
+ }
181
+ else if (HuatuMarker.TYPES.cross.includes(type)) {
182
+ shape = new SvgShapeCross(fitNumInRange(w, 0.2, 100));
183
+ hasStroke = true;
184
+ }
185
+ else if (HuatuMarker.TYPES.polygon.includes(type)) {
186
+ if (!params.n)
187
+ return `Polygon side count N must be presented!`;
188
+ shape = new SvgShapePolygon(size, fitNumInRange(params.n, 3, 30));
189
+ hasFill = true;
190
+ hasStroke = true;
191
+ }
192
+ else {
193
+ return `Marker type '${type}' is not defined!`;
194
+ }
195
+ if (hasStroke) {
196
+ if (params.strokeColor)
197
+ stroke.color = params.strokeColor;
198
+ if (params.strokeWidth)
199
+ stroke.width = params.strokeWidth;
200
+ }
201
+ if (hasFill) {
202
+ if (params.fillColor)
203
+ fill.color = params.fillColor;
204
+ if (params.fillOpacity)
205
+ fill.opacity = params.fillOpacity;
206
+ }
207
+ return new SvgMarker(`mkr-${name}`, shape, orient, refX, refY, stroke, fill);
208
+ }
209
+ }
@@ -0,0 +1,435 @@
1
+ import { WT_REGEX } from "../tools/regex.js";
2
+ import { WtHuatu } from "./Huatu.js";
3
+ import { resolvePointLike } from "../tools/utils.js";
4
+ import { HuatuYml } from "./HuatuYml.js";
5
+ import { HuatuComponentCache } from "../component/HuatuComponentCache.js";
6
+ export function resolveHuatuSize(size) {
7
+ const wh = resolvePointLike(size);
8
+ if (wh &&
9
+ WT_REGEX.FLOAT_NUMBER.test(wh.x) &&
10
+ WT_REGEX.FLOAT_NUMBER.test(wh.y)) {
11
+ return {
12
+ width: parseFloat(wh.x),
13
+ height: parseFloat(wh.y)
14
+ };
15
+ }
16
+ return null;
17
+ }
18
+ export const FORBIDDEN_NAMES = [
19
+ "config",
20
+ "size", "title", "desc",
21
+ "viewbox", "viewarea", "viewbetween",
22
+ "vars",
23
+ "points", "shapes", "cpoints", "xpoints", "pointseries", "shapeseries",
24
+ "points2", "shapes2", "cpoints2", "xpoints2", "pointseries2", "shapeseries2",
25
+ "points3", "shapes3", "cpoints3", "xpoints3", "pointseries3", "shapeseries3",
26
+ "points4", "shapes4", "cpoints4", "xpoints4", "pointseries4", "shapeseries4",
27
+ "components", "placements",
28
+ "paths", "markers", "patterns", "clips",
29
+ "styles", "labelstyles",
30
+ "symbols", "blocks", "arrays", "layers",
31
+ "draw", "jobs",
32
+ "inputvars", "ports",
33
+ ];
34
+ export function resolveYmlModelSync(ymlObj) {
35
+ const huatu = new WtHuatu();
36
+ if (!ymlObj)
37
+ return huatu;
38
+ // Copy the original object
39
+ const yml = HuatuYml.copyObj(ymlObj);
40
+ // Resolve meta data
41
+ if (yml.title)
42
+ huatu.title = yml.title;
43
+ if (yml.desc)
44
+ huatu.desc = yml.desc;
45
+ if (yml.size) {
46
+ const size = resolveHuatuSize(yml.size);
47
+ if (size) {
48
+ if (size.width > 0)
49
+ huatu.width = size.width;
50
+ if (size.height > 0)
51
+ huatu.height = size.height;
52
+ }
53
+ else {
54
+ huatu.resolvingErrors.push({
55
+ title: `Size input of [${yml.size}] cannot be resolved!`
56
+ });
57
+ }
58
+ }
59
+ // Resolve Global Config
60
+ if (yml.config) {
61
+ const cfg = WtHuatu.resolveConfig(yml.config);
62
+ // Inject the configuration into Global This
63
+ if (Object.keys(cfg).length > 0) {
64
+ huatu.config = cfg;
65
+ }
66
+ }
67
+ // The unified named fields resolving function
68
+ const resolveNamedFields = (field, moduleName, resolveCall, acceptedTypes, ignoreNames) => {
69
+ const fieldVal = yml[field];
70
+ if (typeof fieldVal === "string") {
71
+ huatu.resolvingErrors.push({
72
+ title: `${moduleName} definition "${field}" is incorrect, please check!`,
73
+ });
74
+ return;
75
+ }
76
+ if (fieldVal) {
77
+ for (const name in fieldVal) {
78
+ // Check Name
79
+ if (!WT_REGEX.VAR_NAME.test(name)) {
80
+ huatu.resolvingErrors.push({
81
+ title: `${moduleName} name '${name}' has incorrect format, please use only alphanumeric and underscore(_)!`
82
+ });
83
+ continue;
84
+ }
85
+ const lcName = name.toLowerCase();
86
+ if (FORBIDDEN_NAMES.includes(lcName) && (!ignoreNames || !ignoreNames.includes(lcName))) {
87
+ huatu.resolvingErrors.push({
88
+ title: `${moduleName} name '${name}' is forbidden, please pick another one!`
89
+ });
90
+ continue;
91
+ }
92
+ // Check if definition empty
93
+ let isEmpty = false;
94
+ let notAccepted = false;
95
+ let val = fieldVal[name];
96
+ let valType = "string";
97
+ if (!val) {
98
+ isEmpty = true;
99
+ }
100
+ else if (typeof val === "string") {
101
+ valType = "string";
102
+ // Trim spaces
103
+ val = val.trim();
104
+ if (!val)
105
+ isEmpty = true;
106
+ else if (acceptedTypes && !acceptedTypes.includes("string"))
107
+ notAccepted = true;
108
+ }
109
+ else if (Array.isArray(val)) {
110
+ valType = "list";
111
+ // Make sure list items are strings
112
+ val = val.filter((x, idx) => {
113
+ if (typeof x !== "string") {
114
+ huatu.resolvingErrors.push({ title: `${moduleName} '${name}' has some invalid definition in the list (${idx + 1}-th item), please check!` });
115
+ return false;
116
+ }
117
+ else {
118
+ return x.trim();
119
+ }
120
+ });
121
+ if (val.length < 1)
122
+ isEmpty = true;
123
+ else if (acceptedTypes && !acceptedTypes.includes("list"))
124
+ notAccepted = true;
125
+ }
126
+ else {
127
+ valType = "object";
128
+ if (Object.keys(val).length < 1) {
129
+ isEmpty = true;
130
+ }
131
+ else if (acceptedTypes && !acceptedTypes.includes("object"))
132
+ notAccepted = true;
133
+ }
134
+ if (isEmpty) {
135
+ huatu.resolvingErrors.push({
136
+ title: `${moduleName} '${name}' has no definition (it is empty)!`
137
+ });
138
+ continue;
139
+ }
140
+ if (notAccepted) {
141
+ huatu.resolvingErrors.push({
142
+ title: `${moduleName} [${name}] cannot be defined as "${valType}"!`,
143
+ });
144
+ continue;
145
+ }
146
+ // Call the function and evaluate results
147
+ const errMsg = resolveCall.call(huatu, name, val);
148
+ if (errMsg.length > 1) {
149
+ huatu.resolvingErrors.push({
150
+ title: `${moduleName} [${name}] resolving failed`,
151
+ msgs: [...errMsg]
152
+ });
153
+ }
154
+ else if (errMsg.length === 1) {
155
+ huatu.resolvingErrors.push({
156
+ title: `${moduleName} [${name}] resolving failed: ${errMsg[0]}`,
157
+ });
158
+ }
159
+ }
160
+ }
161
+ };
162
+ // Resolve Var, this is the first step;
163
+ resolveNamedFields("vars", "Var", huatu.resolveVar, ["string"]);
164
+ /** The first round to resolve points, shapes, cpoints, xpoints and series */
165
+ resolveNamedFields("points", "Point", huatu.resolvePoint, ["string"]);
166
+ resolveNamedFields("shapes", "Shape", huatu.resolveShape, ["string"]);
167
+ resolveNamedFields("cpoints", "Calculated Point", huatu.resolveCPoint, ["string"]);
168
+ resolveNamedFields("xpoints", "Intersection Point", huatu.resolveXPoint, ["string"]);
169
+ resolveNamedFields("pointSeries", "Point Series", huatu.resolvePointSeries, ["string"]);
170
+ resolveNamedFields("shapeSeries", "Shape Series", huatu.resolveShapeSeries, ["string"]);
171
+ /**
172
+ * Here add extra 3 round of resolving Shapes/CPoints/Xpoints, This is to make it possible
173
+ * that new shapes created based on the points calculated by intersection or from model.
174
+ */
175
+ // Resolve Shapes, the second Round
176
+ resolveNamedFields("points2", "Point", huatu.resolvePoint, ["string"]);
177
+ resolveNamedFields("shapes2", "Shape", huatu.resolveShape, ["string"]);
178
+ resolveNamedFields("cpoints2", "Calculated Point", huatu.resolveCPoint, ["string"]);
179
+ resolveNamedFields("xpoints2", "Intersection Point", huatu.resolveXPoint, ["string"]);
180
+ resolveNamedFields("pointSeries2", "Point Series", huatu.resolvePointSeries, ["string"]);
181
+ resolveNamedFields("shapeSeries2", "Shape Series", huatu.resolveShapeSeries, ["string"]);
182
+ // Resolve Shapes, the third Round
183
+ resolveNamedFields("points3", "Point", huatu.resolvePoint, ["string"]);
184
+ resolveNamedFields("shapes3", "Shape", huatu.resolveShape, ["string"]);
185
+ resolveNamedFields("cpoints3", "Calculated Point", huatu.resolveCPoint, ["string"]);
186
+ resolveNamedFields("xpoints3", "Intersection Point", huatu.resolveXPoint, ["string"]);
187
+ resolveNamedFields("pointSeries3", "Point Series", huatu.resolvePointSeries, ["string"]);
188
+ resolveNamedFields("shapeSeries3", "Shape Series", huatu.resolveShapeSeries, ["string"]);
189
+ // Resolve Shapes, the fourth Round
190
+ resolveNamedFields("points4", "Point", huatu.resolvePoint, ["string"]);
191
+ resolveNamedFields("shapes4", "Shape", huatu.resolveShape, ["string"]);
192
+ resolveNamedFields("cpoints4", "Calculated Point", huatu.resolveCPoint, ["string"]);
193
+ resolveNamedFields("xpoints4", "Intersection Point", huatu.resolveXPoint, ["string"]);
194
+ resolveNamedFields("pointSeries4", "Point Series", huatu.resolvePointSeries, ["string"]);
195
+ resolveNamedFields("shapeSeries4", "Shape Series", huatu.resolveShapeSeries, ["string"]);
196
+ /** ========= Repeating Rounds ended ========= */
197
+ // Resolve Components
198
+ resolveNamedFields("components", "Component Definitions", huatu.resolveComponentDef, ["string", "object"]);
199
+ // Resolve Component Placement
200
+ resolveNamedFields("placements", "Component Placements", huatu.resolveComponentPlacement, ["string", "object"]);
201
+ // Resolve paths
202
+ resolveNamedFields("paths", "Path", huatu.resolvePath, ["string", 'list']);
203
+ // Resolve marker
204
+ resolveNamedFields("markers", "Marker", huatu.resolveMarker, ["string", "object"]);
205
+ // Resolve Pattern
206
+ resolveNamedFields("patterns", "Pattern", huatu.resolvePattern, ["string", "object"]);
207
+ // Resolve Clips
208
+ resolveNamedFields("clips", "Clip-Path", huatu.resolveClip, ["string", "list"]);
209
+ // Resolve styles
210
+ resolveNamedFields("styles", "Style", huatu.resolveStyle, ["string", "object"]);
211
+ // Resolve Label Styles
212
+ resolveNamedFields("labelStyles", "Label Style", huatu.resolveLabelStyle, ["string", "object"]);
213
+ // Resolve symbols
214
+ resolveNamedFields("symbols", "Symbol", huatu.resolveSymbol, ["string", "list"]);
215
+ // Resolve blocks
216
+ resolveNamedFields("blocks", "Block", huatu.resolveBlock, ["string", "list"]);
217
+ // Resolve arrays
218
+ resolveNamedFields("arrays", "Array", huatu.resolveArray, ["string", "object"]);
219
+ // Resolve Layers
220
+ resolveNamedFields("layers", "Layer", huatu.resolveLayer, ["string", "list"]);
221
+ // Resolve ViewBox
222
+ let vbDef = yml.viewBox || yml.viewArea || yml.viewBetween;
223
+ if (vbDef) {
224
+ let vb = huatu.resolveViewBoxFromDef(vbDef);
225
+ if (typeof vb === "string")
226
+ huatu.resolvingErrors.push({
227
+ title: `ViewBox Resolving Failed: ${vb}`
228
+ });
229
+ else if (vb)
230
+ huatu.viewBox = vb;
231
+ else {
232
+ huatu.warnings.push(`'${vbDef}' cannot resolve to a valid View Box!`);
233
+ }
234
+ }
235
+ // Resolve Jobs, Including the global draw
236
+ if (yml.jobs && yml.jobs["draw"]) {
237
+ huatu.resolvingErrors.push({
238
+ title: `You cannot define a job named as 'draw', please place the 'draw' job at root!`
239
+ });
240
+ delete yml.jobs["draw"]; // Delete it
241
+ }
242
+ if (yml.draw) {
243
+ if (yml.jobs)
244
+ yml.jobs["draw"] = yml.draw;
245
+ else
246
+ yml.jobs = { draw: yml.draw };
247
+ }
248
+ resolveNamedFields("jobs", "Job", huatu.resolveJob, ["string", "list", "object"], ["draw"]);
249
+ huatu.draw = huatu.jobs.find(j => j.name === "draw");
250
+ // Return after resolving
251
+ return huatu;
252
+ }
253
+ export async function resolveYmlModel(ymlObj) {
254
+ if (!ymlObj)
255
+ return new WtHuatu();
256
+ // Prepare Components if any
257
+ await HuatuComponentCache.prepareComponents(ymlObj);
258
+ return resolveYmlModelSync(ymlObj);
259
+ }
260
+ export function resolveYmlModelOfComponent(ymlObj) {
261
+ const comp = new WtHuatu();
262
+ if (!ymlObj)
263
+ return comp;
264
+ // Copy the original object
265
+ const yml = HuatuYml.copyObj(ymlObj);
266
+ // Resolve meta data
267
+ if (yml.title)
268
+ comp.title = yml.title;
269
+ if (yml.desc)
270
+ comp.desc = yml.desc;
271
+ // The unified named fields resolving function
272
+ const resolveNamedFields = (field, moduleName, resolveCall, acceptedTypes, ignoreNames) => {
273
+ const fieldVal = yml[field];
274
+ if (typeof fieldVal === "string") {
275
+ comp.resolvingErrors.push({
276
+ title: `${moduleName} definition "${field}" is incorrect, please check!`,
277
+ });
278
+ return;
279
+ }
280
+ if (fieldVal) {
281
+ for (const name in fieldVal) {
282
+ // Check Name
283
+ if (!WT_REGEX.VAR_NAME.test(name)) {
284
+ comp.resolvingErrors.push({
285
+ title: `${moduleName} name '${name}' has incorrect format, please use only alphanumeric and underscore(_)!`
286
+ });
287
+ continue;
288
+ }
289
+ const lcName = name.toLowerCase();
290
+ if (FORBIDDEN_NAMES.includes(lcName) && (!ignoreNames || !ignoreNames.includes(lcName))) {
291
+ comp.resolvingErrors.push({
292
+ title: `${moduleName} name '${name}' is forbidden, please pick another one!`
293
+ });
294
+ continue;
295
+ }
296
+ // Check if definition empty
297
+ let isEmpty = false;
298
+ let notAccepted = false;
299
+ let val = fieldVal[name];
300
+ let valType = "string";
301
+ if (!val) {
302
+ isEmpty = true;
303
+ }
304
+ else if (typeof val === "string") {
305
+ valType = "string";
306
+ // Trim spaces
307
+ val = val.trim();
308
+ if (!val)
309
+ isEmpty = true;
310
+ else if (acceptedTypes && !acceptedTypes.includes("string"))
311
+ notAccepted = true;
312
+ }
313
+ else if (Array.isArray(val)) {
314
+ valType = "list";
315
+ // Make sure list items are strings
316
+ val = val.filter((x, idx) => {
317
+ if (typeof x !== "string") {
318
+ comp.resolvingErrors.push({ title: `${moduleName} '${name}' has some invalid definition in the list (${idx + 1}-th item), please check!` });
319
+ return false;
320
+ }
321
+ else {
322
+ return x.trim();
323
+ }
324
+ });
325
+ if (val.length < 1)
326
+ isEmpty = true;
327
+ else if (acceptedTypes && !acceptedTypes.includes("list"))
328
+ notAccepted = true;
329
+ }
330
+ else {
331
+ valType = "object";
332
+ if (Object.keys(val).length < 1) {
333
+ isEmpty = true;
334
+ }
335
+ else if (acceptedTypes && !acceptedTypes.includes("object"))
336
+ notAccepted = true;
337
+ }
338
+ if (isEmpty) {
339
+ comp.resolvingErrors.push({
340
+ title: `${moduleName} '${name}' has no definition (it is empty)!`
341
+ });
342
+ continue;
343
+ }
344
+ if (notAccepted) {
345
+ comp.resolvingErrors.push({
346
+ title: `${moduleName} [${name}] cannot be defined as "${valType}"!`,
347
+ });
348
+ continue;
349
+ }
350
+ // Call the function and evaluate results
351
+ const errMsg = resolveCall.call(comp, name, val);
352
+ if (errMsg.length > 1) {
353
+ comp.resolvingErrors.push({
354
+ title: `${moduleName} [${name}] resolving failed`,
355
+ msgs: [...errMsg]
356
+ });
357
+ }
358
+ else if (errMsg.length === 1) {
359
+ comp.resolvingErrors.push({
360
+ title: `${moduleName} [${name}] resolving failed: ${errMsg[0]}`,
361
+ });
362
+ }
363
+ }
364
+ }
365
+ };
366
+ // Resolve Var, this is the first step;
367
+ resolveNamedFields("vars", "Var", comp.resolveVar, ["string"]);
368
+ /** The first round to resolve points, shapes, cpoints, xpoints and series */
369
+ resolveNamedFields("points", "Point", comp.resolvePoint, ["string"]);
370
+ resolveNamedFields("shapes", "Shape", comp.resolveShape, ["string"]);
371
+ resolveNamedFields("cpoints", "Calculated Point", comp.resolveCPoint, ["string"]);
372
+ resolveNamedFields("xpoints", "Intersection Point", comp.resolveXPoint, ["string"]);
373
+ resolveNamedFields("pointSeries", "Point Series", comp.resolvePointSeries, ["string"]);
374
+ resolveNamedFields("shapeSeries", "Shape Series", comp.resolveShapeSeries, ["string"]);
375
+ /**
376
+ * Here add extra 3 round of resolving Shapes/CPoints/Xpoints, This is to make it possible
377
+ * that new shapes created based on the points calculated by intersection or from model.
378
+ */
379
+ // Resolve Shapes, the second Round
380
+ resolveNamedFields("points2", "Point", comp.resolvePoint, ["string"]);
381
+ resolveNamedFields("shapes2", "Shape", comp.resolveShape, ["string"]);
382
+ resolveNamedFields("cpoints2", "Calculated Point", comp.resolveCPoint, ["string"]);
383
+ resolveNamedFields("xpoints2", "Intersection Point", comp.resolveXPoint, ["string"]);
384
+ resolveNamedFields("pointSeries2", "Point Series", comp.resolvePointSeries, ["string"]);
385
+ resolveNamedFields("shapeSeries2", "Shape Series", comp.resolveShapeSeries, ["string"]);
386
+ // Resolve Shapes, the third Round
387
+ resolveNamedFields("points3", "Point", comp.resolvePoint, ["string"]);
388
+ resolveNamedFields("shapes3", "Shape", comp.resolveShape, ["string"]);
389
+ resolveNamedFields("cpoints3", "Calculated Point", comp.resolveCPoint, ["string"]);
390
+ resolveNamedFields("xpoints3", "Intersection Point", comp.resolveXPoint, ["string"]);
391
+ resolveNamedFields("pointSeries3", "Point Series", comp.resolvePointSeries, ["string"]);
392
+ resolveNamedFields("shapeSeries3", "Shape Series", comp.resolveShapeSeries, ["string"]);
393
+ // Resolve Shapes, the fourth Round
394
+ resolveNamedFields("points4", "Point", comp.resolvePoint, ["string"]);
395
+ resolveNamedFields("shapes4", "Shape", comp.resolveShape, ["string"]);
396
+ resolveNamedFields("cpoints4", "Calculated Point", comp.resolveCPoint, ["string"]);
397
+ resolveNamedFields("xpoints4", "Intersection Point", comp.resolveXPoint, ["string"]);
398
+ resolveNamedFields("pointSeries4", "Point Series", comp.resolvePointSeries, ["string"]);
399
+ resolveNamedFields("shapeSeries4", "Shape Series", comp.resolveShapeSeries, ["string"]);
400
+ /** ========= Repeating Rounds ended ========= */
401
+ // Resolve paths
402
+ resolveNamedFields("paths", "Path", comp.resolvePath, ["string", 'list']);
403
+ // Resolve marker
404
+ resolveNamedFields("markers", "Marker", comp.resolveMarker, ["string", "object"]);
405
+ // Resolve Pattern
406
+ resolveNamedFields("patterns", "Pattern", comp.resolvePattern, ["string", "object"]);
407
+ // Resolve styles
408
+ resolveNamedFields("styles", "Style", comp.resolveStyle, ["string", "object"]);
409
+ // Resolve Label Styles
410
+ resolveNamedFields("labelStyles", "Label Style", comp.resolveLabelStyle, ["string", "object"]);
411
+ // Resolve ViewBox
412
+ let vbDef = yml.viewBox || yml.viewArea || yml.viewBetween;
413
+ if (vbDef) {
414
+ let vb = comp.resolveViewBoxFromDef(vbDef);
415
+ if (typeof vb === "string")
416
+ comp.resolvingErrors.push({
417
+ title: `ViewBox Resolving Failed: ${vb}`
418
+ });
419
+ else if (vb)
420
+ comp.viewBox = vb;
421
+ else {
422
+ comp.warnings.push(`'${vbDef}' cannot resolve to a valid View Box!`);
423
+ }
424
+ }
425
+ if (yml.draw) {
426
+ if (yml.jobs)
427
+ yml.jobs["draw"] = yml.draw;
428
+ else
429
+ yml.jobs = { draw: yml.draw };
430
+ }
431
+ resolveNamedFields("jobs", "Job", comp.resolveJob, ["string", "list", "object"], ["draw"]);
432
+ comp.draw = comp.jobs.find(j => j.name === "draw");
433
+ // Return after resolving
434
+ return comp;
435
+ }