oakscriptjs 0.9.5 → 0.9.6

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 (177) hide show
  1. package/dist/cjs/array/index.d.ts +84 -27
  2. package/dist/cjs/array/index.d.ts.map +1 -1
  3. package/dist/cjs/array/index.js +235 -78
  4. package/dist/cjs/array/index.js.map +3 -3
  5. package/dist/cjs/callsite/index.d.ts +81 -2
  6. package/dist/cjs/callsite/index.d.ts.map +1 -1
  7. package/dist/cjs/callsite/index.js +62 -1
  8. package/dist/cjs/callsite/index.js.map +2 -2
  9. package/dist/cjs/color/index.d.ts +7 -3
  10. package/dist/cjs/color/index.d.ts.map +1 -1
  11. package/dist/cjs/color/index.js +6 -1
  12. package/dist/cjs/color/index.js.map +2 -2
  13. package/dist/cjs/index.d.ts +1 -1
  14. package/dist/cjs/index.js +1 -1
  15. package/dist/cjs/index.js.map +1 -1
  16. package/dist/cjs/label/index.d.ts.map +1 -1
  17. package/dist/cjs/label/index.js +2 -1
  18. package/dist/cjs/label/index.js.map +2 -2
  19. package/dist/cjs/linefill/index.d.ts.map +1 -1
  20. package/dist/cjs/linefill/index.js +1 -0
  21. package/dist/cjs/linefill/index.js.map +2 -2
  22. package/dist/cjs/math/index.d.ts +76 -21
  23. package/dist/cjs/math/index.d.ts.map +1 -1
  24. package/dist/cjs/math/index.js +155 -41
  25. package/dist/cjs/math/index.js.map +3 -3
  26. package/dist/cjs/matrix/index.d.ts.map +1 -1
  27. package/dist/cjs/matrix/index.js +42 -36
  28. package/dist/cjs/matrix/index.js.map +2 -2
  29. package/dist/cjs/runtime/series.d.ts +9 -0
  30. package/dist/cjs/runtime/series.d.ts.map +1 -1
  31. package/dist/cjs/runtime/series.js +16 -2
  32. package/dist/cjs/runtime/series.js.map +2 -2
  33. package/dist/cjs/script/index.d.ts +15 -31
  34. package/dist/cjs/script/index.d.ts.map +1 -1
  35. package/dist/cjs/script/index.js +32 -0
  36. package/dist/cjs/script/index.js.map +2 -2
  37. package/dist/cjs/session/calendar.d.ts.map +1 -1
  38. package/dist/cjs/session/calendar.js +15 -2
  39. package/dist/cjs/session/calendar.js.map +2 -2
  40. package/dist/cjs/str/index.d.ts +50 -38
  41. package/dist/cjs/str/index.d.ts.map +1 -1
  42. package/dist/cjs/str/index.js +43 -15
  43. package/dist/cjs/str/index.js.map +2 -2
  44. package/dist/cjs/str/messageformat.d.ts +2 -1
  45. package/dist/cjs/str/messageformat.d.ts.map +1 -1
  46. package/dist/cjs/str/messageformat.js +4 -1
  47. package/dist/cjs/str/messageformat.js.map +2 -2
  48. package/dist/cjs/str/numberformat.d.ts +4 -0
  49. package/dist/cjs/str/numberformat.d.ts.map +1 -1
  50. package/dist/cjs/str/numberformat.js +26 -4
  51. package/dist/cjs/str/numberformat.js.map +3 -3
  52. package/dist/cjs/ta/index.d.ts +86 -43
  53. package/dist/cjs/ta/index.d.ts.map +1 -1
  54. package/dist/cjs/ta/index.js +173 -267
  55. package/dist/cjs/ta/index.js.map +3 -3
  56. package/dist/cjs/ta/running-sum.d.ts +54 -2
  57. package/dist/cjs/ta/running-sum.d.ts.map +1 -1
  58. package/dist/cjs/ta/running-sum.js +132 -52
  59. package/dist/cjs/ta/running-sum.js.map +2 -2
  60. package/dist/cjs/ta-series.d.ts +4 -4
  61. package/dist/cjs/ta-series.d.ts.map +1 -1
  62. package/dist/cjs/ta-series.js +4 -3
  63. package/dist/cjs/ta-series.js.map +2 -2
  64. package/dist/cjs/time/datestring.d.ts +1 -0
  65. package/dist/cjs/time/datestring.d.ts.map +1 -1
  66. package/dist/cjs/time/datestring.js +7 -0
  67. package/dist/cjs/time/datestring.js.map +2 -2
  68. package/dist/cjs/time/index.d.ts.map +1 -1
  69. package/dist/cjs/time/index.js +2 -1
  70. package/dist/cjs/time/index.js.map +2 -2
  71. package/dist/cjs/time/session.d.ts +28 -9
  72. package/dist/cjs/time/session.d.ts.map +1 -1
  73. package/dist/cjs/time/session.js +74 -28
  74. package/dist/cjs/time/session.js.map +2 -2
  75. package/dist/cjs/time/timezone.d.ts +5 -0
  76. package/dist/cjs/time/timezone.d.ts.map +1 -1
  77. package/dist/cjs/time/timezone.js +15 -1
  78. package/dist/cjs/time/timezone.js.map +2 -2
  79. package/dist/esm/array/index.d.ts +84 -27
  80. package/dist/esm/array/index.d.ts.map +1 -1
  81. package/dist/esm/array/index.js +373 -111
  82. package/dist/esm/array/index.js.map +1 -1
  83. package/dist/esm/callsite/index.d.ts +81 -2
  84. package/dist/esm/callsite/index.d.ts.map +1 -1
  85. package/dist/esm/callsite/index.js +145 -3
  86. package/dist/esm/callsite/index.js.map +1 -1
  87. package/dist/esm/color/index.d.ts +7 -3
  88. package/dist/esm/color/index.d.ts.map +1 -1
  89. package/dist/esm/color/index.js +15 -3
  90. package/dist/esm/color/index.js.map +1 -1
  91. package/dist/esm/index.d.ts +1 -1
  92. package/dist/esm/index.js +1 -1
  93. package/dist/esm/label/index.d.ts.map +1 -1
  94. package/dist/esm/label/index.js +2 -1
  95. package/dist/esm/label/index.js.map +1 -1
  96. package/dist/esm/linefill/index.d.ts.map +1 -1
  97. package/dist/esm/linefill/index.js +3 -0
  98. package/dist/esm/linefill/index.js.map +1 -1
  99. package/dist/esm/math/index.d.ts +76 -21
  100. package/dist/esm/math/index.d.ts.map +1 -1
  101. package/dist/esm/math/index.js +227 -61
  102. package/dist/esm/math/index.js.map +1 -1
  103. package/dist/esm/matrix/index.d.ts.map +1 -1
  104. package/dist/esm/matrix/index.js +57 -43
  105. package/dist/esm/matrix/index.js.map +1 -1
  106. package/dist/esm/runtime/series.d.ts +9 -0
  107. package/dist/esm/runtime/series.d.ts.map +1 -1
  108. package/dist/esm/runtime/series.js +18 -1
  109. package/dist/esm/runtime/series.js.map +1 -1
  110. package/dist/esm/script/index.d.ts +15 -31
  111. package/dist/esm/script/index.d.ts.map +1 -1
  112. package/dist/esm/script/index.js +44 -1
  113. package/dist/esm/script/index.js.map +1 -1
  114. package/dist/esm/session/calendar.d.ts.map +1 -1
  115. package/dist/esm/session/calendar.js +22 -2
  116. package/dist/esm/session/calendar.js.map +1 -1
  117. package/dist/esm/str/index.d.ts +50 -38
  118. package/dist/esm/str/index.d.ts.map +1 -1
  119. package/dist/esm/str/index.js +103 -52
  120. package/dist/esm/str/index.js.map +1 -1
  121. package/dist/esm/str/messageformat.d.ts +2 -1
  122. package/dist/esm/str/messageformat.d.ts.map +1 -1
  123. package/dist/esm/str/messageformat.js +7 -2
  124. package/dist/esm/str/messageformat.js.map +1 -1
  125. package/dist/esm/str/numberformat.d.ts +4 -0
  126. package/dist/esm/str/numberformat.d.ts.map +1 -1
  127. package/dist/esm/str/numberformat.js +38 -4
  128. package/dist/esm/str/numberformat.js.map +1 -1
  129. package/dist/esm/ta/index.d.ts +86 -43
  130. package/dist/esm/ta/index.d.ts.map +1 -1
  131. package/dist/esm/ta/index.js +296 -348
  132. package/dist/esm/ta/index.js.map +1 -1
  133. package/dist/esm/ta/running-sum.d.ts +54 -2
  134. package/dist/esm/ta/running-sum.d.ts.map +1 -1
  135. package/dist/esm/ta/running-sum.js +166 -71
  136. package/dist/esm/ta/running-sum.js.map +1 -1
  137. package/dist/esm/ta-series.d.ts +4 -4
  138. package/dist/esm/ta-series.d.ts.map +1 -1
  139. package/dist/esm/ta-series.js +5 -4
  140. package/dist/esm/ta-series.js.map +1 -1
  141. package/dist/esm/time/datestring.d.ts +1 -0
  142. package/dist/esm/time/datestring.d.ts.map +1 -1
  143. package/dist/esm/time/datestring.js +12 -0
  144. package/dist/esm/time/datestring.js.map +1 -1
  145. package/dist/esm/time/index.d.ts.map +1 -1
  146. package/dist/esm/time/index.js +3 -1
  147. package/dist/esm/time/index.js.map +1 -1
  148. package/dist/esm/time/session.d.ts +28 -9
  149. package/dist/esm/time/session.d.ts.map +1 -1
  150. package/dist/esm/time/session.js +113 -42
  151. package/dist/esm/time/session.js.map +1 -1
  152. package/dist/esm/time/timezone.d.ts +5 -0
  153. package/dist/esm/time/timezone.d.ts.map +1 -1
  154. package/dist/esm/time/timezone.js +21 -1
  155. package/dist/esm/time/timezone.js.map +1 -1
  156. package/package.json +1 -1
  157. package/src/array/index.ts +352 -127
  158. package/src/callsite/index.ts +147 -3
  159. package/src/color/index.ts +15 -5
  160. package/src/index.ts +1 -1
  161. package/src/label/index.ts +2 -1
  162. package/src/linefill/index.ts +2 -0
  163. package/src/math/index.ts +256 -74
  164. package/src/matrix/index.ts +52 -52
  165. package/src/runtime/series.ts +22 -1
  166. package/src/script/index.ts +53 -1
  167. package/src/session/calendar.ts +22 -2
  168. package/src/str/index.ts +95 -51
  169. package/src/str/messageformat.ts +7 -2
  170. package/src/str/numberformat.ts +39 -4
  171. package/src/ta/index.ts +306 -386
  172. package/src/ta/running-sum.ts +187 -74
  173. package/src/ta-series.ts +8 -7
  174. package/src/time/datestring.ts +10 -0
  175. package/src/time/index.ts +3 -1
  176. package/src/time/session.ts +97 -47
  177. package/src/time/timezone.ts +21 -1
