Refactor handout.typ
			#7
		
		
	| @ -151,34 +151,96 @@ | ||||
| // MARK: Sections | ||||
| // | ||||
|  | ||||
| #let generic(t) = block( | ||||
| /// 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, and are prefixed with `obj` | ||||
| ///   This label can then be used to reference this object. | ||||
| /// | ||||
| /// For example: | ||||
| /// ``` | ||||
| /// #problem(label: "problem1") | ||||
| /// This is @obj: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", t), | ||||
|     text(weight: "bold", obj_content), | ||||
|   ) | ||||
|  | ||||
| #let _generic_base(kind, ..args) = { | ||||
|   counter("obj").step() | ||||
|   if args.pos().len() == 0 { | ||||
|     generic([ | ||||
|       #kind | ||||
|       #context counter("obj").display(): | ||||
|     ]) | ||||
|   } else { | ||||
|     generic( | ||||
|       [ | ||||
|         #kind | ||||
|         #context counter("obj").display(): | ||||
|       ] | ||||
|         + " " | ||||
|         + args.pos().at(0), | ||||
|   // 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 label_name = "obj:" + label_name | ||||
|     let meta = ( | ||||
|       "obj_meta_ref_kind": kind, | ||||
|       // "obj_content": obj_content, | ||||
|       "label": label(label_name), | ||||
|       "counter": counter("obj"), | ||||
|     ) | ||||
|     [ #metadata(meta) #label(label_name) ] | ||||
|   } | ||||
| } | ||||
|  | ||||
| #let problem(..args) = _generic_base("Problem", ..args) | ||||
| #let definition(..args) = _generic_base("Definition", ..args) | ||||
| #let theorem(..args) = _generic_base("Theorem", ..args) | ||||
| // `ref` implementation for object meta-references, | ||||
| // see `show: ref`. | ||||
| #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. | ||||
|   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 | ||||
| } | ||||
|  | ||||
|  | ||||
| #let problem = _mkobj("Problem") | ||||
| #let definition = _mkobj("Definition") | ||||
| #let theorem = _mkobj("Theorem") | ||||
|  | ||||
|  | ||||
| // | ||||
| @ -272,6 +334,14 @@ | ||||
|     ] | ||||
|   } | ||||
|  | ||||
|   show ref: it => { | ||||
|     // Custom impl for object references | ||||
|     let x = _ref_obj(it) | ||||
|     if (x != none) { return x } | ||||
|  | ||||
|     return it // Use default `ref` implementation | ||||
|   } | ||||
|  | ||||
|   make_title( | ||||
|     group, | ||||
|     quarter, | ||||
|  | ||||
		Reference in New Issue
	
	Block a user