initial commit + basic sequences

This commit is contained in:
Louis Heredero 2024-06-18 13:39:38 +02:00
parent 322c5bdbc9
commit 14cbda2ffb
Signed by: HEL
GPG Key ID: 8D83DE470F8544E7
6 changed files with 193 additions and 0 deletions

BIN
gallery/example1.pdf Normal file

Binary file not shown.

19
gallery/example1.typ Normal file
View 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
View 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
View File

@ -0,0 +1 @@
#import "diagram.typ": diagram, from-plantuml

108
src/renderer.typ Normal file
View 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
View 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/*" ]