@@ -13,6 +13,7 @@
13
13
  * call), which PineScript computes with a state kept between calls.
14
14
  * - {@link lowestByBar} / {@link highestByBar} / {@link linreg}: `ta.lowest` / `ta.highest` / `ta.linreg` in a
15
15
  * conditional block, whose history is kept by bar (not by call).
16
+ * - {@link sum} / {@link sma}: `math.sum` / `ta.sma` in a `for` / `while` loop, called several times on one bar.
16
17
  *
17
18
  * Since PineScript v6, `and` / `or` are lazy: the right operand runs only when the left operand does not decide
18
19
  * the result. A ta.* call in the right operand of `a or b` runs on the bars where `a` is false, in `a and b` on the
@@ -43,6 +44,8 @@
43
44
 
44
45
  import type { Source } from '../types/index.js';
45
46
  import { linreg as linregSeries } from '../ta/index.js';
47
+ import { RunningSum, isNa } from '../ta/running-sum.js';
48
+ import { seededRandom } from '../math/index.js';
46
49
 
47
50
  /**
48
51
  * Runs `fn` on the bars where `called` is true only, like a ta.* call inside an `if` block.
@@ -115,11 +118,19 @@ export function barssince(): (condition: boolean | number) => number {
115
118
  }
116
119
 
117
120
  /**
118
- * One `ta.cross(a, b)` call site: compared with the last call where both arguments were not na; false before such
119
- * a call.
121
+ * One `ta.cross(a, b)` call site, rules of `ta.cross`: the site keeps the side of the last call where `a` was
122
+ * strictly above or strictly below `b` (none before such a call; equal values and na arguments do not change it),
123
+ * and is true when the arguments are strictly on the other side. False with an na argument.
120
124
  */
