@utilix-tech/sdk 0.2.0 → 0.3.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/README.md +42 -5
- package/dist/chunk-T3JTY2M5.js +134 -0
- package/dist/{chunk-XXYZLLHI.js → chunk-YBBYFAOV.js} +167 -1
- package/dist/index.cjs +298 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/media-DF2cx3pK.d.cts +28 -0
- package/dist/media-DF2cx3pK.d.ts +28 -0
- package/dist/{text-DqAjPtQ0.d.cts → text-CI7JAl7F.d.cts} +28 -2
- package/dist/{text-DqAjPtQ0.d.ts → text-CI7JAl7F.d.ts} +28 -2
- package/dist/tools/media.cjs +130 -0
- package/dist/tools/media.d.cts +1 -0
- package/dist/tools/media.d.ts +1 -0
- package/dist/tools/media.js +2 -0
- package/dist/tools/text.cjs +166 -0
- package/dist/tools/text.d.cts +1 -1
- package/dist/tools/text.d.ts +1 -1
- package/dist/tools/text.js +1 -1
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -26,13 +26,13 @@ yarn add @utilix-tech/sdk
|
|
|
26
26
|
pnpm add @utilix-tech/sdk
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
**Requires Node.js 18 or later.**
|
|
29
|
+
**Requires Node.js 18 or later.** The public npm package includes bundled TypeScript types, so no `@types/` package is needed.
|
|
30
30
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
## Quick Start
|
|
34
34
|
|
|
35
|
-
Each of the
|
|
35
|
+
Each of the 16 modules is available as a dedicated subpath import. Import only what you use; bundlers automatically tree-shake the rest.
|
|
36
36
|
|
|
37
37
|
```ts
|
|
38
38
|
// Pick exactly the modules you need
|
|
@@ -127,7 +127,7 @@ generateHtpasswdFile([{ username: "alice", password: "secret" }]);
|
|
|
127
127
|
|
|
128
128
|
```ts
|
|
129
129
|
import { convertCase, slugify, countWords, generateWords, generateParagraphs,
|
|
130
|
-
escapeString, htmlToMarkdown, applyOps } from "@utilix-tech/sdk/text";
|
|
130
|
+
escapeString, htmlToMarkdown, applyOps, detectPassiveVoice } from "@utilix-tech/sdk/text";
|
|
131
131
|
|
|
132
132
|
convertCase("hello world", "camelCase"); // "helloWorld"
|
|
133
133
|
convertCase("hello world", "PascalCase"); // "HelloWorld"
|
|
@@ -145,6 +145,9 @@ generateParagraphs(3); // lorem ipsum paragraphs
|
|
|
145
145
|
applyOps(text, ["sort", "deduplicate", "trim"]);
|
|
146
146
|
|
|
147
147
|
htmlToMarkdown("<h1>Hello</h1><p>World</p>");
|
|
148
|
+
|
|
149
|
+
// Flag passive-voice sentences, e.g. "was written", "were approved by the team"
|
|
150
|
+
detectPassiveVoice("The report was reviewed by the committee. They approved it.");
|
|
148
151
|
```
|
|
149
152
|
|
|
150
153
|
---
|
|
@@ -397,6 +400,22 @@ analyzeString("café"); // { length: 4, codePoints: [...], ... }
|
|
|
397
400
|
|
|
398
401
|
---
|
|
399
402
|
|
|
403
|
+
### `/media` — Image Header Parsing
|
|
404
|
+
|
|
405
|
+
```ts
|
|
406
|
+
import { readImageInfo } from "@utilix-tech/sdk/media";
|
|
407
|
+
|
|
408
|
+
// Reads format, dimensions, bit depth, and alpha channel straight from
|
|
409
|
+
// file bytes — no decoding, no canvas, no image library.
|
|
410
|
+
const bytes = await fs.promises.readFile("photo.png");
|
|
411
|
+
readImageInfo(new Uint8Array(bytes));
|
|
412
|
+
// { format: "png", width: 1920, height: 1080, bitDepth: 8, colorType: "rgba", hasAlpha: true }
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Supports PNG, JPEG, GIF, WebP, and BMP.
|
|
416
|
+
|
|
417
|
+
---
|
|
418
|
+
|
|
400
419
|
## All Modules at a Glance
|
|
401
420
|
|
|
402
421
|
| Import | What it does |
|
|
@@ -415,6 +434,8 @@ analyzeString("café"); // { length: 4, codePoints: [...], ... }
|
|
|
415
434
|
| `@utilix-tech/sdk/color` | Hex/RGB/HSL/HSV/CMYK convert, palette generation, contrast check |
|
|
416
435
|
| `@utilix-tech/sdk/css` | CSS gradient, box-shadow, border-radius, keyframe animation generators |
|
|
417
436
|
| `@utilix-tech/sdk/misc` | SVG optimize/sanitize, file size format, Unicode inspector |
|
|
437
|
+
| `@utilix-tech/sdk/ai_agent` | Token estimate/trim, chunk text, extract URLs/JSON/keywords, sanitize HTML, flatten/merge JSON, dedupe lines, validate schema, PII/secret/injection detect |
|
|
438
|
+
| `@utilix-tech/sdk/media` | Image format & dimension reading from raw bytes — PNG, JPEG, GIF, WebP, BMP |
|
|
418
439
|
|
|
419
440
|
---
|
|
420
441
|
|
|
@@ -430,14 +451,30 @@ Both SDKs return plain JSON-serializable objects so you can share test fixtures
|
|
|
430
451
|
|
|
431
452
|
---
|
|
432
453
|
|
|
433
|
-
##
|
|
454
|
+
## REST API
|
|
434
455
|
|
|
435
456
|
**This package is Surface A** — everything runs in-process in your Node.js runtime. No outbound requests, no API key, no rate limits.
|
|
436
457
|
|
|
437
|
-
|
|
458
|
+
The same 100+ tools are also available as a hosted **REST API** at `https://api.utilix.tech/v1` for environments where you can't ship a Node.js runtime, or for cross-language teams.
|
|
459
|
+
|
|
460
|
+
```bash
|
|
461
|
+
curl -X POST https://api.utilix.tech/v1/tools/hash \
|
|
462
|
+
-H "Authorization: Bearer utx_live_..." \
|
|
463
|
+
-H "Content-Type: application/json" \
|
|
464
|
+
-d '{"input": "hello world", "algorithm": "sha256"}'
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
- **Free**: 1,000 requests/day — no credit card required
|
|
468
|
+
- **Pro**: 10,000 requests/day — $9/month
|
|
469
|
+
- Try it live at **[utilix.tech/api](https://utilix.tech/api)** — no signup needed for the first 10 endpoints
|
|
470
|
+
- Get your API key at **[utilix.tech/dashboard](https://utilix.tech/dashboard)**
|
|
438
471
|
|
|
439
472
|
---
|
|
440
473
|
|
|
474
|
+
## Publishing (maintainers)
|
|
475
|
+
|
|
476
|
+
CI publishes automatically via npm Trusted Publishing (OIDC) on every push to `main` that bumps `version`. Requires npm **>=11.5.1** — older versions (e.g. the npm bundled with Node 20) sign provenance but skip the OIDC auth exchange, so `npm publish` fails with a 404 as if unauthenticated.
|
|
477
|
+
|
|
441
478
|
## License
|
|
442
479
|
|
|
443
480
|
MIT — see [LICENSE](./LICENSE) for details.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { __export } from './chunk-MLKGABMK.js';
|
|
2
|
+
|
|
3
|
+
// src/tools/media.ts
|
|
4
|
+
var media_exports = {};
|
|
5
|
+
__export(media_exports, {
|
|
6
|
+
readImageInfo: () => readImageInfo
|
|
7
|
+
});
|
|
8
|
+
function readU32BE(bytes, offset) {
|
|
9
|
+
return (bytes[offset] << 24 | bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]) >>> 0;
|
|
10
|
+
}
|
|
11
|
+
function readI32LE(bytes, offset) {
|
|
12
|
+
return bytes[offset] | bytes[offset + 1] << 8 | bytes[offset + 2] << 16 | bytes[offset + 3] << 24;
|
|
13
|
+
}
|
|
14
|
+
var PNG_COLOR_TYPES = {
|
|
15
|
+
0: "grayscale",
|
|
16
|
+
2: "rgb",
|
|
17
|
+
3: "palette",
|
|
18
|
+
4: "grayscale+alpha",
|
|
19
|
+
6: "rgba"
|
|
20
|
+
};
|
|
21
|
+
function readPng(bytes) {
|
|
22
|
+
if (bytes.length < 33) return { error: "Truncated PNG file" };
|
|
23
|
+
const width = readU32BE(bytes, 16);
|
|
24
|
+
const height = readU32BE(bytes, 20);
|
|
25
|
+
const bitDepth = bytes[24];
|
|
26
|
+
const colorTypeNum = bytes[25];
|
|
27
|
+
const colorType = PNG_COLOR_TYPES[colorTypeNum] ?? "unknown";
|
|
28
|
+
const hasAlpha = colorTypeNum === 4 || colorTypeNum === 6;
|
|
29
|
+
return { format: "png", width, height, bitDepth, colorType, hasAlpha };
|
|
30
|
+
}
|
|
31
|
+
function readGif(bytes) {
|
|
32
|
+
if (bytes.length < 10) return { error: "Truncated GIF file" };
|
|
33
|
+
const width = bytes[6] | bytes[7] << 8;
|
|
34
|
+
const height = bytes[8] | bytes[9] << 8;
|
|
35
|
+
return { format: "gif", width, height };
|
|
36
|
+
}
|
|
37
|
+
function readBmp(bytes) {
|
|
38
|
+
if (bytes.length < 30) return { error: "Truncated BMP file" };
|
|
39
|
+
const width = readI32LE(bytes, 18);
|
|
40
|
+
const heightRaw = readI32LE(bytes, 22);
|
|
41
|
+
const bitDepth = bytes[28] | bytes[29] << 8;
|
|
42
|
+
return { format: "bmp", width: Math.abs(width), height: Math.abs(heightRaw), bitDepth };
|
|
43
|
+
}
|
|
44
|
+
function readWebp(bytes) {
|
|
45
|
+
if (bytes.length < 16) return { error: "Truncated WebP file" };
|
|
46
|
+
const fourCC = String.fromCharCode(bytes[12], bytes[13], bytes[14], bytes[15]);
|
|
47
|
+
if (fourCC === "VP8 ") {
|
|
48
|
+
if (bytes.length < 30) return { error: "Truncated WebP file" };
|
|
49
|
+
const width = (bytes[26] | bytes[27] << 8) & 16383;
|
|
50
|
+
const height = (bytes[28] | bytes[29] << 8) & 16383;
|
|
51
|
+
return { format: "webp", width, height };
|
|
52
|
+
}
|
|
53
|
+
if (fourCC === "VP8L") {
|
|
54
|
+
if (bytes.length < 25) return { error: "Truncated WebP file" };
|
|
55
|
+
const bits = bytes[21] | bytes[22] << 8 | bytes[23] << 16 | bytes[24] << 24;
|
|
56
|
+
const width = (bits & 16383) + 1;
|
|
57
|
+
const height = (bits >>> 14 & 16383) + 1;
|
|
58
|
+
const hasAlpha = !!(bits >>> 28 & 1);
|
|
59
|
+
return { format: "webp", width, height, hasAlpha };
|
|
60
|
+
}
|
|
61
|
+
if (fourCC === "VP8X") {
|
|
62
|
+
if (bytes.length < 30) return { error: "Truncated WebP file" };
|
|
63
|
+
const flags = bytes[20];
|
|
64
|
+
const hasAlpha = !!(flags & 16);
|
|
65
|
+
const width = (bytes[24] | bytes[25] << 8 | bytes[26] << 16) + 1;
|
|
66
|
+
const height = (bytes[27] | bytes[28] << 8 | bytes[29] << 16) + 1;
|
|
67
|
+
return { format: "webp", width, height, hasAlpha };
|
|
68
|
+
}
|
|
69
|
+
return { error: "Unrecognized WebP chunk format" };
|
|
70
|
+
}
|
|
71
|
+
var JPEG_SOF_MARKERS = /* @__PURE__ */ new Set([
|
|
72
|
+
192,
|
|
73
|
+
193,
|
|
74
|
+
194,
|
|
75
|
+
195,
|
|
76
|
+
197,
|
|
77
|
+
198,
|
|
78
|
+
199,
|
|
79
|
+
201,
|
|
80
|
+
202,
|
|
81
|
+
203,
|
|
82
|
+
205,
|
|
83
|
+
206,
|
|
84
|
+
207
|
|
85
|
+
]);
|
|
86
|
+
function readJpeg(bytes) {
|
|
87
|
+
let offset = 2;
|
|
88
|
+
while (offset < bytes.length - 1) {
|
|
89
|
+
if (bytes[offset] !== 255) {
|
|
90
|
+
offset++;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const marker = bytes[offset + 1];
|
|
94
|
+
if (marker === 216 || marker === 1 || marker >= 208 && marker <= 215) {
|
|
95
|
+
offset += 2;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (marker === 217) break;
|
|
99
|
+
if (offset + 3 >= bytes.length) break;
|
|
100
|
+
const segmentLength = bytes[offset + 2] << 8 | bytes[offset + 3];
|
|
101
|
+
if (JPEG_SOF_MARKERS.has(marker)) {
|
|
102
|
+
if (offset + 9 >= bytes.length) return { error: "Truncated JPEG SOF segment" };
|
|
103
|
+
const bitDepth = bytes[offset + 4];
|
|
104
|
+
const height = bytes[offset + 5] << 8 | bytes[offset + 6];
|
|
105
|
+
const width = bytes[offset + 7] << 8 | bytes[offset + 8];
|
|
106
|
+
const components = bytes[offset + 9];
|
|
107
|
+
const colorType = components === 1 ? "grayscale" : components === 3 ? "rgb" : components === 4 ? "cmyk" : "unknown";
|
|
108
|
+
return { format: "jpeg", width, height, bitDepth, colorType };
|
|
109
|
+
}
|
|
110
|
+
offset += 2 + segmentLength;
|
|
111
|
+
}
|
|
112
|
+
return { error: "No SOF marker found in JPEG (file may be corrupt)" };
|
|
113
|
+
}
|
|
114
|
+
function readImageInfo(bytes) {
|
|
115
|
+
if (bytes.length < 10) return { error: "File too small to determine format" };
|
|
116
|
+
if (bytes[0] === 137 && bytes[1] === 80 && bytes[2] === 78 && bytes[3] === 71 && bytes[4] === 13 && bytes[5] === 10 && bytes[6] === 26 && bytes[7] === 10) {
|
|
117
|
+
return readPng(bytes);
|
|
118
|
+
}
|
|
119
|
+
if (bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70) {
|
|
120
|
+
return readGif(bytes);
|
|
121
|
+
}
|
|
122
|
+
if (bytes[0] === 66 && bytes[1] === 77) {
|
|
123
|
+
return readBmp(bytes);
|
|
124
|
+
}
|
|
125
|
+
if (bytes[0] === 82 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 70 && bytes[8] === 87 && bytes[9] === 69 && bytes[10] === 66 && bytes[11] === 80) {
|
|
126
|
+
return readWebp(bytes);
|
|
127
|
+
}
|
|
128
|
+
if (bytes[0] === 255 && bytes[1] === 216) {
|
|
129
|
+
return readJpeg(bytes);
|
|
130
|
+
}
|
|
131
|
+
return { error: "Unrecognized image format \u2014 supported: PNG, JPEG, GIF, WebP, BMP" };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export { media_exports, readImageInfo };
|
|
@@ -20,6 +20,7 @@ __export(text_exports, {
|
|
|
20
20
|
csvToHtml: () => csvToHtml,
|
|
21
21
|
csvToMarkdown: () => csvToMarkdown,
|
|
22
22
|
detectDelimiter: () => detectDelimiter,
|
|
23
|
+
detectPassiveVoice: () => detectPassiveVoice,
|
|
23
24
|
diffLines: () => diffLines,
|
|
24
25
|
diffLinesSimple: () => diffLinesSimple,
|
|
25
26
|
diffStats: () => diffStats,
|
|
@@ -2223,5 +2224,170 @@ function getMorseTiming(morse) {
|
|
|
2223
2224
|
}
|
|
2224
2225
|
return result;
|
|
2225
2226
|
}
|
|
2227
|
+
var BE_VERBS = /* @__PURE__ */ new Set(["am", "is", "are", "was", "were", "be", "been", "being"]);
|
|
2228
|
+
var IRREGULAR_PARTICIPLES = /* @__PURE__ */ new Set([
|
|
2229
|
+
"awoken",
|
|
2230
|
+
"been",
|
|
2231
|
+
"become",
|
|
2232
|
+
"begun",
|
|
2233
|
+
"bent",
|
|
2234
|
+
"bet",
|
|
2235
|
+
"bitten",
|
|
2236
|
+
"bled",
|
|
2237
|
+
"blown",
|
|
2238
|
+
"born",
|
|
2239
|
+
"bought",
|
|
2240
|
+
"bound",
|
|
2241
|
+
"bred",
|
|
2242
|
+
"broken",
|
|
2243
|
+
"brought",
|
|
2244
|
+
"built",
|
|
2245
|
+
"burnt",
|
|
2246
|
+
"burst",
|
|
2247
|
+
"caught",
|
|
2248
|
+
"chosen",
|
|
2249
|
+
"clung",
|
|
2250
|
+
"come",
|
|
2251
|
+
"cost",
|
|
2252
|
+
"crept",
|
|
2253
|
+
"cut",
|
|
2254
|
+
"dealt",
|
|
2255
|
+
"dived",
|
|
2256
|
+
"done",
|
|
2257
|
+
"drawn",
|
|
2258
|
+
"dreamt",
|
|
2259
|
+
"driven",
|
|
2260
|
+
"drunk",
|
|
2261
|
+
"dug",
|
|
2262
|
+
"eaten",
|
|
2263
|
+
"fallen",
|
|
2264
|
+
"fed",
|
|
2265
|
+
"felt",
|
|
2266
|
+
"fit",
|
|
2267
|
+
"fled",
|
|
2268
|
+
"flown",
|
|
2269
|
+
"forbidden",
|
|
2270
|
+
"forgiven",
|
|
2271
|
+
"forgotten",
|
|
2272
|
+
"fought",
|
|
2273
|
+
"found",
|
|
2274
|
+
"frozen",
|
|
2275
|
+
"given",
|
|
2276
|
+
"gone",
|
|
2277
|
+
"gotten",
|
|
2278
|
+
"grown",
|
|
2279
|
+
"hidden",
|
|
2280
|
+
"held",
|
|
2281
|
+
"hung",
|
|
2282
|
+
"hurt",
|
|
2283
|
+
"kept",
|
|
2284
|
+
"knelt",
|
|
2285
|
+
"knit",
|
|
2286
|
+
"known",
|
|
2287
|
+
"laid",
|
|
2288
|
+
"lain",
|
|
2289
|
+
"led",
|
|
2290
|
+
"left",
|
|
2291
|
+
"lent",
|
|
2292
|
+
"let",
|
|
2293
|
+
"lit",
|
|
2294
|
+
"lost",
|
|
2295
|
+
"made",
|
|
2296
|
+
"meant",
|
|
2297
|
+
"met",
|
|
2298
|
+
"mistaken",
|
|
2299
|
+
"paid",
|
|
2300
|
+
"proven",
|
|
2301
|
+
"put",
|
|
2302
|
+
"quit",
|
|
2303
|
+
"read",
|
|
2304
|
+
"rid",
|
|
2305
|
+
"ridden",
|
|
2306
|
+
"risen",
|
|
2307
|
+
"run",
|
|
2308
|
+
"said",
|
|
2309
|
+
"sat",
|
|
2310
|
+
"sawn",
|
|
2311
|
+
"seen",
|
|
2312
|
+
"sent",
|
|
2313
|
+
"set",
|
|
2314
|
+
"sewn",
|
|
2315
|
+
"shaken",
|
|
2316
|
+
"shed",
|
|
2317
|
+
"shone",
|
|
2318
|
+
"shot",
|
|
2319
|
+
"shown",
|
|
2320
|
+
"shrunk",
|
|
2321
|
+
"shut",
|
|
2322
|
+
"sold",
|
|
2323
|
+
"sought",
|
|
2324
|
+
"sown",
|
|
2325
|
+
"spent",
|
|
2326
|
+
"spoken",
|
|
2327
|
+
"spread",
|
|
2328
|
+
"sprung",
|
|
2329
|
+
"stolen",
|
|
2330
|
+
"stood",
|
|
2331
|
+
"stuck",
|
|
2332
|
+
"stung",
|
|
2333
|
+
"struck",
|
|
2334
|
+
"strung",
|
|
2335
|
+
"sung",
|
|
2336
|
+
"sunk",
|
|
2337
|
+
"swept",
|
|
2338
|
+
"sworn",
|
|
2339
|
+
"swum",
|
|
2340
|
+
"swung",
|
|
2341
|
+
"taken",
|
|
2342
|
+
"taught",
|
|
2343
|
+
"thought",
|
|
2344
|
+
"thrown",
|
|
2345
|
+
"told",
|
|
2346
|
+
"torn",
|
|
2347
|
+
"understood",
|
|
2348
|
+
"upset",
|
|
2349
|
+
"woken",
|
|
2350
|
+
"won",
|
|
2351
|
+
"worn",
|
|
2352
|
+
"wound",
|
|
2353
|
+
"woven",
|
|
2354
|
+
"written"
|
|
2355
|
+
]);
|
|
2356
|
+
function isPastParticiple(word) {
|
|
2357
|
+
const w = word.toLowerCase();
|
|
2358
|
+
if (IRREGULAR_PARTICIPLES.has(w)) return true;
|
|
2359
|
+
return w.length > 3 && /^[a-z]+ed$/.test(w);
|
|
2360
|
+
}
|
|
2361
|
+
function splitIntoSentences(text) {
|
|
2362
|
+
const matches = text.match(/[^.!?]+[.!?]*/g);
|
|
2363
|
+
if (!matches) return [];
|
|
2364
|
+
return matches.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2365
|
+
}
|
|
2366
|
+
function detectPassiveVoice(text) {
|
|
2367
|
+
const sentences = splitIntoSentences(text);
|
|
2368
|
+
const analyzed = sentences.map((sentence, index) => {
|
|
2369
|
+
const words = sentence.match(/[a-zA-Z']+/g) ?? [];
|
|
2370
|
+
const matches = [];
|
|
2371
|
+
for (let i = 0; i < words.length; i++) {
|
|
2372
|
+
if (!BE_VERBS.has(words[i].toLowerCase())) continue;
|
|
2373
|
+
let j = i + 1;
|
|
2374
|
+
let adverbCount = 0;
|
|
2375
|
+
while (j < words.length && adverbCount < 2 && /ly$/i.test(words[j]) && !isPastParticiple(words[j])) {
|
|
2376
|
+
j++;
|
|
2377
|
+
adverbCount++;
|
|
2378
|
+
}
|
|
2379
|
+
if (j < words.length && isPastParticiple(words[j])) {
|
|
2380
|
+
const hasAgent = words.slice(j + 1, j + 5).some((w) => w.toLowerCase() === "by");
|
|
2381
|
+
matches.push({ phrase: words.slice(i, j + 1).join(" "), hasAgent });
|
|
2382
|
+
i = j;
|
|
2383
|
+
}
|
|
2384
|
+
}
|
|
2385
|
+
return { index, text: sentence, isPassive: matches.length > 0, matches };
|
|
2386
|
+
});
|
|
2387
|
+
const totalSentences = analyzed.length;
|
|
2388
|
+
const passiveSentences = analyzed.filter((s) => s.isPassive).length;
|
|
2389
|
+
const passivePercent = totalSentences > 0 ? Math.round(passiveSentences / totalSentences * 1e3) / 10 : 0;
|
|
2390
|
+
return { sentences: analyzed, totalSentences, passiveSentences, passivePercent };
|
|
2391
|
+
}
|
|
2226
2392
|
|
|
2227
|
-
export { CASE_FORMATS, DEFAULT_CONVERT_OPTIONS, ESCAPE_MODES, LINE_OPS, MORSE_CODE, addBorder, analyzeText, applyOp, applyOps, centerText, convertAll, convertCase, countWords, csvToHtml, csvToMarkdown, detectDelimiter, diffLines, diffLinesSimple, diffStats, escapeAll, escapeString, extractHeadings, formatReadingTime, generate, generateDiff, generateHtmlTable, generateMarkdownTable, generateParagraphs, generateSentences, generateWords, getAvailableFonts, getMorseForChar, getMorseTiming, htmlToMarkdown, isValidMorse, markdownToHtml, morseToText, numberToOrdinal, numberToRoman, numberToWords, ordinalWords, parseDiff, parseTableData, readabilityScore, renderMarkdown, romanToNumber, sentenceCount, slugify, slugifyAll, syllableCount, textToAscii, textToMorse, text_exports, unescapeString, wordFrequency };
|
|
2393
|
+
export { CASE_FORMATS, DEFAULT_CONVERT_OPTIONS, ESCAPE_MODES, LINE_OPS, MORSE_CODE, addBorder, analyzeText, applyOp, applyOps, centerText, convertAll, convertCase, countWords, csvToHtml, csvToMarkdown, detectDelimiter, detectPassiveVoice, diffLines, diffLinesSimple, diffStats, escapeAll, escapeString, extractHeadings, formatReadingTime, generate, generateDiff, generateHtmlTable, generateMarkdownTable, generateParagraphs, generateSentences, generateWords, getAvailableFonts, getMorseForChar, getMorseTiming, htmlToMarkdown, isValidMorse, markdownToHtml, morseToText, numberToOrdinal, numberToRoman, numberToWords, ordinalWords, parseDiff, parseTableData, readabilityScore, renderMarkdown, romanToNumber, sentenceCount, slugify, slugifyAll, syllableCount, textToAscii, textToMorse, text_exports, unescapeString, wordFrequency };
|