Refactor handout.typ
Reviewed-on: #7 Co-authored-by: Mark <mark@betalupi.com> Co-committed-by: Mark <mark@betalupi.com>
This commit is contained in:
100
lib/typst/local/handout/0.1.0/object.typ
Normal file
100
lib/typst/local/handout/0.1.0/object.typ
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
/// This module defines all handout "objects"
|
||||
/// (problems, theorems, definitions, etc)
|
||||
|
||||
/// Core render code for all objects (problems, theorems, etc)
|
||||
/// This should never be used directly by client code.
|
||||
///
|
||||
/// Args:
|
||||
/// - kind: the kind of object to make ("Problem", "Definition", etc)
|
||||
/// - label_name: a string. If provided, generate metadata for this object
|
||||
/// under the given label. Labels must be unique.
|
||||
/// This label can then be used to reference this object.
|
||||
///
|
||||
/// For example:
|
||||
/// ```
|
||||
/// #problem(label: "problem1")
|
||||
/// This is @problem1
|
||||
/// ```
|
||||
#let _obj_base(kind, ..args, label_name: none) = {
|
||||
counter("obj").step()
|
||||
let n = context counter("obj").get().first()
|
||||
|
||||
// The complete title text of this object,
|
||||
// like "Problem 5:" or "Theorem: "
|
||||
let obj_content = if args.pos().len() == 0 {
|
||||
[#kind #n:]
|
||||
} else {
|
||||
[#kind #n: #args.pos().at(0)]
|
||||
}
|
||||
|
||||
// Render the object
|
||||
block(
|
||||
above: 8mm,
|
||||
below: 2mm,
|
||||
text(weight: "bold", obj_content),
|
||||
)
|
||||
|
||||
// Generate labeled metadata for this object.
|
||||
//
|
||||
// This can be viewed directly with `#context query(<label>).first().value`,
|
||||
// Or referenced with `@label` (we define a custom renderer for this metadata later)
|
||||
if label_name != none {
|
||||
let meta = (
|
||||
"obj_meta_ref_kind": kind,
|
||||
// "obj_content": obj_content,
|
||||
"label": label(label_name),
|
||||
"counter": counter("obj"),
|
||||
)
|
||||
[ #metadata(meta) #label(label_name) ]
|
||||
}
|
||||
}
|
||||
|
||||
// `ref` implementation for object meta-references.
|
||||
// Returns `none` if `it` is not object metadata.
|
||||
#let ref_obj(it) = {
|
||||
let magic_key = "obj_meta_ref_kind"
|
||||
if not (
|
||||
it.element != none
|
||||
and it.element.has("value")
|
||||
and type(it.element.value) == "dictionary"
|
||||
and it.element.value.keys().contains(magic_key)
|
||||
) {
|
||||
// This label is not attached to object metadata
|
||||
return none
|
||||
}
|
||||
|
||||
let v = it.element.value
|
||||
let obj_type = v.at(magic_key)
|
||||
|
||||
// The value of this object's counter at its label
|
||||
let obj_count = v.counter.at(v.label).first()
|
||||
|
||||
// Produces text like "Problem 2",
|
||||
// which takes you to the referenced object when clicked.
|
||||
return link(v.label, [#obj_type #obj_count])
|
||||
}
|
||||
|
||||
/// Factory function for objects.
|
||||
/// Provided for convenience, lets us define objects in one line.
|
||||
#let _mkobj(kind) = {
|
||||
let out(..args, label: none) = _obj_base(
|
||||
kind,
|
||||
..args,
|
||||
label_name: label,
|
||||
)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// MARK: export
|
||||
//
|
||||
// Functions for client code are defined below
|
||||
|
||||
#let problem = _mkobj("Problem")
|
||||
#let definition = _mkobj("Definition")
|
||||
#let theorem = _mkobj("Theorem")
|
||||
#let example = _mkobj("Example")
|
||||
#let remark = _mkobj("Remark")
|
Reference in New Issue
Block a user