turkce-utils 0.0.0-stage → 0.1.1
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 +250 -2
- package/dist/case.d.ts +12 -0
- package/dist/case.d.ts.map +1 -0
- package/dist/case.js +18 -0
- package/dist/case.js.map +1 -0
- package/dist/cli.d.ts +10 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +119 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/initials.d.ts +12 -0
- package/dist/initials.d.ts.map +1 -0
- package/dist/initials.js +16 -0
- package/dist/initials.js.map +1 -0
- package/dist/normalize.d.ts +14 -0
- package/dist/normalize.d.ts.map +1 -0
- package/dist/normalize.js +27 -0
- package/dist/normalize.js.map +1 -0
- package/dist/numbers.d.ts +11 -0
- package/dist/numbers.d.ts.map +1 -0
- package/dist/numbers.js +76 -0
- package/dist/numbers.js.map +1 -0
- package/dist/ordinal.d.ts +11 -0
- package/dist/ordinal.d.ts.map +1 -0
- package/dist/ordinal.js +43 -0
- package/dist/ordinal.js.map +1 -0
- package/dist/readability.d.ts +24 -0
- package/dist/readability.d.ts.map +1 -0
- package/dist/readability.js +50 -0
- package/dist/readability.js.map +1 -0
- package/dist/slug.d.ts +18 -0
- package/dist/slug.d.ts.map +1 -0
- package/dist/slug.js +47 -0
- package/dist/slug.js.map +1 -0
- package/dist/sort.d.ts +12 -0
- package/dist/sort.d.ts.map +1 -0
- package/dist/sort.js +17 -0
- package/dist/sort.js.map +1 -0
- package/dist/syllables.d.ts +9 -0
- package/dist/syllables.d.ts.map +1 -0
- package/dist/syllables.js +12 -0
- package/dist/syllables.js.map +1 -0
- package/dist/title.d.ts +6 -0
- package/dist/title.d.ts.map +1 -0
- package/dist/title.js +14 -0
- package/dist/title.js.map +1 -0
- package/dist/truncate.d.ts +6 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +18 -0
- package/dist/truncate.js.map +1 -0
- package/package.json +64 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mehmet Fatih Doğan
|
|
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
CHANGED
|
@@ -1,3 +1,251 @@
|
|
|
1
|
-
#
|
|
1
|
+
# turkce-utils
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/fatihdogann/turkce-utils/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/turkce-utils)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](#development)
|
|
7
|
+
|
|
8
|
+
Zero-dependency TypeScript helpers for Turkish text — and a `turkce` CLI.
|
|
9
|
+
|
|
10
|
+
Turkish is not English with a few accents: `I` lowercases to `ı`, `i`
|
|
11
|
+
uppercases to `İ`, the alphabet puts `ç`, `ğ`, `ı`, `ö`, `ş`, `ü` in their own
|
|
12
|
+
places, and reading difficulty needs its own formula. `turkce-utils` packages
|
|
13
|
+
those rules into small, tested, dependency-free functions.
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { slugify, upperTr, sortTr } from "turkce-utils";
|
|
17
|
+
|
|
18
|
+
slugify("Çılgın Şöför İĞÜ"); // "cilgin-sofor-igu"
|
|
19
|
+
upperTr("istanbul ışık"); // "İSTANBUL IŞIK"
|
|
20
|
+
sortTr(["üzüm", "armut", "çilek"]); // ["armut", "çilek", "üzüm"]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install turkce-utils
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Requires Node.js 20 or later. The published package is compiled ESM with type
|
|
30
|
+
declarations and **zero runtime dependencies**.
|
|
31
|
+
|
|
32
|
+
Working on the library itself? Node.js 22.18+ can run the TypeScript sources
|
|
33
|
+
directly — see [Development](#development).
|
|
34
|
+
|
|
35
|
+
## Modules
|
|
36
|
+
|
|
37
|
+
| Module | What it does |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| `slug` | Turkish-aware slug generation |
|
|
40
|
+
| `case` | Turkish letter casing (i/İ, ı/I) |
|
|
41
|
+
| `sort` | Turkish alphabet collation |
|
|
42
|
+
| `title` | Turkish title casing |
|
|
43
|
+
| `normalize` | Normalise typographic punctuation and whitespace |
|
|
44
|
+
| `numbers` | Spell out numbers in Turkish |
|
|
45
|
+
| `ordinal` | Turkish ordinal numbers |
|
|
46
|
+
| `syllables` | Count syllables |
|
|
47
|
+
| `readability` | Ateşman readability score |
|
|
48
|
+
| `truncate` | Truncate on a word boundary |
|
|
49
|
+
| `initials` | Initials from a full name |
|
|
50
|
+
| `cli` | `turkce` command line interface |
|
|
51
|
+
|
|
52
|
+
## API
|
|
53
|
+
|
|
54
|
+
### `slugify(input, options?)`
|
|
55
|
+
|
|
56
|
+
Turkish-aware slug: `ç → c`, `ğ → g`, `ı → i`, `İ → i`, `ö → o`, `ş → s`, `ü → u`.
|
|
57
|
+
Remaining diacritics are folded, punctuation is dropped.
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { slugify } from "turkce-utils";
|
|
61
|
+
|
|
62
|
+
slugify("Çılgın Şöför İĞÜ"); // "cilgin-sofor-igu"
|
|
63
|
+
slugify("Türkçe Metin", { separator: "_" }); // "turkce_metin"
|
|
64
|
+
slugify("kahve falı bakıyoruz", { maxLength: 10 }); // "kahve"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Options: `separator` (default `"-"`), `lowercase` (default `true`), `maxLength`.
|
|
68
|
+
|
|
69
|
+
### `lowerTr(input)` / `upperTr(input)`
|
|
70
|
+
|
|
71
|
+
Turkish letter casing. JavaScript maps `I → i` and `i → I`; Turkish pairs the
|
|
72
|
+
dotless `ı` with `I` and the dotted `i` with `İ`.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
import { lowerTr, upperTr } from "turkce-utils";
|
|
76
|
+
|
|
77
|
+
lowerTr("İSTANBUL"); // "istanbul"
|
|
78
|
+
lowerTr("IŞIK"); // "ışık"
|
|
79
|
+
upperTr("istanbul ışık"); // "İSTANBUL IŞIK"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### `sortTr(items)` / `compareTr(a, b)`
|
|
83
|
+
|
|
84
|
+
Sort by the Turkish alphabet — `ç` after `c`, `ğ` after `g`, `ı` before `i`,
|
|
85
|
+
`ö`, `ş`, `ü` in place — backed by `Intl.Collator("tr")`.
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { sortTr } from "turkce-utils";
|
|
89
|
+
|
|
90
|
+
sortTr(["zeytin", "armut", "üzüm", "çilek", "ıspanak", "incir"]);
|
|
91
|
+
// ["armut", "çilek", "ıspanak", "incir", "üzüm", "zeytin"]
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### `titleCaseTr(input)`
|
|
95
|
+
|
|
96
|
+
Title-case with Turkish rules; the suffix after an apostrophe stays lowercase.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { titleCaseTr } from "turkce-utils";
|
|
100
|
+
|
|
101
|
+
titleCaseTr("çılgın şöför istanbul'da"); // "Çılgın Şöför İstanbul'da"
|
|
102
|
+
titleCaseTr("TÜRKÇE METİN IŞIK"); // "Türkçe Metin Işık"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### `normalizeTr(input, options?)`
|
|
106
|
+
|
|
107
|
+
NFC normalisation plus typographic fixes: smart quotes → `"`/`'`, en/em dashes →
|
|
108
|
+
`-`, `…` → `...`, non-breaking and zero-width spaces handled, whitespace collapsed.
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { normalizeTr } from "turkce-utils";
|
|
112
|
+
|
|
113
|
+
normalizeTr("“Merhaba” —dünya…"); // '"Merhaba" -dünya...'
|
|
114
|
+
normalizeTr(" bir iki "); // "bir iki"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### `numberToWordsTr(value)` / `integerToWordsTr(value)`
|
|
118
|
+
|
|
119
|
+
Spell out numbers in Turkish, including negatives and decimals.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { numberToWordsTr } from "turkce-utils";
|
|
123
|
+
|
|
124
|
+
numberToWordsTr(1234); // "bin iki yüz otuz dört"
|
|
125
|
+
numberToWordsTr(1000000); // "bir milyon"
|
|
126
|
+
numberToWordsTr(-5); // "eksi beş"
|
|
127
|
+
numberToWordsTr(3.5); // "üç virgül beş"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`1000` is spoken as `bin`, never `bir bin`.
|
|
131
|
+
|
|
132
|
+
### `ordinalTr(value)` / `ordinalWordTr(value)`
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { ordinalTr, ordinalWordTr } from "turkce-utils";
|
|
136
|
+
|
|
137
|
+
ordinalTr(3); // "3."
|
|
138
|
+
ordinalWordTr(3); // "üçüncü"
|
|
139
|
+
ordinalWordTr(4); // "dördüncü"
|
|
140
|
+
ordinalWordTr(121); // "yüz yirmi birinci"
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Suffixes follow Turkish vowel harmony.
|
|
144
|
+
|
|
145
|
+
### `syllablesTr(input)`
|
|
146
|
+
|
|
147
|
+
Turkish is one vowel per syllable, so the count is the number of vowel groups.
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import { syllablesTr } from "turkce-utils";
|
|
151
|
+
|
|
152
|
+
syllablesTr("Türkçe"); // 2
|
|
153
|
+
syllablesTr("yapıyoruz"); // 4
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `atestmanScore(text)` / `atestmanGrade(score)`
|
|
157
|
+
|
|
158
|
+
Ateşman readability score for Turkish (Ateşman, 1997):
|
|
159
|
+
|
|
160
|
+
```text
|
|
161
|
+
score = 198.43 − 40.175 × (syllables / words) − 2.610 × (words / sentences)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
import { atestmanScore } from "turkce-utils";
|
|
166
|
+
|
|
167
|
+
atestmanScore("Merhaba dünya. Nasılsın?");
|
|
168
|
+
// { score: 87.38, grade: "kolay", syllables: 8, words: 3, sentences: 2 }
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Grades: `çok kolay` (90+), `kolay` (70+), `orta` (50+), `zor` (30+), `çok zor`.
|
|
172
|
+
|
|
173
|
+
### `truncateTr(text, maxLength, ellipsis?)`
|
|
174
|
+
|
|
175
|
+
Shorten text on the last word boundary, never exceeding `maxLength`.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
import { truncateTr } from "turkce-utils";
|
|
179
|
+
|
|
180
|
+
truncateTr("kahve falı bakıyoruz", 12); // "kahve falı…"
|
|
181
|
+
truncateTr("abcdef", 4, "..."); // "a..."
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### `initialsTr(input, options?)`
|
|
185
|
+
|
|
186
|
+
Initials from a full name, uppercased with Turkish rules.
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
import { initialsTr } from "turkce-utils";
|
|
190
|
+
|
|
191
|
+
initialsTr("Mehmet Fatih Doğan"); // "MFD"
|
|
192
|
+
initialsTr("ışık inci"); // "Iİ"
|
|
193
|
+
initialsTr("Mehmet Fatih Doğan", { separator: "." }); // "M.F.D"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### CLI
|
|
197
|
+
|
|
198
|
+
The package ships a `turkce` command covering every helper:
|
|
199
|
+
|
|
200
|
+
```console
|
|
201
|
+
$ turkce slug "Çılgın Şöför"
|
|
202
|
+
cilgin-sofor
|
|
203
|
+
|
|
204
|
+
$ turkce words 1234
|
|
205
|
+
bin iki yüz otuz dört
|
|
206
|
+
|
|
207
|
+
$ printf 'üzüm\narmut\nçilek\n' | turkce sort
|
|
208
|
+
armut
|
|
209
|
+
çilek
|
|
210
|
+
üzüm
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Run `turkce --help` for the full command list.
|
|
214
|
+
|
|
215
|
+
## Development
|
|
216
|
+
|
|
217
|
+
Node.js 22.18+ runs the TypeScript sources directly (native type stripping),
|
|
218
|
+
so no build step is needed for tests:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
npm test # node --test
|
|
222
|
+
npm run typecheck # tsc --noEmit
|
|
223
|
+
npm run build # tsc -> dist/
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Every module has a matching test in `test/`. The library has **zero runtime
|
|
227
|
+
dependencies**.
|
|
228
|
+
|
|
229
|
+
### Releasing
|
|
230
|
+
|
|
231
|
+
Versions are published from GitHub Actions using npm **trusted publishing**
|
|
232
|
+
(OIDC), so no long-lived npm token is stored anywhere. Bump the version and push
|
|
233
|
+
a matching tag:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
npm version patch # or minor / major
|
|
237
|
+
git push --follow-tags
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
[`.github/workflows/publish.yml`](.github/workflows/publish.yml) checks that the
|
|
241
|
+
tag matches `package.json`, runs the typecheck and the tests, and publishes with
|
|
242
|
+
a provenance attestation. It can also be started manually as a dry run.
|
|
243
|
+
|
|
244
|
+
## Developer
|
|
245
|
+
|
|
246
|
+
**Mehmet Fatih Doğan** — Software Developer.
|
|
247
|
+
|
|
248
|
+
- 🌐 Portfolio & Contact: [mehmetfatihdogan.com.tr](https://mehmetfatihdogan.com.tr)
|
|
249
|
+
- 💻 GitHub: [@fatihdogann](https://github.com/fatihdogann)
|
|
250
|
+
|
|
251
|
+
For questions, bug reports, or feedback about this project, feel free to contact me through [my website](https://mehmetfatihdogan.com.tr).
|
package/dist/case.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware letter casing.
|
|
3
|
+
*
|
|
4
|
+
* JavaScript's `toLowerCase`/`toUpperCase` follow the Unicode default, which
|
|
5
|
+
* maps `I` to `i` and `i` to `I`. Turkish is different: the dotless `ı` pairs
|
|
6
|
+
* with `I`, and the dotted `i` pairs with `İ`.
|
|
7
|
+
*/
|
|
8
|
+
/** Lowercase a string using Turkish rules (`I` → `ı`, `İ` → `i`). */
|
|
9
|
+
export declare function lowerTr(input: string): string;
|
|
10
|
+
/** Uppercase a string using Turkish rules (`i` → `İ`, `ı` → `I`). */
|
|
11
|
+
export declare function upperTr(input: string): string;
|
|
12
|
+
//# sourceMappingURL=case.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"case.d.ts","sourceRoot":"","sources":["../src/case.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAKH,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,qEAAqE;AACrE,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C"}
|
package/dist/case.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware letter casing.
|
|
3
|
+
*
|
|
4
|
+
* JavaScript's `toLowerCase`/`toUpperCase` follow the Unicode default, which
|
|
5
|
+
* maps `I` to `i` and `i` to `I`. Turkish is different: the dotless `ı` pairs
|
|
6
|
+
* with `I`, and the dotted `i` pairs with `İ`.
|
|
7
|
+
*/
|
|
8
|
+
const LOWER = { I: "ı", İ: "i" };
|
|
9
|
+
const UPPER = { i: "İ", ı: "I" };
|
|
10
|
+
/** Lowercase a string using Turkish rules (`I` → `ı`, `İ` → `i`). */
|
|
11
|
+
export function lowerTr(input) {
|
|
12
|
+
return input.replace(/[Iİ]/g, (char) => LOWER[char] ?? char).toLowerCase();
|
|
13
|
+
}
|
|
14
|
+
/** Uppercase a string using Turkish rules (`i` → `İ`, `ı` → `I`). */
|
|
15
|
+
export function upperTr(input) {
|
|
16
|
+
return input.replace(/[iı]/g, (char) => UPPER[char] ?? char).toUpperCase();
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=case.js.map
|
package/dist/case.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"case.js","sourceRoot":"","sources":["../src/case.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,KAAK,GAAqC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;AACnE,MAAM,KAAK,GAAqC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;AAEnE,qEAAqE;AACrE,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7E,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AAC7E,CAAC"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `turkce` — a small CLI over the turkce-utils helpers.
|
|
4
|
+
*
|
|
5
|
+
* Usage: `turkce <command> [text...]`, or pipe text on stdin.
|
|
6
|
+
*/
|
|
7
|
+
export declare const HELP = "turkce \u2014 Turkish text helpers\n\nUsage:\n turkce <command> [text...] text can also be piped on stdin\n\nCommands:\n slug URL-safe slug (\u00E7 -> c, \u011F -> g, ...)\n upper Turkish uppercase (i -> \u0130, \u0131 -> I)\n lower Turkish lowercase (I -> \u0131, \u0130 -> i)\n title Turkish title case\n normalize normalise quotes, dashes, whitespace\n words spell out a number (1234 -> \"bin iki y\u00FCz otuz d\u00F6rt\")\n ordinal spill out an ordinal (3 -> \"\u00FC\u00E7\u00FCnc\u00FC\")\n syllables count syllables\n readability Ate\u015Fman readability score\n initials initials from a full name\n truncate shorten text (max 80 chars)\n sort sort lines by the Turkish alphabet\n\nOptions:\n -h, --help show this help\n";
|
|
8
|
+
/** Run a command against `input` and return the text to print. */
|
|
9
|
+
export declare function runCommand(command: string, input: string): string;
|
|
10
|
+
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;GAIG;AAgBH,eAAO,MAAM,IAAI,kzBAqBhB,CAAC;AAEF,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CA+BjE"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `turkce` — a small CLI over the turkce-utils helpers.
|
|
4
|
+
*
|
|
5
|
+
* Usage: `turkce <command> [text...]`, or pipe text on stdin.
|
|
6
|
+
*/
|
|
7
|
+
import { slugify } from "./slug.js";
|
|
8
|
+
import { lowerTr, upperTr } from "./case.js";
|
|
9
|
+
import { sortTr } from "./sort.js";
|
|
10
|
+
import { titleCaseTr } from "./title.js";
|
|
11
|
+
import { normalizeTr } from "./normalize.js";
|
|
12
|
+
import { numberToWordsTr } from "./numbers.js";
|
|
13
|
+
import { ordinalWordTr } from "./ordinal.js";
|
|
14
|
+
import { syllablesTr } from "./syllables.js";
|
|
15
|
+
import { atestmanScore } from "./readability.js";
|
|
16
|
+
import { truncateTr } from "./truncate.js";
|
|
17
|
+
import { initialsTr } from "./initials.js";
|
|
18
|
+
import { realpathSync } from "node:fs";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
20
|
+
export const HELP = `turkce — Turkish text helpers
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
turkce <command> [text...] text can also be piped on stdin
|
|
24
|
+
|
|
25
|
+
Commands:
|
|
26
|
+
slug URL-safe slug (ç -> c, ğ -> g, ...)
|
|
27
|
+
upper Turkish uppercase (i -> İ, ı -> I)
|
|
28
|
+
lower Turkish lowercase (I -> ı, İ -> i)
|
|
29
|
+
title Turkish title case
|
|
30
|
+
normalize normalise quotes, dashes, whitespace
|
|
31
|
+
words spell out a number (1234 -> "bin iki yüz otuz dört")
|
|
32
|
+
ordinal spill out an ordinal (3 -> "üçüncü")
|
|
33
|
+
syllables count syllables
|
|
34
|
+
readability Ateşman readability score
|
|
35
|
+
initials initials from a full name
|
|
36
|
+
truncate shorten text (max 80 chars)
|
|
37
|
+
sort sort lines by the Turkish alphabet
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
-h, --help show this help
|
|
41
|
+
`;
|
|
42
|
+
/** Run a command against `input` and return the text to print. */
|
|
43
|
+
export function runCommand(command, input) {
|
|
44
|
+
switch (command) {
|
|
45
|
+
case "slug":
|
|
46
|
+
return slugify(input);
|
|
47
|
+
case "upper":
|
|
48
|
+
return upperTr(input);
|
|
49
|
+
case "lower":
|
|
50
|
+
return lowerTr(input);
|
|
51
|
+
case "title":
|
|
52
|
+
return titleCaseTr(input);
|
|
53
|
+
case "normalize":
|
|
54
|
+
return normalizeTr(input);
|
|
55
|
+
case "words":
|
|
56
|
+
return numberToWordsTr(Number(input.trim()));
|
|
57
|
+
case "ordinal":
|
|
58
|
+
return ordinalWordTr(Number(input.trim()));
|
|
59
|
+
case "syllables":
|
|
60
|
+
return String(syllablesTr(input));
|
|
61
|
+
case "initials":
|
|
62
|
+
return initialsTr(input);
|
|
63
|
+
case "truncate":
|
|
64
|
+
return truncateTr(input, 80);
|
|
65
|
+
case "sort":
|
|
66
|
+
return sortTr(input.split("\n").filter((line) => line.length > 0)).join("\n");
|
|
67
|
+
case "readability": {
|
|
68
|
+
const result = atestmanScore(input);
|
|
69
|
+
return `${result.score} (${result.grade}) — ${result.words} kelime, ${result.sentences} cümle`;
|
|
70
|
+
}
|
|
71
|
+
default:
|
|
72
|
+
throw new Error(`unknown command: ${command}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function readStdin() {
|
|
76
|
+
const chunks = [];
|
|
77
|
+
for await (const chunk of process.stdin)
|
|
78
|
+
chunks.push(chunk);
|
|
79
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
80
|
+
}
|
|
81
|
+
async function main(argv) {
|
|
82
|
+
const [command, ...rest] = argv;
|
|
83
|
+
if (!command || command === "-h" || command === "--help" || command === "help") {
|
|
84
|
+
process.stdout.write(HELP);
|
|
85
|
+
return command ? 0 : 1;
|
|
86
|
+
}
|
|
87
|
+
const input = rest.length > 0 ? rest.join(" ") : (await readStdin()).replace(/\n$/, "");
|
|
88
|
+
try {
|
|
89
|
+
process.stdout.write(runCommand(command, input) + "\n");
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
process.stderr.write(`turkce: ${error.message}\n`);
|
|
94
|
+
return 1;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* True when this file is the process entry point.
|
|
99
|
+
*
|
|
100
|
+
* `process.argv[1]` can be a symlink — npm links `node_modules/.bin/turkce`
|
|
101
|
+
* to `dist/cli.js` — so both sides are resolved to their real path first.
|
|
102
|
+
*/
|
|
103
|
+
function isEntryPoint() {
|
|
104
|
+
const invoked = process.argv[1];
|
|
105
|
+
if (!invoked)
|
|
106
|
+
return false;
|
|
107
|
+
try {
|
|
108
|
+
return realpathSync(invoked) === realpathSync(fileURLToPath(import.meta.url));
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (isEntryPoint()) {
|
|
115
|
+
main(process.argv.slice(2)).then((code) => {
|
|
116
|
+
process.exitCode = code;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { slugify } from "./slug.ts";
|
|
2
|
+
export type { SlugifyOptions } from "./slug.ts";
|
|
3
|
+
export { lowerTr, upperTr } from "./case.ts";
|
|
4
|
+
export { compareTr, sortTr } from "./sort.ts";
|
|
5
|
+
export { titleCaseTr } from "./title.ts";
|
|
6
|
+
export { normalizeTr } from "./normalize.ts";
|
|
7
|
+
export type { NormalizeTrOptions } from "./normalize.ts";
|
|
8
|
+
export { numberToWordsTr, integerToWordsTr } from "./numbers.ts";
|
|
9
|
+
export { ordinalTr, ordinalWordTr } from "./ordinal.ts";
|
|
10
|
+
export { syllablesTr } from "./syllables.ts";
|
|
11
|
+
export { atestmanScore, atestmanGrade } from "./readability.ts";
|
|
12
|
+
export type { ReadabilityResult, AtestmanGrade } from "./readability.ts";
|
|
13
|
+
export { truncateTr } from "./truncate.ts";
|
|
14
|
+
export { initialsTr } from "./initials.ts";
|
|
15
|
+
export type { InitialsTrOptions } from "./initials.ts";
|
|
16
|
+
export { runCommand, HELP } from "./cli.ts";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAChE,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { slugify } from "./slug.js";
|
|
2
|
+
export { lowerTr, upperTr } from "./case.js";
|
|
3
|
+
export { compareTr, sortTr } from "./sort.js";
|
|
4
|
+
export { titleCaseTr } from "./title.js";
|
|
5
|
+
export { normalizeTr } from "./normalize.js";
|
|
6
|
+
export { numberToWordsTr, integerToWordsTr } from "./numbers.js";
|
|
7
|
+
export { ordinalTr, ordinalWordTr } from "./ordinal.js";
|
|
8
|
+
export { syllablesTr } from "./syllables.js";
|
|
9
|
+
export { atestmanScore, atestmanGrade } from "./readability.js";
|
|
10
|
+
export { truncateTr } from "./truncate.js";
|
|
11
|
+
export { initialsTr } from "./initials.js";
|
|
12
|
+
export { runCommand, HELP } from "./cli.js";
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initials from Turkish names.
|
|
3
|
+
*/
|
|
4
|
+
export interface InitialsTrOptions {
|
|
5
|
+
/** Keep only the first N initials. */
|
|
6
|
+
limit?: number;
|
|
7
|
+
/** String placed between initials. Defaults to `""`. */
|
|
8
|
+
separator?: string;
|
|
9
|
+
}
|
|
10
|
+
/** Build uppercase initials from a full name: "Mehmet Fatih Doğan" → "MFD". */
|
|
11
|
+
export declare function initialsTr(input: string, options?: InitialsTrOptions): string;
|
|
12
|
+
//# sourceMappingURL=initials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initials.d.ts","sourceRoot":"","sources":["../src/initials.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,MAAM,CAWjF"}
|
package/dist/initials.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initials from Turkish names.
|
|
3
|
+
*/
|
|
4
|
+
import { upperTr } from "./case.js";
|
|
5
|
+
/** Build uppercase initials from a full name: "Mehmet Fatih Doğan" → "MFD". */
|
|
6
|
+
export function initialsTr(input, options = {}) {
|
|
7
|
+
const separator = options.separator ?? "";
|
|
8
|
+
const initials = input
|
|
9
|
+
.trim()
|
|
10
|
+
.split(/\s+/)
|
|
11
|
+
.filter((word) => word.length > 0)
|
|
12
|
+
.map((word) => upperTr(word[0] ?? ""));
|
|
13
|
+
const limited = options.limit !== undefined && options.limit >= 0 ? initials.slice(0, options.limit) : initials;
|
|
14
|
+
return limited.join(separator);
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=initials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initials.js","sourceRoot":"","sources":["../src/initials.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,UAA6B,EAAE;IACvE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK;SACnB,IAAI,EAAE;SACN,KAAK,CAAC,KAAK,CAAC;SACZ,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;SACjC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAEzC,MAAM,OAAO,GACX,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IAClG,OAAO,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalise Turkish text for storage and comparison.
|
|
3
|
+
*
|
|
4
|
+
* Applies NFC, replaces typographic punctuation (smart quotes, en/em dashes,
|
|
5
|
+
* ellipsis, non-breaking spaces) with plain ASCII equivalents and collapses
|
|
6
|
+
* repeated whitespace.
|
|
7
|
+
*/
|
|
8
|
+
export interface NormalizeTrOptions {
|
|
9
|
+
/** Collapse runs of whitespace and trim the result. Defaults to `true`. */
|
|
10
|
+
collapseWhitespace?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/** Return a normalised copy of `input`. */
|
|
13
|
+
export declare function normalizeTr(input: string, options?: NormalizeTrOptions): string;
|
|
14
|
+
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,kBAAkB;IACjC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAWD,2CAA2C;AAC3C,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CASnF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalise Turkish text for storage and comparison.
|
|
3
|
+
*
|
|
4
|
+
* Applies NFC, replaces typographic punctuation (smart quotes, en/em dashes,
|
|
5
|
+
* ellipsis, non-breaking spaces) with plain ASCII equivalents and collapses
|
|
6
|
+
* repeated whitespace.
|
|
7
|
+
*/
|
|
8
|
+
const REPLACEMENTS = [
|
|
9
|
+
[/[\u2018\u2019\u201A\u201B\u2032]/g, "'"],
|
|
10
|
+
[/[\u201C\u201D\u201E\u201F\u2033]/g, '"'],
|
|
11
|
+
[/[\u2013\u2014\u2015]/g, "-"],
|
|
12
|
+
[/\u2026/g, "..."],
|
|
13
|
+
[/\u00A0|\u2007|\u202F/g, " "],
|
|
14
|
+
[/\u200B|\u200C|\u200D|\uFEFF/g, ""],
|
|
15
|
+
];
|
|
16
|
+
/** Return a normalised copy of `input`. */
|
|
17
|
+
export function normalizeTr(input, options = {}) {
|
|
18
|
+
let out = input.normalize("NFC");
|
|
19
|
+
for (const [pattern, replacement] of REPLACEMENTS) {
|
|
20
|
+
out = out.replace(pattern, replacement);
|
|
21
|
+
}
|
|
22
|
+
if (options.collapseWhitespace ?? true) {
|
|
23
|
+
out = out.replace(/\s+/g, " ").trim();
|
|
24
|
+
}
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../src/normalize.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,MAAM,YAAY,GAA6C;IAC7D,CAAC,mCAAmC,EAAE,GAAG,CAAC;IAC1C,CAAC,mCAAmC,EAAE,GAAG,CAAC;IAC1C,CAAC,uBAAuB,EAAE,GAAG,CAAC;IAC9B,CAAC,SAAS,EAAE,KAAK,CAAC;IAClB,CAAC,uBAAuB,EAAE,GAAG,CAAC;IAC9B,CAAC,8BAA8B,EAAE,EAAE,CAAC;CACrC,CAAC;AAEF,2CAA2C;AAC3C,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,UAA8B,EAAE;IACzE,IAAI,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,KAAK,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,YAAY,EAAE,CAAC;QAClD,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,OAAO,CAAC,kBAAkB,IAAI,IAAI,EAAE,CAAC;QACvC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACxC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spell out numbers in Turkish.
|
|
3
|
+
*
|
|
4
|
+
* Supports integers up to the trillions, negatives and simple decimals
|
|
5
|
+
* (separated with the Turkish decimal comma word, `virgül`).
|
|
6
|
+
*/
|
|
7
|
+
/** Spell out an integer in Turkish. */
|
|
8
|
+
export declare function integerToWordsTr(value: number): string;
|
|
9
|
+
/** Spell out a number in Turkish, including negatives and decimals. */
|
|
10
|
+
export declare function numberToWordsTr(value: number): string;
|
|
11
|
+
//# sourceMappingURL=numbers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numbers.d.ts","sourceRoot":"","sources":["../src/numbers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2BH,uCAAuC;AACvC,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CA6BtD;AAED,uEAAuE;AACvE,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAcrD"}
|
package/dist/numbers.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spell out numbers in Turkish.
|
|
3
|
+
*
|
|
4
|
+
* Supports integers up to the trillions, negatives and simple decimals
|
|
5
|
+
* (separated with the Turkish decimal comma word, `virgül`).
|
|
6
|
+
*/
|
|
7
|
+
const UNITS = [
|
|
8
|
+
"sıfır", "bir", "iki", "üç", "dört", "beş", "altı", "yedi", "sekiz", "dokuz",
|
|
9
|
+
];
|
|
10
|
+
const TENS = [
|
|
11
|
+
"", "on", "yirmi", "otuz", "kırk", "elli", "altmış", "yetmiş", "seksen", "doksan",
|
|
12
|
+
];
|
|
13
|
+
const SCALES = ["", "bin", "milyon", "milyar", "trilyon"];
|
|
14
|
+
function belowThousand(value) {
|
|
15
|
+
const words = [];
|
|
16
|
+
const hundreds = Math.floor(value / 100);
|
|
17
|
+
const tens = Math.floor((value % 100) / 10);
|
|
18
|
+
const units = value % 10;
|
|
19
|
+
if (hundreds > 0) {
|
|
20
|
+
if (hundreds > 1)
|
|
21
|
+
words.push(UNITS[hundreds]);
|
|
22
|
+
words.push("yüz");
|
|
23
|
+
}
|
|
24
|
+
if (tens > 0)
|
|
25
|
+
words.push(TENS[tens]);
|
|
26
|
+
if (units > 0)
|
|
27
|
+
words.push(UNITS[units]);
|
|
28
|
+
return words;
|
|
29
|
+
}
|
|
30
|
+
/** Spell out an integer in Turkish. */
|
|
31
|
+
export function integerToWordsTr(value) {
|
|
32
|
+
if (!Number.isFinite(value) || !Number.isInteger(value)) {
|
|
33
|
+
throw new RangeError("integerToWordsTr: expected a finite integer");
|
|
34
|
+
}
|
|
35
|
+
if (value === 0)
|
|
36
|
+
return "sıfır";
|
|
37
|
+
const negative = value < 0;
|
|
38
|
+
let remaining = Math.abs(value);
|
|
39
|
+
const groups = [];
|
|
40
|
+
while (remaining > 0) {
|
|
41
|
+
groups.push(remaining % 1000);
|
|
42
|
+
remaining = Math.floor(remaining / 1000);
|
|
43
|
+
}
|
|
44
|
+
const words = [];
|
|
45
|
+
for (let i = groups.length - 1; i >= 0; i--) {
|
|
46
|
+
const group = groups[i];
|
|
47
|
+
if (group === 0)
|
|
48
|
+
continue;
|
|
49
|
+
// "1000" is spoken as "bin", never "bir bin".
|
|
50
|
+
if (i === 1 && group === 1) {
|
|
51
|
+
words.push("bin");
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
words.push(...belowThousand(group));
|
|
55
|
+
if (i > 0)
|
|
56
|
+
words.push(SCALES[i]);
|
|
57
|
+
}
|
|
58
|
+
return (negative ? "eksi " : "") + words.join(" ");
|
|
59
|
+
}
|
|
60
|
+
/** Spell out a number in Turkish, including negatives and decimals. */
|
|
61
|
+
export function numberToWordsTr(value) {
|
|
62
|
+
const sign = value < 0 ? "eksi " : "";
|
|
63
|
+
const absolute = Math.abs(value);
|
|
64
|
+
const integerPart = Math.trunc(absolute);
|
|
65
|
+
const fraction = absolute - integerPart;
|
|
66
|
+
if (fraction === 0)
|
|
67
|
+
return integerToWordsTr(value);
|
|
68
|
+
const fractionDigits = fraction.toFixed(10).slice(2).replace(/0+$/, "");
|
|
69
|
+
const head = integerPart === 0 ? "sıfır" : integerToWordsTr(integerPart);
|
|
70
|
+
const tail = fractionDigits
|
|
71
|
+
.split("")
|
|
72
|
+
.map((digit) => UNITS[Number(digit)])
|
|
73
|
+
.join(" ");
|
|
74
|
+
return `${sign}${head} virgül ${tail}`;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=numbers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"numbers.js","sourceRoot":"","sources":["../src/numbers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,KAAK,GAAG;IACZ,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;CACpE,CAAC;AAEX,MAAM,IAAI,GAAG;IACX,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ;CACzE,CAAC;AAEX,MAAM,MAAM,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAU,CAAC;AAEnE,SAAS,aAAa,CAAC,KAAa;IAClC,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,KAAK,GAAG,EAAE,CAAC;IAEzB,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;QACjB,IAAI,QAAQ,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAE,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,IAAI,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAE,CAAC,CAAC;IACtC,IAAI,KAAK,GAAG,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAE,CAAC,CAAC;IACzC,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,MAAM,IAAI,UAAU,CAAC,6CAA6C,CAAC,CAAC;IACtE,CAAC;IACD,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IAEhC,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;IAC3B,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAEhC,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,OAAO,SAAS,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;QAC9B,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACzB,IAAI,KAAK,KAAK,CAAC;YAAE,SAAS;QAC1B,8CAA8C;QAC9C,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAClB,SAAS;QACX,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACrD,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,IAAI,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,QAAQ,GAAG,WAAW,CAAC;IACxC,IAAI,QAAQ,KAAK,CAAC;QAAE,OAAO,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAEnD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxE,MAAM,IAAI,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACzE,MAAM,IAAI,GAAG,cAAc;SACxB,KAAK,CAAC,EAAE,CAAC;SACT,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAE,CAAC;SACrC,IAAI,CAAC,GAAG,CAAC,CAAC;IACb,OAAO,GAAG,IAAI,GAAG,IAAI,WAAW,IAAI,EAAE,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish ordinal numbers.
|
|
3
|
+
*
|
|
4
|
+
* `ordinalTr` returns the numeric form with a trailing dot ("3."), while
|
|
5
|
+
* `ordinalWordTr` spells the ordinal out ("üçüncü") using Turkish vowel harmony.
|
|
6
|
+
*/
|
|
7
|
+
/** Numeric ordinal: 3 → "3.". */
|
|
8
|
+
export declare function ordinalTr(value: number): string;
|
|
9
|
+
/** Spelled-out ordinal: 3 → "üçüncü", 21 → "yirmi birinci". */
|
|
10
|
+
export declare function ordinalWordTr(value: number): string;
|
|
11
|
+
//# sourceMappingURL=ordinal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ordinal.d.ts","sourceRoot":"","sources":["../src/ordinal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA6BH,iCAAiC;AACjC,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKnD"}
|
package/dist/ordinal.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish ordinal numbers.
|
|
3
|
+
*
|
|
4
|
+
* `ordinalTr` returns the numeric form with a trailing dot ("3."), while
|
|
5
|
+
* `ordinalWordTr` spells the ordinal out ("üçüncü") using Turkish vowel harmony.
|
|
6
|
+
*/
|
|
7
|
+
import { integerToWordsTr } from "./numbers.js";
|
|
8
|
+
const HARMONY = {
|
|
9
|
+
a: "ı", ı: "ı",
|
|
10
|
+
e: "i", i: "i",
|
|
11
|
+
o: "u", u: "u",
|
|
12
|
+
ö: "ü", ü: "ü",
|
|
13
|
+
};
|
|
14
|
+
const VOWELS = "aeıioöuüâîû";
|
|
15
|
+
const IRREGULAR = { dört: "dörd" };
|
|
16
|
+
function lastVowel(word) {
|
|
17
|
+
for (let i = word.length - 1; i >= 0; i--) {
|
|
18
|
+
const char = word[i];
|
|
19
|
+
if (VOWELS.includes(char))
|
|
20
|
+
return HARMONY[char] ?? "i";
|
|
21
|
+
}
|
|
22
|
+
return "i";
|
|
23
|
+
}
|
|
24
|
+
function ordinaliseWord(word) {
|
|
25
|
+
const base = IRREGULAR[word] ?? word;
|
|
26
|
+
const vowel = lastVowel(word);
|
|
27
|
+
const endsWithVowel = VOWELS.includes(word[word.length - 1]);
|
|
28
|
+
return endsWithVowel ? `${base}nc${vowel}` : `${base}${vowel}nc${vowel}`;
|
|
29
|
+
}
|
|
30
|
+
/** Numeric ordinal: 3 → "3.". */
|
|
31
|
+
export function ordinalTr(value) {
|
|
32
|
+
if (!Number.isInteger(value))
|
|
33
|
+
throw new RangeError("ordinalTr: expected an integer");
|
|
34
|
+
return `${value}.`;
|
|
35
|
+
}
|
|
36
|
+
/** Spelled-out ordinal: 3 → "üçüncü", 21 → "yirmi birinci". */
|
|
37
|
+
export function ordinalWordTr(value) {
|
|
38
|
+
const words = integerToWordsTr(value).split(" ");
|
|
39
|
+
const last = words.pop();
|
|
40
|
+
words.push(ordinaliseWord(last));
|
|
41
|
+
return words.join(" ");
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ordinal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ordinal.js","sourceRoot":"","sources":["../src/ordinal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,OAAO,GAAqC;IAChD,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;CACf,CAAC;AAEF,MAAM,MAAM,GAAG,aAAa,CAAC;AAC7B,MAAM,SAAS,GAAqC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;AAErE,SAAS,SAAS,CAAC,IAAY;IAC7B,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAE,CAAC;QACtB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC;IACzD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACrC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,CAAC;IAC9D,OAAO,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,KAAK,KAAK,EAAE,CAAC;AAC3E,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,gCAAgC,CAAC,CAAC;IACrF,OAAO,GAAG,KAAK,GAAG,CAAC;AACrB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;IAC1B,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC;IACjC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ateşman readability score for Turkish text (Ateşman, 1997).
|
|
3
|
+
*
|
|
4
|
+
* ```text
|
|
5
|
+
* score = 198.43 − 40.175 × (syllables / words) − 2.610 × (words / sentences)
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* Higher scores mean easier text. The score is clamped to the 0–100 range.
|
|
9
|
+
*/
|
|
10
|
+
export interface ReadabilityResult {
|
|
11
|
+
/** Ateşman score, clamped to 0–100. */
|
|
12
|
+
score: number;
|
|
13
|
+
/** Qualitative band for the score. */
|
|
14
|
+
grade: AtestmanGrade;
|
|
15
|
+
syllables: number;
|
|
16
|
+
words: number;
|
|
17
|
+
sentences: number;
|
|
18
|
+
}
|
|
19
|
+
export type AtestmanGrade = "çok kolay" | "kolay" | "orta" | "zor" | "çok zor";
|
|
20
|
+
/** Map an Ateşman score to its qualitative band. */
|
|
21
|
+
export declare function atestmanGrade(score: number): AtestmanGrade;
|
|
22
|
+
/** Compute the Ateşman readability score for Turkish text. */
|
|
23
|
+
export declare function atestmanScore(text: string): ReadabilityResult;
|
|
24
|
+
//# sourceMappingURL=readability.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readability.d.ts","sourceRoot":"","sources":["../src/readability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,MAAM,WAAW,iBAAiB;IAChC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,sCAAsC;IACtC,KAAK,EAAE,aAAa,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAW/E,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAM1D;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAkB7D"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ateşman readability score for Turkish text (Ateşman, 1997).
|
|
3
|
+
*
|
|
4
|
+
* ```text
|
|
5
|
+
* score = 198.43 − 40.175 × (syllables / words) − 2.610 × (words / sentences)
|
|
6
|
+
* ```
|
|
7
|
+
*
|
|
8
|
+
* Higher scores mean easier text. The score is clamped to the 0–100 range.
|
|
9
|
+
*/
|
|
10
|
+
import { syllablesTr } from "./syllables.js";
|
|
11
|
+
const WORD = /[\p{L}\p{N}]+/gu;
|
|
12
|
+
function tokenize(text) {
|
|
13
|
+
const words = text.match(WORD) ?? [];
|
|
14
|
+
const trimmed = text.trim();
|
|
15
|
+
if (trimmed === "")
|
|
16
|
+
return { words, sentences: 1 };
|
|
17
|
+
const ends = trimmed.match(/[.!?…]+/g)?.length ?? 0;
|
|
18
|
+
const trailing = /[.!?…]$/.test(trimmed) ? 0 : 1;
|
|
19
|
+
return { words, sentences: Math.max(1, ends + trailing) };
|
|
20
|
+
}
|
|
21
|
+
/** Map an Ateşman score to its qualitative band. */
|
|
22
|
+
export function atestmanGrade(score) {
|
|
23
|
+
if (score >= 90)
|
|
24
|
+
return "çok kolay";
|
|
25
|
+
if (score >= 70)
|
|
26
|
+
return "kolay";
|
|
27
|
+
if (score >= 50)
|
|
28
|
+
return "orta";
|
|
29
|
+
if (score >= 30)
|
|
30
|
+
return "zor";
|
|
31
|
+
return "çok zor";
|
|
32
|
+
}
|
|
33
|
+
/** Compute the Ateşman readability score for Turkish text. */
|
|
34
|
+
export function atestmanScore(text) {
|
|
35
|
+
const { words, sentences } = tokenize(text);
|
|
36
|
+
const wordCount = words.length;
|
|
37
|
+
const syllableCount = words.reduce((total, word) => total + syllablesTr(word), 0);
|
|
38
|
+
const score = wordCount === 0
|
|
39
|
+
? 0
|
|
40
|
+
: 198.43 - 40.175 * (syllableCount / wordCount) - 2.61 * (wordCount / sentences);
|
|
41
|
+
const clamped = Math.max(0, Math.min(100, Math.round(score * 100) / 100));
|
|
42
|
+
return {
|
|
43
|
+
score: clamped,
|
|
44
|
+
grade: atestmanGrade(clamped),
|
|
45
|
+
syllables: syllableCount,
|
|
46
|
+
words: wordCount,
|
|
47
|
+
sentences,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=readability.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readability.js","sourceRoot":"","sources":["../src/readability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,IAAI,GAAG,iBAAiB,CAAC;AAc/B,SAAS,QAAQ,CAAC,IAAY;IAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IACnD,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,WAAW,CAAC;IACpC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,OAAO,CAAC;IAChC,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC;IAC/B,IAAI,KAAK,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;IAC/B,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAElF,MAAM,KAAK,GACT,SAAS,KAAK,CAAC;QACb,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,aAAa,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC,CAAC;IACrF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAE1E,OAAO;QACL,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC;QAC7B,SAAS,EAAE,aAAa;QACxB,KAAK,EAAE,SAAS;QAChB,SAAS;KACV,CAAC;AACJ,CAAC"}
|
package/dist/slug.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware slug generation.
|
|
3
|
+
*
|
|
4
|
+
* `slugify` transliterates Turkish letters to their ASCII counterparts
|
|
5
|
+
* (ç→c, ğ→g, ı→i, İ→i, ö→o, ş→s, ü→u), folds remaining diacritics,
|
|
6
|
+
* drops punctuation and produces a URL-safe, separator-joined string.
|
|
7
|
+
*/
|
|
8
|
+
export interface SlugifyOptions {
|
|
9
|
+
/** Separator between words. Defaults to `"-"`. */
|
|
10
|
+
separator?: string;
|
|
11
|
+
/** Lowercase the result. Defaults to `true`. */
|
|
12
|
+
lowercase?: boolean;
|
|
13
|
+
/** Hard limit for the returned slug length. Truncation happens on a word boundary. */
|
|
14
|
+
maxLength?: number;
|
|
15
|
+
}
|
|
16
|
+
/** Convert arbitrary text into a URL-safe slug, respecting Turkish letters. */
|
|
17
|
+
export declare function slugify(input: string, options?: SlugifyOptions): string;
|
|
18
|
+
//# sourceMappingURL=slug.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAeH,MAAM,WAAW,cAAc;IAC7B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sFAAsF;IACtF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,+EAA+E;AAC/E,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,MAAM,CA8B3E"}
|
package/dist/slug.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware slug generation.
|
|
3
|
+
*
|
|
4
|
+
* `slugify` transliterates Turkish letters to their ASCII counterparts
|
|
5
|
+
* (ç→c, ğ→g, ı→i, İ→i, ö→o, ş→s, ü→u), folds remaining diacritics,
|
|
6
|
+
* drops punctuation and produces a URL-safe, separator-joined string.
|
|
7
|
+
*/
|
|
8
|
+
const TURKISH = {
|
|
9
|
+
ç: "c", Ç: "c",
|
|
10
|
+
ğ: "g", Ğ: "g",
|
|
11
|
+
ı: "i", I: "i",
|
|
12
|
+
İ: "i", i: "i",
|
|
13
|
+
ö: "o", Ö: "o",
|
|
14
|
+
ş: "s", Ş: "s",
|
|
15
|
+
ü: "u", Ü: "u",
|
|
16
|
+
â: "a", Â: "a",
|
|
17
|
+
î: "i", Î: "i",
|
|
18
|
+
û: "u", Û: "u",
|
|
19
|
+
};
|
|
20
|
+
/** Convert arbitrary text into a URL-safe slug, respecting Turkish letters. */
|
|
21
|
+
export function slugify(input, options = {}) {
|
|
22
|
+
const separator = options.separator ?? "-";
|
|
23
|
+
const lowercase = options.lowercase ?? true;
|
|
24
|
+
if (separator === "")
|
|
25
|
+
throw new RangeError("slugify: separator must not be empty");
|
|
26
|
+
let out = "";
|
|
27
|
+
for (const char of input.normalize("NFC")) {
|
|
28
|
+
const mapped = TURKISH[char];
|
|
29
|
+
if (mapped !== undefined) {
|
|
30
|
+
out += mapped;
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
out += char.normalize("NFKD").replace(/[\u0300-\u036f]/g, "");
|
|
34
|
+
}
|
|
35
|
+
out = out.replace(/[^a-zA-Z0-9]+/g, separator);
|
|
36
|
+
const escaped = separator.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
37
|
+
out = out.replace(new RegExp(`^(${escaped})+|(${escaped})+$`, "g"), "");
|
|
38
|
+
if (lowercase)
|
|
39
|
+
out = out.toLowerCase();
|
|
40
|
+
if (options.maxLength !== undefined && out.length > options.maxLength) {
|
|
41
|
+
const cut = out.slice(0, options.maxLength);
|
|
42
|
+
const lastSep = cut.lastIndexOf(separator);
|
|
43
|
+
out = (lastSep > 0 ? cut.slice(0, lastSep) : cut).replace(new RegExp(`(${escaped})+$`), "");
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=slug.js.map
|
package/dist/slug.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.js","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,OAAO,GAAqC;IAChD,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;IACd,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG;CACf,CAAC;AAWF,+EAA+E;AAC/E,MAAM,UAAU,OAAO,CAAC,KAAa,EAAE,UAA0B,EAAE;IACjE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,GAAG,CAAC;IAC3C,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC;IAC5C,IAAI,SAAS,KAAK,EAAE;QAAE,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;IAEnF,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,GAAG,IAAI,MAAM,CAAC;YACd,SAAS;QACX,CAAC;QACD,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC;IAChE,CAAC;IAED,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;IAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;IACjE,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,OAAO,OAAO,OAAO,KAAK,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IACxE,IAAI,SAAS;QAAE,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAEvC,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;QACtE,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;QAC3C,GAAG,GAAG,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CACvD,IAAI,MAAM,CAAC,IAAI,OAAO,KAAK,CAAC,EAC5B,EAAE,CACH,CAAC;IACJ,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/sort.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware collation.
|
|
3
|
+
*
|
|
4
|
+
* Sorts using the Turkish alphabet, where ç follows c, ğ follows g, ı comes
|
|
5
|
+
* before i, ö follows o, ş follows s and ü follows u. Backed by `Intl.Collator`
|
|
6
|
+
* so no lookup tables are needed.
|
|
7
|
+
*/
|
|
8
|
+
/** Compare two strings by the Turkish alphabet. Returns a negative, zero or positive number. */
|
|
9
|
+
export declare function compareTr(a: string, b: string): number;
|
|
10
|
+
/** Return a new array sorted by the Turkish alphabet. */
|
|
11
|
+
export declare function sortTr<T extends string>(items: readonly T[]): T[];
|
|
12
|
+
//# sourceMappingURL=sort.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort.d.ts","sourceRoot":"","sources":["../src/sort.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,gGAAgG;AAChG,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,EAAE,CAEjE"}
|
package/dist/sort.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware collation.
|
|
3
|
+
*
|
|
4
|
+
* Sorts using the Turkish alphabet, where ç follows c, ğ follows g, ı comes
|
|
5
|
+
* before i, ö follows o, ş follows s and ü follows u. Backed by `Intl.Collator`
|
|
6
|
+
* so no lookup tables are needed.
|
|
7
|
+
*/
|
|
8
|
+
const collator = new Intl.Collator("tr", { sensitivity: "variant", numeric: false });
|
|
9
|
+
/** Compare two strings by the Turkish alphabet. Returns a negative, zero or positive number. */
|
|
10
|
+
export function compareTr(a, b) {
|
|
11
|
+
return collator.compare(a, b);
|
|
12
|
+
}
|
|
13
|
+
/** Return a new array sorted by the Turkish alphabet. */
|
|
14
|
+
export function sortTr(items) {
|
|
15
|
+
return [...items].sort(compareTr);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=sort.js.map
|
package/dist/sort.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sort.js","sourceRoot":"","sources":["../src/sort.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AAErF,gGAAgG;AAChG,MAAM,UAAU,SAAS,CAAC,CAAS,EAAE,CAAS;IAC5C,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,MAAM,CAAmB,KAAmB;IAC1D,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count syllables in Turkish words.
|
|
3
|
+
*
|
|
4
|
+
* Turkish is written as one vowel per syllable, so the syllable count is the
|
|
5
|
+
* number of vowel groups.
|
|
6
|
+
*/
|
|
7
|
+
/** Count the syllables in a word or sentence. */
|
|
8
|
+
export declare function syllablesTr(input: string): number;
|
|
9
|
+
//# sourceMappingURL=syllables.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syllables.d.ts","sourceRoot":"","sources":["../src/syllables.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,iDAAiD;AACjD,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEjD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Count syllables in Turkish words.
|
|
3
|
+
*
|
|
4
|
+
* Turkish is written as one vowel per syllable, so the syllable count is the
|
|
5
|
+
* number of vowel groups.
|
|
6
|
+
*/
|
|
7
|
+
const VOWEL_GROUP = /[aeıioöuüâîû]+/g;
|
|
8
|
+
/** Count the syllables in a word or sentence. */
|
|
9
|
+
export function syllablesTr(input) {
|
|
10
|
+
return input.toLowerCase().match(VOWEL_GROUP)?.length ?? 0;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=syllables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"syllables.js","sourceRoot":"","sources":["../src/syllables.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAEtC,iDAAiD;AACjD,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC;AAC7D,CAAC"}
|
package/dist/title.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title.d.ts","sourceRoot":"","sources":["../src/title.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,0FAA0F;AAC1F,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIjD"}
|
package/dist/title.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turkish-aware title casing.
|
|
3
|
+
*/
|
|
4
|
+
import { lowerTr, upperTr } from "./case.js";
|
|
5
|
+
// Word separators: whitespace and opening punctuation, but never an apostrophe
|
|
6
|
+
// (so "istanbul'da" keeps its lowercase suffix).
|
|
7
|
+
const WORD_START = /(^|[\s([{"«»""\-–—/|]+)(\p{L})/gu;
|
|
8
|
+
/** Title-case a string, capitalising the first letter of each word with Turkish rules. */
|
|
9
|
+
export function titleCaseTr(input) {
|
|
10
|
+
return lowerTr(input).replace(WORD_START, (_match, separator, letter) => {
|
|
11
|
+
return separator + upperTr(letter);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=title.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title.js","sourceRoot":"","sources":["../src/title.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE7C,+EAA+E;AAC/E,iDAAiD;AACjD,MAAM,UAAU,GAAG,kCAAkC,CAAC;AAEtD,0FAA0F;AAC1F,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,SAAiB,EAAE,MAAc,EAAE,EAAE;QACtF,OAAO,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truncate Turkish text on a word boundary.
|
|
3
|
+
*/
|
|
4
|
+
/** Shorten `text` to at most `maxLength` characters, appending an ellipsis. */
|
|
5
|
+
export declare function truncateTr(text: string, maxLength: number, ellipsis?: string): string;
|
|
6
|
+
//# sourceMappingURL=truncate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../src/truncate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,SAAM,GAAG,MAAM,CAWlF"}
|
package/dist/truncate.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Truncate Turkish text on a word boundary.
|
|
3
|
+
*/
|
|
4
|
+
/** Shorten `text` to at most `maxLength` characters, appending an ellipsis. */
|
|
5
|
+
export function truncateTr(text, maxLength, ellipsis = "…") {
|
|
6
|
+
if (maxLength <= 0)
|
|
7
|
+
return "";
|
|
8
|
+
if (text.length <= maxLength)
|
|
9
|
+
return text;
|
|
10
|
+
const budget = maxLength - ellipsis.length;
|
|
11
|
+
if (budget <= 0)
|
|
12
|
+
return ellipsis.slice(0, maxLength);
|
|
13
|
+
const slice = text.slice(0, budget + 1);
|
|
14
|
+
const lastSpace = slice.lastIndexOf(" ");
|
|
15
|
+
const cut = lastSpace > 0 ? slice.slice(0, lastSpace) : text.slice(0, budget);
|
|
16
|
+
return cut.replace(/\s+$/, "") + ellipsis;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=truncate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.js","sourceRoot":"","sources":["../src/truncate.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,+EAA+E;AAC/E,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,SAAiB,EAAE,QAAQ,GAAG,GAAG;IACxE,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAC9B,IAAI,IAAI,CAAC,MAAM,IAAI,SAAS;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,MAAM,GAAG,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC3C,IAAI,MAAM,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;IAErD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;IACxC,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC9E,OAAO,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,QAAQ,CAAC;AAC5C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,66 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "turkce-utils",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Zero-dependency TypeScript helpers for Turkish text: slugify, Turkish-aware case & sort, title case, number-to-words, syllables and Ateşman readability — plus a CLI.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"turkish",
|
|
7
|
+
"türkçe",
|
|
8
|
+
"turkce",
|
|
9
|
+
"turkish-language",
|
|
10
|
+
"slugify",
|
|
11
|
+
"slug",
|
|
12
|
+
"text",
|
|
13
|
+
"text-utils",
|
|
14
|
+
"string",
|
|
15
|
+
"i18n",
|
|
16
|
+
"locale",
|
|
17
|
+
"collation",
|
|
18
|
+
"readability",
|
|
19
|
+
"atestman",
|
|
20
|
+
"okunabilirlik",
|
|
21
|
+
"number-to-words",
|
|
22
|
+
"syllables",
|
|
23
|
+
"cli"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"author": "Mehmet Fatih Doğan",
|
|
27
|
+
"type": "module",
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=20.0.0"
|
|
30
|
+
},
|
|
31
|
+
"main": "./dist/index.js",
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/index.d.ts",
|
|
36
|
+
"import": "./dist/index.js"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"bin": {
|
|
40
|
+
"turkce": "dist/cli.js"
|
|
41
|
+
},
|
|
42
|
+
"files": [
|
|
43
|
+
"dist",
|
|
44
|
+
"README.md",
|
|
45
|
+
"LICENSE"
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"test": "node --test",
|
|
49
|
+
"typecheck": "tsc --noEmit",
|
|
50
|
+
"build": "tsc",
|
|
51
|
+
"prepare": "npm run build",
|
|
52
|
+
"prepublishOnly": "npm run build"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^24.0.0",
|
|
56
|
+
"typescript": "^5.7.2"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/fatihdogann/turkce-utils.git"
|
|
61
|
+
},
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/fatihdogann/turkce-utils/issues"
|
|
64
|
+
},
|
|
65
|
+
"homepage": "https://github.com/fatihdogann/turkce-utils#readme"
|
|
66
|
+
}
|