Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/preview/comozeidex/0.3.0/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 Comozeidam

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
51 changes: 51 additions & 0 deletions packages/preview/comozeidex/0.3.0/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# comozeidex

A Typst template for building a hierarchical index or binder —
**Areas → Categories → IDs → notes** — with styled headings and an
optional table of contents.

## Usage

Start a new project from the template:

```
typst init @preview/comozeidex:0.3.0 my-index
```

This gives you a ready-to-edit `main.typ`:

```typ
#import "@preview/comozeidex:0.3.0": *
#show: doc.with(title: "My Index")
#toc() // optional table of contents

= Home // Area (level 1)
== Finances // Category (level 2)
=== 11.01 Bank Statements // ID (level 3)
#info[Monthly statements, PDF only]
#physloc[Filing cabinet, drawer 2]
#subid[11.01.01 — Checking account]
==== Some note as its own line // looks like #info, no bullet
```

## Knobs

Styling is controlled by module-level variables at the top of
`lib.typ` — fonts, sizes, indents, and colors for each heading level,
plus tables, code blocks, blockquotes, and links. Set
`number-sections = false` to turn off outline-style numbering (on by
default) if your Area/Category/ID headings already carry their own
hand-typed numbers.

## Helpers

- `doc(title:)` — the document wrapper; apply with `#show: doc.with(...)`.
- `toc()` — an optional table-of-contents page.
- `info(body)`, `physloc(body)`, `subid(body)` — bulleted leaf notes
under an ID heading.
- `callout(body, fill:)`, `blockquote(body)`, `divider()` — general
prose-page helpers.

## License

MIT, see [LICENSE](LICENSE).
271 changes: 271 additions & 0 deletions packages/preview/comozeidex/0.3.0/lib.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,271 @@
// "My Index" — Typst template. Defines styles/helpers only; doesn't
// print anything itself. Usage in the actual document:
//
// #import "template.typ": *
// #show: doc.with(title: "My Index")
// #toc() <- optional table of contents
//
// = Home <- Area (level 1)
// == Finances <- Category (level 2)
// === 11.01 Bank Statements <- ID (level 3)
// #info[Monthly statements, PDF only]
// #physloc[Filing cabinet, drawer 2]
// #subid[11.01.01 — Checking account]
// ==== Some note as its own line <- looks like #info, no bullet
//
// #tbl([a], [b], [c]) <- 3 equal-width columns
// #tbl(cols: 2, [a], [b]) <- 2 equal-width columns
// #tbl(columns: (2fr, 1fr), ..) <- custom column widths
//
// Put tables on their own line, NOT on the same line as a heading.
// Safe to tweak values below; don't rename anything left of `=`.

// ---- Knobs ----
// Toggle: prints "1", "1.1", "1.1.1", "1.1.1.1" in front of =, ==,
// ===, ==== headings (outline-style, each level nested under its
// parent). Off by default since Area/Category/ID headings already
// carry their own hand-typed numbers (like "11.01") — turning this
// on adds an extra outline number in front of those, it doesn't
// replace them. Uses Typst's real heading numbering under the hood,
// so #toc() automatically shows the same numbers, in sync, for free.
#let number-sections = false

// Font size inside all tables (including plain #table).



#let idx-font = ("Recursive Mn Csl St", "DejaVu Sans Mono") // first must match OS font name exactly; second is the fallback
#let idx-heading-weight = "medium" // only Medium is installed for now
#let idx-body-weight = "medium"

#let size-area = 12pt // Area (level 1)
#let size-category = 11pt // Category (level 2)
#let size-id = 10pt // ID (level 3)
#let size-note = 8pt // info/physloc/subid/level-4 headings
#let table-font-size = 8pt // table font size

#let indent-area = 0in // Area headings have no indent
#let indent-category = 0.5in
#let indent-id = 0.75in
#let indent-note = 1in
#let indent-note-step = 0.25in // how far #info sits in from its heading

#let area-color = rgb("#660000")
#let category-color = rgb("#879D89")
#let id-color = rgb("#546E87")
#let physloc-color = rgb("#EE0000")
#let page-bg = rgb("#f4ecd8")
#let heading-4-color = rgb("#000000")

