diff --git a/packages/preview/verseatile/0.2.0/LICENSE b/packages/preview/verseatile/0.2.0/LICENSE new file mode 100644 index 0000000000..871ec2245e --- /dev/null +++ b/packages/preview/verseatile/0.2.0/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Alexander Abt + +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/verseatile/0.2.0/README.md b/packages/preview/verseatile/0.2.0/README.md new file mode 100644 index 0000000000..27e8283d20 --- /dev/null +++ b/packages/preview/verseatile/0.2.0/README.md @@ -0,0 +1,154 @@ +# verseatile + +[![Typst universe](https://img.shields.io/badge/dynamic/toml?url=https%3A%2F%2Fraw.githubusercontent.com%2Fswitchlex%2Fverseatile%2Frefs%2Fheads%2Fmain%2Ftypst.toml&query=%24.package.version&prefix=v.&logo=typst&label=Typst%20Universe&labelColor=white&color=grey)](https://typst.app/universe/package/verseatile) +[![Manual](https://img.shields.io/badge/Manual-pdf-grey?labelColor=white)](https://raw.githubusercontent.com/switchlex/verseatile/0.2.0/docs/manual.pdf) +[![License](https://img.shields.io/badge/License-MIT-grey?labelColor=white)](./LICENSE) + +verseatile is a small package for setting poetry with [Typst](https://github.com/typst/typst), capable of easily indenting and numbering verses while providing many options for customization. + +![Examples](examples/example.png) + +## Getting started + +To print a poem, simply use the #poem function: +```typst +#import "@preview/verseatile:0.2.0": * + +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, + +Piplea dulcis. Nil sine te mei \ +prosunt honores; hunc fidibus novis, \ +hunc Lesbio sacrare plectro \ +teque tuasque decet sorores. + +][0] +``` + +### Using indentpatterns + +To configure the indentation of verses provide an indentpattern (such as 0012) as the thrid argument of the #poem function: + +```typst +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, + +Piplea dulcis. Nil sine te mei \ +prosunt honores; hunc fidibus novis, \ +hunc Lesbio sacrare plectro \ +teque tuasque decet sorores. + +][0012] +``` + +### Numbering verses + +To display verse numbers toggle #show-verse-numbers: + +```typst +#show-verse-numbers.update(true) +``` + +Verse numbers can also be set to number only every $n$-th verse: + +```typst +#verse-number-modulo.update(2) +``` + +### Using presets + +Presets are preconfigured style sets that can be used for simple and effective styling. To apply a preset use: + +```typst +#show: preset-〈name〉 +``` + +As of v.0.2.0 the following presets are included with the package: + +- `classic` + - `classic-headings` + +### Putting it all together + +Utilizing both the indentpattern and numbering verses while applying a preset, one might arrive at this simple, yet elegant rendition of our poem shown on the left in the [example image](examples/example.png) at the top of the page: + +```typst +#import "@preview/verseatile:0.2.0": * + +#show: preset-classic + +#show-verse-numbers.update(true) +#verse-number-modulo.update(2) + +#poem[Hor. carm. i, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, + +Piplea dulcis. Nil sine te mei \ +prosunt honores; hunc fidibus novis, \ +hunc Lesbio sacrare plectro \ +teque tuasque decet sorores. + +][0012] +``` + +## Advanced usage +For advanced usage such as inline poemtitles, interjections, dedications, splitting verses, setting cycles of poems as well as detailed options for customization confer the [manual](docs/manual.pdf). + +## Changelog + +### v.0.2.0 + +- New features: + - Added presets. + - Added interjections and dedications. + - Added functionality to split verses via `#splitverse[]` and `#versesplit`. + - Added subtitles for cycles and poems in cycles. + - Made the indentation of the first verse of a stanza configurable via `#stanza-indent.update()`. + - Made the starting verse number configurable via `#verse-numbers-start.update()`. +- Presets: + - Added presets (`classic`, `classic-headings`). +- Fixes: + - Reworked inline poemtitles to prevent false headings being displayed in the outline in certain constellations. +- Documentation: + - Updated the manual. + - Updated the readme. + +### v.0.1.1 + +- New features: + - Made the distance between verse numbers and the poem configurable via `#verse-number-distance.update()`. +- Fixes: + - Reworked verse numbers to prevent them causing issues with indentation in certain constellations. +- Documentation: + - Updated the manual. + +### v.0.1.0 + +Initial release. diff --git a/packages/preview/verseatile/0.2.0/docs/manual.pdf b/packages/preview/verseatile/0.2.0/docs/manual.pdf new file mode 100644 index 0000000000..eaa75eaabd Binary files /dev/null and b/packages/preview/verseatile/0.2.0/docs/manual.pdf differ diff --git a/packages/preview/verseatile/0.2.0/docs/manual.typ b/packages/preview/verseatile/0.2.0/docs/manual.typ new file mode 100644 index 0000000000..9b3b95894e --- /dev/null +++ b/packages/preview/verseatile/0.2.0/docs/manual.typ @@ -0,0 +1,737 @@ +#import "@preview/mantys:1.0.2": * +#import "@local/verseatile:0.2.0": * + +#show: mantys( + name: "verseatile", + version: "0.2.0", + authors: ( + "by Alexander Abt", + ), + license: "MIT", + description: "Easily set poetry.", + repository: "https://github.com/switchlex/verseatile", + title: "verseatile", + abstract: [ + verseatile is a small package for setting poetry with Typst, capable of easily indenting and numbering verses while providing many options for customization. + ], + theme: themes.default +) + +#set text(size: 11pt) + +#let preset-card = { + show-verse-numbers.update(true) + always-align-poemtitle.update(false) + move(dx: 15pt)[ + #grid(columns: 2, column-gutter: 30pt, + {cycle[Cycletitle][Cyclesubtitle][ + + #poem-incycle[Poemtitle-incycle][Poemsubtitle-incycle][ + + numbered-verse + + #interjection[Interjection] + + numbered-verse + + ][0]]}, + {poem[Poemtitle][ + + #dedication[Dedication] + + numbered-verse + + ][0] + poem[][ + + #inline-poemtitle[inline-poemtitle] rest-of-verse + + ][0]})]} + += Setting poems + +== Getting Started + +To print a poem simply use the @cmd:poem function: + +#command("poem", arg("poemtitle"), arg("poembody"), arg("indentpattern"))[ + #argument("poemtitle", types:("content"))[ + The poem's title. + ] + #argument("poembody", types:("content"))[ + The poem itself --- The end of a verse must be marked with »#sym.backslash«. The end of a stanza however must not be marked with »#sym.backslash« but with an empty line. + ] + #warning-alert[#icons.warning Note that (as of v.0.2.0) the #arg("poembody") must also start with an empty line for indentation and verse numbers to properly work.] + #argument("indentpattern", types:("content"))[ + Specification for the indentation of verses --- If no line in the poem is to be specially indented this should be 0. For advanced use of indentpatterns see @indentpatterns. + ] +] + +A first example might look like this: + +#side-by-side[ +```typ +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0] +```][ +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0] +] + +#pagebreak() + +== Inline poemtitles + +If #arg("poemtitle") is left empty, a part of the first verse can be set as an inline poemtitle using the @cmd:inline-poemtitle function: + +#command("inline-poemtitle", arg("part-of-verse"))[] + +Inline poemtitles can also be useful for advanced styling (see @advanced-styling). When using them the first verse will by default be printed at the same height that it would have been, if there was a normal (one line) #arg("poemtitle"). This can however be changed. + +#variable("always-align-poemtitle", types:("bool",), value: true)[ + This can be configured by using: + #side-by-side[ + ```typ + #always-align-poemtitle.update() + ``` + ][#align(right)[Default: `true`]] +] + +An example of using an inline poemtitle without alignment might look like this: + +#side-by-side[ +```typ +#always-align-poemtitle.update(false) + +#poem[][ + +#inline-poemtitle[Musis amicus] + tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0] +```][ +#always-align-poemtitle.update(false) + +#poem[][ + +#inline-poemtitle[Musis amicus] + tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0] +] + +#pagebreak() + +== Indentation + +By default all verses are indented in relation to the poemtitle. + +#variable("base-indent", types:("length",), value: 1em)[ + This can be configured by using: + #side-by-side[ + ```typ + #base-indent.update() + ``` + ][#align(right)[Default: `1em`]] +] + +=== stanza-indent + +Special indentation for the first verse in each stanza can also be added. + +#variable("stanza-indent", types:("length",), value: 0em)[ + This can be configured by using: + #side-by-side[ + ```typ + #stanza-indent.update() + ``` + ][#align(right)[Default: `0em`]] +] + +=== indentpatterns + +An #arg("indentpattern") specifies how the verses of the #arg("poembody") for a given poem are to be indented. It consist of a series of numbers demarking the level of indentation and is repeatedly applied. With every level (starting from $0$) the verse is incrementally indented by the same space. + +#variable("verse-indent", types:("length",), value: 1em)[ + This can be configured by using: + #side-by-side[ + ```typ + #verse-indent.update() + ``` + ][#align(right)[Default: `1em`]] +] + +An example of indenting every third line of the poem to the first and every fourth line to the second level by using an #arg("indentpattern") might look like this: + +#side-by-side[ +```typ +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0012] +```][ +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0012] +] + +#pagebreak() + +== Numbering verses + +Verse numbers can be displayed by using: + +#side-by-side[ + ```typ + #show-verse-numbers.update(true) + ``` +][#align(right)[Default: `false`]] + +They are placed at a configurable distance from the leftmost border of the #arg("poembody"). + +#variable("verse-number-distance", types:("length",), value: 5pt)[ + This can be configured by using: + #side-by-side[ + ```typ + #verse-number-distance.update() + ``` + ][#align(right)[Default: `5pt`]] +] + +By default verse numbers start at $1$. This can however be changed. + +#variable("verse-number-start", types:("int",), value: 1)[ + This can be configured by using: + #side-by-side[ + ```typ + #verse-number-start.update() + ``` + ][#align(right)[Default: `1`]] +] + +They can be configured so that only every $n$-th verse number will be displayed. + +#variable("verse-number-modulo", types:("int",), value: 1)[ + This can be configured by using: + #side-by-side[ + ```typ + #verse-number-modulo.update() + ``` + ][#align(right)[Default: `1`]] +] + +An example of displaying verse numbers for every second verse might look like this: + +#side-by-side[ +```typ +#show-verse-numbers.update(true) +#verse-number-modulo.update(2) + +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0012] +```][ +#show-verse-numbers.update(true) +#verse-number-modulo.update(2) + +#poem[Hor. carm. I, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +rex gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, ... + +][0012] +] + +#pagebreak() + +== Using interjections + +=== interjections + +Interjections can be placed at any point in the #arg("poembody"). They are not counted as verses, will be rendered with normal spacing and can be useful for advanced styling (see @advanced-styling). + +#warning-alert[#icons.warning Note that (as of v.0.2.0) a line interjections must not be followed with »\\«.] + +An example of interjected strophe- and antistrophe markings might look like this: + +#side-by-side[ +```typ +#show-verse-numbers.update(true) +#verse-number-start.update(176) +#verse-number-modulo.update(2) + +#poem-incycle[Aischyl. Ag. 176--191][ + +#interjection[στρ. γ.] + +τὸν φρονεῖν βροτοὺς ὁδώ- \ +σαντα, τὸν πάθει μάθος \ +θέντα κυρίως ἔχειν. \ +στάζει δʼ ἔν θʼ ὕπνῳ πρὸ καρδίας \ +μνησιπήμων πόνος· καὶ παρʼ ἄ- \ +κοντας ἦλθε σωφρονεῖν. \ +δαιμόνων δέ που χάρις βίαιος \ +σέλμα σεμνὸν ἡμένων. + +#interjection[ἀντ. γ.] + +καὶ τόθʼ ἡγεμὼν ὁ πρέ- \ +σβυς νεῶν Ἀχαιικῶν, \ +μάντιν οὔτινα ψέγων, \ +ἐμπαίοις τύχαισι συμπνέων, \ +εὖτʼ ἀπλοίᾳ κεναγγεῖ βαρύ- \ +νοντʼ Ἀχαιικὸς λεώς, \ +Χαλκίδος πέραν ἔχων παλιρρόχ- \ +θοις ἐν Αὐλίδος τόποις· + +][0] +```][ +#show-verse-numbers.update(true) +#verse-number-start.update(176) +#verse-number-modulo.update(2) + +#move(dx:15pt)[ + +#poem-incycle[Aischyl. Ag. 176--191][ + +#interjection[στρ. γ.] + +τὸν φρονεῖν βροτοὺς ὁδώ- \ +σαντα, τὸν πάθει μάθος \ +θέντα κυρίως ἔχειν. \ +στάζει δʼ ἔν θʼ ὕπνῳ πρὸ καρδίας \ +μνησιπήμων πόνος· καὶ παρʼ ἄ- \ +κοντας ἦλθε σωφρονεῖν. \ +δαιμόνων δέ που χάρις βίαιος \ +σέλμα σεμνὸν ἡμένων. + +#interjection[ἀντ. γ.] + +καὶ τόθʼ ἡγεμὼν ὁ πρέ- \ +σβυς νεῶν Ἀχαιικῶν, \ +μάντιν οὔτινα ψέγων, \ +ἐμπαίοις τύχαισι συμπνέων, \ +εὖτʼ ἀπλοίᾳ κεναγγεῖ βαρύ- \ +νοντʼ Ἀχαιικὸς λεώς, \ +Χαλκίδος πέραν ἔχων παλιρρόχ- \ +θοις ἐν Αὐλίδος τόποις· + +][0]] +] + +=== dedications + +Dedications work very similar to interjections. They can placed at the beginning of the #arg("poembody"), will be rendered with apropriate spacing (see @spacing) and can be useful for advanced styling (see @advanced-styling). + +#command("dedication", arg("part-of-verse"))[] + +An dedicated example poem might look like this: + +#side-by-side[ +```typ +#poem[Cat. carm. 1][ + +#dedication[ad Cornelium] + +Cui dono lepidum novum libellum \ +arido modo pumice expolitum? \ +Corneli, tibi; namque tu solebas \ +meas esse aliquid putare nugas, \ +iam tum cum ausus es unus Italorum \ +omne aevum tribus explicare chartis, \ +doctis, Iuppiter, et laboriosis! \ +quare habe tibi quidquid hoc libelli \ +qualecumque, quod, o patrona virgo, \ +plus uno maneat perenne saeclo. + +][0] +```][ +#show-verse-numbers.update(false) + +#poem[Cat. carm. 1][ + +#dedication[ad Cornelium] + +Cui dono lepidum novum libellum \ +arido modo pumice expolitum? \ +Corneli, tibi; namque tu solebas \ +meas esse aliquid putare nugas, \ +iam tum cum ausus es unus Italorum \ +omne aevum tribus explicare chartis, \ +doctis, Iuppiter, et laboriosis! \ +quare habe tibi quidquid hoc libelli \ +qualecumque, quod, o patrona virgo, \ +plus uno maneat perenne saeclo. + +][0] +] + +#pagebreak() + +== Splitting verses + +#error-alert[#icons.warning Note that (as of v.0.2.0) verse numbers for split verses will only be counted and displayed correctly if they are used within the same stanza!] + +Single verses can be split over multiple lines by using the @cmd:splitverse and @cmd:versesplit functions. To split a verse into two parts the first part must be wrapped by the former: + +#command("splitverse", arg("part-of-verse"))[] + +#warning-alert[#icons.warning Note that (as of v.0.2.0) a line using the @cmd:splitverse function must be followed with »\\«.] + +The second part in the following line must then be preceeded by a call of the latter: + +#command("versesplit")[] + +To split a verse into multiple parts, wrap every part before the last in the @cmd:splitverse function and preceed only the last by a call of @cmd:versesplit. + +An example of splitting a verse into three parts might look like this: + +#example[ +```typ +#show-verse-numbers.update(true) + +#poem[Cat. carm. 85][ + +#splitverse[Odi et amo.] \ +#splitverse[quare id faciam,] \ +#versesplit fortasse requiris. \ +nescio, sed fieri sentio et excrucior. + +][01] +```][ +#show-verse-numbers.update(true) +#verse-number-modulo.update(1) +#verse-number-start.update(1) + +#move(dx: 15pt)[ + +#poem[Cat. carm. 85][ + +#splitverse[Odi et amo.] \ +#splitverse[quare id faciam,] \ +#versesplit fortasse requiris. \ +nescio, sed fieri sentio et excrucior. + +][01]] +] + += Setting cycles + +Cycles of multiple poems can be printed by using the @cmd:cycle function: + +#command("cycle", arg("cycletitle"), arg("..cyclesubtitle"), arg("cyclebody"))[ + #argument("cycletitle", types:("content"))[ + The cycle's title. + ] + #argument("..cyclesubtitle", types:("content"))[ + The cycle's subtitle --- Cycles _can_ be given subtitles for advanced sytling (see @advanced-styling); this does not need be specified. By default it is rendered directly behind the #arg("cycletitle"). + ] + #argument("cyclebody", types:("content"))[ + The poems belonging to the cycle --- see @cmd:poem-incycle. + ] +] + +The poems belonging to the cycle are then printed by using the @cmd:poem-incycle function inside the #arg("cyclebody"): + +#command("poem-incycle", arg("poemtitle"), arg("..poemsubtitle"), arg("poembody"), arg("indentpattern"))[ + #argument("poemtitle", types:("content"))[ + The poem's title. + ] + #argument("..poemsubtitle", types:("content"))[ + The poem's subtitle --- Poems in cycles _can_ be given subtitles for advanced sytling (see @advanced-styling); this does not need be specified. By default it is rendered directly behind the #arg("poemtitle"). + ] + #argument("poembody", types:("content"))[ + The poem itself --- see @cmd:poem. + ] + #argument("indentpattern", types:("content"))[ + Specification for the indentation of verses --- see @cmd:poem and @indentpatterns. + ] +] + +An example of a cycle might look like this: + +#example[ +```typ +#cycle[Martialis epigrammata][(XIV, 45 ff.)][ + +#poem-incycle[XLV.][Pila paganica][ + +Haec quae difficili turget paganica pluma, \ +Folle minus laxast et minus arta pila. + +][01] + +#poem-incycle[XLVI.][Pila trigonalis][ + +Si me nobilibus scis expulsare sinistris, \ +Sum tua. Tu nescis? rustice, redde pilam. + +][01] + +#poem-incycle[XLVII.][Follis][ + +Ite procul, iuvenes: mitis mihi convenit aetas: \ +Folle decet pueros ludere, folle senes. + +][01] +```][ +#show-verse-numbers.update(false) + +#cycle[Martialis epigrammata][(XIV, 45 ff.)][ + +#poem-incycle[XLV.][Pila paganica][ + +Haec quae difficili turget paganica pluma, \ +Folle minus laxast et minus arta pila. + +][01] + +#poem-incycle[XLVI.][Pila trigonalis][ + +Si me nobilibus scis expulsare sinistris, \ +Sum tua. Tu nescis? rustice, redde pilam. + +][01] + +#poem-incycle[XLVII.][Follis][ + +Ite procul, iuvenes: mitis mihi convenit aetas: \ +Folle decet pueros ludere, folle senes. + +][01]] +] + += Styling options + +== Using presets + +Presets are preconfigured style sets that can be used for simple and effective styling. A preset can be applied by using: + +#side-by-side[ + ```typ + #show: preset-〈name〉 + ``` +][] + +As of v.0.2.0 the following presets are included with the package: + +=== classic + +#example[ +```typ +#show: preset-classic +```][ +#show: preset-classic +#preset-card +] + +==== classic-headings + +#example[ + ```typst + #show: preset-classic-headings + ```][ + Based on the `classic` preset with titles of poems and cycles being rendered as second- and poemtitles in cycles being rendered as third-level headings. + ] + +== Advanced sytling + +=== Spacing + +Most spacing is controlled by setting the vertical space between the #arg("poemtitle") and the #arg("poembody") which is predefined to scale with the document's text size. + +#variable("v-after-poemtitle", types:("length",), value: 20em)[ + #side-by-side[ + ```typ + #v-after-pormtitle.update() + ``` + ][#align(right)[Default: `20em` at `11pt`]] +] + +The vertical space following the #arg("cycletitle") will also equal #var("v-after-poemtitle") while vertical space following the poemtitles in the cycle will be exactly $frac(1, 2, style: "skewed")$ of that. + +If @cmd:dedication is called at the beginning of the #arg("poembody") it will be placed exactly $frac(1, 2, style: "skewed")$ (when used with @cmd:poem) or exactly $frac(1, 4, style: "skewed")$ (when used with @cmd:poem-incycle) of #var("v-after-poemtitle") away from the #arg("poemtitle"). The vertical space between the dedication and the first verse will be twice that distance. + +=== Visuals + +The styling of almost all relevant elements can also be completely customized by using show-rules. This is possible with + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @getting-started] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @inline-poemtitles] +] + +#warning-alert[#icons.warning Note that (as of v.0.2.0), if \ is shown to be a heading, inline poemtitles may be shown different but will also appear in the outline (on the same level).] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @numbering-verses] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @interjections] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @dedications] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @setting-cycles] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @setting-cycles] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @setting-cycles] +] + +#side-by-side[ + ```typst + #show + ``` +][#align(right)[ + see @setting-cycles] +] + += Changelog + +#text(size: 14pt, weight: "bold")[v.0.2.0] + +- New features: + - Added presets. + - Added interjections and dedications. + - Added functionality to split verses via `#splitverse[]` and `#versesplit`. + - Added subtitles for cycles and poems in cycles. + - Made the indentation of the first verse of a stanza configurable via `#stanza-indent.update()`. + - Made the starting verse number configurable via `#verse-numbers-start.update()`. +- Presets: + - Added presets (`classic`, `classic-headings`). +- Fixes: + - Reworked inline poemtitles to prevent false headings being displayed in the outline in certain constellations. +- Documentation: + - Updated the manual. + - Updated the readme. + +#text(size: 14pt, weight: "bold")[v.0.1.1] + +- New features: + - Made the distance between verse numbers and the poem configurable via `#verse-number-distance.update()`. +- Fixes: + - Reworked verse numbers to prevent them causing issues with indentation in certain constellations. +- Documentation: + - Updated the manual. + +#text(size: 14pt, weight: "bold")[v.0.1.0] + +Initial release. diff --git a/packages/preview/verseatile/0.2.0/examples/example.png b/packages/preview/verseatile/0.2.0/examples/example.png new file mode 100644 index 0000000000..195f015e2f Binary files /dev/null and b/packages/preview/verseatile/0.2.0/examples/example.png differ diff --git a/packages/preview/verseatile/0.2.0/examples/example.typ b/packages/preview/verseatile/0.2.0/examples/example.typ new file mode 100644 index 0000000000..8240bfbe87 --- /dev/null +++ b/packages/preview/verseatile/0.2.0/examples/example.typ @@ -0,0 +1,86 @@ +#import "@preview/verseatile:0.2.0": * + +#set page(height: auto, width: auto) + +#show: preset-classic + +#show-verse-numbers.update(true) +#verse-number-modulo.update(2) + +#poem[Hor. carm. i, 26][ + +Musis amicus tristitiam et metus \ +tradam protervis in mare Creticum \ +portare ventis, quis sub Arcto \ +gelidae metuatur orae, + +quid Tiridaten terreat, unice \ +securus. O quae fontibus integris \ +gaudes, apricos necte flores, \ +necte meo Lamiae coronam, + +Piplea dulcis. Nil sine te mei \ +prosunt honores; hunc fidibus novis, \ +hunc Lesbio sacrare plectro \ +teque tuasque decet sorores. + +][0012] + +#pagebreak() + +#show-verse-numbers.update(false) + +#cycle[Martialis epigrammata][(XIV, 45 ff.)][ + +#poem-incycle[XLV.][Pila paganica][ + +Haec quae difficili turget paganica pluma, \ +Folle minus laxast et minus arta pila. + +][01] + +#poem-incycle[XLVI.][Pila trigonalis][ + +Si me nobilibus scis expulsare sinistris, \ +Sum tua. Tu nescis? rustice, redde pilam. + +][01] + +#poem-incycle[XLVII.][Follis][ + +Ite procul, iuvenes: mitis mihi convenit aetas: \ +Folle decet pueros ludere, folle senes. + +][01]] + +#pagebreak() + +#show-verse-numbers.update(true) +#verse-number-modulo.update(2) +#verse-number-start.update(176) + +#poem[Aischyl. Ag. 176--191][ + +#interjection[στρ. γ.] + +τὸν φρονεῖν βροτοὺς ὁδώ- \ +σαντα, τὸν πάθει μάθος \ +θέντα κυρίως ἔχειν. \ +στάζει δʼ ἔν θʼ ὕπνῳ πρὸ καρδίας \ +μνησιπήμων πόνος· καὶ παρʼ ἄ- \ +κοντας ἦλθε σωφρονεῖν. \ +δαιμόνων δέ που χάρις βίαιος \ +σέλμα σεμνὸν ἡμένων. + +#interjection[ἀντ. γ.] + +καὶ τόθʼ ἡγεμὼν ὁ πρέ- \ +σβυς νεῶν Ἀχαιικῶν, \ +μάντιν οὔτινα ψέγων, \ +ἐμπαίοις τύχαισι συμπνέων, \ +εὖτʼ ἀπλοίᾳ κεναγγεῖ βαρύ- \ +νοντʼ Ἀχαιικὸς λεώς, \ +Χαλκίδος πέραν ἔχων παλιρρόχ- \ +θοις ἐν Αὐλίδος τόποις· + +][0] diff --git a/packages/preview/verseatile/0.2.0/lib.typ b/packages/preview/verseatile/0.2.0/lib.typ new file mode 100644 index 0000000000..853108a3cf --- /dev/null +++ b/packages/preview/verseatile/0.2.0/lib.typ @@ -0,0 +1,157 @@ +// Importing presets + +#import "presets.typ": ( + preset-classic, + preset-classic-headings) + +// Global parameters + +#let base-indent = state("base-indent", 1em) +#let verse-indent = state("verse-indent", 1em) +#let stanza-indent = state("stanza-indent", 0pt) + +#let always-align-poemtitle = state("always-align-poemtitle", true) +#let v-after-poemtitle = state("v-after-poemtitle", 20em/11) + +#let show-verse-numbers = state("show-verse-numbers", false) +#let verse-number-start = state("verse-number-start", 1) +#let verse-number-modulo = state("verse-number-modulo", 1) +#let verse-number-distance = state("verse-number-distance", 5pt) + +// Splitting verses + +#let current-versesplit = state("current-versesplit", 0pt) + +#let splitverse(part-of-verse) = [#context [ + #h(current-versesplit.get())#part-of-verse + #current-versesplit.update(current-versesplit.get() + measure(part-of-verse).width)]] + +#let versesplit = [#context [ + #h(current-versesplit.get()) + #current-versesplit.update(0pt)]] + +#let is-splitverse(content) = { + let arr = content.fields().values() + if arr.len() != 0 { + arr.last() == } + else {return false}} + +// Printing inline poemtitles + +#let inline-poemtitle(part-of-verse) = { + [#box(height: 0pt, width: 0pt, clip: true, + [#hide[#part-of-verse]])] + [#box(part-of-verse)]} + +// Printing interjections and dedications + +#let interjection(interjectionbody) = { + [#interjectionbody]} + +#let dedication(dedicationbody) = { + [#dedicationbody]} + +#let is-interjection(content) = { + let arr = content.fields().values() + if arr.len() != 0 { + arr.last() == or arr.last() == } + else {return false}} + +#let is-dedication(content) = { + let arr = content.fields().values() + if arr.len() != 0 { + arr.last() == } + else {return false}} + +// Printing poembodys + +#let print-poembody(poembody, indentpattern, nesting) = { + + // Map the indent pattern and poembody to an array + + let verseindents = () + for verseindent in indentpattern.fields().values().at(0) [ + #verseindents.push(int(verseindent)+1)] + let poemcontent = poembody.fields().values().at(0) + poemcontent.pop() + + // Insert the indents and versenumbers into the poembody + + let current-element = 1 + let current-verse = 1 + let current-verse-number = verse-number-start.get() + if is-dedication(poemcontent.at(1)) { + poemcontent.remove(0) + poemcontent.insert(0, [#v(-v-after-poemtitle.get() / (2 * nesting)) #h(base-indent.get())]) + poemcontent.insert(2, v(v-after-poemtitle.get() / nesting, weak: true))} + for element in poemcontent { + let current-indent = (verseindents.at(calc.rem-euclid(current-verse - 1, verseindents.len())) - 1) * verse-indent.get() + base-indent.get() + if element == parbreak() or element == linebreak() { + if show-verse-numbers.get() and not (is-interjection(poemcontent.at(current-element, default: [])) or is-splitverse(poemcontent.at(current-element + 1, default: []))) { + [#poemcontent.insert(current-element,[#box(width: 0pt)[#if calc.rem-euclid(current-verse-number, verse-number-modulo.get()) == 0 [ + #align(right)[#current-verse-number #h(verse-number-distance.get())]]] + #if element == parbreak() and not is-interjection(poemcontent.at(current-element, default: [])) [#h(stanza-indent.get())] + #h(current-indent - 2.75pt)])]} + else if (is-interjection(poemcontent.at(current-element, default: [])) or is-splitverse(poemcontent.at(current-element + 1, default: []))) [ + #poemcontent.insert(current-element,h(base-indent.get()))] + else [ + #poemcontent.insert(current-element,h(current-indent))] + current-element += 1 + if not (is-interjection(poemcontent.at(current-element, default: [])) or is-splitverse(poemcontent.at(current-element + 1, default: []))) { + current-verse += 1 + current-verse-number += 1}} + current-element += 1} + + // Print the indented and numbered poembody + + for element in poemcontent { + [#element]}} + +// Printing poems + +#let poem(poemtitle, poembody, indentpattern) = {[ + + #context { + + // Print the poemtitle + + if poemtitle != [] [#poemtitle\ ] else if always-align-poemtitle.get() [#box(width: measure([0 ]).values().at(0), height: measure([0 ]).values().at(1))] + v(v-after-poemtitle.get(), weak: true) + + // Print the poembody + + print-poembody(poembody, indentpattern, 1)}]} + +// Printing cycles + +#let cycle(cycletitle, ..cyclesubtitle, cyclebody) = {[ + + #context { + + // Print the cycle + + if cyclesubtitle != arguments() [ + #cycletitle + #cyclesubtitle.at(0)\ ] + else [#cycletitle\ ] + v(v-after-poemtitle.get(), weak: true) + [#cyclebody]}]} + +// Printing poems in cycles + +#let poem-incycle(poemtitle, ..poemsubtitle, poembody, indentpattern) = {[ + + #context{ + + // Print the poemtitle + + if poemsubtitle != arguments() [ + #poemtitle + #poemsubtitle.at(0)\ ] + else if poemtitle != [] [#poemtitle\ ] + else [#box(width: measure([0 ]).values().at(0), height: measure([0 ]).values().at(1))] + v(v-after-poemtitle.get() / 2, weak: true) + + // Print the poembody + + print-poembody(poembody, indentpattern, 2)}]} diff --git a/packages/preview/verseatile/0.2.0/presets.typ b/packages/preview/verseatile/0.2.0/presets.typ new file mode 100644 index 0000000000..0d3daa064f --- /dev/null +++ b/packages/preview/verseatile/0.2.0/presets.typ @@ -0,0 +1,54 @@ +/// Classic Presets + +#let classic(body) = { + show : it => [#h(0.5em) #text( + size: 10em/11 + )[#it]] + show : it => [#h(0.25em) #text( + style: "italic", + size: 10em/11 + )[#it]] + show : it => [#text( + )[#smallcaps(it)]] + show : it => [#h(-0.5em) #text( + style: "italic", + size: 8em/11 + )[#it]] + show : it => [#h(-0.5em) #text( + style: "italic", + size: 9em/11 + )[#smallcaps(all:true, it)]] + show : set text( + size: 8em/11, + number-type: "lining") +body} + +// classic + +#let preset-classic(body) = { + show : it => [#text( + size: 14em/11, + number-type: "old-style", + number-width: "proportional" + )[#smallcaps(it)]] + show : it => [#text( + size: 14em/11, + number-type: "old-style", + number-width: "proportional" + )[#smallcaps(it)]] + show : it =>[#text( + size: 12em/11, + number-type: "old-style", + number-width: "proportional" + )[#smallcaps(all: true, it)]] + show: classic +body} + +// classic-headings + +#let preset-classic-headings(body) = { + show : it => box(heading(level: 2, it)) + show : it => box(heading(level: 2, it)) + show : it => box(heading(level: 3, it)) + show: classic +body} diff --git a/packages/preview/verseatile/0.2.0/typst.toml b/packages/preview/verseatile/0.2.0/typst.toml new file mode 100644 index 0000000000..629101cb72 --- /dev/null +++ b/packages/preview/verseatile/0.2.0/typst.toml @@ -0,0 +1,11 @@ +[package] +name = "verseatile" +version = "0.2.0" +entrypoint = "lib.typ" +authors = ["Alexander Abt"] +license = "MIT" +description = "Easily set poetry." +repository = "https://github.com/switchlex/verseatile" +keywords = ["verse", "poem", "poetry"] +categories = ["text", "layout"] +exclude = ["examples/*", "docs/*"]