diff --git a/lib/typst/local/handout/0.1.0/handout.typ b/lib/typst/local/handout/0.1.0/handout.typ deleted file mode 100755 index f35cebd..0000000 --- a/lib/typst/local/handout/0.1.0/handout.typ +++ /dev/null @@ -1,286 +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 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 -// - -#let generic(t) = block( - above: 8mm, - below: 2mm, - text(weight: "bold", t), -) - -#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), - ) - } -} - -#let problem(..args) = _generic_base("Problem", ..args) -#let definition(..args) = _generic_base("Definition", ..args) -#let theorem(..args) = _generic_base("Theorem", ..args) - - -// -// MARK: Misc -// - - -#let hint(content) = { - text(fill: rgb(100, 100, 100), style: "oblique", "Hint: ") - text(fill: rgb(100, 100, 100), content) -} - -#let note(content) = { - text(fill: rgb(100, 100, 100), content) -} - -#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) - ] - } - - make_title( - group, - quarter, - title, - { - if by == none { none } else { [#preparedby(by)\ ] } - if subtitle == none { none } else { subtitle } - }, - ) - - if show_solutions { - warn - } - doc -} - diff --git a/lib/typst/local/handout/0.1.0/header.typ b/lib/typst/local/handout/0.1.0/header.typ new file mode 100644 index 0000000..a46cc67 --- /dev/null +++ b/lib/typst/local/handout/0.1.0/header.typ @@ -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), + ), + ), + ), + ) +} diff --git a/lib/typst/local/handout/0.1.0/lib.typ b/lib/typst/local/handout/0.1.0/lib.typ new file mode 100755 index 0000000..d9f0e32 --- /dev/null +++ b/lib/typst/local/handout/0.1.0/lib.typ @@ -0,0 +1,113 @@ +/// 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", +/// ) +/// +/// +/// ``` +#let handout( + doc, + group: none, + title: none, + by: none, + subtitle: none, +) = { + set page( + margin: 20mm, + width: 8.5in, + height: 11in, + footer: align( + center, + context counter(page).display(), + ), + footer-descent: 5mm, + ) + + // + // Text style + set text(font: "New Computer Modern") + set par( + leading: 0.55em, + first-line-indent: 0mm, + justify: true, + spacing: 0.5em, + ) + + // + // List style + show list: set block(spacing: 0.5em, below: 1em) + set list( + tight: false, + indent: 5mm, + spacing: 3mm, + ) + + // + // Heading style + set heading(numbering: (..nums) => nums.pos().at(0)) + show heading.where(level: 1): it => { + set align(center) + set text(weight: "bold") + block[ + Section #counter(heading).display(): #text(it.body) + ] + } + + // + // Hack for custom references + show ref: it => { + import "object.typ": ref_obj + + let x = ref_obj(it) // Custom impl for object references + if (x != none) { return x } + + return it // Use default `ref` implementation otherwise + } + + + // + // 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 +} + diff --git a/lib/typst/local/handout/0.1.0/misc.typ b/lib/typst/local/handout/0.1.0/misc.typ new file mode 100755 index 0000000..841798c --- /dev/null +++ b/lib/typst/local/handout/0.1.0/misc.typ @@ -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), + ), + ), + ) +} diff --git a/lib/typst/local/handout/0.1.0/object.typ b/lib/typst/local/handout/0.1.0/object.typ new file mode 100644 index 0000000..7d4d09b --- /dev/null +++ b/lib/typst/local/handout/0.1.0/object.typ @@ -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(