#let link-color = rgb("#546E87")
#let table-header-fill = rgb("#e4d9bd")
#let table-stripe-fill = rgb("#faf6ec")
#let table-line-color = area-color.lighten(40%)
#let quote-bar-color = category-color
#let code-bg = rgb("#eee6d3")
#let code-header-fill = code-bg.darken(8%)
#let code-font = "DejaVu Sans Mono"
#let code-line-numbers = true
#let code-line-number-color = id-color.lighten(35%)



// ---- Document wrapper ----
#let doc(title: "My Index", body) = {
set document(title: title)
set page(paper: "us-letter", margin: 1in, numbering: "1", number-align: center, fill: page-bg)
set text(font: idx-font, size: 12pt, weight: idx-body-weight, lang: "en")
set par(justify: false, leading: 0.68em)
set heading(numbering: if number-sections { "1.1.1.1" } else { none })

// Area (level 1)
show heading.where(level: 1): it => block(above: 1.7em, below: 0.7em)[
#if it.numbering != none [
#context text(fill: area-color, size: size-area, weight: idx-heading-weight)[
#counter(heading).display(it.numbering) ~ #it.body
]
] else [
#text(fill: area-color, size: size-area, weight: idx-heading-weight, it.body)
]
]

// Category (level 2)
show heading.where(level: 2): it => pad(left: indent-category)[
#block(above: 1.1em, below: 0.35em)[
#if it.numbering != none [
#context text(fill: category-color, size: size-category, weight: idx-heading-weight)[
#counter(heading).display(it.numbering) ~ #it.body
]
] else [
#text(fill: category-color, size: size-category, weight: idx-heading-weight, it.body)
]
]
]

// ID (level 3)
show heading.where(level: 3): it => pad(left: indent-id)[
#block(above: 0.55em, below: 0.15em)[
#if it.numbering != none [
#context text(fill: id-color, size: size-id, weight: idx-heading-weight)[
#counter(heading).display(it.numbering) ~ #it.body
]
] else [
#text(fill: id-color, size: size-id, weight: idx-heading-weight, it.body)
]
]
]

// Generic line (level 4): styled like #info (plain black, note
// size/weight, same indent) but with no bullet, so it reads as a
// one-off heading rather than a bulleted note.
show heading.where(level: 4): it => block(above: 1em, below: 0.4em)[
#pad(left: indent-note)[
#if it.numbering != none [
#context text(font: idx-font, size: size-note, weight: idx-body-weight)[
#counter(heading).display(it.numbering) ~ #it.body
]
] else [
#text(font: idx-font, size: size-note, weight: idx-body-weight, it.body)
]
]
]

// Lists
set list(indent: 0.25in, spacing: 0.6em, marker: ([•], [◦], [‣]))
set enum(indent: 0.25in, spacing: 0.6em, numbering: "1.a.i.")

// Tables: header row shaded, body rows striped
set table(
stroke: 0.5pt + table-line-color,
inset: 6pt,
fill: (x, y) => if y == 0 { table-header-fill } else if calc.odd(y) { table-stripe-fill } else { none },
)
show table.cell.where(y: 0): set text(weight: "bold")

// Table text size (applies to every table, including plain #table)
show table.cell: set text(size: table-font-size)

// Let very long unbroken strings wrap inside table cells
show table: it => {
show regex("[^\\s]{20,}"): w => w.text.clusters().join(sym.zws)
it
}

// Code blocks: shaded box, language label, optional line numbers
show raw: set text(font: code-font, size: 9pt)
show raw.where(block: true): it => block(
fill: code-bg,
radius: 4pt,
width: 100%,
clip: true,
)[
#if it.lang != none [
#block(width: 100%, inset: (x: 10pt, top: 6pt, bottom: 6pt), fill: code-header-fill)[
#text(size: 8pt, fill: id-color, weight: "bold", tracking: 0.5pt, upper(it.lang))
]
]
#block(inset: 10pt, width: 100%)[
#if code-line-numbers [
#grid(
columns: (auto, 1fr),
column-gutter: 10pt,
row-gutter: 0pt,
..it.lines.map(line => (
box(height: 1.4em, text(fill: code-line-number-color, str(line.number))),
box(height: 1.4em, line.body),
)).flatten()
)
] else [
#it
]
]
]

