anarsec.guide/layout/anarsec_article.typ
2024-11-22 16:45:57 -05:00

211 lines
5.2 KiB
Typst

#let anarsec_article(
title: none,
frontimage: none,
backimage: none,
lastediteddate: none,
description: none,
subtitle: none,
category: none,
backcoverinsidecontent: none,
lang: none,
content
) = {
set document(date: none)
set text(lang: lang)
set text(hyphenate: true)
// format lists
set list(marker: ([], [--]))
// front cover
page()[
#place(
center + top,
dy: 250pt,
image(frontimage)
)
#place(
center + top,
dy: 100pt,
)[
#set text(font: "Jost")
#text(35pt, title)
#{
if subtitle != "None" {
text(18pt, subtitle)
}
}
]
#place(
center + bottom,
dy: -20pt,
)[
#set text(font: "Jost")
#if lang == "en" [
#text(18pt)[Series: #category]
]
#if lang == "fr" [
#text(18pt)[Séries: #category]
]
]
]
// inside cover
page()[
#if lang == "en" [
#set align(center + bottom)
#text()[This version of the zine was last edited on #lastediteddate. Visit anarsec.guide to see whether it has been updated since.]
#text()[The dagger symbol #super[] on a word means that there is a glossary entry for it. Ai ferri corti.]
]
#if lang == "fr" [
#set align(center + bottom)
#text()[Cette version de la brochure a été modifiée pour la dernière fois le #lastediteddate. Visitez anarsec.guide/fr pour savoir si elle a été mise à jour depuis.]
#text()[Le symbole de dague #super[] près d'un mot indique qu'une entrée existe dans le glossaire pour ce mot. Ai ferri corti.]
]
]
// set headings
show heading.where(level: 1): it => {
block(width: 100%)[
#set align(center)
#set text(size: 22pt, font: "Jost")
#text(underline(it.body))
#v(10pt)
]
}
show heading.where(level: 2): it => block(width: 100%)[
#set text(size: 16pt, font: "Jost")
#text(it.body)
#v(10pt)
]
show heading.where(level: 3): it => block(width: 100%)[
#set text(size: 13pt, font: "Jost", style: "italic")
#text(it.body)
#v(10pt)
]
show heading.where(level: 4): it => block(width: 100%)[
#set text(size: 11pt, font: "Jost")
#text(underline(it.body))
#v(10pt)
]
// table of contents
outline(indent: 20pt, depth: 2)
// format links
let before = ""
let after = ""
let rec = ""
if lang != "en" {
before = "/" + lang
after = lang + "/"
}
if lang == "en" {
rec = "Appendix: Recommendations"
}
else if lang == "fr" {
rec = "Annexe: Recommendations"
}
let glossaryFootnote = state("x", [#footnote[anarsec.guide/glossary]<glossary-footnote>])
show link: it => {
it.body
if type(it.dest) == "string" {
if it.dest == ("https://anarsec.guide/" + after + "recommendations") or it.dest == (before + "/recommendations") {
text[ (#emph()[rec])]
}
else if it.dest.starts-with(before + "/recommendations#") or it.dest.starts-with(before + "/recommendations/#") {
context {
let elements = query(label(it.dest.trim(before + "/recommendations#", at: start).trim(before + "/recommendations/#", at: start)))
text[ (#emph()[rec])]
}
}
else if it.dest.starts-with("https://") or it.dest.starts-with("http://") {
footnote[#it.dest.trim("https://", at: start).trim("http://", at: start).trim("www.", at: start)]
}
else if it.dest.starts-with(before + "/glossary#") or it.dest.starts-with(before + "/glossary/#") {
context {
let elements = query(heading.where(label: label(it.dest.trim(before + "/glossary#", at: start).trim(before + "/glossary/#", at: start))))
if elements.len() != 0 {
text[#super[]]
}
else {
context glossaryFootnote.get()
glossaryFootnote.update(x => footnote(<glossary-footnote>))
}
}
}
else if it.dest.starts-with("/") {
footnote({text[anarsec.guide] + it.dest})
}
}
else if type(it.dest) == "label" {
locate(location => {
let elements = query(it.dest, location)
text[ (#emph(elements.first().body))]
})
}
}
// content
set page(numbering: "1")
set align(left)
pagebreak(weak: true)
content
set page(numbering: none)
set heading(outlined: false)
// back cover inside
page()[
// set headings
#show heading.where(level: 1): it => {
block(width: 100%)[
#set align(center)
#set text(size: 22pt, font: "Jost")
#text(it.body)
#v(10pt)
]
}
// format links
#show link: it => {
it.body
}
#backcoverinsidecontent
]
// back cover
page()[
#text()[
#place(center + horizon, dy: -100pt, block(width: 100%, align(left, par(justify: true, description))))
#place(center + bottom, dy: 20pt, image(height: 250pt, backimage))
]
]
}
// blockquote function ; TODO: remove when typst has a native blockquote function (see https://github.com/typst/typst/issues/105)
#let blockquote(
content
) = align(center)[
#block(width: 92%, fill: rgb(230, 230, 230), radius: 4pt, inset: 8pt)[
#align(left)[
#text(content)
]
]
]