121
125
  export function cross(): (a: number, b: number) => boolean {
122
- return twoSeriesSite((a, b, pa, pb) => (a > b && pa <= pb) || (a < b && pa >= pb));
126
+ let side = 0; // -1: last strictly below, 1: last strictly above, 0: none yet
127
+ return (a, b) => {
128
+ if (Number.isNaN(a) || Number.isNaN(b)) return false;
129
+ const result = (side < 0 && a > b) || (side > 0 && a < b);
130
+ if (a < b) side = -1;
131
+ else if (a > b) side = 1;
132
+ return result;
133
+ };
123
134
  }
124
135
 
125
136
  /** One `ta.lowest` / `ta.highest` call site with a series length; rules in {@link lowest}. */
@@ -289,3 +300,136 @@ export function linreg(): (barIndex: number, value: number, length: number, offs
289
300
  };
290
301
  }
291
302
 
303
+
304
+ /**
305
+ * One `math.sum` call site in a loop; rules in {@link sum}. With `squares`, it also keeps the running sum of the
306
+ * squared values (for {@link stdev}). Returns `[sum, sumOfSquares]` (NaN when not kept).
307
+ */
308
+ function loopSumSite(
309
+ name: string,
310
+ squares: boolean
311
+ ): (barIndex: number, value: number, length: number) => [number, number] {
312
+ const running = new RunningSum();
313
+ const runningSq = new RunningSum();
314
+ let lastBar = NaN;
315
+ let pending = false;
316
+ return (barIndex, value, length) => {
317
+ const len = Math.floor(length);
318
+ if (!(len >= 1)) throw new Error(`callsite.${name}: length must be at least 1 (got ${length})`);
319
+ if (barIndex !== lastBar) {
320
+ if (pending) {
321
+ running.commit();
322
+ if (squares) runningSq.commit();
323
+ }
324
+ pending = false;
325
+ lastBar = barIndex;
326
+ }
327
+ if (isNa(value)) {
328
+ pending = false;
329
+ return [running.stepNa(len), squares ? runningSq.stepNa(len) : NaN];
330
+ }
331
+ const x = value;
332
+ const out: [number, number] = [running.step(x, len), squares ? runningSq.step(x * x, len) : NaN];
333
+ pending = true;
334
+ return out;
335
+ };
336
+ }
337
+
338
+ /**
339
+ * One `math.sum(source, length)` call site inside a `for` / `while` loop, called with `(barIndex, value, length)` on
340
+ * each call.
341
+ *
342
+ * PineScript rules (measured on calls in loops, 1 to 3 calls per bar, and bars without a call):
343
+ * - the call site keeps one history value per bar: the value of its last call on that bar
344
+ * - every call on a bar starts from the state of the earlier bars, so it gives the sum of its value and the last
345
+ * `length - 1` kept values; the last call of the bar is the one kept for the later bars
346
+ * - the length can change from one call to the next (also on the same bar): each call first moves the kept sum to
347
+ * its own length as `math.sum` with a series length does (Kahan steps of the raw values)
348
+ * - a bar without a call is not in the history (as a call in an `if` block)
349
+ * - the sum is the same compensated running sum as `math.sum` (bit for bit)
350
+ *
351
+ * An na value is skipped as in `math.sum` (it returns the sum of the last `length` earlier values); when it is the
352
+ * last call of a bar, the bar is not in the history (not measured).
353
+ *
354
+ * @example
355
+ * ```typescript
356
+ * // Pine: for i = 0 to 2
357
+ * // s = math.sum(close * (1 + 0.01 * i), 7)
358
+ * const site = callsite.sum();
359
+ * for (let b = 0; b < closes.length; b++) {
360
+ * for (let i = 0; i <= 2; i++) {
361
+ * const s = site(b, closes[b]! * (1 + 0.01 * i), 7);
362
+ * }
363
+ * }
364
+ * ```
365
+ */
366
+ export function sum(): (barIndex: number, value: number, length: number) => number {
367
+ const site = loopSumSite('sum', false);
368
+ return (barIndex, value, length) => site(barIndex, value, length)[0];
369
+ }
370
+
371
+ /**
372
+ * One `ta.sma(source, length)` call site inside a `for` / `while` loop, called with `(barIndex, value, length)` on
373
+ * each call: {@link sum} divided by the length (same rules).
374
+ *
375
+ * @example
376
+ * ```typescript
377
+ * // Pine: evaluate(ratio) => ta.sma(gann(ratio), n) // called once per ratio in a while loop
378
+ * const site = callsite.sma();
379
+ * for (let b = 0; b < closes.length; b++) {
380
+ * for (const ratio of ratios) {
381
+ * const avg = site(b, gann(b, ratio), n);
382
+ * }
383
+ * }
384
+ * ```
385
+ */
386
+ export function sma(): (barIndex: number, value: number, length: number) => number {
387
+ const site = loopSumSite('sma', false);
388
+ return (barIndex, value, length) => site(barIndex, value, length)[0] / Math.floor(length);
389
+ }
390
+
391
+ /**
392
+ * One `ta.stdev(source, length, biased)` call site inside a `for` / `while` loop, called with
393
+ * `(barIndex, value, length, biased?)` on each call: the running sums of the values and of their squares follow the
394
+ * rules of {@link sum}; the result is computed from them as `ta.stdev` (bit for bit).
395
+ *
396
+ * @example
397
+ * ```typescript
398
+ * // Pine: for len in lengths
399
+ * // [mid, up, lo] = ta.bb(close, len, 2)
400
+ * const avgSite = callsite.sma();
401
+ * const devSite = callsite.stdev();
402
+ * for (let b = 0; b < closes.length; b++) {
403
+ * for (const len of lengths) {
404
+ * const mid = avgSite(b, closes[b]!, len);
405
+ * const dev = devSite(b, closes[b]!, len);
406
+ * }
407
+ * }
408
+ * ```
409
+ */
410
+ export function stdev(): (barIndex: number, value: number, length: number, biased?: boolean) => number {
411
+ const site = loopSumSite('stdev', true);
412
+ return (barIndex, value, length, biased = true) => {
413
+ const len = Math.floor(length);
414
+ const [s, sq] = site(barIndex, value, length);
415
+ const mean = s / len;
416
+ const variance = biased ? sq / len - mean * mean : sq / (len - 1) - (mean * s) / (len - 1);
417
+ if (!biased && len <= 1) return NaN;
418
+ return Number.isNaN(variance) ? NaN : variance > 0 ? Math.sqrt(variance) : 0;
419
+ };
420
+ }
421
+
422
+ /**
423
+ * One `math.random(min, max, seed)` call site: PineScript keeps one generator per call site, so two call sites
424
+ * with the same seed give the same sequence. Called with `(min?, max?)` once per bar.
425
+ *
426
+ * @example
427
+ * ```typescript
428
+ * // Pine: a = math.random(0, 1, 42), b = math.random(0, 1, 42) // a == b on every bar
429
+ * const a = callsite.random(42);
430
+ * const b = callsite.random(42);
431
+ * ```
432
+ */
433
+ export function random(seed: number): (min?: number, max?: number) => number {
434
+ return seededRandom(seed);
435
+ }
@@ -107,7 +107,10 @@ export function from_hex(hex: string, transp?: simple_float): string {
107
107
  * - Replaces the transparency with the new value
108
108
  * - Useful for creating semi-transparent versions of existing colors
109
109
  * - PineScript clamps the transparency to 0..100 (`color.new(c, 140)` is fully transparent, `color.new(c, -5)` is
110
- * opaque); an `na` transparency is fully transparent
110
+ * opaque); an `na` transparency is fully transparent (measured: the colour is not na, its RGB is kept)
111
+ * - an `na` colour (null / undefined) gives black with the new transparency: `color.new(na, 30)` is
112
+ * `rgba(0, 0, 0, 0.7)`, as PineScript does for an na colour variable (measured, #150). In PineScript, the constant
113
+ * `color.new(color(na), 30)` is computed at compile time and stays na; a JS function cannot tell the two apart.
111
114
  *
112
115
  * @example
113
116
  * ```typescript
@@ -117,7 +120,8 @@ export function from_hex(hex: string, transp?: simple_float): string {
117
120
  * color.new_color(red, 100) // Returns: "rgba(255, 0, 0, 0)" - Fully transparent
118
121
  * ```
119
122
  */
120
- export function new_color(baseColor: color, transp: simple_float): string {
123
+ export function new_color(baseColor: color | null | undefined, transp: simple_float): string {
124
+ if (baseColor === null || baseColor === undefined) return rgb(0, 0, 0, transp); // na colour: black
121
125
  // Parse the color and apply transparency
122
126
  const rgba = parseColor(baseColor);
123
127
  return rgb(rgba.r, rgba.g, rgba.b, transp);
@@ -185,6 +189,7 @@ export function b(clr: color): int {
185
189
  * - Converts alpha channel (0-1) to transparency (0-100)
186
190
  * - PineScript stores the alpha as a byte (0-255) and returns an integer transparency:
187
191
  * `color.t(color.new(c, 33.3))` is 33
192
+ * - an `na` colour (null / undefined) is fully transparent: 100
188
193
  *
189
194
  * @example
190
195
  * ```typescript
@@ -193,7 +198,8 @@ export function b(clr: color): int {
193
198
  * color.t(color.rgb(255, 0, 0, 100)) // Returns: 100 (fully transparent)
194
199
  * ```
195
200
  */
196
- export function t(clr: color): float {
201
+ export function t(clr: color | null | undefined): float {
202
+ if (clr === null || clr === undefined) return 100;
197
203
  return Math.round((1 - alphaByte(parseColor(clr).a) / 255) * 100);
198
204
  }
199
205
 
@@ -362,8 +368,12 @@ export function from_gradient(
362
368
  const c2 = rgba(top_color);
363
369
  const a = c1.a * (1 - k) + c2.a * k;
364
370
  if (a === 0) return transparent;
365
- // operation order with the fewest differences to PineScript (channels as 0-1, alpha as a byte)
366
- const mix = (x1: number, x2: number) => Math.floor((((x1 / 255) * c1.a) * (1 - k) + ((x2 / 255) * c2.a) * k) / (a / 255));
371
+ // PineScript order (bit for bit, #146): premultiplied channels ((alpha / 255) * channel) * weight, divided by the
372
+ // byte-alpha mix / 255, truncated. At an end (k = 0 / 1) this is floor(x * a / a): the end colour or one unit less.
373
+ const scale = a / 255;
374
+ const w1 = c1.a / 255;
375
+ const w2 = c2.a / 255;
376
+ const mix = (x1: number, x2: number) => Math.floor(((w1 * x1) * (1 - k) + (w2 * x2) * k) / scale);
367
377
  const [r, g, b] = [mix(c1.r, c2.r), mix(c1.g, c2.g), mix(c1.b, c2.b)];
368
378
  const alpha = Math.floor(a);
369
379
  return alpha === 255 ? `rgb(${r}, ${g}, ${b})` : `rgba(${r}, ${g}, ${b}, ${alpha / 255})`;
package/src/index.ts CHANGED
@@ -164,7 +164,7 @@ export type { LightweightSeriesDefinitions } from './runtime/adapters/Lightweigh
164
164
  export { SimpleInputAdapter } from './runtime/adapters/SimpleInputAdapter.js';
165
165
 
166
166
  // Version
167
- export const VERSION = '0.9.5';
167
+ export const VERSION = '0.9.6';
168
168
 
169
169
  /**
170
170
  * Library information
@@ -85,7 +85,8 @@ export function new_label(...args: unknown[]): Label {
85
85
  y,
86
86
  xloc: xloc ?? 'bar_index',
87
87
  yloc: yloc ?? 'price',
88
- text,
88
+ // PineScript: a label without text has the text "" (label.get_text gives "")
89
+ text: text ?? '',
89
90
  tooltip,
90
91
  color: labelColor,
91
92
  style,
@@ -40,6 +40,8 @@ import type { Linefill, Line, color } from '../types/index.js';
40
40
  * ```
41
41
  */
42
42
  export function new_linefill(line1: Line, line2: Line, fillColor?: color): Linefill {
43
+ // PineScript: an na line gives an na linefill
44
+ if (line1 === null || line1 === undefined || line2 === null || line2 === undefined) return null as unknown as Linefill;
43
45
  return register('linefill', {
44
46
  line1,
45
47
  line2,