cizgile 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 productdevbook
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Transliteration table values are derived from simov/slugify (MIT, Copyright (c)
26
+ Simeon Velichkov) and sindresorhus/transliterate (MIT, Copyright (c) Sindre
27
+ Sorhus).
package/README.md ADDED
@@ -0,0 +1,291 @@
1
+ <p align="center">
2
+ <br>
3
+ <img src=".github/assets/cover.svg?v=1a3fd12" alt="cizgile — Zero-dependency URL slug engine" width="100%">
4
+ <br><br>
5
+ <b style="font-size: 2em;">cizgile</b>
6
+ <br><br>
7
+ Zero-dependency URL slug engine.
8
+ <br>
9
+ Turn any title into a clean URL slug — in any language — and work with URLs the way RFC 3986 and RFC 3987 describe them. Pure TypeScript, works everywhere.
10
+ <br><br>
11
+ <a href="https://npmjs.com/package/cizgile"><img src="https://img.shields.io/npm/v/cizgile?style=flat&colorA=18181B&colorB=34d399" alt="npm version"></a>
12
+ <a href="https://npmjs.com/package/cizgile"><img src="https://img.shields.io/npm/dm/cizgile?style=flat&colorA=18181B&colorB=34d399" alt="npm downloads"></a>
13
+ <a href="https://bundlephobia.com/result?p=cizgile"><img src="https://img.shields.io/bundlephobia/minzip/cizgile?style=flat&colorA=18181B&colorB=34d399" alt="bundle size"></a>
14
+ <a href="https://github.com/productdevbook/cizgile/blob/main/LICENSE"><img src="https://img.shields.io/github/license/productdevbook/cizgile?style=flat&colorA=18181B&colorB=34d399" alt="license"></a>
15
+ </p>
16
+
17
+ ## Install
18
+
19
+ ```sh
20
+ npm install cizgile
21
+ ```
22
+
23
+ ```ts
24
+ import { slugify } from "cizgile"
25
+
26
+ slugify("Hello, World!") // "hello-world"
27
+ slugify("İstanbul Şişli & Çığ", { locale: "tr" }) // "istanbul-sisli-ve-cig"
28
+ slugify("Straße Über Ärger", { locale: "de" }) // "strasse-ueber-aerger"
29
+ slugify("你好 World", { unicode: true }) // "你好-world"
30
+ ```
31
+
32
+ No dependencies. ESM only. Node 20+, Bun, Deno, browsers, edge workers.
33
+
34
+ ## Why cizgile
35
+
36
+ - **Slugs that are correct by construction.** Every ASCII slug is a valid URL path segment (RFC 3986 `segment-nz-nc`) — no percent-encoding needed, no `.` or `..`, no accidental scheme prefix.
37
+ - **Speaks your language.** 19 locales (`tr`, `de`, `da`, `sv`, `uk`, `bg`, …) and 7 scripts (Latin, Cyrillic, Greek, Arabic, Armenian, Georgian, Dhivehi). `ß` → `ss`, `İ` → `i`, `Щ` → `shch`.
38
+ - **Unicode slugs when you want them.** `你好-world` stays readable, and `iriToUri` gives you the exact percent-encoded form for the wire.
39
+ - **A real URL toolkit underneath.** Resolve, normalise, compare, validate and relativise URLs by the RFC, cross-checked against the WHATWG `URL` parser.
40
+ - **Small and tree-shakeable.** `import { slugify }` ships the Latin table only; other scripts load only when you import them.
41
+
42
+ ## Three entry points
43
+
44
+ | import | what you get |
45
+ | ----------------------- | --------------------------------------------------------------------------------------------- |
46
+ | `cizgile` | `slugify`, `isSlug`, `createSlugger`, `truncateSlug`, `decamelize`, script and bidi guards |
47
+ | `cizgile/transliterate` | `transliterate`, per-script tables, locales, `defineLocale` |
48
+ | `cizgile/uri` | percent-encoding, `resolveUri`, `normalizeUri`, `relativize`, validators, IRI ↔ URI, punycode |
49
+
50
+ ## Slugs
51
+
52
+ ### Everyday use
53
+
54
+ ```ts
55
+ import { slugify } from "cizgile"
56
+
57
+ slugify("Déjà Vu!") // "deja-vu"
58
+ slugify("don't stop") // "dont-stop"
59
+ slugify("v1.2.3", { preserveCharacters: ["."] }) // "v1.2.3"
60
+ slugify("Hello World", { separator: "_" }) // "hello_world"
61
+ slugify("Donald E. Knuth", { lowercase: false }) // "Donald-E-Knuth"
62
+ slugify("getHTTPResponse", { decamelize: true }) // "get-http-response"
63
+ slugify("the quick brown fox", { maxLength: 9 }) // "the-quick"
64
+ slugify("C++ & Rust", { replacements: [["C++", "cpp"]] }) // "cpp-and-rust"
65
+ ```
66
+
67
+ ### Languages and scripts
68
+
69
+ Locale ids for Latin-script languages; Cyrillic locales and other scripts come from `cizgile/transliterate` so they only end up in your bundle when you use them.
70
+
71
+ ```ts
72
+ import { slugify } from "cizgile"
73
+ import { cyrillic, greek, uk, defineLocale, de } from "cizgile/transliterate"
74
+
75
+ slugify("Çay & Simit", { locale: "tr" }) // "cay-ve-simit"
76
+ slugify("Fisch & Chips", { locale: "de" }) // "fisch-und-chips"
77
+ slugify("Ærø", { locale: "da" }) // "aeroe"
78
+ slugify("Київ", { locale: uk }) // "kyiv"
79
+ slugify("Привет мир", { transliterate: [cyrillic] }) // "privet-mir"
80
+ slugify("Καλημέρα", { transliterate: [greek] }) // "kalimera"
81
+
82
+ const swiss = defineLocale(de, { id: "de-CH", table: { ß: "ss" } })
83
+ slugify("Straße", { locale: swiss }) // "strasse"
84
+ ```
85
+
86
+ Locale ids: `az da de es fi fr hu it nb nl pt sv tr vi`. Locale objects: those plus `bg mk ru sr uk`.
87
+
88
+ ### Unicode slugs
89
+
90
+ ```ts
91
+ import { slugify } from "cizgile"
92
+ import { iriToUri, uriToIri } from "cizgile/uri"
93
+
94
+ const slug = slugify("Ünïcödé final ①", { unicode: true }) // "ünïcödé-final-1"
95
+ const wire = iriToUri(slug) // "%C3%BCn%C3%AFc%C3%B6d%C3%A9-final-1"
96
+ uriToIri(wire) === slug // true
97
+ ```
98
+
99
+ Unicode slugs keep letters, digits and combining marks, are NFKC-normalised, never start with a mark and contain no invisible or bidi-control characters. Two optional guards for user-supplied titles:
100
+
101
+ ```ts
102
+ slugify("pаypal", { unicode: true, scripts: "single" }) // throws — that "а" is Cyrillic
103
+ slugify("مرحبا 123", { unicode: true, bidi: "encode" }) // "%D9%85%D8%B1%D8%AD%D8%A8%D8%A7-123"
104
+ ```
105
+
106
+ `scripts` applies the UTS #39 restriction levels (`"single"`, `"highly-restrictive"`, `"moderately-restrictive"`, `"any"`); `bidi` enforces RFC 3987 §4.2 (`"allow"`, `"encode"`, `"throw"`).
107
+
108
+ ### Unique slugs
109
+
110
+ ```ts
111
+ import { createSlugger } from "cizgile"
112
+
113
+ const slug = createSlugger()
114
+ slug("Hello") // "hello"
115
+ slug("Hello") // "hello-2"
116
+ slug("hello-2") // "hello-2-2" — never a duplicate
117
+ slug.reset()
118
+ ```
119
+
120
+ ### Validation
121
+
122
+ ```ts
123
+ import { isSlug } from "cizgile"
124
+
125
+ isSlug("hello-world") // true
126
+ isSlug("Hello World") // false
127
+ isSlug("hello_world", { separator: "_" }) // true
128
+ isSlug("你好-world", { unicode: true }) // true
129
+ ```
130
+
131
+ `isSlug` accepts exactly what `slugify` would produce under the same options.
132
+
133
+ ### All options
134
+
135
+ | option | default | what it does |
136
+ | --------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
137
+ | `separator` | `"-"` | Joins words. Any URL-safe punctuation (`- _ . ~ !$&'()*+,;= @`) or `""`. |
138
+ | `lowercase` | `true` | `false` keeps the original case. |
139
+ | `unicode` | `false` | Keep letters from every script instead of transliterating to ASCII. |
140
+ | `locale` | — | Language-specific rules: a locale id or a `Locale` object. |
141
+ | `transliterate` | `true` | `false` skips the tables (accents still fold); an array adds script tables. |
142
+ | `decamelize` | `false` | `fooBar` → `foo-bar`, `HTMLParser` → `html-parser`. |
143
+ | `replacements` | `[]` | `[from, to]` pairs applied first; spaces in `to` become separators. |
144
+ | `remove` | `/['’]/g` | Characters to delete rather than turn into separators (`don't` → `dont`). |
145
+ | `preserveCharacters` | `[]` | Extra URL-safe characters to keep, e.g. `["."]` for version numbers. |
146
+ | `preserveLeadingUnderscore` | `false` | `_draft` → `_draft`. |
147
+ | `preserveTrailingSeparator` | `false` | Keep a trailing separator while the user is still typing. |
148
+ | `maxLength` | — | Cut at a word boundary, never inside a character (emoji sequences, combining marks). Counts UTF-16 code units like `.length`. |
149
+ | `scripts` | `"any"` | Unicode mode: UTS #39 mixed-script restriction level. |
150
+ | `bidi` | `"allow"` | Unicode mode: RFC 3987 §4.2 direction rule — `"encode"` or `"throw"` on violation. |
151
+
152
+ The pipeline runs in this order: strip control/format characters → NFC → `replacements` → NFKC → `decamelize` → transliterate (locale → your tables → Latin → symbols → strip accents) → lowercase → `remove` → separators → `maxLength` → guards. Output is idempotent: `slugify(slugify(x)) === slugify(x)`.
153
+
154
+ ## Transliteration on its own
155
+
156
+ ```ts
157
+ import { transliterate, cyrillic, locales } from "cizgile/transliterate"
158
+
159
+ transliterate("Straße Ærø") // "Strasse AEro"
160
+ transliterate("Привет", { tables: [cyrillic] }) // "Privet"
161
+ transliterate("Ängsö", { locale: locales.sv }) // "Aengsoe"
162
+ transliterate("你好") // "你好" — unknown scripts are kept (use unknown: "drop" to remove)
163
+ ```
164
+
165
+ Tables: `latin symbols cyrillic cyrillicUk cyrillicBg cyrillicMk cyrillicSr greek arabic persian urdu pashto armenian georgian dhivehi`, plus `allScripts`. Where a letter is spelled differently at the start of a word (Armenian `ե`, Ukrainian `є ї й ю я`), the capital carries the word-initial form. `defineLocale` and `mergeTables` return new objects — nothing global is ever mutated.
166
+
167
+ ## URL toolkit
168
+
169
+ Everything in `cizgile/uri` follows RFC 3986 / RFC 3987 to the letter and is tested against the RFC's own examples and the WHATWG `URL` parser.
170
+
171
+ ```ts
172
+ import {
173
+ resolveUri,
174
+ relativize,
175
+ normalizeUri,
176
+ equivalentUris,
177
+ encodePathSegment,
178
+ percentEncode,
179
+ percentDecode,
180
+ isUri,
181
+ isAbsoluteUri,
182
+ isIPv6Address,
183
+ extractUri,
184
+ iriToUri,
185
+ uriToIri,
186
+ domainToAscii,
187
+ } from "cizgile/uri"
188
+
189
+ resolveUri("http://a/b/c/d;p?q", "../../g") // "http://a/g"
190
+ relativize("http://a/b/c/d;p?q", "http://a/b/g") // "../g"
191
+ normalizeUri("HTTP://www.EXAMPLE.com:80/%7e%41/./b/../c") // "http://www.example.com/~A/c"
192
+ equivalentUris("http://example.com", "http://example.com:80/") // true
193
+ encodePathSegment("a/b?c") // "a%2Fb%3Fc"
194
+ percentEncode("À ア") // "%C3%80%20%E3%82%A2"
195
+ isAbsoluteUri("http://a/b#c") // false — fragments are not allowed in an absolute-URI
196
+ isIPv6Address("::ffff:192.0.2.1") // true
197
+ extractUri("<http://a/b>.") // "http://a/b"
198
+ iriToUri("http://例え.jp/résumé", { host: "punycode" }) // "http://xn--r8jz45g.jp/r%C3%A9sum%C3%A9"
199
+ ```
200
+
201
+ <details>
202
+ <summary><b>Full reference</b></summary>
203
+
204
+ **Characters and percent-encoding (RFC 3986 §2)**
205
+ `isUnreserved` `isReserved` `isGenDelim` `isSubDelim` `isPchar` `isSegmentNzNc` `isQueryChar` `isScheme` — per code point.
206
+ `percentEncode(text, keep?)` — UTF-8, uppercase hex. `keep` names a set: RFC `"unreserved" "pchar" "segment-nz-nc" "path" "query" "fragment" "userinfo"`, WHATWG `"whatwg-c0-control" "whatwg-fragment" "whatwg-query" "whatwg-special-query" "whatwg-path" "whatwg-userinfo" "whatwg-component" "form"`, or a predicate.
207
+ `percentDecode(text, { plusAsSpace })`, `normalizePercentEncoding(text)`.
208
+ `encodePathSegment(seg, { noColon })`, `encodePath(path, { relative })`, `encodeQuery`, `encodeFragment`, `encodeForm`.
209
+
210
+ **Hosts (§3.2.2)**
211
+ `isIPv4Address` `isIPv6Address` `isIPvFuture` `isIPLiteral` `isRegName` `isHost` `parseHost` `parseAuthority` `serializeAuthority`. `0x7f.0.0.1` and `2130706433` are registered names, not addresses (§7.4).
212
+
213
+ **Parsing and validation (§4, Appendix A/B)**
214
+ `parseUri` `serializeUri` — components stay distinct from "absent"; the serializer inserts `/.` or `./` where the grammar requires it.
215
+ `isUriReference` `isUri` `isAbsoluteUri` `isRelativeReference` `classifyReference` `pathForm` — validating parser built from the ABNF.
216
+ `isIriReference` `isIri` `isIunreserved` `isIpchar` — the same for IRIs (RFC 3987 §2.2).
217
+ `extractUri(text)` — Appendix C: strips `<>`, quotes, `URL:` prefixes, trailing punctuation and line-wrap whitespace.
218
+
219
+ **Resolution (§5)**
220
+ `resolveUri(base, ref, { strict, allowRelativeBase })` — every §5.4 example passes; strict by default (`http:g` stays `http:g`).
221
+ `relativize(base, target)` — shortest reference that resolves back to `target`.
222
+ `removeDotSegments(path)` — the literal two-buffer algorithm. `mergePaths(base, refPath)`.
223
+ `isSameDocumentReference(base, ref, { normalize })`.
224
+
225
+ **Normalisation and comparison (§6)**
226
+ `normalizeUri(uri, { defaultPorts, schemeBased, userinfo })` — case, percent-encoding, dot segments, default ports, empty path → `/`; `userinfo: "strip-password" | "strip"` for logs.
227
+ `normalizePath(path, { trailingSlash })`.
228
+ `equivalentUris(a, b, { level, base, ignoreFragment })` — `"simple"`, `"syntax"` or `"scheme"` (default). Never maps IRIs to URIs (RFC 3987 §5.3.1).
229
+
230
+ **IRIs (RFC 3987)**
231
+ `isUcschar` `isIprivate` `isBidiControl` `hasBidiControls`.
232
+ `iriToUri(iri, { bidi, nfc, strict, host })` — percent-encodes without altering characters (§3.1 step 1c); `host: "punycode"` converts the domain; `strict` rejects characters no IRI may contain.
233
+ `uriToIri(uri)` — decodes only what §3.2 allows, per component.
234
+ `punycodeEncode` `punycodeDecode` `domainToAscii` `domainToUnicode` — RFC 3492, no dependencies.
235
+
236
+ Deliberately not implemented: RFC 6874 IPv6 zone identifiers (reverted by RFC 9844) and the network-based normalisation of §6.2.4.
237
+
238
+ </details>
239
+
240
+ ## For AI agents
241
+
242
+ If you are an assistant writing code with this library, these are the facts that matter:
243
+
244
+ - Import paths: `cizgile` (slugs), `cizgile/transliterate` (tables, locales), `cizgile/uri` (URLs). ESM only, no default exports, no side effects, no runtime dependencies.
245
+ - `slugify(text, options?)` returns `""` for input with nothing usable — it never throws on ordinary text. It throws `RangeError`/`TypeError` only for invalid options (`separator: "/"`, `preserveCharacters` containing the separator, a non-global `remove` regex, a negative `maxLength`) and, in unicode mode, when `scripts` or `bidi: "throw"` rejects the result.
246
+ - The ASCII output is always a valid path segment; put it in a URL as-is. For `unicode: true` output, call `iriToUri(slug)` before putting it on the wire.
247
+ - Cyrillic and other non-Latin scripts are opt-in: pass `transliterate: [cyrillic]` or a locale object such as `uk` from `cizgile/transliterate`. Without them, Cyrillic text produces `""` in ASCII mode.
248
+ - `createSlugger()` is the way to get unique slugs in a document or import job; do not append counters yourself.
249
+ - Use `resolveUri`, `normalizeUri` and `equivalentUris` instead of string concatenation or `new URL()` when you need RFC behaviour (strict scheme handling, no special-scheme rewriting, no host IDNA unless you ask for it).
250
+ - Every exported function has an explicit TypeScript signature; the `.d.mts` files in `dist/` are the authoritative API.
251
+
252
+ ## How it compares
253
+
254
+ | input | cizgile | Django `slugify` | Rails `parameterize` | `@sindresorhus/slugify` |
255
+ | --------------------------- | -------------------- | ---------------- | -------------------- | ----------------------- |
256
+ | `" Joel is a slug "` | `joel-is-a-slug` | same | same | same |
257
+ | `"jack & jill"` | `jack-and-jill` | `jack-jill` | `jack-jill` | `jack-and-jill` |
258
+ | `"don't"` | `dont` | `dont` | `don-t` | `dont` |
259
+ | `"fooBar"` | `foobar` | `foobar` | `foobar` | `foo-bar` |
260
+ | `"snake_case"` | `snake-case` | `snake_case` | `snake_case` | `snake-case` |
261
+ | `"Straße"` (`locale: "de"`) | `strasse` | `strae` | `strasse` | `strasse` |
262
+ | `"Привет"` | `""` (opt-in tables) | `""` | `""` | `privet` |
263
+
264
+ `decamelize` is off by default (Django/Rails behaviour) and `&` is spelled out (sindresorhus behaviour); both are one option away.
265
+
266
+ ## Specifications
267
+
268
+ RFC 3986 (with errata 2033, 4547, 4789, 5428), RFC 3987, RFC 3492, RFC 8820, RFC 9844, the WHATWG URL Standard's percent-encode sets, Unicode UTS #39 restriction levels and UAX #29 grapheme boundaries, Google Search Central's URL guidance. The test suite runs every example those documents contain.
269
+
270
+ ## Development
271
+
272
+ ```sh
273
+ bun install
274
+ bun run test # oxlint, oxfmt, tsc, vitest under node, then vitest under bun
275
+ bun run build # rolldown → dist/*.mjs + dist/*.d.mts
276
+ bun run coverage
277
+ bun run release # bumpp: bump, tag, push — the tag publishes to npm
278
+ ```
279
+
280
+ ## Credits
281
+
282
+ - [simov/slugify](https://github.com/simov/slugify) — the charmap + per-locale override idea and most Cyrillic, Greek, Arabic and symbol values.
283
+ - [sindresorhus/slugify](https://github.com/sindresorhus/slugify) and [sindresorhus/transliterate](https://github.com/sindresorhus/transliterate) — `decamelize`, custom replacements, the counter slugger, and the Armenian, Georgian and Dhivehi tables.
284
+ - [Django](https://github.com/django/django) and [Rails](https://github.com/rails/rails) — the reference behaviours the parity tests are written against.
285
+ - The [WHATWG URL Standard](https://url.spec.whatwg.org/) — percent-encode sets and the parser every result is cross-checked with.
286
+ - [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986) by Berners-Lee, Fielding and Masinter, and [RFC 3987](https://datatracker.ietf.org/doc/html/rfc3987) by Duerst and Suignard.
287
+ - [Rolldown](https://rolldown.rs), [Oxc](https://oxc.rs), [Vitest](https://vitest.dev), [Bun](https://bun.sh) and [TypeScript](https://www.typescriptlang.org).
288
+
289
+ ## License
290
+
291
+ MIT. Transliteration values are derived from simov/slugify and sindresorhus/transliterate (both MIT).
@@ -0,0 +1,55 @@
1
+ import { a as TransliterationTable, i as LocaleId, n as LatinLocaleId, r as Locale } from "./shared/types-C1iMvUXh.mjs";
2
+ //#region src/slug/bidi.d.ts
3
+ export declare function isBidiSafeComponent(text: string): boolean;
4
+ //#endregion
5
+ //#region src/slug/decamelize.d.ts
6
+ export declare function decamelize(input: string): string;
7
+ //#endregion
8
+ //#region src/slug/scripts.d.ts
9
+ type ScriptRestriction = "single" | "highly-restrictive" | "moderately-restrictive" | "any";
10
+ interface ScriptCheck {
11
+ readonly ok: boolean;
12
+ readonly scripts: readonly string[];
13
+ }
14
+ export declare function detectScripts(text: string): string[];
15
+ export declare function checkScripts(text: string, level?: ScriptRestriction): ScriptCheck;
16
+ //#endregion
17
+ //#region src/slug/options.d.ts
18
+ interface SlugifyOptions {
19
+ readonly separator?: string;
20
+ readonly lowercase?: boolean;
21
+ readonly unicode?: boolean;
22
+ readonly locale?: LatinLocaleId | Locale;
23
+ readonly transliterate?: boolean | readonly TransliterationTable[];
24
+ readonly decamelize?: boolean;
25
+ readonly replacements?: ReadonlyArray<readonly [string, string]>;
26
+ readonly remove?: RegExp | false;
27
+ readonly preserveCharacters?: readonly string[];
28
+ readonly preserveLeadingUnderscore?: boolean;
29
+ readonly preserveTrailingSeparator?: boolean;
30
+ readonly maxLength?: number;
31
+ readonly scripts?: ScriptRestriction;
32
+ readonly bidi?: "allow" | "encode" | "throw";
33
+ }
34
+ type IsSlugOptions = Pick<SlugifyOptions, "separator" | "lowercase" | "unicode" | "preserveCharacters" | "preserveLeadingUnderscore" | "preserveTrailingSeparator" | "maxLength" | "scripts" | "bidi">;
35
+ //#endregion
36
+ //#region src/slug/is-slug.d.ts
37
+ export declare function isSlug(input: string, options?: IsSlugOptions): boolean;
38
+ //#endregion
39
+ //#region src/slug/slugger.d.ts
40
+ interface Slugger {
41
+ (input: string, options?: SlugifyOptions): string;
42
+ reset(): void;
43
+ has(slug: string): boolean;
44
+ reserve(slug: string): void;
45
+ }
46
+ export declare function createSlugger(defaults?: SlugifyOptions): Slugger;
47
+ export declare const slugifyWithCounter: (defaults?: SlugifyOptions) => Slugger;
48
+ //#endregion
49
+ //#region src/slug/slugify.d.ts
50
+ export declare function slugify(input: string, options?: SlugifyOptions): string;
51
+ //#endregion
52
+ //#region src/slug/truncate.d.ts
53
+ export declare function truncateSlug(slug: string, maxLength: number, separator?: string): string;
54
+ //#endregion
55
+ export type { IsSlugOptions, LatinLocaleId, Locale, LocaleId, ScriptCheck, ScriptRestriction, Slugger, SlugifyOptions, TransliterationTable };