@verifyhash/slugify-lite 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 +21 -0
- package/README.md +112 -0
- package/index.js +0 -0
- package/package.json +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 <OWNER-NAME PLACEHOLDER>
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# slugify-lite
|
|
2
|
+
|
|
3
|
+
A tiny, **zero-dependency, zero-network** Node.js library that turns an arbitrary
|
|
4
|
+
string into a clean URL slug: `"Héllo, World!"` → `"hello-world"`. One CommonJS
|
|
5
|
+
file (`index.js`), no install step, no I/O, no runtime `require` of anything —
|
|
6
|
+
drop it into any project and `require` it.
|
|
7
|
+
|
|
8
|
+
## Who it's for
|
|
9
|
+
|
|
10
|
+
JavaScript/Node developers who need slugs for URLs, filenames, anchor IDs, or
|
|
11
|
+
database keys and want a **small, auditable, single-file** helper instead of
|
|
12
|
+
pulling in a larger dependency graph. It covers the everyday Western-European
|
|
13
|
+
case (accented Latin letters like `é`, `ü`, `ñ`, `ß`, `ø`, `æ`) with a pinned,
|
|
14
|
+
in-repo character map — no lookup tables downloaded at runtime, no transitive
|
|
15
|
+
packages. If you already reach for [`slugify`](https://www.npmjs.com/package/slugify)
|
|
16
|
+
or [`@sindresorhus/slugify`](https://www.npmjs.com/package/@sindresorhus/slugify)
|
|
17
|
+
but want zero deps and full control over the map, this is that.
|
|
18
|
+
|
|
19
|
+
## Install / use
|
|
20
|
+
|
|
21
|
+
No install — copy `index.js`, or `require` it directly:
|
|
22
|
+
|
|
23
|
+
```js
|
|
24
|
+
const slugify = require('./index.js');
|
|
25
|
+
|
|
26
|
+
slugify('Héllo, World!'); // 'hello-world'
|
|
27
|
+
slugify('Crème brûlée'); // 'creme-brulee'
|
|
28
|
+
slugify('Straße'); // 'strasse' (ß -> ss)
|
|
29
|
+
|
|
30
|
+
// custom separator
|
|
31
|
+
slugify('Hello World', { separator: '_' }); // 'hello_world'
|
|
32
|
+
|
|
33
|
+
// preserve case
|
|
34
|
+
slugify('CamelCase API', { lowercase: false }); // 'CamelCase-API'
|
|
35
|
+
|
|
36
|
+
// truncate to a max length on a WORD boundary (never mid-word)
|
|
37
|
+
slugify('The quick brown fox', { maxLength: 15 }); // 'the-quick-brown'
|
|
38
|
+
slugify('The quick brown fox', { maxLength: 13 }); // 'the-quick'
|
|
39
|
+
|
|
40
|
+
// custom replacements, merged OVER the built-in map (raw-char match)
|
|
41
|
+
slugify('100% cotton & wool', {
|
|
42
|
+
replacements: { '%': ' percent ', '&': ' and ' }
|
|
43
|
+
}); // '100-percent-cotton-and-wool'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## API
|
|
47
|
+
|
|
48
|
+
### `slugify(input, options?) → string`
|
|
49
|
+
|
|
50
|
+
`input` is coerced with `String()`; `null`/`undefined` return `''`.
|
|
51
|
+
|
|
52
|
+
| option | type | default | meaning |
|
|
53
|
+
| -------------- | --------- | ------- | ----------------------------------------------------------------------------------------- |
|
|
54
|
+
| `separator` | `string` | `'-'` | Character(s) used to join words. May be multi-character or `''`; matched literally. |
|
|
55
|
+
| `lowercase` | `boolean` | `true` | Lowercase the result. Set `false` to preserve case (transliteration still happens). |
|
|
56
|
+
| `maxLength` | `number` | — | Max output length. Truncated on a **word boundary** — never mid-word, never a trailing separator. |
|
|
57
|
+
| `replacements` | `object` | — | Single-char → string map, merged **over** the built-in map. Matched against the raw character (before lowercasing). |
|
|
58
|
+
|
|
59
|
+
Pipeline, in order: (1) transliterate each character (custom `replacements`
|
|
60
|
+
win over the built-in map, then the built-in map, else the char passes through);
|
|
61
|
+
(2) lowercase unless `lowercase: false`; (3) collapse every run of non-ASCII-
|
|
62
|
+
alphanumeric characters (`[^A-Za-z0-9]+`) to a single separator, which strips
|
|
63
|
+
punctuation, whitespace, and any unmapped characters; (4) trim leading/trailing
|
|
64
|
+
separators; (5) if `maxLength` is set, keep whole words while the running slug
|
|
65
|
+
(words joined by `separator`) stays `<= maxLength`.
|
|
66
|
+
|
|
67
|
+
The module also exposes `slugify.slugify`, `slugify.default` (both the same
|
|
68
|
+
function), and `slugify.charMap` — a **frozen** copy of the built-in map for
|
|
69
|
+
inspection.
|
|
70
|
+
|
|
71
|
+
## Limits (please read — this is the honest part)
|
|
72
|
+
|
|
73
|
+
- **It only romanizes what the built-in map covers.** The map is a small,
|
|
74
|
+
hand-maintained table of common accented/Latin-1 and a few Latin-Extended
|
|
75
|
+
characters (roughly `à á â ã ä å ā ă ą æ ç ć č ð è é ê ë ē ę ě ñ ń ň ø ō œ ß
|
|
76
|
+
þ ù ú û ü ū ů ý ÿ ž …` plus their uppercase forms). It is **not**
|
|
77
|
+
Unicode-complete and does **not** do context-aware romanization.
|
|
78
|
+
- **Non-Latin scripts are stripped, not transliterated.** Cyrillic (`Москва`),
|
|
79
|
+
Greek, Arabic, Hebrew, Hangul, and CJK (`日本語`) are **not** in the map, so
|
|
80
|
+
step 3 removes them. `slugify('日本語 test')` → `'test'`, and
|
|
81
|
+
`slugify('日本語')` → `''`. If you need Chinese→pinyin, Cyrillic→Latin, or
|
|
82
|
+
Greek→Latin romanization, use a dedicated transliteration library — that is
|
|
83
|
+
deliberately out of scope here.
|
|
84
|
+
- **Emoji and symbols are dropped** unless you supply a `replacements` entry
|
|
85
|
+
for them (e.g. `{ '&': ' and ' }`).
|
|
86
|
+
- **`maxLength` never splits a word.** If the very first word is longer than
|
|
87
|
+
`maxLength`, the result is `''` (there is no whole word that fits). It counts
|
|
88
|
+
the separator length between words, but does not hyphenate or ellipsize.
|
|
89
|
+
- **Custom `replacements` match the raw character**, before lowercasing — so to
|
|
90
|
+
override `ø` supply the lowercase key `'ø'`; an uppercase `'Ø'` in the input
|
|
91
|
+
is handled by the built-in uppercase map entry unless you add `'Ø'` yourself.
|
|
92
|
+
- **No collision avoidance / uniqueness.** Two different inputs can slug to the
|
|
93
|
+
same string (`'Café!'` and `'café'` both → `'cafe'`). If you need unique
|
|
94
|
+
slugs, dedupe at the call site.
|
|
95
|
+
|
|
96
|
+
## Running the tests
|
|
97
|
+
|
|
98
|
+
One command, Node's built-in `assert` only — no test runner, no dependencies:
|
|
99
|
+
|
|
100
|
+
```sh
|
|
101
|
+
node test/index.test.js
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
It prints `slugify-lite: all N tests passed.` and exits `0` on success. The
|
|
105
|
+
suite covers accented→ASCII transliteration (including `ß→ss`, `æ→ae`),
|
|
106
|
+
punctuation/whitespace collapsing, custom separators, non-Latin/CJK/emoji
|
|
107
|
+
passthrough behavior, `maxLength` word-boundary truncation, custom replacement
|
|
108
|
+
overrides, empty/whitespace-only input, and leading/trailing separator trimming.
|
|
109
|
+
|
|
110
|
+
## License
|
|
111
|
+
|
|
112
|
+
MIT — see `LICENSE`.
|
package/index.js
ADDED
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@verifyhash/slugify-lite",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Zero-dependency, zero-network string-to-URL-slug library for Node.js: Latin-1/accent transliteration via a pinned in-repo map, custom separator, word-boundary maxLength truncation, and custom replacement overrides.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"slug",
|
|
7
|
+
"slugify",
|
|
8
|
+
"url",
|
|
9
|
+
"transliterate",
|
|
10
|
+
"ascii",
|
|
11
|
+
"seo",
|
|
12
|
+
"zero-dependency"
|
|
13
|
+
],
|
|
14
|
+
"main": "index.js",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "node test/index.test.js"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"files": [
|
|
20
|
+
"index.js",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/verifyhash/libs.git",
|
|
30
|
+
"directory": "slugify-lite"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/verifyhash/libs/tree/main/slugify-lite#readme",
|
|
33
|
+
"bugs": {
|
|
34
|
+
"url": "https://github.com/verifyhash/libs/issues"
|
|
35
|
+
}
|
|
36
|
+
}
|