// Blockquotes
show quote.where(block: true): it => block(
inset: (left: 1em),
stroke: (left: 2pt + quote-bar-color),
)[
#set text(style: "italic")
#it.body
]

// Links
show link: it => text(fill: link-color, underline(it))

// Figure captions
show figure.caption: it => text(fill: id-color, size: size-note, style: "italic", it)

// Title block
align(center)[
#text(fill: area-color, size: 22pt, weight: "bold", title)
]
v(0.5em)
line(length: 100%, stroke: 0.5pt + area-color.lighten(30%))
v(1em)

body
}

// ---- Table of contents ----
// Call #toc() once, right after #show: doc.with(...), if you
// want a listing page. Its own "Table of Contents" heading is never
// numbered and never lists itself — only the real headings below it
// show up, with the same numbers as in the body (or no numbers, if
// number-sections is off).
#let toc() = {
align(center)[ #text(fill: area-color, size: 18pt, weight: idx-heading-weight)[Table of Contents]]
show outline.entry.where(level: 1): it => text(fill: area-color.lighten(25%).desaturate(50%), it)
show outline.entry.where(level: 2): it => text(fill: category-color.lighten(25%).desaturate(50%), it)
show outline.entry.where(level: 3): it => text(fill: id-color.lighten(25%).desaturate(50%), it)
show outline.entry.where(level: 4): it => text(fill: heading-4-color.lighten(45%).desaturate(50%), it)
outline(title: none, indent: auto)
colbreak()
}

// ---- Leaf notes (info / physloc / subid) ----
#let note(body, fill: black, weight: idx-body-weight, style: "normal", indent: indent-note) = pad(left: indent)[
#set text(font: idx-font, size: size-note, fill: fill, weight: weight, style: style)
#box[•~#body]
]

// Shared helper: looks up the last heading before the note and indents
// one step past that heading's indent. #info and #physloc both use it.
#let note-under-heading(body, ..args) = context {
let hs = query(selector(heading).before(here()))
let lvl = if hs.len() == 0 { 0 } else { hs.last().level }
let base = if lvl <= 1 { indent-area }
else if lvl == 2 { indent-category }
else if lvl == 3 { indent-id }
else { indent-note }
note(body, indent: base + indent-note-step, ..args)
}

#let info(body) = note-under-heading(body)
#let physloc(body) = note-under-heading(body, fill: physloc-color, weight: "bold", style: "italic")
#let subid(body) = note(body)

// ---- General prose-page helpers ----
#let callout(body, fill: table-header-fill) = block(
fill: fill,
inset: 10pt,
radius: 4pt,
width: 100%,
body,
)

#let blockquote(body) = quote(block: true, body)

#let divider() = line(
length: 100%,
stroke: 1.25pt + area-color.transparentize(25%),
)

// ---- Table helper ----
// Equal-width table: #tbl([a], [b], [c]), #tbl(cols: 2, ..).
// Pass columns: (...) to set custom column widths instead of cols.
#let tbl(cols: 3, columns: none, ..args) = {
let c = if columns != none { columns } else { (1fr,) * cols }
set text(size: table-font-size)
table(columns: c, ..args)
}
10 changes: 10 additions & 0 deletions packages/preview/comozeidex/0.3.0/template/main.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#import "@preview/comozeidex:0.3.0": *
#show: doc.with(title: "My Index")
#toc()

= Home
== Finances
=== 11.01 Bank Statements
#info[Monthly statements, PDF only]
#physloc[Filing cabinet, drawer 2]
#subid[11.01.01 — Checking account]
Binary file added packages/preview/comozeidex/0.3.0/thumbnail.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions packages/preview/comozeidex/0.3.0/typst.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "comozeidex"
version = "0.3.0"
entrypoint = "lib.typ"
authors = ["Comozeidam <@Comozeidam>"]
license = "MIT"
description = "Styled headings and helpers for building a hierarchical index or binder — areas, categories, IDs, and notes. "
categories = ["office", "layout"]

[template]
path = "template"
entrypoint = "main.typ"
thumbnail = "thumbnail.png"
Loading