105 lines
3.2 KiB
Typst
105 lines
3.2 KiB
Typst
// Таблицы — как в «Пример работы с Typst.typ» и gost: figure + table + table.header.
|
||
// Разрыв длинных таблиц и подпись сверху задаёт шаблон modern-g7-32 (style.typ).
|
||
|
||
#show table: set text(hyphenate: true)
|
||
|
||
#let pz-appendix-title(body) = heading(level: 1)[#body]
|
||
|
||
#let pz-column-count(columns) = if type(columns) == int {
|
||
columns
|
||
} else if type(columns) == array {
|
||
columns.len()
|
||
} else {
|
||
1
|
||
}
|
||
|
||
// Строка из ..range().map(i => ([a], [b])) в body.pos() — один аргумент-массив.
|
||
#let pz-flatten-cells(cells) = cells.fold((), (acc, cell) => {
|
||
if type(cell) == array { acc + cell } else { acc + (cell,) }
|
||
})
|
||
|
||
#let pz-table-inner(columns, header-cells, tab-num, start-page, ..rows) = {
|
||
let col-n = pz-column-count(columns)
|
||
let cont-cell = table.cell(
|
||
colspan: col-n,
|
||
stroke: none,
|
||
inset: (x: 0pt, y: 2pt),
|
||
align: left,
|
||
)[
|
||
#context {
|
||
if start-page.get() == none {
|
||
start-page.update(here().page())
|
||
}
|
||
let first-page = start-page.get()
|
||
if first-page != none and here().page() > first-page {
|
||
[Продолжение таблицы #tab-num]
|
||
}
|
||
}
|
||
]
|
||
let header-row = if header-cells.len() > 0 {
|
||
(cont-cell, ..header-cells)
|
||
} else {
|
||
(cont-cell,)
|
||
}
|
||
table(
|
||
columns: columns,
|
||
table.header(..header-row),
|
||
..rows,
|
||
)
|
||
}
|
||
|
||
#let pz-table(caption, columns, ..body) = {
|
||
let pos = body.pos()
|
||
let has-header = pos.len() > 0 and pos.first().func() == table.header
|
||
let header-cells = if has-header { pos.first().children } else { () }
|
||
let tail = pz-flatten-cells(if has-header { pos.slice(1) } else { pos })
|
||
let start-page = state("pz-table-start-page", none)
|
||
figure(
|
||
kind: table,
|
||
context {
|
||
let fig-loc = here()
|
||
let tab-num = counter(figure.where(kind: table)).at(fig-loc).first()
|
||
start-page.update(none)
|
||
pz-table-inner(columns, header-cells, tab-num, start-page, ..arguments(..tail))
|
||
},
|
||
caption: caption,
|
||
)
|
||
}
|
||
|
||
// Реестры unit-тестов: перенос длинных идентификаторов (camelCase, _); сетка как в примере Typst.
|
||
#let pz-test-table(caption, columns, ..body) = {
|
||
let pos = body.pos()
|
||
let has-header = pos.len() > 0 and pos.first().func() == table.header
|
||
let header-cells = if has-header { pos.first().children } else { () }
|
||
let tail = pz-flatten-cells(if has-header { pos.slice(1) } else { pos })
|
||
let start-page = state("pz-table-start-page", none)
|
||
figure(
|
||
kind: table,
|
||
{
|
||
show table: set text(hyphenate: true, size: 9pt)
|
||
show table.cell: cell => {
|
||
show regex("[a-z0-9][A-Z]"): m => {
|
||
m.text.first() + sym.zws + m.text.last()
|
||
}
|
||
show regex("[_]"): it => it + sym.zws
|
||
cell
|
||
}
|
||
context {
|
||
let fig-loc = here()
|
||
let tab-num = counter(figure.where(kind: table)).at(fig-loc).first()
|
||
start-page.update(none)
|
||
pz-table-inner(columns, header-cells, tab-num, start-page, ..arguments(..tail))
|
||
}
|
||
},
|
||
caption: caption,
|
||
)
|
||
}
|
||
|
||
#let pz-fig(path, caption, lbl) = [
|
||
#figure(
|
||
image("../images/" + path, width: 100%),
|
||
caption: caption,
|
||
)
|
||
#label(lbl)
|
||
]
|