diff --git a/packages/preview/obsidius/0.2.0/README.md b/packages/preview/obsidius/0.2.0/README.md new file mode 100644 index 0000000000..8fd1d2dd25 --- /dev/null +++ b/packages/preview/obsidius/0.2.0/README.md @@ -0,0 +1,31 @@ +# Obsidius + +![Preview of Obsidius](./sample/sample.png) + +Obsidius is a modern template for typst with a design inspired by [Obsidian](https://obsidian.md). +It features utility functions to add Obsidians callouts to the document, for example to add warnings and solutions. + +Get started by adding the following code to your document: + +```typst +#import "@preview/obsidius:0.1.0": * + +#show: notes.with("Your fancy title"); +``` + +## Callouts + +Callouts are colored blocks in your document with content outside the normal narrative flow. +For example, if you describe how to cook pasta, you can add a warning like this: + +```typst +#warning[ +Be careful with the water temperature. Foam can easily push your lid and rise out of your pot, +creating a mess on your stove. +] +``` + +There is also the `#solution[]` callout. +You can also create your own custom callout, see the [sample document](sample/sample.typ) for more details. + +This template package is licensed under [MIT](https://opensource.org/license/mit). diff --git a/packages/preview/obsidius/0.2.0/lib.typ b/packages/preview/obsidius/0.2.0/lib.typ new file mode 100644 index 0000000000..00ca040598 --- /dev/null +++ b/packages/preview/obsidius/0.2.0/lib.typ @@ -0,0 +1,238 @@ +// use tailwind colors: text 700, fill 100, stroke 300 +#let twColors = ( + red: (oklch(50.5%, 0.213, 27.518deg), oklch(93.6%, 0.032, 17.717deg), oklch(80.8%, 0.114, 19.571deg)), + orange: (oklch(55.3%, 0.195, 38.402deg), oklch(95.4%, 0.038, 75.164deg), oklch(83.7%, 0.128, 66.29deg)), + yellow: (oklch(55.4%, 0.135, 66.442deg), oklch(97.3%, 0.071, 103.193deg), oklch(90.5%, 0.182, 98.111deg)), + green: (oklch(52.7%, 0.154, 150.069deg), oklch(96.2%, 0.044, 156.743deg), oklch(87.1%, 0.15, 154.449deg)), + teal: (oklch(51.1%, 0.096, 186.391deg), oklch(95.3%, 0.051, 180.801deg), oklch(85.5%, 0.138, 181.071deg)), + sky: (oklch(50%, 0.134, 242.749deg), oklch(95.1%, 0.026, 236.824deg), oklch(82.8%, 0.111, 230.318deg)), + blue: (oklch(48.8%, 0.243, 264.376deg), oklch(93.2%, 0.032, 255.585deg), oklch(80.9%, 0.105, 251.813deg)), + purple: (oklch(49.6%, 0.265, 301.924deg), oklch(94.6%, 0.033, 307.174deg), oklch(82.7%, 0.119, 306.383deg)), + gray: (oklch(37.3%, 0.034, 259.733deg), oklch(96.7%, 0.003, 264.542deg), oklch(87.2%, 0.01, 258.338deg)), +) + +#let fonts = ( + sans: "Noto Sans", + mono: "Noto Sans Mono", + serif: "Noto Sans Serif", + math: "" +) + +#let emptyblock((fontcolor, bgcolor, bordercolor), width: 100%, height: auto, content) = { + set text(fill: fontcolor) + block(width: width, height: height, inset: (x: 0.75em, y: 0.5em), radius: 0.5em, breakable: false, + fill: bgcolor, stroke: (paint: bordercolor, thickness: 1pt), content) +} + +#let callout(icon, title, content, colors) = { + emptyblock(colors, + [ + #heading(outlined: false, numbering: none, depth: 3, { + box(text(font: "Material Symbols Outlined", icon), baseline: 1pt) + h(2pt) + title + }) + + #content + ]) +} + +#let inactive-text-color = rgb("#98A1AE") + +#let getCurrentHeader(lvl) = { + query(heading.where(level: lvl).after(here()) + .or(heading.where(level: lvl).before(here()))) + .sorted( + key: h => h.location().page(), + by: (l, r) => { + let diffL = here().page() - l; + if diffL < 0 { + // if it's negative, the header comes after here(). + // we give that a lower priority than headers before here() + // this breaks after 1 000 000 pages, but that should be fine + diffL = calc.abs(diffL) + 1000000 + } + let diffR = here().page() - r; + if diffR < 0 { + diffR = 100 * calc.abs(diffR) + } + diffL <= diffR + }) + .at(0, default: (body: [])) +} + +// callout definitions + +#let addTitle(title) = if title != [] { + ": " + title +} else [] + + +#let note(content) = callout("comment", [Note], content, twColors.gray) + +#let summary(content) = callout("summarize", [Summary], content, twColors.teal) + +#let fact(content) = callout("info", "Fact", content, twColors.sky) + +// todo + +// hint + +#let solution(content, title: []) = callout("check", if title == [] {"Solution"} else {title}, content, twColors.green) + +#let idea(content, title: []) = callout("lightbulb", [Idea#addTitle(title)], content, twColors.yellow) + +#let question(content, title: []) = callout("question_mark", [Question#addTitle(title)], content, twColors.orange) + +#let warning(content) = callout("warning", "Warning", content, twColors.orange) + +#let problem(content, title: []) = callout("dangerous", [Problem#addTitle(title)], content, twColors.red) + +#let example(content, title: []) = callout("edit", [Example#addTitle(title)], content, twColors.purple) + + +// useful to show code including math content +#let code(title, body, params: none) = { + set text(font: "JetBrains Mono") + callout("code", title, [ + #if params != none [ + *Input:* #params.input \ + *Output:* #params.output + + #line(length: 100%, stroke: (paint: oklch(55.1%, 0.027, 264.364deg), dash: "dashed")) + ] + + #body + ], + twColors.gray) +} + +// compare two things side by side +#let compare(..args) = { + // assumes even number of arguments + let half-args = calc.div-euclid(args.len(), 2) + grid(columns: half-args, gutter: 1em, + ..for i in range(args.len()) { + if i >= half-args { + continue + } + (emptyblock((black, none, twColors.gray.at(2)), [ + #{ + set align(center) + heading(args.at(i), outlined: false, numbering: none, depth: 3) + } + #args.at(i + half-args) + ]),) + } + ) +} + +#let good-bad(good, bad) = { + grid(columns: 2, gutter: 1em, + callout("check", [Pro], good, twColors.green), + callout("close", [Con], bad, twColors.red) + ) +} + +#let questions(body) = { + set text(fill: inactive-text-color) + [ + *Questions* + #body + ] +} + +#let notes(title, content) = { + // meta information + set document(title: title) + + // page layout and style + set page(numbering: "1", header: context { + // get the current header on level 1 + let h = getCurrentHeader(1) + + + set text(fill: inactive-text-color) + set align(center) + emph([ + #document.title + #if h.body != [] [/] + #h.body + ]) + }) + + set text(font: fonts.sans) + + set heading(numbering: "1.1") + show heading: set text(weight: "extrabold") + show heading.where(level: 1): it => { + pagebreak(weak: true) + it + } + + show figure.caption: set text(rgb("#98A1AE")) + + show ref: it => { + set text(fill: inactive-text-color) + [_(see #it)_] + } + show terms.item: it => { + callout("book_2", it.term, it.description, + twColors.sky) + } + + set quote(block: true) + show quote.where(block: true): it => { + let title = if it.attribution == none [ + Quote + ] else { + it.attribution + } + + callout("format_quote", title, it.body, twColors.gray) + } + + set table(stroke: rgb("#E4E6EB") + 0.5pt, fill: (_, y) => if calc.odd(y){ rgb("#F9F9FB") }) + show table.cell.where(y: 0): set text(weight: "bold") + show table: set align(start) + + show raw: set text(font: fonts.mono) + show raw.where(block: true): it => { + emptyblock(twColors.gray, { + place(top+right, text(font: fonts.sans, fill: inactive-text-color, it.lang)) + + show raw.line: line => { + if line.number < 10 { + text(fill: gray)[$" "$#line.number] + } else { + text(fill: gray)[#line.number] + } + h(1em) + line.body + } + it + }) + } + + show image: i => { + block(clip: true, radius: 0.5em, stroke: twColors.gray.at(2), i) + } + + show link: url => { + set text(stretch: 90%) + underline(url) + /* + " " + emoji.globe.meridian + */ + } + + + if fonts.math != "" { + show math.equation: set text(font: fonts.math) + } + + content +} + diff --git a/packages/preview/obsidius/0.2.0/sample/sample.pdf b/packages/preview/obsidius/0.2.0/sample/sample.pdf new file mode 100644 index 0000000000..d71478bc3f Binary files /dev/null and b/packages/preview/obsidius/0.2.0/sample/sample.pdf differ diff --git a/packages/preview/obsidius/0.2.0/sample/sample.png b/packages/preview/obsidius/0.2.0/sample/sample.png new file mode 100644 index 0000000000..504a84cf29 Binary files /dev/null and b/packages/preview/obsidius/0.2.0/sample/sample.png differ diff --git a/packages/preview/obsidius/0.2.0/sample/sample.typ b/packages/preview/obsidius/0.2.0/sample/sample.typ new file mode 100644 index 0000000000..753d157191 --- /dev/null +++ b/packages/preview/obsidius/0.2.0/sample/sample.typ @@ -0,0 +1,138 @@ +#import "@preview/obsidius:0.2.0": * + +#show: notes.with("Template summary"); + += Overview + +Here is a simple step-by-step guide on how to use this template: + ++ Create a new document `mynotes.typ` with the following content: + ```typst + #import "lib.typ": * + + #show: notes.with("Your fancy title"); + ``` ++ Write your normal typst notes ++ Use additional feature such as callouts ++ Have fun #emoji.party + +== Standard functionality + +/ Template: a preset format for a document or file. + +With this template, you can write notes with a modern style. +It features sans-serif fonts and *callouts* for quotes and definitions. +Colors are based on the tailwind color scheme. +The style is heavily inspired by Obsidian #footnote[https://obsidian.md/]. The callout feature is also borrowed from them. +You can also add #highlight[callouts] to your document, instructions are below @custom. + +#quote(attribution: "The author, 2025")[ +I use this template to summarize my lectures at university. It is so great. +] + +Tables feature a custom style as well: + +#figure(caption: "Feature overview", +table(columns: (auto, auto, auto), + table.header([Feature], [Default], [This template]), + [Modern style], [#emoji.crossmark], [#emoji.checkmark.box], + [Colorful boxes], [#emoji.crossmark], [#emoji.checkmark.box], +)) + +== Additional functions + +In addition to the default functions @default, you also get additional callouts for _warnings_, _solutions_ and more! @callouts + +#warning[ + Once you started using this template, you can never stop! +] + +#solution[ + Attend the lectures to use it even more often! +] + +You can also include questions to help learn the lecture content: + +#questions[ + + How do I use the notes template? + + What additional functions does the notes template provide? +] + +You can compare two things: + +#compare[A][B][ +- more features +- more complicated +][ +- not all features in there +- simpler to use +] + +You can also write pseudo code including math content: + +#code(params: ( + input: [side lengths a and b as float], + output: [area as float] +))[Get area][ ++ #lorem(5) ++ return $A = a times b$ +] + +== Custom callouts + +Feel free to add your own custom callouts to your document if you need more. +To keep the colors consistent, I recommend using colors from the Tailwind color scheme #footnote[https://tailwindcss.com/docs/colors]. +For example, you could add a todo callout and use it together with the _cheq_ package #footnote[https://typst.app/universe/package/cheq]: + +```typst +#import "@preview/cheq:0.2.2": checklist + +#show: checklist.with(stroke: rgb("#6F05E7")) + +#let todo(content) = { + callout("checklist", "ToDo", content, + (rgb("#6F05E7"), rgb("#EDE8FD"), rgb("#C4B3FF"))) // hint: use tailwind colors 700, 100, 300 +} + +#todo[ + - [x] show how to create custom color boxes + - [ ] create more functions +] +``` + +Which would look like this: + +#import "@preview/cheq:0.2.2": checklist + +#show: checklist.with(stroke: rgb("#6F05E7")) + +#let todo(content) = { + callout("checklist", "ToDo", content, + (rgb("#6F05E7"), rgb("#EDE8FD"), rgb("#C4B3FF"))) +} +#todo[ + - [x] #lorem(5) + - [ ] #lorem(7) +] + += List of all available callouts + +#let text = lorem(20) + +#note(text) + +#summary(text) + +#fact(text) + +#solution(text) + +#idea(text) + +#question(text) + +#warning(text) + +#problem(text) + +#example(text) diff --git a/packages/preview/obsidius/0.2.0/template/main.typ b/packages/preview/obsidius/0.2.0/template/main.typ new file mode 100644 index 0000000000..9f8d084169 --- /dev/null +++ b/packages/preview/obsidius/0.2.0/template/main.typ @@ -0,0 +1,6 @@ +#import "@preview/obsidius:0.2.0": * + +// change the title of the document here +#show: notes.with("My notes"); + +Now just start writing! diff --git a/packages/preview/obsidius/0.2.0/typst.toml b/packages/preview/obsidius/0.2.0/typst.toml new file mode 100644 index 0000000000..06be938959 --- /dev/null +++ b/packages/preview/obsidius/0.2.0/typst.toml @@ -0,0 +1,16 @@ +[package] +name = "obsidius" +version = "0.2.0" +entrypoint = "lib.typ" +authors = ["Lorenz Hoffmann <@l0drex>"] +license = "MIT" +description = "Modern template for study notes." +repository = "https://github.com/l0drex/obsidius" +keywords = ["Obsidian", "notes", "study", "university"] +categories = ["report", "components"] +exclude = ["sample/"] + +[template] +path = "template" +entrypoint = "main.typ" +thumbnail = "sample/sample.png"