Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3076e44207 | ||
|
|
473dca962f | ||
|
|
9edc60516e |
No files matched your search
@@ -3,7 +3,7 @@
|
|||||||
Circuiteria is a [Typst](https://typst.app) package for drawing block circuit diagrams using the [CeTZ](https://typst.app/universe/package/cetz) package.
|
Circuiteria is a [Typst](https://typst.app) package for drawing block circuit diagrams using the [CeTZ](https://typst.app/universe/package/cetz) package.
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="./gallery/platypus.png" alt="A platypus / Perry the Platypus meme made with colored rounded rectangles">
|
<img src="./gallery/platypus.png" alt="Perry the platypus">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
@@ -11,17 +11,17 @@ Circuiteria is a [Typst](https://typst.app) package for drawing block circuit di
|
|||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<a href="./gallery/test.typ">
|
<a href="./gallery/test.typ">
|
||||||
<img src="./gallery/test.png" width="500px" alt="Block diagram of a multi-cycle RISC-V FPGA processor">
|
<img src="./gallery/test.png" width="500px">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">A bit of everything</td>
|
<td colspan="2">A bit of eveything</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<a href="./gallery/test5.typ">
|
<a href="./gallery/test5.typ">
|
||||||
<img src="./gallery/test5.png" width="500px" alt="Block diagram of a single-cycle RISC-V processor">
|
<img src="./gallery/test5.png" width="500px">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -31,12 +31,12 @@ Circuiteria is a [Typst](https://typst.app) package for drawing block circuit di
|
|||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="./gallery/test4.typ">
|
<a href="./gallery/test4.typ">
|
||||||
<img src="./gallery/test4.png" width="250px" alt="Top-level block diagram of a single-cycle RISC-V processor">
|
<img src="./gallery/test4.png" width="250px">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="./gallery/test6.typ">
|
<a href="./gallery/test6.typ">
|
||||||
<img src="./gallery/test6.png" width="250px" alt="Block diagram of a simple single-cycle RISC-V ALU">
|
<img src="./gallery/test6.png" width="250px">
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -56,7 +56,7 @@ For more information, see the [manual](manual.pdf)
|
|||||||
|
|
||||||
To use this package, simply import [circuiteria](https://typst.app/universe/package/circuiteria) and call the `circuit` function:
|
To use this package, simply import [circuiteria](https://typst.app/universe/package/circuiteria) and call the `circuit` function:
|
||||||
```typ
|
```typ
|
||||||
#import "@preview/circuiteria:0.2.1"
|
#import "@preview/circuiteria:0.2.0"
|
||||||
#circuiteria.circuit({
|
#circuiteria.circuit({
|
||||||
import circuiteria: *
|
import circuiteria: *
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -79,81 +79,6 @@ wire.stub("p", "south", name: "south", length: 15pt)
|
|||||||
wire.stub("p", "west", name: "west", length: 3em)
|
wire.stub("p", "west", name: "west", length: 3em)
|
||||||
```)
|
```)
|
||||||
|
|
||||||
#let breakout = example(```
|
|
||||||
// 16 breakouts: 4 directions × 4 label positions, laid out
|
|
||||||
// two per row so the labels have room to breathe.
|
|
||||||
let dirs = ("north-east", "north-west", "south-east", "south-west")
|
|
||||||
let poss = ("north-east", "north-west", "south-east", "south-west")
|
|
||||||
let short = (
|
|
||||||
"north-east": "NE", "north-west": "NW",
|
|
||||||
"south-east": "SE", "south-west": "SW",
|
|
||||||
)
|
|
||||||
let cols = 2
|
|
||||||
let dx = 5
|
|
||||||
let dy = 2
|
|
||||||
for (i, dir) in dirs.enumerate() {
|
|
||||||
for (j, pos) in poss.enumerate() {
|
|
||||||
let n = i * poss.len() + j
|
|
||||||
let r = calc.floor(n / cols)
|
|
||||||
let c = calc.rem(n, cols)
|
|
||||||
draw.circle((c * dx, -r * dy), radius: .05)
|
|
||||||
wire.breakout("b" + str(n),
|
|
||||||
x: c * dx, y: -r * dy,
|
|
||||||
direction: dir,
|
|
||||||
port-side: if dir.ends-with("east") { "west" } else { "east" },
|
|
||||||
name: short.at(dir) + "/" + short.at(pos),
|
|
||||||
name-pos: pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```)
|
|
||||||
|
|
||||||
#let breakout-label = example(```
|
|
||||||
// name-pos matches direction → label sits at the end point.
|
|
||||||
wire.breakout("b1", x: 0, y: 0, direction: "north-east",
|
|
||||||
port-side: "east",
|
|
||||||
name: "at end", name-pos: "north-east")
|
|
||||||
|
|
||||||
// name-pos opposite to direction → label would cover the line, so
|
|
||||||
// it falls back to the start point.
|
|
||||||
wire.breakout("b2", x: 4, y: 0, direction: "north-east",
|
|
||||||
port-side: "east",
|
|
||||||
name: "at start", name-pos: "south-west")
|
|
||||||
```, vertical: true)
|
|
||||||
|
|
||||||
#let breakout-wire = example(```
|
|
||||||
// Bus fan-out: a horizontal wire from the left block to the lower
|
|
||||||
// right block carries the full 10-bit bus. A breakout in the middle
|
|
||||||
// of that wire taps bits [9:5] and routes them to the upper right
|
|
||||||
// block via an L-shaped zigzag (up, then right).
|
|
||||||
element.block(x: 0, y: 0, w: 2, h: 2, id: "src",
|
|
||||||
fill: util.colors.blue,
|
|
||||||
ports: (east: ((id: "out"),)))
|
|
||||||
element.block(x: 6, y: 0, w: 2, h: 2, id: "dstL",
|
|
||||||
fill: util.colors.green,
|
|
||||||
ports: (west: ((id: "in"),)))
|
|
||||||
element.block(x: 6, y: 4, w: 2, h: 2, id: "dstU",
|
|
||||||
fill: util.colors.orange,
|
|
||||||
ports: (west: ((id: "in"),)))
|
|
||||||
|
|
||||||
// Full bus wire, labelled "[9:0]" on the left.
|
|
||||||
wire.wire("wbus", ("src-port-out", "dstL-port-in"),
|
|
||||||
name: "[9:0]", name-pos: "start")
|
|
||||||
|
|
||||||
// Breakout tapped from the midpoint of the bus.
|
|
||||||
wire.breakout("tap",
|
|
||||||
x: (rel: 2, to: "src-port-out"),
|
|
||||||
y: (from: "src-port-out"),
|
|
||||||
direction: "north-east",
|
|
||||||
port-side: "west",
|
|
||||||
name: "[9:5]", name-pos: "north-east")
|
|
||||||
|
|
||||||
// L-shaped wire from the breakout up and then right to the upper
|
|
||||||
// block's input.
|
|
||||||
wire.wire("wtap", ("tap-port-tap", "dstU-port-in"),
|
|
||||||
style: "zigzag", zigzag-dir: "horizontal",
|
|
||||||
zigzag-ratio: 100%)
|
|
||||||
```)
|
|
||||||
|
|
||||||
#let gate-and = example(```
|
#let gate-and = example(```
|
||||||
gates.gate-and(x: 0, y: 0, w: 1.5, h: 1.5)
|
gates.gate-and(x: 0, y: 0, w: 1.5, h: 1.5)
|
||||||
gates.gate-and(x: 3, y: 0, w: 1.5, h: 1.5, inverted: "all")
|
gates.gate-and(x: 3, y: 0, w: 1.5, h: 1.5, inverted: "all")
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 45 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "@preview/circuiteria:0.2.1": *
|
#import "../src/lib.typ": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 160 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
#import "../src/lib.typ": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
wire.wire(
|
wire.wire(
|
||||||
"wExtender-ImmSrc", (
|
"wExtender-ImmSrc", (
|
||||||
"Extender.north",
|
"Extender.north",
|
||||||
(18, -2)
|
(18, -2, 0)
|
||||||
),
|
),
|
||||||
style: "zigzag",
|
style: "zigzag",
|
||||||
zigzag-ratio: 0%,
|
zigzag-ratio: 0%,
|
||||||
@@ -138,8 +138,8 @@
|
|||||||
)
|
)
|
||||||
wire.wire(
|
wire.wire(
|
||||||
"wBus", (
|
"wBus", (
|
||||||
(v => (v.at(0), -3.5), mid),
|
(v => (v.at(0), -3.5, 0), mid),
|
||||||
(horizontal: (), vertical: (0, 3.5)),
|
(horizontal: (), vertical: (0, 3.5, 0)),
|
||||||
),
|
),
|
||||||
bus: true
|
bus: true
|
||||||
)
|
)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 160 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
#import "../src/lib.typ": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
wire.wire(
|
wire.wire(
|
||||||
"wExtender-ImmSrc", (
|
"wExtender-ImmSrc", (
|
||||||
"Extender.north",
|
"Extender.north",
|
||||||
(18, -2)
|
(18, -2, 0)
|
||||||
),
|
),
|
||||||
style: "zigzag",
|
style: "zigzag",
|
||||||
zigzag-ratio: 0%,
|
zigzag-ratio: 0%,
|
||||||
@@ -145,8 +145,8 @@
|
|||||||
)
|
)
|
||||||
wire.wire(
|
wire.wire(
|
||||||
"wBus", (
|
"wBus", (
|
||||||
(v => (v.at(0), -3.5), mid),
|
(v => (v.at(0), -3.5, 0), mid),
|
||||||
(horizontal: (), vertical: (0, 3.5)),
|
(horizontal: (), vertical: (0, 3.5, 0)),
|
||||||
),
|
),
|
||||||
bus: true
|
bus: true
|
||||||
)
|
)
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 66 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
#import "../src/lib.typ": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 195 KiB |
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "@preview/circuiteria:0.2.1": *
|
#import "../src/lib.typ": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 274 KiB |
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "@preview/circuiteria:0.2.1": *
|
#import "../src/lib.typ": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 76 KiB |
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw
|
#import "/src/cetz.typ": draw
|
||||||
#import "@preview/circuiteria:0.2.1": *
|
#import "../src/lib.typ": *
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 40 KiB |
@@ -1,4 +1,4 @@
|
|||||||
#import "@preview/circuiteria:0.2.1": circuit, element, util, wire
|
#import "../src/lib.typ": circuit, element, util, wire
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
#set page(width: auto, height: auto, margin: .5cm)
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB |
@@ -1,117 +0,0 @@
|
|||||||
// Demonstrates the wire.breakout element used to split off slices of a
|
|
||||||
// bus that connects blocks. The main bus wires are always laid out
|
|
||||||
// orthogonally; breakouts diagonally tap intermediate points on those
|
|
||||||
// wires and route the sub-bus to another block via an L-shaped zigzag.
|
|
||||||
#import "/src/lib.typ": circuit, element, util, wire
|
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
|
||||||
|
|
||||||
#circuit({
|
|
||||||
// ---- Source block on the left, main sink on the right ----
|
|
||||||
element.block(x: 0, y: 0, w: 2, h: 2, id: "src", fill: util.colors.blue, ports: (
|
|
||||||
east: ((id: "out"),),
|
|
||||||
))
|
|
||||||
|
|
||||||
element.block(x: 15, y: 0, w: 2, h: 2, id: "dstMain", fill: util.colors.green, ports: (
|
|
||||||
west: ((id: "in"),),
|
|
||||||
))
|
|
||||||
|
|
||||||
// Full bus from src to dstMain, labelled [15:0] at the start.
|
|
||||||
wire.wire("wbus", ("src-port-out", "dstMain-port-in"), name: "[15:0]", name-pos: "start")
|
|
||||||
|
|
||||||
// ---- Upper-left sink: taps bits [11:8] via NW breakout ----
|
|
||||||
element.block(x: 0, y: 4, w: 2, h: 2, id: "dstNW", fill: util.colors.yellow, ports: (
|
|
||||||
east: ((id: "in"),),
|
|
||||||
))
|
|
||||||
|
|
||||||
wire.breakout(
|
|
||||||
"tapNE",
|
|
||||||
x: (rel: 3, to: "src-port-out"),
|
|
||||||
y: (from: "src-port-out"),
|
|
||||||
direction: "north-east",
|
|
||||||
port-side: "west",
|
|
||||||
name: "[15:12]",
|
|
||||||
name-pos: "north-east",
|
|
||||||
)
|
|
||||||
|
|
||||||
// L-shape: up first, then left into dstNW.
|
|
||||||
wire.wire(
|
|
||||||
"wNW",
|
|
||||||
("tapNE-port-tapNE", "dstNW-port-in"),
|
|
||||||
style: "zigzag",
|
|
||||||
zigzag-dir: "horizontal",
|
|
||||||
zigzag-ratio: 100%,
|
|
||||||
)
|
|
||||||
|
|
||||||
// ---- Upper-right sink: taps bits [15:12] via NE breakout ----
|
|
||||||
element.block(x: 15, y: 4, w: 2, h: 2, id: "dstNE", fill: util.colors.orange, ports: (
|
|
||||||
west: ((id: "in"),),
|
|
||||||
))
|
|
||||||
|
|
||||||
wire.breakout(
|
|
||||||
"tapNW",
|
|
||||||
x: (rel: 7, to: "src-port-out"),
|
|
||||||
y: (from: "src-port-out"),
|
|
||||||
direction: "north-west",
|
|
||||||
port-side: "east",
|
|
||||||
name: "[11:8]",
|
|
||||||
name-pos: "north-east",
|
|
||||||
)
|
|
||||||
|
|
||||||
// L-shape: up first, then right into dstNE.
|
|
||||||
wire.wire(
|
|
||||||
"wNE",
|
|
||||||
("tapNW-port-tapNW", "dstNE-port-in"),
|
|
||||||
style: "zigzag",
|
|
||||||
zigzag-dir: "horizontal",
|
|
||||||
zigzag-ratio: 100%,
|
|
||||||
)
|
|
||||||
|
|
||||||
// ---- Lower-left sink: taps bits [3:0] via SW breakout ----
|
|
||||||
element.block(x: 0, y: -4, w: 2, h: 2, id: "dstSW", fill: util.colors.purple, ports: (
|
|
||||||
east: ((id: "in"),),
|
|
||||||
))
|
|
||||||
|
|
||||||
wire.breakout(
|
|
||||||
"tapSE",
|
|
||||||
x: (rel: 5, to: "src-port-out"),
|
|
||||||
y: (from: "src-port-out"),
|
|
||||||
direction: "south-east",
|
|
||||||
port-side: "west",
|
|
||||||
name: "[7:4]",
|
|
||||||
name-pos: "south-east",
|
|
||||||
)
|
|
||||||
|
|
||||||
// L-shape: down first, then left into dstSW.
|
|
||||||
wire.wire(
|
|
||||||
"wSW",
|
|
||||||
("tapSE-port-tapSE", "dstSW-port-in"),
|
|
||||||
style: "zigzag",
|
|
||||||
zigzag-dir: "horizontal",
|
|
||||||
zigzag-ratio: 100%,
|
|
||||||
)
|
|
||||||
|
|
||||||
// ---- Lower-right sink: taps bits [7:4] via SE breakout ----
|
|
||||||
element.block(x: 15, y: -4, w: 2, h: 2, id: "dstSE", fill: util.colors.pink, ports: (
|
|
||||||
west: ((id: "in"),),
|
|
||||||
))
|
|
||||||
|
|
||||||
wire.breakout(
|
|
||||||
"tapSW",
|
|
||||||
x: (rel: 11, to: "src-port-out"),
|
|
||||||
y: (from: "src-port-out"),
|
|
||||||
direction: "south-west",
|
|
||||||
port-side: "east",
|
|
||||||
name: "[3:0]",
|
|
||||||
name-pos: "south-west",
|
|
||||||
)
|
|
||||||
|
|
||||||
// L-shape: down first, then right into dstSE.
|
|
||||||
wire.wire(
|
|
||||||
"wSE",
|
|
||||||
("tapSW-port-tapSW", "dstSE-port-in"),
|
|
||||||
style: "zigzag",
|
|
||||||
zigzag-dir: "horizontal",
|
|
||||||
zigzag-ratio: 100%,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
Before Width: | Height: | Size: 4.1 KiB |
@@ -1,46 +0,0 @@
|
|||||||
// Demonstrates the `(rel: <number>, to: <anchor>)` shorthand for the `y`
|
|
||||||
// parameter (analogous to the existing shorthand for `x`).
|
|
||||||
#import "/src/lib.typ": circuit, element, util, wire
|
|
||||||
|
|
||||||
#set page(width: auto, height: auto, margin: .5cm)
|
|
||||||
|
|
||||||
#circuit({
|
|
||||||
// Anchor block: absolute placement.
|
|
||||||
element.block(
|
|
||||||
x: 0, y: 0, w: 2, h: 1.5,
|
|
||||||
id: "A",
|
|
||||||
fill: util.colors.orange,
|
|
||||||
ports: (east: ((id: "out"),))
|
|
||||||
)
|
|
||||||
|
|
||||||
// X relative, Y absolute (existing feature).
|
|
||||||
element.block(
|
|
||||||
x: (rel: 1, to: "A.east"), y: 0, w: 2, h: 1.5,
|
|
||||||
id: "B",
|
|
||||||
fill: util.colors.yellow,
|
|
||||||
ports: (west: ((id: "in"),), east: ((id: "out"),))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Both X and Y relative to another element's anchor (new feature).
|
|
||||||
element.block(
|
|
||||||
x: (rel: 1, to: "B.east"),
|
|
||||||
y: (rel: 2, to: "B.south-west"),
|
|
||||||
w: 2, h: 1.5,
|
|
||||||
id: "C",
|
|
||||||
fill: util.colors.green,
|
|
||||||
ports: (west: ((id: "in"),))
|
|
||||||
)
|
|
||||||
|
|
||||||
// Y relative only, X absolute.
|
|
||||||
element.block(
|
|
||||||
x: 0,
|
|
||||||
y: (rel: -2.5, to: "A.south-west"),
|
|
||||||
w: 2, h: 1.5,
|
|
||||||
id: "D",
|
|
||||||
fill: util.colors.blue,
|
|
||||||
ports: (east: ((id: "out"),))
|
|
||||||
)
|
|
||||||
|
|
||||||
wire.wire("wAB", ("A-port-out", "B-port-in"))
|
|
||||||
wire.wire("wBC", ("B-port-out", "C-port-in"), style: "zigzag")
|
|
||||||
})
|
|
||||||
@@ -105,7 +105,7 @@ This package provides a way to make beautiful block circuit diagrams using the C
|
|||||||
|
|
||||||
Simply import Circuiteria and call the `circuit` function:
|
Simply import Circuiteria and call the `circuit` function:
|
||||||
#pad(left: 1em)[```typ
|
#pad(left: 1em)[```typ
|
||||||
#import "@preview/circuiteria:0.2.1"
|
#import "@preview/circuiteria:0.2.0"
|
||||||
#circuiteria.circuit({
|
#circuiteria.circuit({
|
||||||
import circuiteria: *
|
import circuiteria: *
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -24,9 +24,7 @@
|
|||||||
/// If it is a dictionary, it should be in the format `(rel: number, to: str)`, where `rel` is the offset and `to` the base anchor
|
/// If it is a dictionary, it should be in the format `(rel: number, to: str)`, where `rel` is the offset and `to` the base anchor
|
||||||
/// - y (number, dictionary): The y position (bottom-left corner).
|
/// - y (number, dictionary): The y position (bottom-left corner).
|
||||||
///
|
///
|
||||||
/// If it is a dictionary, it can take one of two forms:
|
/// If it is a dictionary, it should be in the format `(from: str, to: str)`, where `from` is the base anchor and `to` is the id of the port to align with the anchor
|
||||||
/// - `(rel: number, to: str)`: `rel` is the y offset and `to` the base anchor (analogous to `x`)
|
|
||||||
/// - `(from: str, to: str)`: `from` is the base anchor and `to` is the id of the port to align with the anchor
|
|
||||||
/// - w (number): Width of the element
|
/// - w (number): Width of the element
|
||||||
/// - h (number): Height of the element
|
/// - h (number): Height of the element
|
||||||
/// - name (none, str): Optional name of the block
|
/// - name (none, str): Optional name of the block
|
||||||
@@ -76,12 +74,13 @@
|
|||||||
if h == none { panic("Parameter h must be set") }
|
if h == none { panic("Parameter h must be set") }
|
||||||
|
|
||||||
if (type(x) == dictionary) {
|
if (type(x) == dictionary) {
|
||||||
x = util.resolve-rel-coord(ctx, x, 0)
|
let offset = x.rel
|
||||||
|
let to = x.to
|
||||||
|
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0, 0), to: to))
|
||||||
|
x = to-pos.at(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type(y) == dictionary and "rel" in y) {
|
if (type(y) == dictionary) {
|
||||||
y = util.resolve-rel-coord(ctx, y, 1)
|
|
||||||
} else if (type(y) == dictionary) {
|
|
||||||
let from = y.from
|
let from = y.from
|
||||||
let to = y.to
|
let to = y.to
|
||||||
let (to-side, i) = find-port(ports, to)
|
let (to-side, i) = find-port(ports, to)
|
||||||
|
|||||||
@@ -91,7 +91,7 @@
|
|||||||
debug: debug
|
debug: debug
|
||||||
)
|
)
|
||||||
|
|
||||||
let in-pos = (rel: (0, h * (h-ratio / 200%)), to: id+".south-west")
|
let in-pos = (rel: (0, h * (h-ratio / 200%), 0), to: id+".south-west")
|
||||||
let out-pos = (id+".south-east", out-pct, id+".north-east")
|
let out-pos = (id+".south-east", out-pct, id+".north-east")
|
||||||
add-port(id, "west", ports.west.first(), in-pos)
|
add-port(id, "west", ports.west.first(), in-pos)
|
||||||
add-port(id, "east", ports.east.first(), out-pos)
|
add-port(id, "east", ports.east.first(), out-pos)
|
||||||
|
|||||||
@@ -61,8 +61,8 @@
|
|||||||
|
|
||||||
draw.hide(draw.group(name: id+"-inner", body))
|
draw.hide(draw.group(name: id+"-inner", body))
|
||||||
draw.rect(
|
draw.rect(
|
||||||
(rel: (-pad-left, -pad-bottom), to: id+"-inner.south-west"),
|
(rel: (-pad-left, -pad-bottom, 0), to: id+"-inner.south-west"),
|
||||||
(rel: (pad-right, pad-top), to: id+"-inner.north-east"),
|
(rel: (pad-right, pad-top, 0), to: id+"-inner.north-east"),
|
||||||
name: id,
|
name: id,
|
||||||
radius: radius,
|
radius: radius,
|
||||||
stroke: stroke,
|
stroke: stroke,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#import "/src/cetz.typ": draw, coordinate
|
#import "/src/cetz.typ": draw, coordinate
|
||||||
#import "/src/util.typ"
|
|
||||||
#import "../ports.typ": add-ports, add-port
|
#import "../ports.typ": add-ports, add-port
|
||||||
#import "../element.typ"
|
#import "../element.typ"
|
||||||
|
|
||||||
@@ -50,12 +49,13 @@
|
|||||||
if h == none { panic("Parameter h must be set") }
|
if h == none { panic("Parameter h must be set") }
|
||||||
|
|
||||||
if (type(x) == dictionary) {
|
if (type(x) == dictionary) {
|
||||||
x = util.resolve-rel-coord(ctx, x, 0)
|
let offset = x.rel
|
||||||
|
let to = x.to
|
||||||
|
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0, 0), to: to))
|
||||||
|
x = to-pos.at(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type(y) == dictionary and "rel" in y) {
|
if (type(y) == dictionary) {
|
||||||
y = util.resolve-rel-coord(ctx, y, 1)
|
|
||||||
} else if (type(y) == dictionary) {
|
|
||||||
let from = y.from
|
let from = y.from
|
||||||
let to = y.to
|
let to = y.to
|
||||||
|
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
let port-pos = int-name + ".0"
|
let port-pos = int-name + ".0"
|
||||||
if inverted == "all" or port-name in inverted {
|
if inverted == "all" or port-name in inverted {
|
||||||
draw.circle(port-pos, radius: inverted-radius, anchor: "east", stroke: stroke)
|
draw.circle(port-pos, radius: inverted-radius, anchor: "east", stroke: stroke)
|
||||||
port-pos = (rel: (-2 * inverted-radius, 0), to: port-pos)
|
port-pos = (rel: (-2 * inverted-radius, 0, 0), to: port-pos)
|
||||||
}
|
}
|
||||||
add-port(
|
add-port(
|
||||||
id, "west",
|
id, "west",
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
let out-pos = id + ".east"
|
let out-pos = id + ".east"
|
||||||
if inverted == "all" or "out" in inverted {
|
if inverted == "all" or "out" in inverted {
|
||||||
draw.circle(out-pos, radius: inverted-radius, anchor: "west", stroke: stroke)
|
draw.circle(out-pos, radius: inverted-radius, anchor: "west", stroke: stroke)
|
||||||
out-pos = (rel: (2 * inverted-radius, 0), to: out-pos)
|
out-pos = (rel: (2 * inverted-radius, 0, 0), to: out-pos)
|
||||||
}
|
}
|
||||||
add-port(
|
add-port(
|
||||||
id, "east",
|
id, "east",
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#import "/src/cetz.typ": draw, coordinate
|
#import "/src/cetz.typ": draw, coordinate
|
||||||
#import "/src/util.typ"
|
|
||||||
#import "../ports.typ": add-ports, add-port
|
#import "../ports.typ": add-ports, add-port
|
||||||
#import "../element.typ"
|
#import "../element.typ"
|
||||||
|
|
||||||
@@ -61,12 +60,13 @@
|
|||||||
if h == none { panic("Parameter h must be set") }
|
if h == none { panic("Parameter h must be set") }
|
||||||
|
|
||||||
if (type(x) == dictionary) {
|
if (type(x) == dictionary) {
|
||||||
x = util.resolve-rel-coord(ctx, x, 0)
|
let offset = x.rel
|
||||||
|
let to = x.to
|
||||||
|
let (ctx, to-pos) = coordinate.resolve(ctx, (rel: (offset, 0, 0), to: to))
|
||||||
|
x = to-pos.at(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type(y) == dictionary and "rel" in y) {
|
if (type(y) == dictionary) {
|
||||||
y = util.resolve-rel-coord(ctx, y, 1)
|
|
||||||
} else if (type(y) == dictionary) {
|
|
||||||
let from = y.from
|
let from = y.from
|
||||||
let to = y.to
|
let to = y.to
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
anchor: "east",
|
anchor: "east",
|
||||||
stroke: stroke
|
stroke: stroke
|
||||||
)
|
)
|
||||||
port-pos = (rel: (-2 * inverted-radius, 0), to: port-pos)
|
port-pos = (rel: (-2 * inverted-radius, 0, 0), to: port-pos)
|
||||||
}
|
}
|
||||||
add-port(
|
add-port(
|
||||||
id, "west",
|
id, "west",
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
let out-pos = id + ".east"
|
let out-pos = id + ".east"
|
||||||
if inverted == "all" or "out" in inverted {
|
if inverted == "all" or "out" in inverted {
|
||||||
draw.circle(out-pos, radius: inverted-radius, anchor: "west", stroke: stroke)
|
draw.circle(out-pos, radius: inverted-radius, anchor: "west", stroke: stroke)
|
||||||
out-pos = (rel: (2 * inverted-radius, 0), to: out-pos)
|
out-pos = (rel: (2 * inverted-radius, 0, 0), to: out-pos)
|
||||||
}
|
}
|
||||||
add-port(
|
add-port(
|
||||||
id, "east",
|
id, "east",
|
||||||
|
|||||||
@@ -17,10 +17,10 @@
|
|||||||
|
|
||||||
let size = if port.at("small", default: false) {8pt} else {1em}
|
let size = if port.at("small", default: false) {8pt} else {1em}
|
||||||
let offset
|
let offset
|
||||||
if (side == "north") { offset = ( 0, -size) }
|
if (side == "north") { offset = ( 0, -size, 0) }
|
||||||
else if (side == "east") { offset = (-size, 0) }
|
else if (side == "east") { offset = (-size, 0, 0) }
|
||||||
else if (side == "south") { offset = ( 0, size) }
|
else if (side == "south") { offset = ( 0, size, 0) }
|
||||||
else if (side == "west") { offset = ( size, 0) }
|
else if (side == "west") { offset = ( size, 0, 0) }
|
||||||
|
|
||||||
let pos1 = (rel: offset, to: pos)
|
let pos1 = (rel: offset, to: pos)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#let version = version(0, 2, 1)
|
#let version = version(0, 2, 0)
|
||||||
#let name = "circuiteria"
|
#let name = "circuiteria"
|
||||||
|
|
||||||
#import "circuit.typ": circuit
|
#import "circuit.typ": circuit
|
||||||
|
|||||||
@@ -1,23 +1,3 @@
|
|||||||
#import "cetz.typ": coordinate
|
|
||||||
|
|
||||||
/// Resolves a relative coordinate shorthand of the form `(rel: <number>, to: <anchor>)`
|
|
||||||
/// to a single scalar along the requested axis.
|
|
||||||
///
|
|
||||||
/// Used to implement the shared `(rel:, to:)` shorthand accepted by the `x` and
|
|
||||||
/// `y` parameters of `elmt`, `gate` and `iec-gate`.
|
|
||||||
///
|
|
||||||
/// - ctx (dictionary): The current CeTZ context
|
|
||||||
/// - val (dictionary): A dictionary with fields `rel` (number) and `to` (anchor)
|
|
||||||
/// - axis (int): `0` for x, `1` for y
|
|
||||||
/// -> number
|
|
||||||
#let resolve-rel-coord(ctx, val, axis) = {
|
|
||||||
let offset = val.rel
|
|
||||||
let to = val.to
|
|
||||||
let delta = if axis == 0 { (offset, 0) } else { (0, offset) }
|
|
||||||
let (_, to-pos) = coordinate.resolve(ctx, (rel: delta, to: to))
|
|
||||||
return to-pos.at(axis)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Predefined color palette
|
/// Predefined color palette
|
||||||
/// #let w = 4
|
/// #let w = 4
|
||||||
/// #box(width: 100%, align(center)[
|
/// #box(width: 100%, align(center)[
|
||||||
@@ -94,44 +74,3 @@
|
|||||||
"center", "north", "east", "west", "south",
|
"center", "north", "east", "west", "south",
|
||||||
"north-east", "north-west", "south-east", "south-west"
|
"north-east", "north-west", "south-east", "south-west"
|
||||||
)
|
)
|
||||||
|
|
||||||
/// Normalizes a coordinate so that 2D points (x, y) are padded
|
|
||||||
/// to (x, y, 0) as required by CeTZ's coordinate resolver.
|
|
||||||
/// Also handles function-based and dictionary-based coordinates
|
|
||||||
/// recursively.
|
|
||||||
///
|
|
||||||
/// - coord (any): A CeTZ-compatible coordinate
|
|
||||||
/// -> any
|
|
||||||
#let normalize-coord(coord) = {
|
|
||||||
if type(coord) == array {
|
|
||||||
if coord.len() == 2 {
|
|
||||||
let (a, b) = coord
|
|
||||||
// Raw 2D point: (x, y) -> (x, y, 0)
|
|
||||||
if type(a) in (int, float) and type(b) in (int, float) {
|
|
||||||
return (a, b, 0)
|
|
||||||
}
|
|
||||||
// Function-based coordinate: (fn, point)
|
|
||||||
if type(a) == function {
|
|
||||||
let orig = a
|
|
||||||
return (v => {
|
|
||||||
let result = orig(v)
|
|
||||||
if type(result) == array and result.len() == 2 {
|
|
||||||
let (rx, ry) = result
|
|
||||||
if type(rx) in (int, float) and type(ry) in (int, float) {
|
|
||||||
return (rx, ry, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if type(coord) == dictionary {
|
|
||||||
let result = (:)
|
|
||||||
for (key, value) in coord {
|
|
||||||
result.insert(key, normalize-coord(value))
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
return coord
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
#import "/src/cetz.typ": draw, coordinate
|
#import "/src/cetz.typ": draw, coordinate
|
||||||
#import "util.typ": opposite-anchor, normalize-coord, resolve-rel-coord
|
#import "util.typ": opposite-anchor
|
||||||
|
|
||||||
/// List of valid wire styles
|
/// List of valid wire styles
|
||||||
/// #examples.wires
|
/// #examples.wires
|
||||||
@@ -157,8 +157,8 @@
|
|||||||
let p3 = (center_x, center_y, 0)
|
let p3 = (center_x, center_y, 0)
|
||||||
|
|
||||||
// setting up the points for that touch the guides
|
// setting up the points for that touch the guides
|
||||||
let p2 = (0, 0, 0)
|
let p2 = (0,0,0)
|
||||||
let p4 = (0, 0, 0)
|
let p4 = (0,0,0)
|
||||||
if side-start in ("north", "south") {
|
if side-start in ("north", "south") {
|
||||||
p2 = (horizontal: p3, vertical: p1)
|
p2 = (horizontal: p3, vertical: p1)
|
||||||
} else {
|
} else {
|
||||||
@@ -241,9 +241,6 @@
|
|||||||
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
panic("Wrong number of points (got " + str(pts.len()) + " instead of 2)")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize user-provided coordinates: (x, y) -> (x, y, 0)
|
|
||||||
let pts = pts.map(normalize-coord)
|
|
||||||
|
|
||||||
let stroke = (
|
let stroke = (
|
||||||
paint: color,
|
paint: color,
|
||||||
thickness: if bus {bus-width} else {signal-width}
|
thickness: if bus {bus-width} else {signal-width}
|
||||||
@@ -368,17 +365,17 @@
|
|||||||
/// - name-offset (number): The name offset, perpendicular to the stub
|
/// - name-offset (number): The name offset, perpendicular to the stub
|
||||||
#let stub(port-id, side, name: none, vertical: false, length: 1em, name-offset: 0) = {
|
#let stub(port-id, side, name: none, vertical: false, length: 1em, name-offset: 0) = {
|
||||||
let end-offset = (
|
let end-offset = (
|
||||||
north: (0, length),
|
north: (0, length, 0),
|
||||||
east: (length, 0),
|
east: (length, 0, 0),
|
||||||
south: (0, -length),
|
south: (0, -length, 0),
|
||||||
west: (-length, 0)
|
west: (-length, 0, 0)
|
||||||
).at(side)
|
).at(side)
|
||||||
|
|
||||||
let name-offset = (
|
let name-offset = (
|
||||||
north: (name-offset, length),
|
north: (name-offset, length, 0),
|
||||||
east: (length, name-offset),
|
east: (length, name-offset, 0),
|
||||||
south: (name-offset, -length),
|
south: (name-offset, -length, 0),
|
||||||
west: (-length, name-offset)
|
west: (-length, name-offset, 0)
|
||||||
).at(side)
|
).at(side)
|
||||||
|
|
||||||
draw.line(
|
draw.line(
|
||||||
@@ -403,141 +400,3 @@
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Draws a wire breakout: a 45° diagonal line starting at (x, y) and
|
|
||||||
/// ending 1 unit away in one of the four diagonal directions. The end
|
|
||||||
/// point exposes a port anchor named `<id>-port-<id>` so wires can attach
|
|
||||||
/// to it as if it were a block port. A synthesized `<id>.center` anchor
|
|
||||||
/// is placed opposite `port-side`, so the cardinal side the port faces
|
|
||||||
/// can be deduced by comparing the port with the `.center` anchor.
|
|
||||||
///
|
|
||||||
/// #examples.breakout
|
|
||||||
///
|
|
||||||
/// Label positions are anchored so that the label sits neatly next to the
|
|
||||||
/// end point of the breakout. When the label direction matches the
|
|
||||||
/// breakout direction (which would overlap the line) the label is
|
|
||||||
/// automatically placed at the start point instead so the text does not
|
|
||||||
/// cover the line.
|
|
||||||
///
|
|
||||||
/// #examples.breakout-label
|
|
||||||
///
|
|
||||||
/// The port anchor makes it easy to fan out a bus:
|
|
||||||
///
|
|
||||||
/// #examples.breakout-wire
|
|
||||||
///
|
|
||||||
/// - id (str): The breakout id (also used as the port id)
|
|
||||||
/// - x (number, dictionary): The starting x position (same forms as `element.block`)
|
|
||||||
/// - y (number, dictionary): The starting y position (same forms as `element.block`)
|
|
||||||
/// - direction (str): One of `"north-east"`, `"north-west"`, `"south-east"`, `"south-west"`
|
|
||||||
/// - length (length, number): The diagonal length (default `1em`, matches port size)
|
|
||||||
/// - port-side (str): Cardinal side used for wire-attach behavior (`"north"`, `"east"`, `"south"`, `"west"`)
|
|
||||||
/// - stroke (stroke): Line stroke (paint + thickness)
|
|
||||||
/// - name (none, str): Optional label displayed near the breakout
|
|
||||||
/// - name-pos (none, str): Label position, one of `"north-west"`, `"north-east"`, `"south-west"`, `"south-east"`
|
|
||||||
/// - debug (bool): If true, shows a red dot at the port anchor
|
|
||||||
#let breakout(
|
|
||||||
id,
|
|
||||||
x: none, y: none,
|
|
||||||
direction: "north-east",
|
|
||||||
length: 1em,
|
|
||||||
port-side: "east",
|
|
||||||
stroke: black + 1pt,
|
|
||||||
name: none,
|
|
||||||
name-pos: none,
|
|
||||||
debug: false,
|
|
||||||
) = draw.get-ctx(ctx => {
|
|
||||||
if x == none { panic("breakout: parameter x must be set") }
|
|
||||||
if y == none { panic("breakout: parameter y must be set") }
|
|
||||||
|
|
||||||
let valid-directions = ("north-east", "north-west", "south-east", "south-west")
|
|
||||||
if not direction in valid-directions {
|
|
||||||
panic("breakout: invalid direction '" + repr(direction)
|
|
||||||
+ "'; must be one of " + repr(valid-directions))
|
|
||||||
}
|
|
||||||
let valid-sides = ("north", "east", "south", "west")
|
|
||||||
if not port-side in valid-sides {
|
|
||||||
panic("breakout: invalid port-side '" + repr(port-side)
|
|
||||||
+ "'; must be one of " + repr(valid-sides))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Diagonal component: length / sqrt(2). Resolve to a canvas-space
|
|
||||||
// number so we can do arithmetic with anchor coordinates.
|
|
||||||
let d-raw = length / calc.sqrt(2)
|
|
||||||
let (_, d-vec) = coordinate.resolve(ctx, (d-raw, 0, 0))
|
|
||||||
let d = d-vec.at(0)
|
|
||||||
|
|
||||||
// Direction sign vector for (dx, dy).
|
|
||||||
let sx = if direction.ends-with("east") { 1 } else { -1 }
|
|
||||||
let sy = if direction.starts-with("north") { 1 } else { -1 }
|
|
||||||
|
|
||||||
// Resolve x.
|
|
||||||
let sx0 = x
|
|
||||||
if type(x) == dictionary {
|
|
||||||
if "rel" in x {
|
|
||||||
sx0 = resolve-rel-coord(ctx, x, 0)
|
|
||||||
} else if "from" in x {
|
|
||||||
let (_, from-pos) = coordinate.resolve(ctx, x.from)
|
|
||||||
sx0 = from-pos.at(0)
|
|
||||||
} else {
|
|
||||||
panic("breakout: unsupported x dictionary: " + repr(x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Resolve y.
|
|
||||||
let sy0 = y
|
|
||||||
if type(y) == dictionary {
|
|
||||||
if "rel" in y {
|
|
||||||
sy0 = resolve-rel-coord(ctx, y, 1)
|
|
||||||
} else if "from" in y {
|
|
||||||
let (_, from-pos) = coordinate.resolve(ctx, y.from)
|
|
||||||
sy0 = from-pos.at(1)
|
|
||||||
} else {
|
|
||||||
panic("breakout: unsupported y dictionary: " + repr(y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let start = (sx0, sy0)
|
|
||||||
let end = (rel: (sx * d, sy * d), to: start)
|
|
||||||
|
|
||||||
// Offset used for the synthesized center anchor: opposite of port-side.
|
|
||||||
let center-offset = (
|
|
||||||
"north": (0, -1em),
|
|
||||||
"east": (-1em, 0),
|
|
||||||
"south": (0, 1em),
|
|
||||||
"west": (1em, 0),
|
|
||||||
).at(port-side)
|
|
||||||
|
|
||||||
let port-anchor-name = id + "-port-" + id
|
|
||||||
|
|
||||||
draw.group(name: id, {
|
|
||||||
draw.line(start, end, stroke: stroke)
|
|
||||||
draw.anchor("start", start)
|
|
||||||
draw.anchor("end", end)
|
|
||||||
draw.anchor("center", (rel: center-offset, to: end))
|
|
||||||
|
|
||||||
if name != none and name-pos != none {
|
|
||||||
let label-anchor = (
|
|
||||||
"north-west": "south-east",
|
|
||||||
"north-east": "south-west",
|
|
||||||
"south-west": "north-east",
|
|
||||||
"south-east": "north-west",
|
|
||||||
).at(name-pos)
|
|
||||||
|
|
||||||
// Overlap case: label direction is opposite to breakout direction,
|
|
||||||
// so the label at the end point would extend back over the line.
|
|
||||||
// Anchor it at the start point instead.
|
|
||||||
let label-pos = if name-pos == opposite-anchor(direction) { start } else { end }
|
|
||||||
|
|
||||||
draw.content(label-pos, anchor: label-anchor, padding: 3pt, name)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Port anchor emitted at top level so it can be referenced by its
|
|
||||||
// bare name (mirrors add-port's approach in ports.typ).
|
|
||||||
if debug {
|
|
||||||
draw.circle(end, name: port-anchor-name,
|
|
||||||
radius: .1, stroke: none, fill: red)
|
|
||||||
} else {
|
|
||||||
draw.hide(draw.circle(end, name: port-anchor-name,
|
|
||||||
radius: 0, stroke: none))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "circuiteria"
|
name = "circuiteria"
|
||||||
version = "0.2.1"
|
version = "0.2.0"
|
||||||
compiler = "0.15.0"
|
compiler = "0.15.0"
|
||||||
repository = "https://git.kb28.ch/HEL/circuiteria"
|
repository = "https://git.kb28.ch/HEL/circuiteria"
|
||||||
entrypoint = "src/lib.typ"
|
entrypoint = "src/lib.typ"
|
||||||
@@ -9,6 +9,6 @@ authors = [
|
|||||||
]
|
]
|
||||||
categories = [ "visualization" ]
|
categories = [ "visualization" ]
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
description = "Drawing block circuits made easy, using CeTZ"
|
description = "Drawing block circuits with Typst made easy, using CeTZ"
|
||||||
keywords = [ "circuit", "block", "draw" ]
|
keywords = [ "circuit", "block", "draw" ]
|
||||||
exclude = [ "gallery", "justfile", "doc" ]
|
exclude = [ "gallery", "justfile", "doc" ]
|
||||||