From 421b5fda91b2c5738f60a184fce13b0d8cda289c Mon Sep 17 00:00:00 2001 From: nleanba <25827850+nleanba@users.noreply.github.com> Date: Mon, 10 Feb 2025 11:09:23 +0100 Subject: [PATCH] theoretic:0.1.1 (#1674) --- packages/preview/theoretic/0.1.1/README.md | 24 + packages/preview/theoretic/0.1.1/UNLICENSE | 24 + packages/preview/theoretic/0.1.1/lib.typ | 704 ++++++++++++++++++++ packages/preview/theoretic/0.1.1/typst.toml | 13 + 4 files changed, 765 insertions(+) create mode 100644 packages/preview/theoretic/0.1.1/README.md create mode 100644 packages/preview/theoretic/0.1.1/UNLICENSE create mode 100644 packages/preview/theoretic/0.1.1/lib.typ create mode 100644 packages/preview/theoretic/0.1.1/typst.toml diff --git a/packages/preview/theoretic/0.1.1/README.md b/packages/preview/theoretic/0.1.1/README.md new file mode 100644 index 000000000..931ed51ff --- /dev/null +++ b/packages/preview/theoretic/0.1.1/README.md @@ -0,0 +1,24 @@ +# Theoretic + +> Opinionated tool to typeset theorems, lemmas and such + +Example Usage: +```typ + #import "@preview/theoretic:0.1.1" as theoretic: theorem, proof, qed + + // Otherwise, references won't work. + #show ref: theoretic.show-ref + + // set up your needed presets + #let corollary = theorem.with(kind: "corollary", supplement: "Corollary") + #let example = theorem.with(kind: "example", supplement: "Example", number: none) + // ..etc + + // use + #theorem(title: [Important Theorem])[#lorem(5)] + #corollary[#lorem(5)] + #example[#lorem(5)] + // ..etc +``` + +[Full manual: ![first page of the documentation](https://github.com/nleanba/typst-theoretic/raw/refs/tags/v0.1.1/preview.svg)](https://github.com/nleanba/typst-theoretic/blob/v0.1.1/main.pdf) \ No newline at end of file diff --git a/packages/preview/theoretic/0.1.1/UNLICENSE b/packages/preview/theoretic/0.1.1/UNLICENSE new file mode 100644 index 000000000..fdddb29aa --- /dev/null +++ b/packages/preview/theoretic/0.1.1/UNLICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/packages/preview/theoretic/0.1.1/lib.typ b/packages/preview/theoretic/0.1.1/lib.typ new file mode 100644 index 000000000..add72439b --- /dev/null +++ b/packages/preview/theoretic/0.1.1/lib.typ @@ -0,0 +1,704 @@ +/// clashes with parameter name +#let _label = label + +/// Function to run at beginning of theorem. +/// +/// Default value of @theorem.fmt-prefix. +/// #example(```typ +/// #fmt-prefix([Theorem], [1.34], none)... +/// +/// #fmt-prefix([Theorem], [1.34], [Pythagoras])... +/// ```) +/// -> content +#let fmt-prefix( + /// -> content + supplement, + /// -> content | none + number, + /// -> content | none + title, +) = { + emph({ + supplement + if number != none [ #number] + if title != none { + h(0.5em) + [(#title)] + } + h(1em) + }) +} + +/// Function to format the body +/// +/// Default value of @theorem.fmt-body. +/// -> content +#let fmt-body( + /// Theorem content. + /// -> content + body, + /// // enables creating a link/reference to the solution. + /// // -> location | none + /// -> content + solution, +) = { + body + if solution != none and solution != [] { + footnote[#link(<_thm_solutions>)[Solution in Appendix]] + // // This causes a document did not converge warning. why? + // context { + // let sol = query(<_thm>).filter(m => m.value.body == solution) + // if sol.len() == 1 { + // footnote[#link(sol.first().location())[Solution in Appendix]] + // } else { + // footnote[#link(<_thm_solutions>)[Solution in Appendix (*??*)]] + // } + // } + } +} + +/// -> state(boolean) +#let _needs_qed = state("_thm_needs_qed", false) + +/// Place a QED mark and clear the `_thm_needs_qed` flag, so that the theorem environment itself won't place one. +/// +/// See @proof.fmt-suffix. +/// // Pass this as @theorem.fmt-suffix for proof environments. +/// -> content +#let qed( + /// -> content + suffix: [#h(1fr)$square$], + /// Whether to place suffix no matter the `_thm_needs_qed` flag. + /// -> boolean + force: true, +) = context { + if force or _needs_qed.get() { + _needs_qed.update(false) + suffix + } +} + +/// Appends the suffix to the body, putting it inside any lists/enums and special casing block equations. +/// -> content +#let _append-qed( + /// -> content + body, + /// -> function | none + fmt-suffix, +) = { + let _body = body + if fmt-suffix != none { + if body.has("children") { + if body.children.last() == [ ] { + _body = body.children.slice(0, -1).join() + } + let candidate = _body.children.last() + if candidate.func() == math.equation and candidate.block and math.equation.numbering == none { + _body = { + _body.children.slice(0, -1).join() + set math.equation(numbering: (..) => {fmt-suffix()}, number-align: bottom) + candidate + counter(math.equation).update((i) => {i - 1}) + } + } else if candidate.func() == enum.item or candidate.func() == list.item { + _body = { + _body.children.slice(0, -1).join() + candidate.func()(_append-qed(candidate.body, fmt-suffix)) + } + } else { + _body = { + _body + fmt-suffix() + } + } + } else { + if _body.func() == math.equation and _body.block and math.equation.numbering == none { + _body = { + set math.equation(numbering: (..) => {fmt-suffix()}, number-align: bottom) + _body + counter(math.equation).update((i) => {i - 1}) + } + } else if _body.func() == enum.item or _body.func() == list.item { + _body = { + _body.func()(_append-qed(_body.body, fmt-suffix)) + } + } else { + _body = { + _body + fmt-suffix() + } + } + } + } + return _body +} + +/// Counts theorems. +/// +/// In most cases, it is not neccesary to reset this manually, it will get updated accordingly if you pass an integer to @theorem.number. +/// -> counter +#let thm-counter = counter("_thm") + +/// Theorem Environment +/// +/// #example(```typ +/// >>> #thm-counter.update(0) +/// #set heading(numbering: none) +/// +/// #theorem[If the headings are not numbered, theorem numbering starts at 1.] +/// +/// = Heading +/// #theorem(title: "Pythagoras")[ +/// Given a right-angled triangle, the length +/// of the hypothenuse squared is equal to the +/// sum of the squares of the remainig sides' +/// lengths. +/// ] +/// ```, scale-preview: 100%) +/// +/// /* #example(```typ +/// >>> #thm-counter.update(0) +/// >>> #counter(heading).update(0) +/// #set heading(numbering: "1.1.") +/// +/// #theorem[Theorem before first numbered heading is "0.\_".] +/// +/// = Heading +/// #theorem(title: "Pythagoras")[ +/// Given a right-angled triangle, the length +/// of the hypothenuse squared is equal to the +/// sum of the squares of the remainig sides' +/// lengths. +/// ] +/// +/// == Subheading +/// #let corollary = theorem.with( +/// kind: "corollary", +/// supplement: "Corollary") +/// #corollary[#lorem(5)] +/// #corollary(number: none)[Skip number] +/// #corollary(number: "P")[Custom "number"] +/// #corollary[Resume numbering] +/// #corollary(number: 10)[Set number] +/// #corollary[Continue with set number] +/// +/// = Heading +/// #theorem()[Restarted numbering.] +/// >>> #counter(heading).update((2,8)) +/// ```, scale-preview: 100%) */ +/// +/// -> content +#let theorem( + /// // Default: @fmt-prefix. + /// -> function + fmt-prefix: fmt-prefix, + + /// // Default: @fmt-body. + /// -> function + fmt-body: fmt-body, + + /// Will be called at the end of the theorem if `_thm_needs_qed` hasn't been cleared. (E.g. by @qed) + /// -> function | none + fmt-suffix: none, + + /// Arguments to pass to the ```typ #block[]``` containing the theorem. + /// -> dict + block-args: (:), + + /// Used for filtering e.g. when creating table of theorems. + /// -> string + kind: "theorem", + + /// What to label the environment. + /// + /// It is recommended to keep `kind` and `supplement` matching (except for "subtypes", e.g. one might have the kind of "Example" and "Counter-Example" both as ```typc "example"```) + /// -> content + supplement: "Theorem", + + ///- If ```typc auto```, will continue numbering from last numbered theorem. + ///- If integer, it will contune the numbering of later theorems from the given number. + ///- If content, it is shown as-is, with no side-effects. + ///#example(```typ + /// >>> // #thm-counter.update(0) + /// >>> // #counter(heading).update(0) + /// >>> // #set heading(numbering: "1.1.") + /// #let corollary = theorem.with( + /// kind: "corollary", + /// supplement: "Corollary") + /// + /// #corollary[#lorem(2)] + /// + /// #corollary(number: none)[Skip number] + /// #corollary[Resume numbering] + /// + /// #corollary(number: "X")[Custom "number"] + /// #corollary[Resume numbering] + /// + /// #corollary(number: 10)[Set number] + /// #corollary[Continue from set number] + /// >>> // #counter(heading).update((2,8)) + /// ```, scale-preview: 100%) + /// -> auto | none | integer | content + number: auto, + + /// Title of the Theorem. Usually shown after the number. + /// -> none | content + title: none, + + /// Title of the Theorem to be used in outlines. + /// ```typc auto``` to use the `title`. + /// -> auto | content + toctitle: auto, + + /// Label (for references) + /// + /// note: Simply putting a ```typ