Refactor handout.typ
This commit is contained in:
parent
73d45c38f6
commit
59c1373405
@ -1,361 +0,0 @@
|
|||||||
/// Typst handout library, used for all documents in this repository.
|
|
||||||
|
|
||||||
|
|
||||||
/// If false, hide instructor info.
|
|
||||||
///
|
|
||||||
/// Compile with the following command to hide solutions:
|
|
||||||
/// `typst compile main.typ --input show_solutions=false`
|
|
||||||
///
|
|
||||||
/// Solutions are shown by default. This behavior
|
|
||||||
/// is less surprising than hiding content by default.
|
|
||||||
#let show_solutions = {
|
|
||||||
if "show_solutions" in sys.inputs {
|
|
||||||
// Show solutions unless they're explicitly disabled
|
|
||||||
not (
|
|
||||||
sys.inputs.show_solutions == "false" or sys.inputs.show_solutions == "no"
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// Show solutions by default
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Colors
|
|
||||||
#let ored = rgb("D62121")
|
|
||||||
#let oorange = rgb("#ffaa3b")
|
|
||||||
#let ogrape = rgb("9C36B5")
|
|
||||||
#let ocyan = rgb("2288BF")
|
|
||||||
#let oteal = rgb("12B886")
|
|
||||||
#let ogreen = rgb("37B26D")
|
|
||||||
#let oblue = rgb("1C7ED6")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// MARK: header
|
|
||||||
//
|
|
||||||
|
|
||||||
#let make_title(
|
|
||||||
group,
|
|
||||||
quarter,
|
|
||||||
title,
|
|
||||||
subtitle,
|
|
||||||
) = {
|
|
||||||
align(
|
|
||||||
center,
|
|
||||||
block(
|
|
||||||
width: 60%,
|
|
||||||
height: auto,
|
|
||||||
breakable: false,
|
|
||||||
align(
|
|
||||||
center,
|
|
||||||
stack(
|
|
||||||
spacing: 7pt,
|
|
||||||
(
|
|
||||||
text(size: 10pt, group) + h(1fr) + text(size: 10pt, quarter)
|
|
||||||
),
|
|
||||||
line(length: 100%, stroke: 0.2mm),
|
|
||||||
(
|
|
||||||
text(size: 20pt, title) + linebreak() + text(size: 10pt, subtitle)
|
|
||||||
),
|
|
||||||
line(length: 100%, stroke: 0.2mm),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let warn = {
|
|
||||||
set text(ored)
|
|
||||||
align(
|
|
||||||
center,
|
|
||||||
block(
|
|
||||||
width: 60%,
|
|
||||||
height: auto,
|
|
||||||
breakable: false,
|
|
||||||
fill: rgb(255, 255, 255),
|
|
||||||
stroke: ored + 2pt,
|
|
||||||
inset: 3mm,
|
|
||||||
(
|
|
||||||
align(center, text(weight: "bold", size: 12pt, [Instructor's Handout]))
|
|
||||||
+ parbreak()
|
|
||||||
+ align(
|
|
||||||
left,
|
|
||||||
text(
|
|
||||||
size: 10pt,
|
|
||||||
[This handout contains solutions and notes.]
|
|
||||||
+ linebreak()
|
|
||||||
+ [Recompile without solutions before distributing.],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let preparedby(name) = (
|
|
||||||
text(
|
|
||||||
size: 10pt,
|
|
||||||
[Prepared by ]
|
|
||||||
+ name
|
|
||||||
+ [ on ]
|
|
||||||
+ datetime
|
|
||||||
.today()
|
|
||||||
.display("[month repr:long] [day padding:none], [year]"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
//
|
|
||||||
// MARK: Solutions
|
|
||||||
//
|
|
||||||
|
|
||||||
#let solution(content) = {
|
|
||||||
if show_solutions {
|
|
||||||
align(
|
|
||||||
center,
|
|
||||||
stack(
|
|
||||||
block(
|
|
||||||
width: 100%,
|
|
||||||
breakable: false,
|
|
||||||
fill: ored,
|
|
||||||
stroke: ored + 2pt,
|
|
||||||
inset: 1.5mm,
|
|
||||||
(
|
|
||||||
align(left, text(fill: white, weight: "bold", [Solution:]))
|
|
||||||
),
|
|
||||||
),
|
|
||||||
block(
|
|
||||||
width: 100%,
|
|
||||||
height: auto,
|
|
||||||
breakable: false,
|
|
||||||
fill: ored.lighten(80%).desaturate(10%),
|
|
||||||
stroke: ored + 2pt,
|
|
||||||
inset: 3mm,
|
|
||||||
align(left, content),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#let if_solutions(content) = {
|
|
||||||
if show_solutions { content }
|
|
||||||
}
|
|
||||||
|
|
||||||
#let if_no_solutions(content) = {
|
|
||||||
if not show_solutions { content }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// MARK: Sections
|
|
||||||
//
|
|
||||||
|
|
||||||
/// 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", 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 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) ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// `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")
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// MARK: Misc
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#let note(content, type: none) = {
|
|
||||||
if type != none {
|
|
||||||
text(fill: rgb(100, 100, 100), style: "oblique", [#type: ])
|
|
||||||
}
|
|
||||||
text(fill: rgb(100, 100, 100), content)
|
|
||||||
}
|
|
||||||
|
|
||||||
#let hint(content) = {
|
|
||||||
note(content, type: "Hint")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#let examplesolution(content) = {
|
|
||||||
let c = oblue
|
|
||||||
|
|
||||||
align(
|
|
||||||
center,
|
|
||||||
stack(
|
|
||||||
block(
|
|
||||||
width: 100%,
|
|
||||||
breakable: false,
|
|
||||||
fill: c,
|
|
||||||
stroke: c + 2pt,
|
|
||||||
inset: 1.5mm,
|
|
||||||
(
|
|
||||||
align(left, text(fill: white, weight: "bold", [Example solution:]))
|
|
||||||
),
|
|
||||||
),
|
|
||||||
block(
|
|
||||||
width: 100%,
|
|
||||||
height: auto,
|
|
||||||
breakable: false,
|
|
||||||
fill: c.lighten(80%).desaturate(10%),
|
|
||||||
stroke: c + 2pt,
|
|
||||||
inset: 3mm,
|
|
||||||
align(left, content),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// MARK: wrapper
|
|
||||||
//
|
|
||||||
|
|
||||||
#let handout(
|
|
||||||
doc,
|
|
||||||
group: none,
|
|
||||||
quarter: none,
|
|
||||||
title: none,
|
|
||||||
by: none,
|
|
||||||
subtitle: none,
|
|
||||||
) = {
|
|
||||||
set par(leading: 0.55em, first-line-indent: 0mm, justify: true)
|
|
||||||
set text(font: "New Computer Modern")
|
|
||||||
set par(spacing: 0.5em)
|
|
||||||
show list: set block(spacing: 0.5em, below: 1em)
|
|
||||||
set heading(numbering: (..nums) => nums.pos().at(0))
|
|
||||||
|
|
||||||
set page(
|
|
||||||
margin: 20mm,
|
|
||||||
width: 8in,
|
|
||||||
height: 11.5in,
|
|
||||||
footer: align(
|
|
||||||
center,
|
|
||||||
context counter(page).display(),
|
|
||||||
),
|
|
||||||
footer-descent: 5mm,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
set list(
|
|
||||||
tight: false,
|
|
||||||
indent: 5mm,
|
|
||||||
spacing: 3mm,
|
|
||||||
)
|
|
||||||
|
|
||||||
show heading.where(level: 1): it => {
|
|
||||||
set align(center)
|
|
||||||
set text(weight: "bold")
|
|
||||||
block[
|
|
||||||
Section #counter(heading).display(): #text(it.body)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
|
||||||
title,
|
|
||||||
{
|
|
||||||
if by == none { none } else { [#preparedby(by)\ ] }
|
|
||||||
if subtitle == none { none } else { subtitle }
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if show_solutions {
|
|
||||||
warn
|
|
||||||
}
|
|
||||||
|
|
||||||
doc
|
|
||||||
}
|
|
||||||
|
|
71
lib/typst/local/handout/0.1.0/header.typ
Normal file
71
lib/typst/local/handout/0.1.0/header.typ
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#import "misc.typ": ored
|
||||||
|
|
||||||
|
#let solution_warning() = {
|
||||||
|
set text(ored)
|
||||||
|
align(
|
||||||
|
center,
|
||||||
|
block(
|
||||||
|
width: 60%,
|
||||||
|
height: auto,
|
||||||
|
breakable: false,
|
||||||
|
fill: rgb(255, 255, 255),
|
||||||
|
stroke: ored + 2pt,
|
||||||
|
inset: 3mm,
|
||||||
|
(
|
||||||
|
align(center, text(weight: "bold", size: 12pt, [Instructor's Handout]))
|
||||||
|
+ parbreak()
|
||||||
|
+ align(
|
||||||
|
left,
|
||||||
|
text(
|
||||||
|
size: 10pt,
|
||||||
|
[
|
||||||
|
This handout contains solutions and notes. \
|
||||||
|
Recompile without solutions before distributing.
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let make_header(
|
||||||
|
title,
|
||||||
|
subtitle: none,
|
||||||
|
by: none,
|
||||||
|
top_left: "",
|
||||||
|
top_right: "",
|
||||||
|
) = {
|
||||||
|
let date = datetime
|
||||||
|
.today()
|
||||||
|
.display("[month repr:long] [day padding:none], [year]")
|
||||||
|
|
||||||
|
if (by != none) {
|
||||||
|
by = text(size: 10pt, [Prepared by #by on #date])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Main title
|
||||||
|
align(
|
||||||
|
center,
|
||||||
|
block(
|
||||||
|
width: 60%,
|
||||||
|
height: auto,
|
||||||
|
breakable: false,
|
||||||
|
align(
|
||||||
|
center,
|
||||||
|
stack(
|
||||||
|
spacing: 7pt,
|
||||||
|
// Top
|
||||||
|
text(size: 10pt, top_left) + h(1fr) + text(size: 10pt, top_right),
|
||||||
|
line(length: 100%, stroke: 0.2mm),
|
||||||
|
// Title
|
||||||
|
text(size: 20pt, title),
|
||||||
|
// Subtitle
|
||||||
|
if (by != none) { text(size: 10pt, by) },
|
||||||
|
if (subtitle != none) { text(size: 10pt, subtitle) },
|
||||||
|
line(length: 100%, stroke: 0.2mm),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
103
lib/typst/local/handout/0.1.0/lib.typ
Executable file
103
lib/typst/local/handout/0.1.0/lib.typ
Executable file
@ -0,0 +1,103 @@
|
|||||||
|
/// Typst handout library, used for all documents in this repository.
|
||||||
|
|
||||||
|
// Re-exports
|
||||||
|
// All functions that maybe used by client code are listed here
|
||||||
|
#import "misc.typ": *
|
||||||
|
#import "object.typ": problem, definition, theorem
|
||||||
|
#import "solution.typ": if_solutions, if_no_solutions, solution
|
||||||
|
|
||||||
|
|
||||||
|
/// Main handout wrapper.
|
||||||
|
/// Use this as follows:
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// #show: handout.with(
|
||||||
|
/// group: "Advanced 2",
|
||||||
|
/// title: [Handout Title],
|
||||||
|
/// by: "author",
|
||||||
|
/// subtitle: "optional",
|
||||||
|
/// )
|
||||||
|
///
|
||||||
|
/// <rest of document>
|
||||||
|
/// ```
|
||||||
|
#let handout(
|
||||||
|
doc,
|
||||||
|
group: none,
|
||||||
|
title: none,
|
||||||
|
by: none,
|
||||||
|
subtitle: none,
|
||||||
|
) = {
|
||||||
|
set page(
|
||||||
|
margin: 20mm,
|
||||||
|
width: 8in,
|
||||||
|
height: 11.5in,
|
||||||
|
footer: align(
|
||||||
|
center,
|
||||||
|
context counter(page).display(),
|
||||||
|
),
|
||||||
|
footer-descent: 5mm,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
set par(leading: 0.55em, first-line-indent: 0mm, justify: true)
|
||||||
|
set text(font: "New Computer Modern")
|
||||||
|
set par(spacing: 0.5em)
|
||||||
|
show list: set block(spacing: 0.5em, below: 1em)
|
||||||
|
set heading(numbering: (..nums) => nums.pos().at(0))
|
||||||
|
|
||||||
|
|
||||||
|
set list(
|
||||||
|
tight: false,
|
||||||
|
indent: 5mm,
|
||||||
|
spacing: 3mm,
|
||||||
|
)
|
||||||
|
|
||||||
|
show heading.where(level: 1): it => {
|
||||||
|
set align(center)
|
||||||
|
set text(weight: "bold")
|
||||||
|
block[
|
||||||
|
Section #counter(heading).display(): #text(it.body)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
show ref: it => {
|
||||||
|
// Custom impl for object references
|
||||||
|
let x = _ref_obj(it)
|
||||||
|
if (x != none) { return x }
|
||||||
|
|
||||||
|
// Use default `ref` implementation otherwise
|
||||||
|
return it
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Begin content
|
||||||
|
//
|
||||||
|
|
||||||
|
// Make handout title
|
||||||
|
{
|
||||||
|
import "header.typ": make_header, solution_warning
|
||||||
|
import "solution.typ": show_solutions
|
||||||
|
|
||||||
|
let url = link(
|
||||||
|
"https://betalupi.com/handouts",
|
||||||
|
"betalupi.com/handouts",
|
||||||
|
)
|
||||||
|
|
||||||
|
make_header(
|
||||||
|
title,
|
||||||
|
subtitle: subtitle,
|
||||||
|
by: by,
|
||||||
|
top_left: group,
|
||||||
|
top_right: url,
|
||||||
|
)
|
||||||
|
|
||||||
|
if show_solutions {
|
||||||
|
solution_warning()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Include rest of document
|
||||||
|
doc
|
||||||
|
}
|
||||||
|
|
49
lib/typst/local/handout/0.1.0/misc.typ
Executable file
49
lib/typst/local/handout/0.1.0/misc.typ
Executable file
@ -0,0 +1,49 @@
|
|||||||
|
/// Miscellaneous utilities
|
||||||
|
|
||||||
|
#let ored = rgb("D62121")
|
||||||
|
#let oorange = rgb("#ffaa3b")
|
||||||
|
#let ogrape = rgb("9C36B5")
|
||||||
|
#let ocyan = rgb("2288BF")
|
||||||
|
#let oteal = rgb("12B886")
|
||||||
|
#let ogreen = rgb("37B26D")
|
||||||
|
#let oblue = rgb("1C7ED6")
|
||||||
|
|
||||||
|
|
||||||
|
#let note(content, type: none) = {
|
||||||
|
set text(fill: rgb(100, 100, 100))
|
||||||
|
if type != none {
|
||||||
|
text(style: "oblique", [#type: ])
|
||||||
|
}
|
||||||
|
text(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
#let hint = note.with(type: "Hint")
|
||||||
|
|
||||||
|
#let examplesolution(content) = {
|
||||||
|
let c = oblue
|
||||||
|
|
||||||
|
align(
|
||||||
|
center,
|
||||||
|
stack(
|
||||||
|
block(
|
||||||
|
width: 100%,
|
||||||
|
breakable: false,
|
||||||
|
fill: c,
|
||||||
|
stroke: c + 2pt,
|
||||||
|
inset: 1.5mm,
|
||||||
|
(
|
||||||
|
align(left, text(fill: white, weight: "bold", [Example solution:]))
|
||||||
|
),
|
||||||
|
),
|
||||||
|
block(
|
||||||
|
width: 100%,
|
||||||
|
height: auto,
|
||||||
|
breakable: false,
|
||||||
|
fill: c.lighten(80%).desaturate(10%),
|
||||||
|
stroke: c + 2pt,
|
||||||
|
inset: 3mm,
|
||||||
|
align(left, content),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
101
lib/typst/local/handout/0.1.0/object.typ
Normal file
101
lib/typst/local/handout/0.1.0/object.typ
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
|
||||||
|
/// 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 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) ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// `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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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")
|
56
lib/typst/local/handout/0.1.0/solution.typ
Executable file
56
lib/typst/local/handout/0.1.0/solution.typ
Executable file
@ -0,0 +1,56 @@
|
|||||||
|
#import "misc.typ": ored
|
||||||
|
|
||||||
|
/// If false, hide instructor info.
|
||||||
|
///
|
||||||
|
/// Compile with the following command to hide solutions:
|
||||||
|
/// `typst compile main.typ --input show_solutions=false`
|
||||||
|
///
|
||||||
|
/// Solutions are shown by default. This behavior
|
||||||
|
/// is less surprising than hiding content by default.
|
||||||
|
#let show_solutions = {
|
||||||
|
if "show_solutions" in sys.inputs {
|
||||||
|
// Show solutions unless they're explicitly disabled
|
||||||
|
not (
|
||||||
|
sys.inputs.show_solutions == "false" or sys.inputs.show_solutions == "no"
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Show solutions by default
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#let if_solutions(content) = {
|
||||||
|
if show_solutions { content }
|
||||||
|
}
|
||||||
|
|
||||||
|
#let if_no_solutions(content) = {
|
||||||
|
if not show_solutions { content }
|
||||||
|
}
|
||||||
|
|
||||||
|
#let solution(content) = {
|
||||||
|
if_solutions(
|
||||||
|
align(
|
||||||
|
center,
|
||||||
|
stack(
|
||||||
|
block(
|
||||||
|
width: 100%,
|
||||||
|
breakable: false,
|
||||||
|
fill: ored,
|
||||||
|
stroke: ored + 2pt,
|
||||||
|
inset: 1.5mm,
|
||||||
|
align(left, text(fill: white, weight: "bold", [Solution:])),
|
||||||
|
),
|
||||||
|
|
||||||
|
block(
|
||||||
|
width: 100%,
|
||||||
|
height: auto,
|
||||||
|
breakable: false,
|
||||||
|
fill: ored.lighten(80%).desaturate(10%),
|
||||||
|
stroke: ored + 2pt,
|
||||||
|
inset: 3mm,
|
||||||
|
align(left, content),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
@ -1,6 +1,12 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "handout"
|
name = "handout"
|
||||||
|
description = "A library for math circle handouts"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
entrypoint = "handout.typ"
|
entrypoint = "lib.typ"
|
||||||
authors = []
|
|
||||||
license = "GPL"
|
homepage = "https://betalupi.com/handouts"
|
||||||
|
repository = "https://git.betalupi.com/Mark/handouts"
|
||||||
|
authors = ["Mark <mark@betalupi.com>"]
|
||||||
|
license = "GPL-3.0-only "
|
||||||
|
disciplines = ["education", "mathematics"]
|
||||||
|
categories = ["layout", "components"]
|
@ -1,13 +1,6 @@
|
|||||||
#import "@local/handout:0.1.0": *
|
#import "@local/handout:0.1.0": *
|
||||||
|
|
||||||
#show: doc => handout(
|
#show: handout.with(
|
||||||
doc,
|
|
||||||
group: "Advanced 2",
|
|
||||||
quarter: link(
|
|
||||||
"https://betalupi.com/handouts",
|
|
||||||
"betalupi.com/handouts",
|
|
||||||
),
|
|
||||||
|
|
||||||
title: [Tropical Polynomials],
|
title: [Tropical Polynomials],
|
||||||
by: "Mark",
|
by: "Mark",
|
||||||
subtitle: "Based on a handout by Bryant Mathews",
|
subtitle: "Based on a handout by Bryant Mathews",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user