gum-jsx 1.6.2 → 1.6.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.
- package/README.md +2 -3
- package/docs/code/Arc.jsx +2 -2
- package/docs/code/Ellipse.jsx +2 -2
- package/docs/code/Images.jsx +1 -1
- package/docs/code/Line.jsx +1 -1
- package/docs/code/Math.jsx +12 -10
- package/docs/code/Network.jsx +1 -1
- package/docs/code/Points.jsx +4 -1
- package/docs/code/Shape.jsx +1 -1
- package/docs/code/SymFill.jsx +1 -1
- package/docs/code/SymShape.jsx +3 -4
- package/docs/code/Tables.jsx +3 -2
- package/docs/text/Box.md +1 -1
- package/docs/text/Element.md +11 -14
- package/docs/text/Gum.md +5 -5
- package/docs/text/Math.md +2 -1
- package/docs/text/SymFill.md +2 -1
- package/docs/text/SymLine.md +2 -1
- package/docs/text/SymPoints.md +2 -1
- package/docs/text/SymShape.md +2 -1
- package/docs/text/SymSpline.md +1 -0
- package/gala/code/atomic_orbitals.jsx +1 -2
- package/gala/code/complex_plot.jsx +1 -1
- package/gala/code/pendulum_physics.jsx +3 -3
- package/gala/code/plot_manual.jsx +2 -2
- package/gala/code/polygon_slide.jsx +3 -4
- package/gala/code/spline_star.jsx +2 -2
- package/gala/code/unit_distance.jsx +96 -0
- package/gala/text/unit_distance.md +7 -0
- package/package.json +1 -1
- package/scripts/gum.ts +14 -11
- package/scripts/test.ts +0 -69
- package/skills/gum-jsx/SKILL.md +12 -15
- package/skills/gum-jsx/references/gala/atomic_orbitals.md +1 -2
- package/skills/gum-jsx/references/gala/complex_plot.md +1 -1
- package/skills/gum-jsx/references/gala/pendulum_physics.md +3 -3
- package/skills/gum-jsx/references/gala/plot_manual.md +2 -2
- package/skills/gum-jsx/references/gala/polygon_slide.md +3 -4
- package/skills/gum-jsx/references/gala/spline_star.md +2 -2
- package/skills/gum-jsx/references/geometry.md +6 -6
- package/skills/gum-jsx/references/layout.md +5 -2
- package/skills/gum-jsx/references/networks.md +1 -1
- package/skills/gum-jsx/references/symbolic.md +12 -8
- package/skills/gum-jsx/references/utilities.md +18 -14
- package/src/elems/core.ts +33 -13
- package/src/elems/geometry.ts +37 -14
- package/src/elems/layout.ts +5 -7
- package/src/elems/math.ts +9 -0
- package/src/elems/network.ts +4 -3
- package/src/elems/plot.ts +19 -35
- package/src/elems/symbolic.ts +30 -24
- package/src/eval.ts +13 -3
- package/src/gum.ts +9 -9
- package/src/lib/const.ts +2 -1
- package/src/lib/interp.ts +10 -4
- package/src/lib/parse.ts +8 -2
- package/src/lib/types.ts +5 -4
- package/src/lib/utils.ts +105 -25
- package/src/render.ts +7 -27
- package/src/types/katex.d.ts +8 -0
package/src/lib/utils.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { DEFAULTS as D, d2r, r2d } from './const'
|
|
4
4
|
import { setSeed, random, uniform, normal, integer } from './rng'
|
|
5
|
-
import type { Point, Rect, Limit, RGBA, MNumber, MPoint, Orient, Side, Side0,
|
|
5
|
+
import type { Point, Rect, Limit, RGBA, MNumber, MPoint, Orient, Side, Side0, Direc, Size, Pair, Grad, Complex, Vector, Attrs } from './types'
|
|
6
6
|
|
|
7
7
|
//
|
|
8
8
|
// environment tests
|
|
@@ -72,6 +72,10 @@ function ensure_vector<T>(x: T | T[], n: number): T[] {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function ensure_pair<T>(x: T | [T, T]): [T, T] {
|
|
76
|
+
return is_array(x) ? x : [ x, x ]
|
|
77
|
+
}
|
|
78
|
+
|
|
75
79
|
function ensure_singleton<T>(x: T[] | undefined): T | undefined {
|
|
76
80
|
if (x == null) return undefined
|
|
77
81
|
return is_array(x) ? x[0] : x
|
|
@@ -433,34 +437,102 @@ function invert(x: number | undefined): number | undefined {
|
|
|
433
437
|
// pair arithmetic
|
|
434
438
|
//
|
|
435
439
|
|
|
436
|
-
function broadcast_point(p: number | Point): Point {
|
|
437
|
-
return is_scalar(p) ? [ p, p ] as Point : p
|
|
438
|
-
}
|
|
439
|
-
|
|
440
440
|
function add2(p0: number | Pair, p1: number | Pair): Pair {
|
|
441
|
-
const [ x0, y0 ] =
|
|
442
|
-
const [ x1, y1 ] =
|
|
441
|
+
const [ x0, y0 ] = ensure_pair(p0)
|
|
442
|
+
const [ x1, y1 ] = ensure_pair(p1)
|
|
443
443
|
return [ x0 + x1, y0 + y1 ]
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
function sub2(p0: number | Pair, p1: number | Pair): Pair {
|
|
447
|
-
const [ x0, y0 ] =
|
|
448
|
-
const [ x1, y1 ] =
|
|
447
|
+
const [ x0, y0 ] = ensure_pair(p0)
|
|
448
|
+
const [ x1, y1 ] = ensure_pair(p1)
|
|
449
449
|
return [ x0 - x1, y0 - y1 ]
|
|
450
450
|
}
|
|
451
451
|
|
|
452
452
|
function mul2(p0: number | Pair, p1: number | Pair): Pair {
|
|
453
|
-
const [ x0, y0 ] =
|
|
454
|
-
const [ x1, y1 ] =
|
|
453
|
+
const [ x0, y0 ] = ensure_pair(p0)
|
|
454
|
+
const [ x1, y1 ] = ensure_pair(p1)
|
|
455
455
|
return [ x0 * x1, y0 * y1 ]
|
|
456
456
|
}
|
|
457
457
|
|
|
458
458
|
function div2(p0: number | Pair, p1: number | Pair): Pair {
|
|
459
|
-
const [ x0, y0 ] =
|
|
460
|
-
const [ x1, y1 ] =
|
|
459
|
+
const [ x0, y0 ] = ensure_pair(p0)
|
|
460
|
+
const [ x1, y1 ] = ensure_pair(p1)
|
|
461
461
|
return [ x0 / x1, y0 / y1 ]
|
|
462
462
|
}
|
|
463
463
|
|
|
464
|
+
//
|
|
465
|
+
// vector arithmetic
|
|
466
|
+
//
|
|
467
|
+
|
|
468
|
+
function broadcast_op(op: (x: number, y: number) => number, v0: Vector, v1: Vector): Vector {
|
|
469
|
+
return zip(v0, v1).map(([ x0, x1 ]) => op(x0, x1))
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
function addn(v0: Vector, v1: Vector): Vector {
|
|
473
|
+
return broadcast_op((x, y) => x + y, v0, v1)
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
function subn(v0: Vector, v1: Vector): Vector {
|
|
477
|
+
return broadcast_op((x, y) => x - y, v0, v1)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function muln(v0: Vector, v1: Vector): Vector {
|
|
481
|
+
return broadcast_op((x, y) => x * y, v0, v1)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function divn(v0: Vector, v1: Vector): Vector {
|
|
485
|
+
return broadcast_op((x, y) => x / y, v0, v1)
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
//
|
|
489
|
+
// complex arithmetic
|
|
490
|
+
//
|
|
491
|
+
|
|
492
|
+
function ensure_complex(z: number | Complex): Complex {
|
|
493
|
+
return is_scalar(z) ? [ z, 0 ] as Complex : z
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function addc(z: number | Complex, w: number | Complex): Complex {
|
|
497
|
+
const [ x, y ] = ensure_complex(z)
|
|
498
|
+
const [ u, v ] = ensure_complex(w)
|
|
499
|
+
return [ x + u, y + v ]
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function subc(z: number | Complex, w: number | Complex): Complex {
|
|
503
|
+
const [ x, y ] = ensure_complex(z)
|
|
504
|
+
const [ u, v ] = ensure_complex(w)
|
|
505
|
+
return [ x - u, y - v ]
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function mulc(z: number | Complex, w: number | Complex): Complex {
|
|
509
|
+
const [ x, y ] = ensure_complex(z)
|
|
510
|
+
const [ u, v ] = ensure_complex(w)
|
|
511
|
+
return [ x * u - y * v, x * v + y * u ]
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
function divc(z: number | Complex, w: number | Complex): Complex {
|
|
515
|
+
const [ x, y ] = ensure_complex(z)
|
|
516
|
+
const [ u, v ] = ensure_complex(w)
|
|
517
|
+
const denom = norm([ u, v ], 2)
|
|
518
|
+
return [ (x * u + y * v) / denom, (y * u - x * v) / denom ]
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
function conjc(z: number | Complex): Complex {
|
|
522
|
+
const [ x, y ] = ensure_complex(z)
|
|
523
|
+
return [ x, -y ]
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
function normc(z: number | Complex): number {
|
|
527
|
+
const [ x, y ] = ensure_complex(z)
|
|
528
|
+
return norm([ x, y ], 2)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function argc(z: number | Complex): number {
|
|
532
|
+
const [ x, y ] = ensure_complex(z)
|
|
533
|
+
return atan2(y, x)
|
|
534
|
+
}
|
|
535
|
+
|
|
464
536
|
//
|
|
465
537
|
// metaposition arithmetic
|
|
466
538
|
//
|
|
@@ -567,7 +639,7 @@ function rect_radial(rect: Rect, absolute: boolean = false): Rect {
|
|
|
567
639
|
// TODO: add optimized path for Point/number case
|
|
568
640
|
function radial_rect(p0: Point | MPoint, r0: number | Size): Rect {
|
|
569
641
|
const p = ensure_mpoint(p0)
|
|
570
|
-
const r =
|
|
642
|
+
const r = ensure_pair(r0)
|
|
571
643
|
const pa = sub2m(p, r)
|
|
572
644
|
const pb = add2m(p, r)
|
|
573
645
|
return [ ...squeeze_mpoint(pa), ...squeeze_mpoint(pb) ]
|
|
@@ -675,21 +747,21 @@ type LimitArgs = {
|
|
|
675
747
|
[key in Orient]?: Limit
|
|
676
748
|
}
|
|
677
749
|
|
|
678
|
-
function join_limits({
|
|
750
|
+
function join_limits({ h, v }: LimitArgs = {}): Rect {
|
|
679
751
|
const [ vlo, vhi ] = v ?? D.lim
|
|
680
752
|
const [ hlo, hhi ] = h ?? D.lim
|
|
681
753
|
return [ hlo, vlo, hhi, vhi ]
|
|
682
754
|
}
|
|
683
755
|
|
|
684
|
-
function split_limits(coord: Rect | undefined): {
|
|
756
|
+
function split_limits(coord: Rect | undefined): { h?: Limit, v?: Limit } {
|
|
685
757
|
if (coord == null) return {}
|
|
686
758
|
const [ xlo, ylo, xhi, yhi ] = coord
|
|
687
|
-
return {
|
|
759
|
+
return { h: [ xlo, xhi ], v: [ ylo, yhi ] }
|
|
688
760
|
}
|
|
689
761
|
|
|
690
|
-
function resolve_limits(xlim: Limit | undefined, ylim: Limit | undefined, coord: Rect | undefined): {
|
|
691
|
-
const {
|
|
692
|
-
return {
|
|
762
|
+
function resolve_limits(xlim: Limit | undefined, ylim: Limit | undefined, coord: Rect | undefined): { h: Limit | undefined, v: Limit | undefined } {
|
|
763
|
+
const { h: xlim0, v: ylim0 } = split_limits(coord)
|
|
764
|
+
return { h: xlim ?? xlim0, v: ylim ?? ylim0 }
|
|
693
765
|
}
|
|
694
766
|
|
|
695
767
|
function detect_coords(xvals: number[], yvals: number[], xlim: Limit | undefined, ylim: Limit | undefined): Rect {
|
|
@@ -795,15 +867,23 @@ function vector_angle(vector: Point): number {
|
|
|
795
867
|
return r2d * Math.atan2(y, x)
|
|
796
868
|
}
|
|
797
869
|
|
|
798
|
-
function
|
|
799
|
-
return [ cos(
|
|
870
|
+
function radian_direc(angle: number): Point {
|
|
871
|
+
return [ cos(angle), sin(angle) ]
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
function angle_direc(angle: number): Point {
|
|
875
|
+
return radian_direc(d2r * angle)
|
|
800
876
|
}
|
|
801
877
|
|
|
802
|
-
function polar(
|
|
803
|
-
const offset = mul2(radius,
|
|
878
|
+
function polar(theta: number, radius: number | Size = 1, center?: Point): Point {
|
|
879
|
+
const offset = mul2(radius, radian_direc(theta))
|
|
804
880
|
return center ? add2(center, offset) : offset
|
|
805
881
|
}
|
|
806
882
|
|
|
883
|
+
function polard(angle: number, radius: number | Size = 1, center?: Point): Point {
|
|
884
|
+
return polar(d2r * angle, radius, center)
|
|
885
|
+
}
|
|
886
|
+
|
|
807
887
|
function norm_side(side: Side): Side0 {
|
|
808
888
|
if (side == 'top' || side == 't' || side == 'north' || side == 'n') return 't'
|
|
809
889
|
if (side == 'bottom' || side == 'b' || side == 'south' || side == 's') return 'b'
|
|
@@ -905,4 +985,4 @@ function binary_search(arr: number[], t: number): number {
|
|
|
905
985
|
// export
|
|
906
986
|
//
|
|
907
987
|
|
|
908
|
-
export { is_browser, is_boolean, is_scalar, is_string, is_number, is_object, is_function, is_array, is_singleton, is_point, ensure_vector, ensure_singleton, ensure_function, check_singleton, check_array, check_string, gzip, zip, reshape, split, concat, squeeze, slice, intersperse, sum, prod, mean, all, any, cumsum, norm, normalize, range, linspace, enumerate, repeat, padvec, meshgrid, lingrid, map_object, filter_object, compress_whitespace, exp, log, log10, sin, cos, tan, cot, abs, pow, sqrt, sign, floor, ceil, round, atan, atan2, isNan, isInf, minimum, maximum, heaviside, heavisign, abs_min, abs_max, min, max, clamp, rescale, sigmoid, logit, smoothstep, identity, invert, setSeed, random, uniform, normal, integer,
|
|
988
|
+
export { is_browser, is_boolean, is_scalar, is_string, is_number, is_object, is_function, is_array, is_singleton, is_point, ensure_vector, ensure_pair, ensure_singleton, ensure_function, check_singleton, check_array, check_string, gzip, zip, reshape, split, concat, squeeze, slice, intersperse, sum, prod, mean, all, any, cumsum, norm, normalize, range, linspace, enumerate, repeat, padvec, meshgrid, lingrid, map_object, filter_object, compress_whitespace, exp, log, log10, sin, cos, tan, cot, abs, pow, sqrt, sign, floor, ceil, round, atan, atan2, isNan, isInf, minimum, maximum, heaviside, heavisign, abs_min, abs_max, min, max, clamp, rescale, sigmoid, logit, smoothstep, identity, invert, setSeed, random, uniform, normal, integer, add2, sub2, mul2, div2, addn, subn, muln, divn, addc, subc, mulc, divc, conjc, normc, argc, ensure_number, ensure_point, ensure_mnumber, ensure_mpoint, addm, subm, add2m, sub2m, make_mpoint, squeeze_mnumber, squeeze_mpoint, rect_size, rect_dims, rect_center, rect_radius, rect_aspect, rect_radial, norm_angle, split_limits, vector_angle, angle_direc, polar, polard, side_direc, unit_direc, norm_side, rgba_repr, interp, palette, detect_coords, resolve_limits, join_limits, invert_orient, aspect_invariant, flip_rect, radial_rect, box_rect, rect_box, cbox_rect, rect_cbox, merge_rects, merge_points, merge_limits, merge_values, expand_limits, expand_rect, upright_rect, upright_limits, rounder, remap_rect, resizer, rescaler, rotate_aspect, prefix_split, prefix_join, binary_search }
|
package/src/render.ts
CHANGED
|
@@ -5,6 +5,8 @@ import { createCanvas, loadImage, registerFont, type ImageData as CanvasImageDat
|
|
|
5
5
|
import type { Size } from './lib/types'
|
|
6
6
|
import { FONT_PATHS } from './fonts/fonts'
|
|
7
7
|
import { light, regular, bold } from './lib/const'
|
|
8
|
+
import { is_string } from './lib/utils'
|
|
9
|
+
import { fitSize } from './eval'
|
|
8
10
|
|
|
9
11
|
// register bundled fonts so SVG <text> resolves consistently
|
|
10
12
|
for (const [ family, path ] of Object.entries(FONT_PATHS)) {
|
|
@@ -19,8 +21,7 @@ for (const [ family, path ] of Object.entries(FONT_PATHS)) {
|
|
|
19
21
|
|
|
20
22
|
interface RasterizeBaseArgs {
|
|
21
23
|
size?: Size
|
|
22
|
-
|
|
23
|
-
height?: number
|
|
24
|
+
rasterSize?: Size
|
|
24
25
|
background?: string
|
|
25
26
|
}
|
|
26
27
|
|
|
@@ -45,32 +46,11 @@ interface FormatImageArgs {
|
|
|
45
46
|
|
|
46
47
|
async function rasterizeSvg(svg: string | Buffer, args: RasterizePixelArgs): Promise<CanvasImageData>
|
|
47
48
|
async function rasterizeSvg(svg: string | Buffer, args?: RasterizePngArgs): Promise<Buffer>
|
|
48
|
-
async function rasterizeSvg(svg: string | Buffer, { size,
|
|
49
|
-
const buf =
|
|
49
|
+
async function rasterizeSvg(svg: string | Buffer, { size, rasterSize, background, pixelData }: RasterizeArgs = {}): Promise<Buffer | CanvasImageData> {
|
|
50
|
+
const buf = is_string(svg) ? Buffer.from(svg) : svg
|
|
50
51
|
const img = await loadImage(buf)
|
|
51
|
-
const
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
// if both width and height given, scale to fit within (prefer smaller scale)
|
|
55
|
-
if (width != null && height != null) {
|
|
56
|
-
const scaleW = width / w0
|
|
57
|
-
const scaleH = height / h0
|
|
58
|
-
if (scaleW < scaleH) height = undefined
|
|
59
|
-
else width = undefined
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// pick output dimensions; preserve aspect when only one of width/height given
|
|
63
|
-
let outW: number, outH: number
|
|
64
|
-
if (width != null) {
|
|
65
|
-
outW = width
|
|
66
|
-
outH = Math.round(width * h0 / w0)
|
|
67
|
-
} else if (height != null) {
|
|
68
|
-
outH = height
|
|
69
|
-
outW = Math.round(height * w0 / h0)
|
|
70
|
-
} else {
|
|
71
|
-
outW = w0
|
|
72
|
-
outH = h0
|
|
73
|
-
}
|
|
52
|
+
const imgSize = size ?? [ img.width, img.height ]
|
|
53
|
+
const [ outW, outH ] = fitSize(imgSize, rasterSize)
|
|
74
54
|
|
|
75
55
|
// create canvas
|
|
76
56
|
const canvas = createCanvas(outW, outH)
|
package/src/types/katex.d.ts
CHANGED
|
@@ -53,6 +53,13 @@ declare module 'katex' {
|
|
|
53
53
|
body: TreeNode[]
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
export type TreeFont = {
|
|
57
|
+
type: 'font'
|
|
58
|
+
mode: SymbolMode
|
|
59
|
+
font: string
|
|
60
|
+
body: TreeNode
|
|
61
|
+
}
|
|
62
|
+
|
|
56
63
|
export type TreeSupSub = {
|
|
57
64
|
type: 'supsub'
|
|
58
65
|
base: TreeNode | null
|
|
@@ -115,6 +122,7 @@ declare module 'katex' {
|
|
|
115
122
|
| TreeOp
|
|
116
123
|
| TreeKern
|
|
117
124
|
| TreeText
|
|
125
|
+
| TreeFont
|
|
118
126
|
| TreeStyling
|
|
119
127
|
| TreeAccent
|
|
120
128
|
| TreeSupSub
|