gum-jsx 1.5.1 → 1.6.1
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 +33 -20
- package/docs/code/Arc.jsx +1 -1
- package/docs/code/Edge.jsx +5 -5
- package/docs/code/Node.jsx +22 -5
- package/docs/code/RoundedLine.jsx +15 -0
- package/docs/code/TitleFrame.jsx +2 -2
- package/docs/meta.json +2 -1
- package/docs/text/Arc.md +4 -4
- package/docs/text/Arrow.md +2 -1
- package/docs/text/Edge.md +2 -1
- package/docs/text/Graph.md +6 -5
- package/docs/text/Group.md +6 -1
- package/docs/text/Plot.md +12 -0
- package/docs/text/Rect.md +1 -1
- package/docs/text/RoundedLine.md +13 -0
- package/docs/text/Stack.md +5 -3
- package/docs/text/Text.md +3 -3
- package/gala/code/macro_economy.jsx +14 -14
- package/package.json +3 -3
- package/prompt/gen.md +15 -21
- package/scripts/dev.ts +276 -0
- package/scripts/gum.ts +33 -286
- package/scripts/skill.ts +7 -12
- package/scripts/test.ts +69 -0
- package/skills/gum-jsx/SKILL.md +21 -22
- package/skills/gum-jsx/references/gala/macro_economy.md +15 -15
- package/skills/gum-jsx/references/geometry.md +44 -7
- package/skills/gum-jsx/references/layout.md +5 -3
- package/skills/gum-jsx/references/networks.md +29 -11
- package/skills/gum-jsx/references/plotting.md +18 -5
- package/skills/gum-jsx/references/text.md +5 -5
- package/src/elems/core.ts +38 -22
- package/src/elems/geometry.ts +124 -8
- package/src/elems/layout.ts +1 -2
- package/src/elems/math.ts +1 -1
- package/src/elems/plot.ts +5 -4
- package/src/elems/text.ts +7 -11
- package/src/eval.ts +2 -3
- package/src/fonts/IBMPlexMono-Bold.ttf +0 -0
- package/src/fonts/IBMPlexMono-Light.ttf +0 -0
- package/src/fonts/IBMPlexMono-Regular.ttf +0 -0
- package/src/fonts/IBMPlexSans-Bold.ttf +0 -0
- package/src/fonts/IBMPlexSans-Light.ttf +0 -0
- package/src/fonts/IBMPlexSans-Regular.ttf +0 -0
- package/src/fonts/NotoEmoji-Variable.ttf +0 -0
- package/src/fonts/fonts.ts +76 -16
- package/src/gum.ts +7 -7
- package/src/lib/const.ts +8 -4
- package/src/lib/text.ts +75 -14
- package/src/lib/theme.ts +1 -1
- package/src/lib/types.ts +21 -1
- package/src/lib/utils.ts +1 -11
- package/src/meta.ts +5 -5
- package/src/render.ts +62 -59
- package/scripts/claude.ts +0 -25
- package/src/fonts/IBMPlexSans-Variable.ttf +0 -0
package/README.md
CHANGED
|
@@ -8,19 +8,31 @@
|
|
|
8
8
|
<br/><br/>
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
<p align="center">
|
|
12
|
+
Gum is a JSX vector graphics language that evaluates to SVG.
|
|
13
|
+
<br/>
|
|
14
|
+
It is designed for plots, diagrams, flow charts, and more.
|
|
15
|
+
</p>
|
|
16
|
+
|
|
17
|
+
<p align="center">
|
|
18
|
+
<a href="https://compendiumlabs.ai/gum/studio">Live Demo</a>
|
|
19
|
+
|
|
|
20
|
+
<a href="https://compendiumlabs.ai/gum/docs">Documentation</a>
|
|
21
|
+
|
|
|
22
|
+
<a href="https://compendiumlabs.ai/gum/docs/gala">Gallery</a>
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
16
26
|
|
|
17
27
|
```bash
|
|
18
|
-
bun i
|
|
28
|
+
bun i gum-jsx
|
|
19
29
|
```
|
|
20
30
|
|
|
21
|
-
To download the skill file (which is just a zip), click on the release on the right or use `skills/gum-jsx.skill`.
|
|
31
|
+
This will install the `gum` command and the `gum-jsx` package. Add a `-g` flag to install globally. To download the skill file (which is just a zip), click on the release on the right or use `skills/gum-jsx.skill`.
|
|
32
|
+
|
|
33
|
+
See [react-gum-jsx](https://github.com/CompendiumLabs/react-gum-jsx) for React bindings. See [gum.py](https://github.com/CompendiumLabs/gum.py) for a Python wrapper.
|
|
22
34
|
|
|
23
|
-
|
|
35
|
+
## Library Usage
|
|
24
36
|
|
|
25
37
|
Write some `gum.jsx` code:
|
|
26
38
|
|
|
@@ -47,42 +59,43 @@ You can also use JavaScript directly:
|
|
|
47
59
|
```javascript
|
|
48
60
|
import { Svg, Box, Text, Circle, Plot, SymLine, pi, sin } from 'gum'
|
|
49
61
|
const elem = new Plot({
|
|
50
|
-
children: new SymLine({ fy: sin, stroke: blue, stroke_width: 2 }),
|
|
62
|
+
children: [ new SymLine({ fy: sin, stroke: blue, stroke_width: 2 }) ],
|
|
51
63
|
xlim: [0, 2*pi], ylim: [-1.5, 1.5], grid: true, margin: [0.2, 0.1], aspect: 2,
|
|
52
64
|
})
|
|
53
65
|
const svg = elem.svg()
|
|
54
66
|
```
|
|
55
67
|
|
|
56
|
-
|
|
68
|
+
## Command Line
|
|
57
69
|
|
|
58
|
-
You can use the `gum` command to convert `gum.jsx` into SVG text or PNG data. You can even just display it directly in the terminal
|
|
70
|
+
You can use the `gum` command to convert `gum.jsx` into SVG text or PNG data. You can even just display it directly in the terminal. For the latter you need a terminal that supports images, such as `ghostty` or `kitty`. There are a bunch of code examples in `docs/code/` and `gala/code/` to try out.
|
|
59
71
|
|
|
60
72
|
Generate an SVG from a `gum.jsx` file:
|
|
61
73
|
|
|
62
74
|
```bash
|
|
63
|
-
|
|
75
|
+
gum input.jsx -o output.svg
|
|
64
76
|
```
|
|
65
77
|
|
|
66
78
|
Generate a PNG from a `gum.jsx` file:
|
|
67
79
|
|
|
68
80
|
```bash
|
|
69
|
-
|
|
81
|
+
gum input.jsx -o output.png
|
|
70
82
|
```
|
|
71
83
|
|
|
72
84
|
Display a `gum.jsx` file in the terminal:
|
|
73
85
|
```bash
|
|
74
|
-
|
|
86
|
+
gum input.jsx
|
|
75
87
|
```
|
|
76
88
|
|
|
77
89
|
CLI options:
|
|
78
90
|
|
|
79
91
|
| Option | Description | Default |
|
|
80
92
|
|--------|-------------|---------|
|
|
93
|
+
| `file` | Gum JSX file to render | stdin |
|
|
81
94
|
| `-s, --size <size>` | Image size in pixels | 1000 |
|
|
82
95
|
| `-t, --theme <theme>` | Theme: `light` or `dark` | light |
|
|
83
|
-
| `-
|
|
84
|
-
| `-
|
|
85
|
-
| `-
|
|
86
|
-
| `-
|
|
87
|
-
| `-
|
|
88
|
-
| `-
|
|
96
|
+
| `-b, --background <color>` | Background color | white |
|
|
97
|
+
| `-f, --format <format>` | Format: `json`, `svg`, `png`, `kitty` | auto |
|
|
98
|
+
| `-o, --output <output>` | Output file | stdout |
|
|
99
|
+
| `-w, --width <width>` | Max width of the PNG | auto |
|
|
100
|
+
| `-h, --height <height>` | Max height of the PNG | auto |
|
|
101
|
+
| `-d, --dev` | Live update display | off |
|
package/docs/code/Arc.jsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// elliptical and circular arcs using
|
|
1
|
+
// elliptical and circular arcs using start and end angles
|
|
2
2
|
<Group>
|
|
3
3
|
<Arc pos={[0.32, 0.5]} size={[0.44, 0.32]} start={-45} end={210} stroke={blue} stroke-width={2} />
|
|
4
4
|
<Arc pos={[0.72, 0.5]} size={0.32} start={90} end={-150} stroke={red} stroke-width={2} />
|
package/docs/code/Edge.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
// Two boxes with text in them that have black borders and gray interiors. The box in the upper left says "hello" and the box in the lower right says "world!". The arrowhead from "Hello" is filled in red and the arrowhead to "World!" is filled in blue.
|
|
2
|
-
<Network aspect node-fill={gray} edge-arrow>
|
|
3
|
-
<Node id="hello" pos={[0.
|
|
4
|
-
<Node id="world" pos={[0.
|
|
5
|
-
<Edge start="hello" end="world"
|
|
1
|
+
// Two boxes with text in them that have black borders and gray interiors. The box in the upper left says "hello" and the box in the lower right says "world!". There is a city-block path connecting the two boxes. The arrowhead from "Hello" is filled in red and the arrowhead to "World!" is filled in blue.
|
|
2
|
+
<Network aspect node-fill={gray} edge-arrow edge-rounded={0.025}>
|
|
3
|
+
<Node id="hello" pos={[0.3, 0.25]}>Hello</Node>
|
|
4
|
+
<Node id="world" pos={[0.7, 0.75]}>World!</Node>
|
|
5
|
+
<Edge start="hello" end="world" points={[[0.3, 0.5], [0.7, 0.5]]}/>
|
|
6
6
|
</Network>
|
package/docs/code/Node.jsx
CHANGED
|
@@ -1,6 +1,23 @@
|
|
|
1
|
-
//
|
|
2
|
-
<Network aspect node-fill={gray}>
|
|
3
|
-
<Node id="
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
// A simple connected network where each rounded node contains an emoji icon stacked above a text label. The example shows idea → design → launch.
|
|
2
|
+
<Network aspect={2} node-fill={gray} node-rounded node-padding node-ysize={0.35}>
|
|
3
|
+
<Node id="idea" pos={[0.2, 0.5]}>
|
|
4
|
+
<VStack spacing={0.15}>
|
|
5
|
+
<Text>💡</Text>
|
|
6
|
+
<Text stack-size={0.25}>Idea</Text>
|
|
7
|
+
</VStack>
|
|
8
|
+
</Node>
|
|
9
|
+
<Node id="design" pos={[0.5, 0.5]}>
|
|
10
|
+
<VStack spacing={0.15}>
|
|
11
|
+
<Text>🎨</Text>
|
|
12
|
+
<Text stack-size={0.25}>Design</Text>
|
|
13
|
+
</VStack>
|
|
14
|
+
</Node>
|
|
15
|
+
<Node id="launch" pos={[0.8, 0.5]}>
|
|
16
|
+
<VStack spacing={0.15}>
|
|
17
|
+
<Text>🚀</Text>
|
|
18
|
+
<Text stack-size={0.25}>Launch</Text>
|
|
19
|
+
</VStack>
|
|
20
|
+
</Node>
|
|
21
|
+
<Edge start="idea" end="design" />
|
|
22
|
+
<Edge start="design" end="launch" />
|
|
6
23
|
</Network>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// a city-block route in blue with rounded corners, with the underlying
|
|
2
|
+
// vertices marked as black dots to show how the corners are rounded
|
|
3
|
+
const points = [
|
|
4
|
+
[0.10, 0.20],
|
|
5
|
+
[0.40, 0.20],
|
|
6
|
+
[0.40, 0.80],
|
|
7
|
+
[0.70, 0.80],
|
|
8
|
+
[0.70, 0.50],
|
|
9
|
+
[0.90, 0.50],
|
|
10
|
+
]
|
|
11
|
+
return <Frame margin>
|
|
12
|
+
<Line opacity={0.3} points={points} />
|
|
13
|
+
<RoundedLine stroke={blue} stroke-width={2} radius={0.08} points={points} />
|
|
14
|
+
<Points point-size={0.015} points={points} />
|
|
15
|
+
</Frame>
|
package/docs/code/TitleFrame.jsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
// Various food emojis are arrnaged in a spaced out grid and framed with the title "Fruits & Veggies". Each emoji is framed by a rounded square
|
|
1
|
+
// Various food emojis are arrnaged in a spaced out grid and framed with the title "Fruits & Veggies". Each emoji is framed by a rounded square
|
|
2
2
|
const emoji = [ '🍇', '🥦', '🍔', '🍉', '🍍', '🌽', '🍩', '🥝', '🍟' ]
|
|
3
3
|
return <TitleFrame title="Fruits & Veggies" margin padding rounded>
|
|
4
4
|
<Grid rows={3} spacing={0.05}>
|
|
5
5
|
{emoji.map(e =>
|
|
6
|
-
<Frame aspect rounded
|
|
6
|
+
<Frame aspect rounded padding><Text>{e}</Text></Frame>
|
|
7
7
|
)}
|
|
8
8
|
</Grid>
|
|
9
9
|
</TitleFrame>
|
package/docs/meta.json
CHANGED
package/docs/text/Arc.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Arc
|
|
2
2
|
|
|
3
|
-
*Inherits*: [Element](/docs/Element)
|
|
3
|
+
*Inherits*: **Path** > [Element](/docs/Element)
|
|
4
4
|
|
|
5
5
|
This draws an elliptical arc that inscribes its allocated rectangle, like [Ellipse](/docs/Ellipse), but only over a selected angular interval.
|
|
6
6
|
|
|
7
7
|
Parameters:
|
|
8
|
-
- `
|
|
9
|
-
- `
|
|
8
|
+
- `start` — first angle in degrees
|
|
9
|
+
- `end` — second angle in degrees
|
|
10
10
|
|
|
11
|
-
Angles follow
|
|
11
|
+
Angles follow the current coordinate system: `0` points right and positive angles follow positive y. In the default screen coordinate system, `90` points down; inside a default [Graph](/docs/Graph), where y is flipped upward, `90` points up. The two angles are treated as an interval; their order does not change the drawn arc.
|
package/docs/text/Arrow.md
CHANGED
|
@@ -13,7 +13,8 @@ Parameters:
|
|
|
13
13
|
- `start-dir` / `end-dir` — the direction of the arrowheads at the start and end
|
|
14
14
|
- `arrow` / `arrow-start` / `arrow-end` — toggles whether the respective arrowheads are included. Defaults to `true` for `arrow-end` and `false` for `arrow-start`, meaning a directed graph edge
|
|
15
15
|
- `arrow-size` = `0.04` — size of the arrowhead
|
|
16
|
-
- `curve` = `null` — curvature factor forwarded to the
|
|
16
|
+
- `curve` = `null` — curvature factor forwarded to the [Spline](/docs/Spline) (`null` or zero means straight line)
|
|
17
|
+
- `rounded` = `null` — corner radius for a city-block path through `points`. When set, the shaft is a [RoundedLine](/docs/RoundedLine) (takes precedence over `curve`)
|
|
17
18
|
|
|
18
19
|
Subunit names:
|
|
19
20
|
- `line` — forwarded to the shaft line
|
package/docs/text/Edge.md
CHANGED
|
@@ -13,4 +13,5 @@ Parameters:
|
|
|
13
13
|
- `points` — the intermediate points to draw the spline between
|
|
14
14
|
- `arrow` / `arrow-start` / `arrow-end` — toggles whether the respective arrowheads are included. Defaults to `true` for `arrow-end` and `false` for `arrow-start`, meaning a directed graph edge
|
|
15
15
|
- `arrow-size` = `0.04` — the arrowhead size to use for both arrows
|
|
16
|
-
- `curve` = `2` — curvature factor forwarded to the
|
|
16
|
+
- `curve` = `2` — curvature factor forwarded to the [Spline](/docs/Spline)
|
|
17
|
+
- `rounded` = `null` — corner radius for a city-block path using [RoundedLine](/docs/RoundedLine)
|
package/docs/text/Graph.md
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
*Inherits*: [Group](/docs/Group) > [Element](/docs/Element)
|
|
4
4
|
|
|
5
|
-
This is the core graphing functionality used in [Plot](/docs/Plot) without the axes and labels. By default, the coordinate system is automatically inferred from the limits of child elements. This can be overridden with custom `xlim`/`ylim` specifications. The Elements that are passed to **Graph** can express their position and size information in this new coordinate system.
|
|
5
|
+
This is the core graphing functionality used in [Plot](/docs/Plot) without the axes and labels. By default, the coordinate system is automatically inferred from the limits of child elements. This can be overridden with custom `xlim`/`ylim`/`coord` specifications. The Elements that are passed to **Graph** can express their position and size information in this new coordinate system.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Unlike [Group](/docs/Group), **Graph** will automatically pass the given `coord` to all children, so they can express their position and size information in this new coordinate system. This is very useful for elements like [Line](/docs/Line) or [Points](/docs/Points), which evaluate their `points` values based on their own coordinate system, not that of the container.
|
|
8
|
+
|
|
9
|
+
You'll often want to use **Graph** (directly or indirectly) to display mathematical curves, as they might otherwise come out looking upside down relative to what you expect (as higher y-values mean "down" in raw SVG).
|
|
8
10
|
|
|
9
11
|
Parameters:
|
|
10
|
-
- `xlim`/`ylim` = `
|
|
11
|
-
- `padding` = `0` —
|
|
12
|
-
- `coord` = `'auto'` — the coordinate system to use for the graph (overrides `xlim`/`ylim`)
|
|
12
|
+
- `xlim`/`ylim`/`coord` = `'auto'` — the coordinate system to use for the graph
|
|
13
|
+
- `padding` = `0` — proportional padding to add when limits are auto-detected from children
|
package/docs/text/Group.md
CHANGED
|
@@ -4,10 +4,15 @@
|
|
|
4
4
|
|
|
5
5
|
This is the main container class that all compound elements are derived from. It accepts a list of child elements and attempts to place them according to their declared properties. Child placement positions are specified in the group's internal coordinates (`coord`), which defaults to the unit square. The coordinate space is specified in `[left, top, right, bottom]` format.
|
|
6
6
|
|
|
7
|
-
The child's `aspect` is an important determinant of its placement. When
|
|
7
|
+
The child's `aspect` is an important determinant of its placement. When the child does not have an aspect, it will fit exactly in the given `rect`. When it does have an aspect, it will be made as large as possible while still fitting in the given `rect`. The `align` argument governs the exact placement in this case, while the `expand` flag makes it as small as possible while still covering the given `rect`.
|
|
8
|
+
|
|
9
|
+
One common pitfall: using `coord` will affect that placement of child elements. But for graphing elements like [Line](/docs/Line) or [Points](/docs/Points), their `points` values are evaluate based on their own coordinate system, not the containing **Group**'s. You must either give them their own `coord` or use [Graph](/docs/Graph), which automatically propagates the coordinate system to all children.
|
|
10
|
+
|
|
11
|
+
To help with debugging, a `debug` flag can be passed to show stencil lines indicating the childrens' placement. The allocated space is shown in dashed blue, while the realized position (accounting for aspect and alignment) is shown in dashed red.
|
|
8
12
|
|
|
9
13
|
Parameters:
|
|
10
14
|
- `children` = `[]` — a list of child elements
|
|
11
15
|
- `aspect` = `null` — the aspect ratio of the group's rectangle (can pass `'auto'` to infer from the children)
|
|
12
16
|
- `coord` = `[0, 0, 1, 1]` — the internal coordinate space to use for child elements (can pass `'auto'` to contain children's rects)
|
|
13
17
|
- `clip` = `false` — clip children to the group's rectangle if `true` (or a custom shape if specified)
|
|
18
|
+
- `debug` = `false` — show debug boxes for the children
|
package/docs/text/Plot.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
Uses [Graph](/docs/Graph) to plot one or more elements over the desired limits and frame them with axes. If not specified by `xlim` and `ylim`, the limits of the plot will be computed from the bounding box of the constituent elements. By default, the `aspect` will be the ratio of the range of the `xlim` and `ylim`. See [Axis](/docs/Axis) for more details on how to customize the axes, ticks, and labels.
|
|
6
6
|
|
|
7
|
+
By default, the extent of **Plot** only includes the graphing area itself, not the axes, labels, or title. To include these, you can set the `margin` parameter to a non-zero value. However, it many cases it makes more sense to enclose **Plot** in a [Frame](/docs/Frame) or [Box](/docs/Box) element and set the `margin` parameter on that instead. This is useful if you want to add border that exactly encloses the graphing area.
|
|
8
|
+
|
|
7
9
|
Parameters:
|
|
8
10
|
- `xlim`/`ylim` = `[0, 1]` — the range over which to graph
|
|
9
11
|
- `xanchor`/`yanchor` — the value at which to place the respective axis. Note that the `xanchor` is a y-value and vice versa. Defaults to `xmin`/`ymin`
|
|
@@ -21,3 +23,13 @@ Subunits:
|
|
|
21
23
|
- `grid`/`xgrid`/`ygrid` — the grid lines arrayed under the graph
|
|
22
24
|
- `label`/`xlabel`/`ylabel` — the axis label elements
|
|
23
25
|
- `title` — the plot title element
|
|
26
|
+
|
|
27
|
+
Title:
|
|
28
|
+
- `title-size` = `0.075` — the size of the title element
|
|
29
|
+
- `title-offset` = `0.05` — the offset of the title element from the top of the plot
|
|
30
|
+
|
|
31
|
+
Labels:
|
|
32
|
+
- `label-size` = `0.05` — the size of the label elements
|
|
33
|
+
- `label-offset` = `0.125` — the offset of the label elements from the axis
|
|
34
|
+
- `xlabel-size`/`ylabel-size` — the size of the x/y label element (overrides `label-size`)
|
|
35
|
+
- `xlabel-offset`/`ylabel-offset` — the offset of the x/y label element from the axis (overrides `label-offset`)
|
package/docs/text/Rect.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
This makes a rectangle. Without any arguments it will fill its entire allocated space. Unless otherwise specified, it has a `null` aspect. Use **Square** for a square with a unit aspect.
|
|
6
6
|
|
|
7
|
-
Specifying a `rounded` argument will round the borders by the same amount for each corner. This can be either a scalar or a pair of scalars corresponding to the x and y radii of the corners. To specify different roundings for each corner, use the **RoundedRect** element.
|
|
7
|
+
Specifying a `rounded` argument will round the borders by the same amount for each corner. This can be either a scalar or a pair of scalars corresponding to the x and y radii of the corners. To specify different roundings for each corner, use the **RoundedRect** element. Rounding is expressed as a fractional value between 0 and 1, where 0 means no rounding and 1 will essentially render an ellipse. Values much greater than 0.1 will start to look a little goofy.
|
|
8
8
|
|
|
9
9
|
Parameters:
|
|
10
10
|
- `rounded` = `null` — proportional border rounding, accepts either scalar or pair of scalars
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# RoundedLine
|
|
2
|
+
|
|
3
|
+
*Inherits*: **Path** > [Element](/docs/Element)
|
|
4
|
+
|
|
5
|
+
The `RoundedLine` element draws a polyline through a series of points with rounded corners at each interior vertex. It is most useful for *city-block* (right-angle) routes — for instance, edges in a network diagram that you want to bend cleanly around obstacles rather than curving with [Spline](/docs/Spline). Spline curvature along an otherwise-straight `points` route produces undulating bumps; `RoundedLine` keeps the straight segments straight and only rounds the turns.
|
|
6
|
+
|
|
7
|
+
Each interior vertex is replaced by a circular arc whose radius is derived from `radius` in coord space. When the coordinate system is not square, `RoundedLine` uses the smaller mapped axis so corners stay circular in pixel space instead of stretching into ellipses. If a segment is too short for the requested radius, the corner is automatically clamped so adjacent corners can never overlap.
|
|
8
|
+
|
|
9
|
+
For straight-line polylines (no corner rounding) use [Line](/docs/Line). For smooth curves through points use [Spline](/docs/Spline).
|
|
10
|
+
|
|
11
|
+
Parameters:
|
|
12
|
+
- `points` — array of point coordinates (minimum of 2 required)
|
|
13
|
+
- `radius` = `0.05` — corner back-off distance in coord space, applied at each interior vertex
|
package/docs/text/Stack.md
CHANGED
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
*Inherits*: [Group](/docs/Group) > [Element](/docs/Element)
|
|
4
4
|
|
|
5
|
-
Stack one or more **Element** either vertically or horizontally. There are specialized components **VStack** and **HStack** that don't take the `direc` argument.
|
|
5
|
+
Stack one or more **Element** either vertically or horizontally. There are specialized components **VStack** and **HStack** that don't take the `direc` argument. This element handles child positioning and sizing, so any child `pos`/`size` arguments will be overridden. Proportional spacing between children can be specified with the `spacing` parameter.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The simplest case is when all children have aspect ratios. In the **HStack** case, the overall aspect ratio of the stack is the sum of the child aspect ratios. Children are allocated space in proportion to their aspect ratios. The **VStack** case is similar, but we need to deal in inverse aspect ratio terms.
|
|
8
|
+
|
|
9
|
+
When some children lack aspect ratios, they will be allocated any remaining space evenly. Regardless of whether a child has an aspect ratio or not, it can be given a fixed size with the `stack-size` parameter. This is specified as a fraction between 0 and 1, independent of spacing. Be warned though, if you specify `stack-size` for a child with an aspect ratio, it will be ignored. If you specify `stack-size` for every child, the resulting stack will have no aspect ratio.
|
|
8
10
|
|
|
9
11
|
Whenever possible, the aspect ratio of the overall stack is set so that all elements with defined aspect ratios will reach full width (in the **VStack** case) or full height (in the **HStack** case).
|
|
10
12
|
|
|
11
13
|
Child parameters:
|
|
12
14
|
- `stack-size` = `null` — the child's relative share of the available space along the stack axis
|
|
13
|
-
- `stack-expand` = `true` — whether to expand the child to fill the remaining space
|
|
14
15
|
|
|
15
16
|
Parameters:
|
|
16
17
|
- `direc` — the direction of stacking: `v` or `h`
|
|
17
18
|
- `spacing` = `0` — total amount of space to add between child elements
|
|
19
|
+
- `justify` = `center` — how to justify children along the stack axis
|
|
18
20
|
- `even` = `false` — whether to distribute sizes evenly (`stack-size = 1 / n`)
|
package/docs/text/Text.md
CHANGED
|
@@ -6,11 +6,11 @@ Displays text and other elements. Note that you will typically not set the font
|
|
|
6
6
|
|
|
7
7
|
If `wrap` is specified, the text will be wrapped to the specified width. In either case, single newlines will be respected, though whitespace will be compressed. There are two wrapper elements related to text:
|
|
8
8
|
|
|
9
|
-
There are two default fonts that are always provided: `sans = 'IBM Plex Sans'` and `mono ='IBM Plex Mono'`. You can use these global variables anywhere.
|
|
10
|
-
|
|
11
9
|
- [TextBox](/docs/TextBox) / **TextFrame** can handle text with a border and background
|
|
12
10
|
- **TextStack** can handle multiple lines of text that are passed in as an array
|
|
13
11
|
|
|
12
|
+
There are two default fonts that are always provided: `sans = 'IBM Plex Sans'` and `mono ='IBM Plex Mono'`. There are three availabe font weights: `light = 300`, `regular = 400`, and `bold = 700`. The default weight is `light`. You can use these global variables anywhere.
|
|
13
|
+
|
|
14
14
|
Parameters:
|
|
15
15
|
- `children` — the text to display
|
|
16
16
|
- `wrap` = `null` — the width (in ems) to wrap the text at (if `null`, the text will not be wrapped)
|
|
@@ -18,4 +18,4 @@ Parameters:
|
|
|
18
18
|
- `justify` = `'left'` — the horizontal justification of the text
|
|
19
19
|
- `color` = `black` — sets the text color using both stroke and fill (this is the usual way)
|
|
20
20
|
- `font-family` = `sans` — the font family (for display and size calculations)
|
|
21
|
-
- `font-weight` = `
|
|
21
|
+
- `font-weight` = `300` — the font weight (for display and size calculations)
|
|
@@ -6,23 +6,23 @@ const col = {
|
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
return <Slide title="Macroeconomic Flows">
|
|
9
|
-
<Network aspect={2} coord={[0, 0, 1.6, 0.8]} node-ysize={0.16} node-rounded={0.06} node-fill={gray} node-
|
|
10
|
-
<Node id="trade" pos={[0.8, 0.15]} fill={col.trade}
|
|
11
|
-
<Node id="prod" pos={[0.3, 0.4]} fill={col.prod}
|
|
12
|
-
<Node id="cons" pos={[1.3, 0.4]} fill={col.cons}
|
|
13
|
-
<Node id="govt" pos={[0.8, 0.65]} ysize={0.12} fill={col.govt}
|
|
9
|
+
<Network aspect={2} coord={[0, 0, 1.6, 0.8]} node-ysize={0.16} node-rounded={0.06} node-fill={gray} node-fill-opacity={0.15} edge-stroke-width={1} edge-arrow-size={0.04} edge-stroke="#444" edge-arrow edge-arrow-curve={2.5} node-text-wrap={6}>
|
|
10
|
+
<Node id="trade" pos={[0.8, 0.15]} fill={col.trade} border-stroke={col.trade} text-color={col.trade}>Foreign Trade</Node>
|
|
11
|
+
<Node id="prod" pos={[0.3, 0.4]} fill={col.prod} border-stroke={col.prod} text-color={col.prod}>Producers (Firms)</Node>
|
|
12
|
+
<Node id="cons" pos={[1.3, 0.4]} fill={col.cons} border-stroke={col.cons} text-color={col.cons}>Consumers (Households)</Node>
|
|
13
|
+
<Node id="govt" pos={[0.8, 0.65]} ysize={0.12} fill={col.govt} border-stroke={col.govt} text-color={col.govt}>Government</Node>
|
|
14
14
|
|
|
15
|
-
<Edge start="prod" end="cons"
|
|
16
|
-
<Edge start="govt" end="prod" end-side="s"
|
|
17
|
-
<Edge start="govt" end="cons" end-side="s"
|
|
18
|
-
<Edge start="trade" end="prod" end-side="n"
|
|
19
|
-
<Edge start="trade" end="cons" end-side="n"
|
|
15
|
+
<Edge start="prod" end="cons" />
|
|
16
|
+
<Edge start="govt" end="prod" end-side="s" />
|
|
17
|
+
<Edge start="govt" end="cons" end-side="s" />
|
|
18
|
+
<Edge start="trade" end="prod" end-side="n" />
|
|
19
|
+
<Edge start="trade" end="cons" end-side="n" />
|
|
20
20
|
|
|
21
21
|
<Text pos={[0.8, 0.35]} ysize={0.05} color={col.prod}>Goods + Services →</Text>
|
|
22
22
|
<Text pos={[0.8, 0.45]} ysize={0.05} color={col.cons}>← Wages, Rent, Profit</Text>
|
|
23
|
-
<Text pos={[0.3, 0.65]} ysize={0.
|
|
24
|
-
<Text pos={[1.3, 0.65]} ysize={0.
|
|
25
|
-
<Text pos={[0.3, 0.13]} ysize={0.
|
|
26
|
-
<Text pos={[1.3, 0.13]} ysize={0.
|
|
23
|
+
<Text pos={[0.3, 0.65]} ysize={0.045} spin={30}>Subsidies / Taxes</Text>
|
|
24
|
+
<Text pos={[1.3, 0.65]} ysize={0.045} spin={-30}>Transfers / Taxes</Text>
|
|
25
|
+
<Text pos={[0.3, 0.13]} ysize={0.045} spin={-30}>Imports / Exports</Text>
|
|
26
|
+
<Text pos={[1.3, 0.13]} ysize={0.045} spin={30}>Transfers</Text>
|
|
27
27
|
</Network>
|
|
28
28
|
</Slide>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gum-jsx",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "Language for vector graphics generation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Douglas Hanley",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"scripts": {
|
|
42
42
|
"cli": "bun ./scripts/gum.ts",
|
|
43
43
|
"test": "bun ./scripts/test.ts",
|
|
44
|
-
"skill": "bun ./scripts/skill.ts && zip -r
|
|
44
|
+
"skill": "bun ./scripts/skill.ts && cd skills && rm -f gum-jsx.skill && zip -r gum-jsx.skill gum-jsx",
|
|
45
45
|
"claude": "bun run skill && bun ./scripts/claude.ts"
|
|
46
46
|
},
|
|
47
47
|
"bin": {
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"@types/node": "^25.2.3",
|
|
52
52
|
"@types/papaparse": "^5.5.2",
|
|
53
53
|
"acorn-jsx": "^5.3.2",
|
|
54
|
+
"canvas": "^3.2.3",
|
|
54
55
|
"emojibase-regex": "^17.0.0",
|
|
55
56
|
"katex": "^0.16.33",
|
|
56
57
|
"linebreak": "^1.1.0",
|
|
@@ -60,7 +61,6 @@
|
|
|
60
61
|
},
|
|
61
62
|
"optionalDependencies": {
|
|
62
63
|
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
63
|
-
"@resvg/resvg-js": "^2.6.2",
|
|
64
64
|
"commander": "^14.0.3",
|
|
65
65
|
"express": "^5.2.1",
|
|
66
66
|
"zod": "^4.3.6"
|
package/prompt/gen.md
CHANGED
|
@@ -1,45 +1,39 @@
|
|
|
1
1
|
# Using CLI commands
|
|
2
2
|
|
|
3
|
-
To test the output of a particular Gum JSX snippet or file, you can pipe it to the `gum` command
|
|
3
|
+
To test the output of a particular Gum JSX snippet or file, you can pipe it to the `gum` command. If this command is not available globally, try to install the `gum-jsx` package with Bun (preferred) or NPM.
|
|
4
|
+
|
|
5
|
+
If you have vision capabilities, seeing an actual image can be useful for see the actual output of the code, either in SVG or PNG format. Even without vision, one can infer properties of the output by reading the SVG output directly.
|
|
4
6
|
|
|
5
7
|
For one off tests, pipe the code using `echo`. It is recommended that you use single quotes as the outer delimiter, to accommodate code that includes double quotes for component properties (e.g. `justify="left"`).
|
|
6
8
|
|
|
7
9
|
For more difficult tasks, use a file provide the filename as an argument or `cat` it in. Using a file allows you to view and refine your code repeatedly. If you wish to avoid output redirection to a file, use the `-o` option to write to a file.
|
|
8
10
|
|
|
9
|
-
In general, it makes a lot of sense to write a draft to a file, view its output, then refine the code until you're satisfied. This way you can start simple and add complexity as needed.
|
|
11
|
+
In general, it makes a lot of sense to write a draft to a file, view its output, then refine the code until you're satisfied. This way you can start simple and add complexity as needed. When in doubt, write the output file to the same directory as the input file with the same base name but with the appropriate extension.
|
|
10
12
|
|
|
11
13
|
**Examples:**
|
|
12
14
|
```bash
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
# Generate PNG from a Gum JSX snippet
|
|
17
|
-
echo '<Rectangle rounded fill={blue} />' | gum -f png > output.png
|
|
18
|
-
|
|
19
|
-
# Generate SVG from a .jsx file
|
|
20
|
-
cat test.jsx | gum -f svg > output.svg
|
|
15
|
+
# generate an .svg file from a .jsx file
|
|
16
|
+
gum test.jsx -o test.svg
|
|
21
17
|
|
|
22
|
-
#
|
|
23
|
-
|
|
18
|
+
# generate a .png file from a .jsx file
|
|
19
|
+
gum test.jsx -o test.png
|
|
24
20
|
|
|
25
|
-
#
|
|
26
|
-
|
|
21
|
+
# generate SVG from a Gum JSX snippet and print to stdout
|
|
22
|
+
echo '<Rectangle rounded fill={blue} />' | gum
|
|
27
23
|
|
|
28
|
-
#
|
|
29
|
-
gum
|
|
24
|
+
# generate PNG from a Gum JSX snippet and save to file
|
|
25
|
+
echo '<Rectangle rounded fill={blue} />' | gum -o test.png
|
|
30
26
|
```
|
|
31
27
|
|
|
32
28
|
**CLI options:**
|
|
33
29
|
- `file`: Gum JSX file to render (reads from stdin if not provided)
|
|
34
30
|
- `-t, --theme <theme>`: theme to use (default: light)
|
|
35
31
|
- `-b, --background <color>`: background color (default: white)
|
|
36
|
-
- `-
|
|
37
|
-
- `-f, --format <format>`: output format: svg or png (default: kitty or auto-detected)
|
|
32
|
+
- `-f, --format <format>`: output format: json, svg, png, kitty (default: auto)
|
|
38
33
|
- `-o, --output <output>`: output file (default: stdout)
|
|
39
34
|
- `-s, --size <size>`: size of the SVG (default: 1000)
|
|
40
|
-
- `-w, --width <width>`: width of the PNG (default:
|
|
41
|
-
- `-h, --height <height>`: height of the PNG (default:
|
|
42
|
-
- `-u, --update`: enable live update display
|
|
35
|
+
- `-w, --width <width>`: max width of the PNG (default: null)
|
|
36
|
+
- `-h, --height <height>`: max height of the PNG (default: null)
|
|
43
37
|
|
|
44
38
|
# Using Gum in TypeScript
|
|
45
39
|
|