initial commit + basic sequences
This commit is contained in:
parent
322c5bdbc9
commit
14cbda2ffb
BIN
gallery/example1.pdf
Normal file
BIN
gallery/example1.pdf
Normal file
Binary file not shown.
19
gallery/example1.typ
Normal file
19
gallery/example1.typ
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#import "/src/lib.typ" as chronos
|
||||||
|
|
||||||
|
#chronos.from-plantuml(```plantuml
|
||||||
|
Alice -> Bob: Authentication Request
|
||||||
|
Bob --> Alice: Authentication Response
|
||||||
|
|
||||||
|
Alice -> Bob: Another authentication Request
|
||||||
|
Alice <-- Bob: Another authentication Response
|
||||||
|
```)
|
||||||
|
|
||||||
|
|
||||||
|
#chronos.diagram({
|
||||||
|
import "/src/diagram.typ": *
|
||||||
|
_seq("Alice", "Bob", comment: "Authentication Request")
|
||||||
|
_seq("Bob", "Alice", comment: "Authentication Response", style: "dashed")
|
||||||
|
|
||||||
|
_seq("Alice", "Bob", comment: "Another authentication Request")
|
||||||
|
_seq("Bob", "Alice", comment: "Another authentication Response", style: "dashed")
|
||||||
|
})
|
51
src/diagram.typ
Normal file
51
src/diagram.typ
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#import "renderer.typ": render
|
||||||
|
|
||||||
|
#let _seq(p1, p2, comment: none, style: auto) = {
|
||||||
|
return ((
|
||||||
|
type: "seq",
|
||||||
|
p1: p1,
|
||||||
|
p2: p2,
|
||||||
|
comment: comment,
|
||||||
|
style: style
|
||||||
|
),)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let _par(name, display-name: auto, start-at: 0) = {
|
||||||
|
return ((
|
||||||
|
type: "par",
|
||||||
|
name: name,
|
||||||
|
display-name: if display-name == auto {name} else {display-name},
|
||||||
|
start-at: start-at
|
||||||
|
),)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let _par-exists(participants, name) = {
|
||||||
|
for p in participants {
|
||||||
|
if name == p.name {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
#let diagram(elements) = {
|
||||||
|
let participants = ()
|
||||||
|
for elmt in elements {
|
||||||
|
if elmt.type == "par" {
|
||||||
|
participants.push(elmt)
|
||||||
|
} else if elmt.type == "seq" {
|
||||||
|
if not _par-exists(participants, elmt.p1) {
|
||||||
|
participants.push(_par(elmt.p1).first())
|
||||||
|
}
|
||||||
|
if not _par-exists(participants, elmt.p2) {
|
||||||
|
participants.push(_par(elmt.p2).first())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(participants, elements)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let from-plantuml(code) = {
|
||||||
|
let code = code.text
|
||||||
|
}
|
1
src/lib.typ
Normal file
1
src/lib.typ
Normal file
@ -0,0 +1 @@
|
|||||||
|
#import "diagram.typ": diagram, from-plantuml
|
108
src/renderer.typ
Normal file
108
src/renderer.typ
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#import "@preview/cetz:0.2.2": canvas, draw
|
||||||
|
|
||||||
|
#let X-SPACE = 2
|
||||||
|
#let Y-SPACE = 30
|
||||||
|
|
||||||
|
#let get-participants-i(participants) = {
|
||||||
|
let pars-i = (:)
|
||||||
|
for (i, p) in participants.enumerate() {
|
||||||
|
pars-i.insert(p.name, i)
|
||||||
|
}
|
||||||
|
return pars-i
|
||||||
|
}
|
||||||
|
|
||||||
|
#let get-columns-width(participants, elements) = {
|
||||||
|
let pars-i = get-participants-i(participants)
|
||||||
|
let cells = ()
|
||||||
|
for elmt in elements {
|
||||||
|
if elmt.type == "seq" {
|
||||||
|
let com = if elmt.comment == none {""} else {elmt.comment}
|
||||||
|
let i1 = pars-i.at(elmt.p1)
|
||||||
|
let i2 = pars-i.at(elmt.p2)
|
||||||
|
cells.push(
|
||||||
|
(
|
||||||
|
elmt: elmt,
|
||||||
|
i1: calc.min(i1, i2),
|
||||||
|
i2: calc.max(i1, i2),
|
||||||
|
cell: box(com, inset: 3pt)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let widths = participants.slice(0, -1).map(_ => 0)
|
||||||
|
for cell in cells.filter(c => c.i2 - c.i1 == 1) {
|
||||||
|
let m = measure(cell.cell)
|
||||||
|
widths.at(cell.i1) = calc.max(
|
||||||
|
widths.at(cell.i1),
|
||||||
|
m.width / 1pt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return widths
|
||||||
|
}
|
||||||
|
|
||||||
|
#let render(participants, elements) = context canvas(length: 1pt, {
|
||||||
|
let pars-i = get-participants-i(participants)
|
||||||
|
|
||||||
|
let widths = get-columns-width(participants, elements)
|
||||||
|
|
||||||
|
let x-pos = (0,)
|
||||||
|
for width in widths {
|
||||||
|
x-pos.push(x-pos.last() + width)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw participants
|
||||||
|
for (i, p) in participants.enumerate() {
|
||||||
|
draw.content(
|
||||||
|
(x-pos.at(i), 0),
|
||||||
|
p.display-name,
|
||||||
|
name: p.name,
|
||||||
|
frame: "rect",
|
||||||
|
padding: (5pt, 3pt),
|
||||||
|
anchor: "south"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
let y = -Y-SPACE
|
||||||
|
// Draw sequences
|
||||||
|
for elmt in elements {
|
||||||
|
if elmt.type == "seq" {
|
||||||
|
let x1 = x-pos.at(pars-i.at(elmt.p1))
|
||||||
|
let x2 = x-pos.at(pars-i.at(elmt.p2))
|
||||||
|
draw.line(
|
||||||
|
(x1, y),
|
||||||
|
(x2, y),
|
||||||
|
mark: (end: "straight")
|
||||||
|
)
|
||||||
|
if elmt.comment != none {
|
||||||
|
draw.content(
|
||||||
|
(calc.min(x1, x2), y),
|
||||||
|
elmt.comment,
|
||||||
|
anchor: "south-west",
|
||||||
|
padding: 3pt
|
||||||
|
)
|
||||||
|
}
|
||||||
|
y -= Y-SPACE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw vertical lines + end participants
|
||||||
|
draw.on-layer(-1, {
|
||||||
|
for (i, p) in participants.enumerate() {
|
||||||
|
let x = x-pos.at(i)
|
||||||
|
draw.line(
|
||||||
|
(x, 0),
|
||||||
|
(x, y),
|
||||||
|
stroke: (dash: "dashed", paint: gray.darken(40%))
|
||||||
|
)
|
||||||
|
draw.content(
|
||||||
|
(x, y),
|
||||||
|
p.display-name,
|
||||||
|
name: p.name,
|
||||||
|
frame: "rect",
|
||||||
|
padding: (5pt, 3pt),
|
||||||
|
anchor: "north"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
14
typst.toml
Normal file
14
typst.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "chronos"
|
||||||
|
version = "0.0.1"
|
||||||
|
compiler = "0.11.0"
|
||||||
|
repository = "https://git.kb28.ch/HEL/chronos"
|
||||||
|
entrypoint = "src/lib.typ"
|
||||||
|
authors = [
|
||||||
|
"Louis Heredero <https://git.kb28.ch/HEL>"
|
||||||
|
]
|
||||||
|
categories = ["visualization"]
|
||||||
|
license = "Apache-2.0"
|
||||||
|
description = "A package to draw sequence diagrams with CeTZ"
|
||||||
|
keywords = ["sequence", "diagram", "plantuml"]
|
||||||
|
exclude = [ "/gallery/*" ]
|
Loading…
Reference in New Issue
Block a user