diff --git a/packages/preview/texst/0.1.0/LICENSE b/packages/preview/texst/0.1.0/LICENSE new file mode 100644 index 0000000000..0256c5aed7 --- /dev/null +++ b/packages/preview/texst/0.1.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Shusuke Ioku + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +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 OR COPYRIGHT HOLDERS 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. diff --git a/packages/preview/texst/0.1.0/README.md b/packages/preview/texst/0.1.0/README.md new file mode 100644 index 0000000000..5e4345c5ac --- /dev/null +++ b/packages/preview/texst/0.1.0/README.md @@ -0,0 +1,129 @@ +# texst + +`TeXst` is a Typst package for LaTeX-like academic paper formatting. + +## Start Here + +Use one of these package imports: + +1. Published package (Typst Universe): + +```typst +#import "@preview/texst:0.1.0": paper +``` + +2. Local package install: + +```typst +#import "@local/texst:0.1.0": paper +``` + +## Manual Install (No `@preview`) + +If you download the repo manually, you can install it as a local Typst package: + +1. Download and unzip this repository. +2. Copy its contents into this folder structure: + - macOS: `~/Library/Application Support/typst/packages/local/texst/0.1.0/` + - Linux: `~/.local/share/typst/packages/local/texst/0.1.0/` + - Windows: `%APPDATA%\\typst\\packages\\local\\texst\\0.1.0\\` +3. Import from `@local` in your Typst file: + +```typst +#import "@local/texst:0.1.0": paper +``` + +## Fastest Way to Use It + +Copy this into your `main.typ`: + +```typst +#import "@preview/texst:0.1.0": paper + +#show: doc => paper( + title: [Paper Title], + subtitle: [Optional Subtitle], + authors: ( + (name: [Author One]), + (name: [Author Two]), + ), + date: datetime.today().display("[month repr:long] [day], [year]"), + abstract: [Write a concise abstract here.], + doc, +) + +#outline(title: [Contents]) + +#heading(level: 1)[Introduction] + +Start writing your paper. + +#heading(level: 1)[Appendix] + +#heading(level: 2)[Additional Material] + +Add supplementary details here. +``` + +## Initialize a Template Project + +```bash +typst init @preview/texst:0.1.0 +``` + +This generates a starter project from `template/main.typ`. + +## What `paper(...)` Does + +`paper(...)` applies: +- page layout and numbering +- typography defaults +- heading style and spacing +- table/figure alignment and numbering +- equation and reference behavior +- title block and abstract formatting + +Your document content is passed through `doc`. + +## Public API + +- `paper(title:, subtitle:, authors:, date:, abstract:, style:, doc)` +- `nneq(eq)` (unnumbered display equation) +- `caption-note(body)` +- `caption-with-note(title, note)` +- `table-note(body)` +- `theorem`, `proof`, `prop`, `lem`, `rem`, `asp` + +## Style Overrides + +Pass a `style` dictionary to override defaults: + +```typst +#show: doc => paper( + title: [Styled Paper], + style: ( + body_font: "Libertinus Serif", + page_margin: (x: 1in, y: 1in), + heading_numbering: "1.", + accent_main: rgb(20, 40, 120), + ), + doc, +) +``` + +Common keys include: +- `page_margin`, `page_numbering` +- `body_font`, `body_size` +- `paragraph_leading`, `paragraph_indent` +- `heading_numbering`, `heading_size`, `heading_weight` +- `footnote_numbering`, `accent_main` + +## Local Development + +- `examples/minimal.typ` is the local smoke test. +- `template/main.typ` is the package template entrypoint. +- Compile locally: + +```bash +typst compile --root . examples/minimal.typ /tmp/minimal.pdf +``` diff --git a/packages/preview/texst/0.1.0/src/lib.typ b/packages/preview/texst/0.1.0/src/lib.typ new file mode 100644 index 0000000000..97d4a62060 --- /dev/null +++ b/packages/preview/texst/0.1.0/src/lib.typ @@ -0,0 +1,223 @@ +#import "@preview/ctheorems:1.1.3": * +#import "@preview/cetz:0.4.2" + +// ============================================================================= +// BASIC SETTINGS (edit here) +// ============================================================================= +#let page-margin = (x: 1.2in, y: 1.2in) +#let page-numbering = "1" + +#let body-font = "New Computer Modern" +#let body-size = 11pt +#let body-top-edge = 0.7em +#let body-bottom-edge = -0.3em + +#let par-leading = 1em +#let par-first-indent = 1.8em + +#let heading-numbering = "1." +#let heading-size = 1em +#let heading-weight = "bold" +#let heading-level1-size = 0.9em + +#let table-text-size = 0.8em +#let table-leading = 0.65em +#let table-top-edge = 0.35em +#let table-bottom-edge = -0.3em + +#let block-above = 1.5em +#let block-below = 1.5em + +#let footnote-numbering = "[1]" + +#let cmain = rgb(0,0,100) +#let csub = rgb("#8b0000") + +// ============================================================================= +// UTILITIES +// ============================================================================= +#let nneq(eq) = math.equation(block: true, numbering: none, eq) +#let caption-note(body) = align(left)[ + #pad(x: 2em, y: 0em)[ + #par(leading: 0.2em)[ + #text(size: 0.9em)[*Note:* #body] + ] + ] +] +#let caption-with-note(title, note) = [#title #caption-note(note)] +#let table-note(body) = align(left)[ + #text(size: 0.9em)[#emph(body)] +] + +#show: thmrules.with(qed-symbol: $square$) +#let theorem = thmbox("theorem", "Theorem") +#let proof = thmproof( + "proof", "Proof" +) +#let prop = thmbox( + "prop", + "Proposition", + inset: (x:2em, y:.5em), + base_level: 0, + base: "prop", + titlefmt: smallcaps, + bodyfmt: body => [ + #body + ] +).with(numbering: "1") +#let lem = thmbox( + "lem", + "Lemma", + inset: (x:2em, y:.5em), + base_level: 0, + base: "lem", + titlefmt: smallcaps, + bodyfmt: body => [ + #body + ] +).with(numbering: "1") +#let rem = thmbox( + "rem", + "Remark", + inset: (x:2em, y:.5em), + base_level: 0, + base: "rem", + titlefmt: smallcaps, + bodyfmt: body => [ + #body + ] +).with(numbering: "1") +#let ass = thmbox( + "ass", + "Assumption", + inset: (x:2em, y:.5em), + base_level: 0, + base: "ass", + titlefmt: smallcaps, + bodyfmt: body => [ + #body + ] +).with(numbering: "1") + +#let paper( + title: none, + subtitle: none, + authors: (), + date: none, + abstract: none, + doc, +) = { + set page( + margin: page-margin, + numbering: page-numbering + ) + + set par( + leading: par-leading, + first-line-indent: par-first-indent, + justify: true + ) + + set text( + font: body-font, + size: body-size, + top-edge: body-top-edge, + bottom-edge: body-bottom-edge + ) + + set math.equation(numbering: "(1)") + set table(align: (x, _) => if x == 0 { left } else { center }) + set figure(numbering: "1") + show ref: it => { + let eq = math.equation + let el = it.element + if el != none and el.func() == eq { + // Override equation references. + numbering( + el.numbering, + ..counter(eq).at(el.location()) + ) + } else { + // Other references as usual. + it + } + } + + set bibliography(style: "american-political-science-association") + show bibliography: set par(first-line-indent: 0em) + + set quote(block: true) + + set heading(numbering: heading-numbering) + show heading: set block(above: 2em, below: 1em) + show heading: set par(leading: 0.3em) + show heading: set text(size: heading-size, weight: heading-weight) + //show heading: set text(font: "PT Sans", weight: "bold") + // Center first level headings only + show heading: it => { + if it.level == 1 { + smallcaps(align(center, text(size: heading-level1-size, it))) + } else { + it + } + } + + set enum(indent: 1.8em) + show enum: set block(above: 1em, below: 1em) + + show table: set text(size: table-text-size) + show table: set par(leading: table-leading) + show table: set text(top-edge: table-top-edge, bottom-edge: table-bottom-edge) + show figure: set block(below: 0em) + set block(above: block-above, below: block-below) + show figure: set align(center) + // Set all tables to be centered + show table: set align(center) + // Also center table captions + show figure.where(kind: table): set align(center) + // Center figures with tables inside them + show figure.where(body: it => { + if it.func() == table { true } else { false } + }): set align(center) + + //show figure.caption: set text(font: "PT Sans", weight: "regular") + set figure(placement: auto) + + show link: set text(rgb(0,0,100)) + show ref: set text(rgb(0,0,100)) + show cite: set text(rgb(0,0,100)) + show footnote: set text(rgb(0,0,100)) + show footnote: set text(weight:"bold") + //show footnote.entry: set par(leading: 1em) + //set footnote.entry(gap: 1em) + set footnote(numbering: footnote-numbering) + + v(4em) + set align(center) + par(leading: .5em)[#text(1.2em)[#title]\ #text(1em)[#subtitle]] + + let count = authors.len() + let ncols = calc.min(count, 3) + grid( + columns: (1fr,) * ncols, + row-gutter: 24pt, + ..authors.map(author => [ + #text(author.name) \ + //#text(0.8em, author.affiliation) \ + //#text(0.8em, link("mailto:" + author.email)) + ]), + ) + + text(date) + + set align(left) + if abstract != none { + pad(x: 3em, + par(leading: 0.4em, + text(0.9em, + [#smallcaps("Abstract.") #abstract] + ))) + } + + doc +} diff --git a/packages/preview/texst/0.1.0/template/main.typ b/packages/preview/texst/0.1.0/template/main.typ new file mode 100644 index 0000000000..71dd9d83f5 --- /dev/null +++ b/packages/preview/texst/0.1.0/template/main.typ @@ -0,0 +1,122 @@ +#import "@preview/texst:0.1.0": paper, nneq, caption-note, table-note, theorem, proof, prop, lem, rem, ass, cmain, csub, caption-with-note + +#show: doc => paper( + title: [Title], + subtitle: [Subtitle], + authors: ( + ( + name: text()[Author Name#footnote(numbering:"*")[Affiliation]], + ), + ), + date: datetime.today().display("[month repr:long] [day], [year]"), + abstract: + text()[ + This is the abstract for the paper. It summarizes the key objectives, findings, and significance of the research. The abstract provides a succinct overview, including the methodology and principal results, allowing readers to quickly grasp the purpose and contributions of the work. Replace this placeholder with your full abstract describing the context, main outcomes, and insights presented in the paper. + ], + doc, +) + +#heading(outlined: false, level: 1)[Introduction] + +This is some placeholder text for the introduction. You can replace this with your actual content. +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas in quam eu magna egestas dictum. +Aliquam erat volutpat. Nulla facilisi. Pellentesque cursus bibendum magna, quis tincidunt quam blandit sed. +Donec dapibus, nisi nec laoreet egestas, sem arcu varius leo, eget cursus nisi erat vitae nibh @tab:sample_table. + +#nneq($ + alpha = beta + gamma +$) + +#figure( + placement: none, + block(width: 80%)[ + // #columns( + // gutter: 2em, + // [ + // #image( + // "", + // width: 100%, + // alt: "Sample Photo 1" + // ) + // ], + // [ + // #image( + // "", + // width: 100%, + // alt: "Sample Photo 2" + // ) + // ] + // ) + ], + caption: [Sample figure with two column photos] +) + + +#figure( + placement: none, + block(width: 100%)[ + #set text(size: 0.8em) + #table( + columns: 7, + align: (left, center, center, center, center, center, center), + inset: (x: 5pt, y: 4pt), + stroke: none, + table.hline(stroke: 1.2pt), + [Sample Outcome:], table.cell(colspan: 6)[_Sample Measure per Unit_], + [Sample Model:], [(A)], [(B)], [(C)], [(D)], [(E)], [(F)], + table.hline(stroke: 0.7pt), + [Sample Effect 1], [$1.1111^(**)$ #linebreak() (0.0101)], [$1.2222^(**)$ #linebreak() (0.0112)], [$1.3333^(**)$ #linebreak() (0.0123)], [$1.4444^(*)$ #linebreak() (0.0134)], [$1.5555^(**)$ #linebreak() (0.0145)], [$1.6666^(**)$ #linebreak() (0.0156)], + [Sample Effect 2], [$2.1111^(***)$ #linebreak() (0.0165)], [$2.2222^(***)$ #linebreak() (0.0170)], [$2.3333^(***)$ #linebreak() (0.0181)], [$2.4444^(***)$ #linebreak() (0.0192)], [$2.5555^(***)$ #linebreak() (0.0203)], [$2.6666^(***)$ #linebreak() (0.0214)], + [Sample Covariate 1], [], [], [], [0.1010 #linebreak() (0.0222)], [$-0.2020$ #linebreak() (0.0233)], [$-0.3030$ #linebreak() (0.0244)], + [Sample Covariate 2], [], [], [], [$-0.1111$ #linebreak() (0.0137)], [0.2222 #linebreak() (0.0148)], [0.3333 #linebreak() (0.0159)], + [Sample Covariate 3], [], [], [], [$-0.4444$ #linebreak() (0.0162)], [$-0.5555$ #linebreak() (0.0173)], [$-0.6666$ #linebreak() (0.0184)], + [Sample Group 4], [], [], [], [0.5050 #linebreak() (0.0195)], [0.6060 #linebreak() (0.0206)], [0.7070 #linebreak() (0.0217)], + table.hline(stroke: 0.4pt), + [Sample Mean], [1.111], [1.222], [1.333], [1.444], [1.555], [1.666], + table.hline(stroke: 0.4pt), + [_Sample Controls_], [], [], [], [], [], [], + [Sample FE 1], [Yes], [Yes], [Yes], [Yes], [Yes], [Yes], + [Sample FE 2], [Yes], [Yes], [Yes], [Yes], [Yes], [Yes], + table.hline(stroke: 0.4pt), + [_Sample Fit Statistics_], [], [], [], [], [], [], + [Sample Observations], [123], [234], [345], [456], [567], [678], + [$R^2$], [0.777], [0.888], [0.999], [0.555], [0.666], [0.444], + [Within $R^2$], [0.111], [0.222], [0.333], [0.444], [0.555], [0.666], + table.hline(stroke: 1.2pt), + table.cell(colspan: 7, table-note([Sample note for errors in round brackets.#linebreak()Signif. Codes: $.^(***)$: 0.001, $.^(**)$: 0.01, $.^(*)$: 0.05, $.^(+)$: 0.1.])) + ) + ], + caption: caption-with-note([Sample Title], [This is a sample caption for the table, describing its structure and what the numbers represent. Replace as needed.]), +) + +#heading(outlined: false, numbering: none, level: 1)[References] + +#bibliography( + "ref.bib", + style: "american-political-science-association", + title: none +) + +#pagebreak() + +#counter(figure).update(0) +#set figure(numbering: (..n) => "A." + numbering("1", n.at(0))) + +#counter(heading).update(0) +#set heading( + numbering: "A.1.", + supplement: "Appendix" +) + +#align(center)[ + #smallcaps(text(1.2em)[*Appendix*]) +] + +#show outline.entry: it => link( + it.element.location(), + it.indented(it.prefix(), it.inner()), +) +#outline() + +#pagebreak() +#heading(level: 1)[Omitted Empirical Results] diff --git a/packages/preview/texst/0.1.0/template/ref.bib b/packages/preview/texst/0.1.0/template/ref.bib new file mode 100644 index 0000000000..f034d0688e --- /dev/null +++ b/packages/preview/texst/0.1.0/template/ref.bib @@ -0,0 +1,6 @@ +@article{example2026, + title={Example Reference}, + author={Doe, Jane}, + journal={Journal of Placeholder Studies}, + year={2026} +} diff --git a/packages/preview/texst/0.1.0/thumbnail.png b/packages/preview/texst/0.1.0/thumbnail.png new file mode 100644 index 0000000000..d257852143 Binary files /dev/null and b/packages/preview/texst/0.1.0/thumbnail.png differ diff --git a/packages/preview/texst/0.1.0/typst.toml b/packages/preview/texst/0.1.0/typst.toml new file mode 100644 index 0000000000..d8b8162199 --- /dev/null +++ b/packages/preview/texst/0.1.0/typst.toml @@ -0,0 +1,15 @@ +[package] +name = "texst" +version = "0.1.0" +entrypoint = "src/lib.typ" +authors = ["Shusuke Ioku"] +license = "MIT" +description = "LaTeX-like academic paper styling and theorem helpers for Typst." +repository = "https://github.com/shusuke-ioku/texst" +keywords = ["academic", "paper", "latex", "theorem"] +categories = ["model", "layout"] + +[template] +path = "template" +entrypoint = "main.typ" +thumbnail = "thumbnail.png"