diff --git a/packages/preview/jurlstify/0.2.1/LICENSE b/packages/preview/jurlstify/0.2.1/LICENSE
new file mode 100644
index 0000000000..44362484f3
--- /dev/null
+++ b/packages/preview/jurlstify/0.2.1/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 SchrodingerBlume
+
+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/jurlstify/0.2.1/README.md b/packages/preview/jurlstify/0.2.1/README.md
new file mode 100644
index 0000000000..0a5200884a
--- /dev/null
+++ b/packages/preview/jurlstify/0.2.1/README.md
@@ -0,0 +1,276 @@
+
+ jurlstify
+ URL typesetting with line-break opportunities — the url.sty port for Typst
+
+
+
+
+
+
+
+
+
+ English | 中文
+
+
+---
+
+## English
+
+A Typst package that ports LaTeX's [`url.sty`](https://ctan.org/pkg/url) line-breaking logic. In justified paragraphs, bare URLs either overflow the margin or force ugly gaps into the surrounding text. jurlstify inserts break opportunities at the same character classes as `url.sty` (`/`, `?`, `&`, `:`, etc.) so Typst's line-breaker can wrap URLs naturally without touching word spacing elsewhere in the paragraph.
+
+### Features
+
+- **url.sty-compatible break classes** — breaks after `.` `/` `?` `&` `#` `:` and more, matching `\UrlBreaks` / `\UrlBigBreaks` / `\UrlNoBreaks`
+- **Hyphen control** — breaks after `-` are suppressed by default (like url.sty); enable with `hyphens: true`
+- **Font inheritance** — defaults to `auto` (inherits body font), avoiding the metric mismatch that monospace causes in CJK text
+- **Stretch mode** — opt-in `stretch: true` lets URL-internal lines align to the right margin in justified paragraphs
+- **Long-run fallback** — opt-in `every: N` adds break opportunities inside unbroken letter/digit runs that contain no natural break character
+- **Visible-hyphen mode** — opt-in `show-hyphen: true` shows a `-` at *every* line break (natural `/` `.` `?` … breaks and `every`-inserted ones alike); default `false` is url.sty-faithful — copy-safe, no hyphen shown
+- **Three usage modes** — standalone `jurlstify()`, hyperlink wrapper `jurl()`, and document-level show rule `jurlstify-links()`
+- **Fully customisable** — override break character lists, font, size, color, and hyphen interval per call
+
+### Quick Start
+
+```typst
+#import "@preview/jurlstify:0.2.1": jurlstify, jurl, jurlstify-links
+
+// Render a URL string with break opportunities
+#jurlstify("https://example.com/very/long/path?query=value&more=stuff#fragment")
+
+// Clickable link — same breaking, wrapped in link()
+#jurl("https://example.com/very/long/path?query=value&more=stuff#fragment")
+
+// Apply automatically to every link() in the document
+#show: jurlstify-links.with()
+#link("https://example.com/automatically/handled")
+```
+
+### API Reference
+
+#### `jurlstify(url, ..options)` — core function
+
+Renders `url` as inline content with Unicode break opportunities at url.sty-compatible positions.
+
+| Parameter | Type | Default | Description |
+|-----------|------|---------|-------------|
+| `url` | `str` | *(required)* | The URL string to render. |
+| `hyphens` | `bool` | `false` | Allow line breaks after `-`. Mirrors url.sty's `hyphens` option. Off by default so `my-domain.com` never breaks mid-word. |
+| `stretch` | `bool` | `false` | Make break points stretchable so URL-internal justified lines reach the right margin. Trade-off: small visible gaps may appear at break points. |
+| `spaces` | `str` | `"nobreak"` | How to handle literal spaces inside a URL. `"nobreak"` → no-break space; `"break"` → ordinary breakable space; `"strip"` → discard. |
+| `breaks` | `array` | *url.sty defaults* | Characters after which a break opportunity is inserted. |
+| `big-breaks` | `array` | `(":",)` | Higher-priority break characters (`\UrlBigBreaks`). |
+| `no-breaks` | `array` | `("(","[","{","<")` | Characters that suppress the break opportunity immediately before them (`\mathopen` class). |
+| `font` | `auto` \| `str` \| `array` | `auto` | URL font. `auto` inherits the surrounding body font. Pass a name or array to override, e.g. a monospace stack. |
+| `size` | `auto` \| `length` | `auto` | Font size. `auto` inherits from context. |
+| `fill` | `auto` \| `color` | `auto` | Text color. `auto` inherits from context. |
+| `every` | `none` \| `int` | `none` | Insert a break opportunity after every N consecutive non-break characters. The marker is invisible unless the line actually breaks there. Useful for URLs with long unbroken letter/digit runs. Disabled by default. |
+| `show-hyphen` | `bool` | `false` | Render **every** break opportunity — the natural `/` `.` `?` `&` `:` breaks **and** any added by `every` — as a visible soft hyphen (`U+00AD`) when the line breaks there. `false` (default) → zero-width space (`U+200B`): breakable but shows nothing; the url.sty-faithful, copy-safe behaviour. `true` → a `-` appears at each broken line end (including after punctuation, e.g. line ends like `…com/-`). A real `-` (under `hyphens: true`) is never doubled. |
+
+```typst
+// Inherit body font, break at / ? & : etc.
+#jurlstify("https://example.com/path?a=1&b=2")
+
+// Allow hyphen breaks
+#jurlstify("https://my-very-long-sub-domain.example.org/path", hyphens: true)
+
+// Justify URL-internal lines to the right margin
+#jurlstify("https://example.com/long/path", stretch: true)
+
+// Add break points every 8 chars in long unbroken runs (invisible by default)
+#jurlstify("https://example.com/averylongpathsegmentwithnobreaks", every: 8)
+
+// Show a "-" at EVERY line break — natural breaks and `every` ones alike
+#jurlstify("https://example.com/very/long/path/segment", show-hyphen: true)
+
+// Monospace font (classic url.sty look)
+#jurlstify("https://example.com/path",
+ font: ("DejaVu Sans Mono", "Menlo", "Consolas", "Courier New"))
+
+// Custom color and size
+#jurlstify("https://example.com/path", fill: blue, size: 9pt)
+```
+
+#### `jurl(dest, display: none, ..options)` — hyperlink wrapper
+
+Renders a clickable hyperlink whose visible text is formatted by `jurlstify`. Accepts all the same keyword options.
+
+| Parameter | Type | Default | Description |
+|-----------|------|---------|-------------|
+| `dest` | `str` | *(required)* | Link destination (URL). |
+| `display` | `none` \| `str` \| content | `none` | Custom display. `none` → destination string formatted by `jurlstify`; string → also formatted by `jurlstify`; content → used as-is. |
+
+```typst
+#jurl("https://example.com/very/long/path")
+#jurl("https://example.com/very/long/path", display: "example site")
+#jurl("https://example.com/path", hyphens: true, fill: blue)
+```
+
+#### `jurlstify-links(..options, body)` — show-rule helper
+
+Document-level show rule that makes every `#link("http://…")` (where body equals destination) automatically use `jurlstify`. Links with explicit display content (`#link(dest, "click here")`) are left untouched.
+
+```typst
+// Declare once near the top of your document
+#show: jurlstify-links.with()
+
+The homepage is #link("https://example.com/very/long/path"). // auto-formatted
+See #link("https://example.com", "the docs") for details. // untouched
+```
+
+Pass options to apply them document-wide:
+
+```typst
+#show: jurlstify-links.with(hyphens: true, fill: blue)
+```
+
+### Default Break Characters
+
+| Parameter | Default characters |
+|-----------|--------------------|
+| `breaks` | `. @ \ / ! _ \| ; > ] ) , ? & ' + = #` |
+| `big-breaks` | `:` |
+| `no-breaks` | `( [ { <` |
+
+### Notes on Justification
+
+jurlstify inserts `U+200B` (ZERO WIDTH SPACE) at break positions — zero width, not stretchable, faithfully mirroring url.sty's zero-stretch muskips. A line consisting entirely of URL characters may end slightly short of the right margin.
+
+Enable `stretch: true` for invisible-but-stretchable word spaces; the paragraph justifier will then align URL-only lines to the right margin at the cost of small visible gaps at break points.
+
+Break quality depends on Typst's optimizer. jurlstify only inserts declarative markers; improvements to Typst's engine automatically improve output.
+
+### License
+
+MIT License — see [LICENSE](LICENSE) for details.
+
+---
+
+## 中文
+
+将 LaTeX [`url.sty`](https://ctan.org/pkg/url) 的换行逻辑移植到 Typst 的排版包。在两端对齐的段落中,裸露的 URL 要么溢出页边距,要么迫使周围文字产生大块空白。jurlstify 在与 `url.sty` 相同的字符类(`/`、`?`、`&`、`:` 等)后插入换行机会,使 Typst 的断行器能在这些位置自然换行,而不影响段落其余部分的字间距。
+
+### 功能特性
+
+- **url.sty 兼容断点** — 在 `.` `/` `?` `&` `#` `:` 等字符处断行,对应 `\UrlBreaks` / `\UrlBigBreaks` / `\UrlNoBreaks`
+- **连字符控制** — 默认抑制 `-` 处的换行(与 url.sty 一致);可通过 `hyphens: true` 开启
+- **字体继承** — 默认 `auto`,继承正文字体,避免等宽字体在中文段落中造成字距错位
+- **拉伸模式** — 可选 `stretch: true`,让整行 URL 也能对齐两端对齐段落的右边距
+- **长串兜底** — 可选 `every: N`,在没有任何自然断点字符的长串字母/数字段中插入额外的换行机会
+- **连字符模式** — 可选 `show-hyphen: true`,让*每一个*断点(`/` `.` `?` … 等自然断点以及 `every` 插入的断点)在实际换行处显示 `-`;默认 `false` 与 url.sty 一致——可安全复制、不显示连字符
+- **三种使用方式** — 独立函数 `jurlstify()`、超链接包装器 `jurl()`、文档级 show rule `jurlstify-links()`
+- **完全可定制** — 可按需覆盖断点字符列表、字体、字号、颜色和软连字符间隔
+
+### 快速上手
+
+```typst
+#import "@preview/jurlstify:0.2.1": jurlstify, jurl, jurlstify-links
+
+// 渲染带换行机会的 URL 字符串
+#jurlstify("https://example.com/very/long/path?query=value&more=stuff#fragment")
+
+// 可点击超链接,同样支持换行
+#jurl("https://example.com/very/long/path?query=value&more=stuff#fragment")
+
+// 全局 show rule:让文档中所有 link() 自动使用 jurlstify
+#show: jurlstify-links.with()
+#link("https://example.com/automatically/handled")
+```
+
+### API 参考
+
+#### `jurlstify(url, ..options)` — 核心函数
+
+将 `url` 渲染为行内内容,在与 url.sty 兼容的位置插入 Unicode 换行机会。
+
+| 参数 | 类型 | 默认值 | 说明 |
+|------|------|--------|------|
+| `url` | `str` | *必填* | 要渲染的 URL 字符串。 |
+| `hyphens` | `bool` | `false` | 是否允许在 `-` 后换行。对应 url.sty 的 `hyphens` 选项。默认关闭,防止 `my-domain.com` 在单词中间断行。 |
+| `stretch` | `bool` | `false` | 让换行点参与两端对齐的拉伸,使纯 URL 行也能对齐右边距。代价:这些行的换行点处可能出现小间隙。 |
+| `spaces` | `str` | `"nobreak"` | URL 内部空格的处理方式。`"nobreak"` → 不换行空格;`"break"` → 普通可换行空格;`"strip"` → 删除空格。 |
+| `breaks` | `array` | *url.sty 默认值* | 插入换行机会的字符列表。 |
+| `big-breaks` | `array` | `(":",)` | 高优先级断点字符(对应 `\UrlBigBreaks`)。 |
+| `no-breaks` | `array` | `("(","[","{","<")` | 禁止在其之前断行的字符(对应 `\mathopen` 类)。 |
+| `font` | `auto` \| `str` \| `array` | `auto` | URL 字体。`auto` 继承正文字体(中文段落推荐)。传入字体名或数组可指定其他字体,例如等宽字体栈。 |
+| `size` | `auto` \| `length` | `auto` | 字号。`auto` 继承上下文。 |
+| `fill` | `auto` \| `color` | `auto` | 文字颜色。`auto` 继承上下文。 |
+| `every` | `none` \| `int` | `none` | 在连续的非断点字符序列中每隔 N 个字符插入一个换行机会。该标记平时不可见,仅在该处实际换行时显示。适用于含有长段字母/数字序列、缺乏自然断点的 URL。默认禁用。 |
+| `show-hyphen` | `bool` | `false` | 让**每一个**断点(`/` `.` `?` `&` `:` 等自然断点**以及** `every` 插入的断点)在实际换行处显示软连字符(`U+00AD`,可见的 `-`)。`false`(默认)→ 改用零宽空格(`U+200B`):可断行但不显示任何字符,与 url.sty 一致、可安全复制。`true` → 每个换行行尾出现 `-`(包括标点后,如行尾 `…com/-`)。真实的 `-`(`hyphens: true` 时)不会被叠加成 `--`。 |
+
+```typst
+// 继承正文字体,在 / ? & : 等处断行
+#jurlstify("https://example.com/path?a=1&b=2")
+
+// 允许连字符处断行
+#jurlstify("https://my-very-long-sub-domain.example.org/path", hyphens: true)
+
+// 使纯 URL 行对齐右边距
+#jurlstify("https://example.com/long/path", stretch: true)
+
+// 在长段无断点路径中每 8 字符加一个断点(默认不可见)
+#jurlstify("https://example.com/averylongpathsegmentwithnobreaks", every: 8)
+
+// 让每一个换行处都显示 “-” —— 自然断点与 every 断点一视同仁
+#jurlstify("https://example.com/very/long/path/segment", show-hyphen: true)
+
+// 等宽字体(经典 url.sty 风格)
+#jurlstify("https://example.com/path",
+ font: ("DejaVu Sans Mono", "Menlo", "Consolas", "Courier New"))
+
+// 自定义颜色与字号
+#jurlstify("https://example.com/path", fill: blue, size: 9pt)
+```
+
+#### `jurl(dest, display: none, ..options)` — 超链接包装器
+
+渲染可点击的超链接,可见文字由 `jurlstify` 格式化。支持与 `jurlstify` 相同的所有关键字选项。
+
+| 参数 | 类型 | 默认值 | 说明 |
+|------|------|--------|------|
+| `dest` | `str` | *必填* | 链接目标(URL)。 |
+| `display` | `none` \| `str` \| content | `none` | 自定义显示内容。`none` → 显示目标 URL 本身(经 `jurlstify` 格式化);字符串 → 同样经 `jurlstify` 处理;content → 原样显示。 |
+
+```typst
+#jurl("https://example.com/very/long/path")
+#jurl("https://example.com/very/long/path", display: "示例网站")
+#jurl("https://example.com/path", hyphens: true, fill: blue)
+```
+
+#### `jurlstify-links(..options, body)` — show rule 辅助函数
+
+文档级 show rule,让所有 body 与目标相同的 `#link("http://…")` 自动使用 `jurlstify` 断行。有显式显示内容的链接(如 `#link(dest, "点击这里")`)不受影响。
+
+```typst
+// 在文档顶部声明一次
+#show: jurlstify-links.with()
+
+项目主页为 #link("https://example.com/very/long/path")。 // 自动格式化
+详见 #link("https://example.com", "文档")。 // 不受影响
+```
+
+全局传入选项:
+
+```typst
+#show: jurlstify-links.with(hyphens: true, fill: blue)
+```
+
+### 默认断点字符
+
+| 参数 | 默认字符 |
+|------|----------|
+| `breaks` | `. @ \ / ! _ \| ; > ] ) , ? & ' + = #` |
+| `big-breaks` | `:` |
+| `no-breaks` | `( [ { <` |
+
+### 关于两端对齐的说明
+
+jurlstify 在断点位置插入 `U+200B`(零宽空格)——宽度为零且不可拉伸,忠实还原了 url.sty 的零伸缩粘连。因此,整行都是 URL 字符的行可能无法对齐右边距。
+
+开启 `stretch: true` 可改为插入不可见但可拉伸的字间距,使段落排版器在纯 URL 行也能对齐右边距,代价是这些行的换行点处可能出现小间隙。
+
+断行质量取决于 Typst 引擎的优化器。jurlstify 只插入声明式标记,Typst 引擎的改进会自动改善输出,无需修改本包。
+
+### 许可
+
+MIT 许可证 — 详见 [LICENSE](LICENSE)。
diff --git a/packages/preview/jurlstify/0.2.1/lib.typ b/packages/preview/jurlstify/0.2.1/lib.typ
new file mode 100644
index 0000000000..e90033e4cd
--- /dev/null
+++ b/packages/preview/jurlstify/0.2.1/lib.typ
@@ -0,0 +1,248 @@
+// jurlstify — URL typesetting with line-break opportunities.
+//
+// Ported from Donald Arseneau's LaTeX `url.sty` (LPPL).
+//
+// Raggedness note:
+// url.sty sets every math-mode muskip to `0mu` — zero natural width AND
+// zero stretch/shrink. That means a line that falls entirely inside a
+// URL has no stretchable glue in LaTeX either, so it can only reach the
+// right margin by luck of where break points fall. The common sense
+// that "url.sty makes URLs justify" is a misconception propagated by
+// TeX's Knuth-Plass breaker, which is aggressive enough that ragged
+// URL-internal lines are rare in practice. We cannot reproduce Knuth-
+// Plass, so we offer the same two trade-offs LaTeX has:
+//
+// 1. `stretch: false` (default, matches url.sty): emit U+200B at
+// break points — zero-width, breakable, non-stretchable. Lines
+// that fall entirely inside a URL may end short of the right
+// margin. This is the honest port of url.sty.
+//
+// 2. `stretch: true`: emit a real U+0020 space wrapped in
+// `text(tracking: …)` that pulls the space advance to zero. The
+// space is invisible when the line is not justified, but the
+// paragraph justifier will expand it like any word space on
+// justified URL-internal lines — buying right-margin alignment
+// at the cost of small visible gaps between URL segments on
+// those lines.
+//
+// Hyphen handling:
+// Unicode assigns "-" to line-break class HY (break after). url.sty
+// keeps hyphens in UrlOrds by default (no break) and only promotes
+// them to UrlBigBreaks under the `hyphens` option. We emit U+2060
+// (WORD JOINER) after "-" when `hyphens: false` to suppress Typst's
+// default break at hyphens.
+
+// ─────────────────────────────────────────────────────────────────────────────
+// Break-class tables — kept identical to `url.sty` defaults.
+// \UrlBreaks / \UrlBigBreaks / \UrlNoBreaks (url.sty §32–35)
+
+#let breaks-default = (
+ ".", "@", "\\", "/", "!", "_", "|", ";", ">", "]",
+ ")", ",", "?", "&", "'", "+", "=", "#",
+)
+
+#let big-breaks-default = (":",)
+
+#let no-breaks-default = ("(", "[", "{", "<")
+
+// Invisible characters used internally.
+#let _zwsp = "\u{200B}" // ZERO WIDTH SPACE — break, zero width, no stretch
+#let _wj = "\u{2060}" // WORD JOINER — forbids line break
+#let _nbsp = "\u{00A0}" // NO-BREAK SPACE
+
+// Stretchable invisible break. A real U+0020 with enough negative tracking to
+// cancel its advance — invisible on unjustified lines, but *does* participate
+// in paragraph justification on URL-internal lines. Opt-in via `stretch: true`.
+#let _stretch-break = text(tracking: -1em, " ")
+
+// ─────────────────────────────────────────────────────────────────────────────
+// Core: render a URL with break+stretch opportunities.
+//
+// Arguments
+// ---------
+// url : str — the URL text.
+// hyphens : bool — allow breaks after "-" (url.sty `hyphens` option).
+// stretch : bool — if true, URL-internal lines can stretch to reach
+// the right margin in a justified paragraph. Trade-
+// off: visible gaps appear at break points on those
+// lines. Default false (matches url.sty's
+// zero-stretch muskips; lines may be ragged).
+// spaces : str — "nobreak" | "break" | "strip". url.sty default is
+// "nobreak" (\penalty\@M); `spaces` option gives "break".
+// breaks : array — override normal break chars.
+// big-breaks : array — override high-priority break chars.
+// no-breaks : array — chars explicitly suppressed from breaking (a break
+// opportunity that would otherwise land *before* one
+// of these is dropped, matching url.sty's `\mathopen`
+// class).
+// font : auto | str | array — URL font; `auto` inherits the
+// surrounding body font. Pass a font name or array
+// (e.g. monospace stack) to override.
+// size : auto | length
+// fill : auto | color
+// every : none | int — insert a break opportunity after every N
+// consecutive non-break characters. The marker is
+// invisible unless the line actually breaks there.
+// Disabled by default (none). Useful when URLs contain
+// long unbroken letter/digit runs that resist all
+// natural break points.
+// show-hyphen : bool — render EVERY break opportunity — the natural url.sty
+// breaks (after "/ . ? & : …") as well as any inserted
+// by `every` — as a visible hyphen when the line
+// actually breaks there.
+// false (default): U+200B ZERO WIDTH SPACE — breakable
+// but shows nothing. The url.sty-faithful, copy-safe
+// behaviour, since a stray "-" could be mistaken for a
+// real character of the URL.
+// true: U+00AD SOFT HYPHEN at every break — a "-"
+// appears at each broken line end. Note this also puts
+// a "-" after punctuation breaks (line ends like
+// "…com/-"). A real "-" (under hyphens: true) is left
+// as the break's own visible hyphen, never doubled.
+
+#let jurlstify(
+ url,
+ hyphens: false,
+ stretch: false,
+ spaces: "nobreak",
+ breaks: breaks-default,
+ big-breaks: big-breaks-default,
+ no-breaks: no-breaks-default,
+ font: auto,
+ size: auto,
+ fill: auto,
+ every: none,
+ show-hyphen: false,
+) = {
+ assert(
+ type(url) == str,
+ message: "jurlstify: expected a string, got " + str(type(url)),
+ )
+ assert(
+ spaces in ("nobreak", "break", "strip"),
+ message: "jurlstify: `spaces` must be \"nobreak\", \"break\", or \"strip\"",
+ )
+ assert(
+ every == none or (type(every) == int and every >= 1),
+ message: "jurlstify: `every` must be none or a positive integer",
+ )
+ assert(
+ type(show-hyphen) == bool,
+ message: "jurlstify: `show-hyphen` must be a boolean",
+ )
+
+ let big = if hyphens { big-breaks + ("-",) } else { big-breaks }
+ let all-breaks = breaks + big
+
+ // url.sty runs inside math mode, which suppresses automatic hyphenation
+ // and ligatures. Typst has no math-mode escape for strings, so we disable
+ // those features directly; otherwise Typst would insert fake hyphens
+ // ("exam-ple.com") and apply language-specific ligatures inside URLs.
+ set text(
+ hyphenate: false,
+ historical-ligatures: false,
+ discretionary-ligatures: false,
+ )
+ set text(font: font) if font != auto
+ set text(size: size) if size != auto
+ set text(fill: fill) if fill != auto
+
+ // Invisible break: U+200B (or a stretchable space in `stretch` mode).
+ // Visible break: U+00AD SOFT HYPHEN — renders "-" only where the line
+ // actually breaks. `show-hyphen` selects which one EVERY break uses.
+ let plain-break = if stretch { _stretch-break } else { _zwsp }
+ let break-marker = if show-hyphen { "\u{00AD}" } else { plain-break }
+
+ // Emit content incrementally: text runs punctuated by break markers.
+ let chars = url.clusters()
+ let n = chars.len()
+ let i = 0
+ let word-run = 0 // consecutive non-break chars since the last natural break
+ while i < n {
+ let c = chars.at(i)
+
+ if c == " " {
+ word-run = 0
+ if spaces == "nobreak" { _nbsp }
+ else if spaces == "break" { c }
+ // "strip": drop the space
+ i += 1
+ continue
+ }
+
+ c
+
+ if c in all-breaks {
+ word-run = 0
+ let nxt = if i + 1 < n { chars.at(i + 1) } else { none }
+ if nxt not in no-breaks {
+ // A real "-" (only reachable under hyphens: true) is already a
+ // visible hyphen — break after it, but don't stack a soft hyphen on
+ // top, which would render an ugly "--" at the line end.
+ if show-hyphen and c == "-" { plain-break } else { break-marker }
+ }
+ } else if c == "-" and not hyphens {
+ word-run = 0
+ _wj
+ } else {
+ word-run += 1
+ if every != none and word-run >= every and i + 1 < n {
+ break-marker
+ word-run = 0
+ }
+ }
+
+ i += 1
+ }
+}
+
+// ─────────────────────────────────────────────────────────────────────────────
+// Convenience wrapper: hyperlink + jurlstify
+//
+// #jurl("https://example.com/long/path")
+// #jurl("https://example.com/long/path", display: "example")
+
+#let jurl(
+ dest,
+ display: none,
+ ..opts,
+) = {
+ let shown = if display == none { dest } else { display }
+ let body = if type(shown) == str {
+ jurlstify(shown, ..opts.named())
+ } else {
+ shown
+ }
+ link(dest, body)
+}
+
+// ─────────────────────────────────────────────────────────────────────────────
+// Show-rule helper: make the built-in `link` element use jurlstify's breaking
+// wherever its body is a plain text run (`link("http://…")`, etc).
+//
+// #show: jurlstify-links.with()
+// #link("https://example.com/foo/bar") // auto-formatted
+
+#let jurlstify-links(
+ ..opts,
+ body,
+) = {
+ let kwargs = opts.named()
+ show link: it => {
+ // Only rewrite when the body is the auto-generated textual form of
+ // `dest` (the common `link("http://…")` case). Explicit display
+ // content such as `link(dest, "click me")` is left untouched — the
+ // user picked it on purpose and almost certainly isn't a URL.
+ if (
+ type(it.dest) == str
+ and it.body.func() == text
+ and type(it.body.text) == str
+ and it.body.text == it.dest
+ ) {
+ link(it.dest, jurlstify(it.body.text, ..kwargs))
+ } else {
+ it
+ }
+ }
+ body
+}
diff --git a/packages/preview/jurlstify/0.2.1/typst.toml b/packages/preview/jurlstify/0.2.1/typst.toml
new file mode 100644
index 0000000000..d436f0ce77
--- /dev/null
+++ b/packages/preview/jurlstify/0.2.1/typst.toml
@@ -0,0 +1,12 @@
+[package]
+name = "jurlstify"
+version = "0.2.1"
+entrypoint = "lib.typ"
+authors = ["SchrodingerBlume "]
+license = "MIT"
+description = "URL typesetting with line-break opportunities, inspired by LaTeX's url package."
+repository = "https://github.com/SchrodingerBlume/typst-jurlstify"
+keywords = ["url", "linebreak", "justify", "hyperref"]
+categories = ["text", "utility", "layout"]
+compiler = "0.13.0"
+exclude = ["*.pdf"]