|
| 1 | +# Meander |
| 2 | + |
| 3 | +`meander` provides a core function `reflow` to segment pages and wrap content around images. |
| 4 | + |
| 5 | +<!-- @scrybe(not version; panic Please specify a version number) --> |
| 6 | +<!-- @scrybe(if publish; grep https; grep {{version}}) --> |
| 7 | +See the [documentation](https://github.com/Vanille-N/meander.typ/releases/download/v0.3.1/docs.pdf). |
| 8 | + |
| 9 | +## Quick start |
| 10 | + |
| 11 | +The function `meander.reflow` takes a sequence of |
| 12 | +- obstacles: use `placed` to put content at specific positions of the page, |
| 13 | +- containers: use `container` to specify where text can be laid out, |
| 14 | +- flowing content: provide text with `content`. |
| 15 | +- optionally `pagebreak`, `colbreak`, `colfill` can be used to produce multi-page |
| 16 | + layouts and fine-tune which text goes into which container. |
| 17 | + |
| 18 | +<!-- @scrybe(not publish; jump import; grep local; grep {{version}}) --> |
| 19 | +<!-- @scrybe(if publish; jump import; grep preview; grep {{version}}) --> |
| 20 | +<!-- @scrybe(jump let; until ```; diff tests/gallery/multi-obstacles/test.typ) --> |
| 21 | +```typ |
| 22 | +#let my-img-1 = box(width: 7cm, height: 7cm, fill: orange) |
| 23 | +#let my-img-2 = box(width: 5cm, height: 3cm, fill: blue) |
| 24 | +#let my-img-3 = box(width: 8cm, height: 4cm, fill: green) |
| 25 | +#let my-img-4 = box(width: 5cm, height: 5cm, fill: red) |
| 26 | +#let my-img-5 = box(width: 4cm, height: 3cm, fill: yellow) |
| 27 | +
|
| 28 | +#import "@preview/meander:0.3.1" |
| 29 | +
|
| 30 | +#meander.reflow({ |
| 31 | + import meander: * |
| 32 | +
|
| 33 | + // As many obstacles as you want |
| 34 | + placed(top + left, my-img-1) |
| 35 | + placed(top + right, my-img-2) |
| 36 | + placed(horizon + right, my-img-3) |
| 37 | + placed(bottom + left, my-img-4) |
| 38 | + placed(bottom + left, dx: 32%, my-img-5) |
| 39 | +
|
| 40 | + // The container wraps around all |
| 41 | + container() |
| 42 | + content[ |
| 43 | + #set par(justify: true) |
| 44 | + #lorem(430) |
| 45 | + ] |
| 46 | +}) |
| 47 | +``` |
| 48 | + |
| 49 | + |
| 50 | +----- |
| 51 | + |
| 52 | +Use multiple `container`s to produce layouts in columns. |
| 53 | + |
| 54 | +<!-- @scrybe(not publish; jump import; grep local; grep {{version}}) --> |
| 55 | +<!-- @scrybe(if publish; jump import; grep preview; grep {{version}}) --> |
| 56 | +<!-- @scrybe(jump let; until ```; diff tests/gallery/two-columns/test.typ) --> |
| 57 | +```typ |
| 58 | +#let my-img-1 = box(width: 7cm, height: 7cm, fill: orange) |
| 59 | +#let my-img-2 = box(width: 5cm, height: 3cm, fill: blue) |
| 60 | +#let my-img-3 = box(width: 8cm, height: 4cm, fill: green) |
| 61 | +
|
| 62 | +#import "@preview/meander:0.3.1" |
| 63 | +
|
| 64 | +#meander.reflow({ |
| 65 | + import meander: * |
| 66 | +
|
| 67 | + placed(bottom + right, my-img-1) |
| 68 | + placed(center + horizon, my-img-2) |
| 69 | + placed(top + right, my-img-3) |
| 70 | +
|
| 71 | + // With two containers we can |
| 72 | + // emulate two columns. |
| 73 | +
|
| 74 | + // The first container takes 60% |
| 75 | + // of the page width. |
| 76 | + container(width: 60%, margin: 5mm) |
| 77 | + // The second container automatically |
| 78 | + // fills the remaining space. |
| 79 | + container() |
| 80 | +
|
| 81 | + content[#lorem(470)] |
| 82 | +}) |
| 83 | +``` |
| 84 | + |
| 85 | + |
| 86 | +------ |
| 87 | + |
| 88 | +If your Meander environment shares page(s) with other content, |
| 89 | +use the option `placement: box`. |
| 90 | +The `overflow` parameter determines what happens to text that doesn't |
| 91 | +fit inside the provided containers. |
| 92 | + |
| 93 | +You can see this in effect in the example below: |
| 94 | +- the text in red is outside of the Meander environment |
| 95 | +- the text in blue is the Meander environment itself |
| 96 | +- the text in black is the overflow handled by Meander |
| 97 | +<!-- @scrybe(not publish; jump import; grep local; grep {{version}}) --> |
| 98 | +<!-- @scrybe(not publish; jump import; grep local; grep {{version}}) --> |
| 99 | +<!-- @scrybe(jump import; until ```; diff tests/gallery/placement/test.typ) --> |
| 100 | +```typ |
| 101 | +#import "@preview/meander:0.3.1" |
| 102 | +#set par(justify: true) |
| 103 | +
|
| 104 | +#text(fill: red)[#lorem(200)] |
| 105 | +
|
| 106 | +#meander.reflow({ |
| 107 | + import meander: * |
| 108 | + // Gets rid of the paragraph break between |
| 109 | + // the columns and the overflow. |
| 110 | + opt.placement.spacing(below: 0.65em) |
| 111 | +
|
| 112 | + // This turns on some debugging information, |
| 113 | + // specifically showing the boundaries |
| 114 | + // of the boxes in green. |
| 115 | + opt.debug.post-thread() |
| 116 | +
|
| 117 | + container( |
| 118 | + width: 48%,height: 50%, |
| 119 | + style: (text-fill: blue), |
| 120 | + ) |
| 121 | + container( |
| 122 | + width: 48%, height: 50%, align: right, |
| 123 | + style: (text-fill: blue), |
| 124 | + ) |
| 125 | +
|
| 126 | + content[#lorem(700)] |
| 127 | +
|
| 128 | + // This applies a style to the text |
| 129 | + // that overflows the layout. |
| 130 | + opt.overflow.custom(data => { |
| 131 | + set text(fill: orange) |
| 132 | + data.styled |
| 133 | + }) |
| 134 | +}) |
| 135 | +
|
| 136 | +#text(fill: red)[#lorem(200)] |
| 137 | +``` |
| 138 | + |
| 139 | + |
| 140 | + |
| 141 | +------ |
| 142 | + |
| 143 | +Meander allows precise control over the boundaries of obstacles, to draw complex paragraph shapes. |
| 144 | + |
| 145 | +<!-- @scrybe(not publish; jump import; grep local; grep {{version}}) --> |
| 146 | +<!-- @scrybe(if publish; jump import; grep preview; grep {{version}}) --> |
| 147 | +<!-- @scrybe(jump import; until ```; diff tests/gallery/circle-hole/test.typ) --> |
| 148 | +```typ |
| 149 | +#import "@preview/meander:0.3.1" |
| 150 | +
|
| 151 | +#meander.reflow({ |
| 152 | + import meander: * |
| 153 | +
|
| 154 | + placed( |
| 155 | + center + horizon, |
| 156 | + boundary: |
| 157 | + // Override the default margin |
| 158 | + contour.margin(1cm) + |
| 159 | + // Then redraw the shape as a grid |
| 160 | + contour.grid( |
| 161 | + // 25 vertical and horizontal subdivisions. |
| 162 | + // Just pick a number that looks good. |
| 163 | + // A good rule of thumb is to start with obstacles |
| 164 | + // about as high as one line of text. |
| 165 | + div: 25, |
| 166 | + // Equation for a circle of center (0.5, 0.5) and radius 0.5 |
| 167 | + (x, y) => calc.pow(2 * x - 1, 2) + calc.pow(2 * y - 1, 2) <= 1 |
| 168 | + ), |
| 169 | + // Underlying object |
| 170 | + circle(radius: 3cm, fill: yellow), |
| 171 | + ) |
| 172 | +
|
| 173 | + container(width: 48%) |
| 174 | + container(align: right, width: 48%) |
| 175 | + content[ |
| 176 | + #set par(justify: true) |
| 177 | + #lorem(570) |
| 178 | + ] |
| 179 | +}) |
| 180 | +``` |
| 181 | + |
| 182 | + |
| 183 | +------ |
| 184 | + |
| 185 | +For a more in-depth introduction, including |
| 186 | +- alternative recontouring techniques, |
| 187 | +- styling options, |
| 188 | +- advanced multi-page layouts, |
| 189 | +- control over content that overflows, |
| 190 | +- tips to get better segmentation, |
| 191 | +<!-- @scrybe(if publish; grep https; grep {{version}}) --> |
| 192 | +please consult the [documentation](https://github.com/Vanille-N/meander.typ/releases/download/v0.3.1/docs.pdf). |
| 193 | + |
0 commit comments