@moxon/api 6.0.0-pre
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/.prettierignore +5 -0
- package/LICENSE +28 -0
- package/README.md +277 -0
- package/dist/app.d.ts +2 -0
- package/dist/app.js +55 -0
- package/dist/app.js.map +1 -0
- package/dist/config/env.d.ts +22 -0
- package/dist/config/env.js +36 -0
- package/dist/config/env.js.map +1 -0
- package/dist/config/plans.d.ts +26 -0
- package/dist/config/plans.js +44 -0
- package/dist/config/plans.js.map +1 -0
- package/dist/config/versions.d.ts +18 -0
- package/dist/config/versions.js +248 -0
- package/dist/config/versions.js.map +1 -0
- package/dist/constants.d.ts +48 -0
- package/dist/constants.js +75 -0
- package/dist/constants.js.map +1 -0
- package/dist/middleware/cors.d.ts +2 -0
- package/dist/middleware/cors.js +31 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/error.d.ts +4 -0
- package/dist/middleware/error.js +8 -0
- package/dist/middleware/error.js.map +1 -0
- package/dist/middleware/json.d.ts +2 -0
- package/dist/middleware/json.js +8 -0
- package/dist/middleware/json.js.map +1 -0
- package/dist/middleware/logger.d.ts +26 -0
- package/dist/middleware/logger.js +65 -0
- package/dist/middleware/logger.js.map +1 -0
- package/dist/middleware/ratelimit.d.ts +2 -0
- package/dist/middleware/ratelimit.js +83 -0
- package/dist/middleware/ratelimit.js.map +1 -0
- package/dist/middleware/version.d.ts +3 -0
- package/dist/middleware/version.js +30 -0
- package/dist/middleware/version.js.map +1 -0
- package/dist/modules/v4/address.d.ts +20 -0
- package/dist/modules/v4/address.js +381 -0
- package/dist/modules/v4/address.js.map +1 -0
- package/dist/modules/v4/agent.d.ts +30 -0
- package/dist/modules/v4/agent.js +92 -0
- package/dist/modules/v4/agent.js.map +1 -0
- package/dist/modules/v4/algorithms.d.ts +90 -0
- package/dist/modules/v4/algorithms.js +279 -0
- package/dist/modules/v4/algorithms.js.map +1 -0
- package/dist/modules/v4/avatar.d.ts +23 -0
- package/dist/modules/v4/avatar.js +136 -0
- package/dist/modules/v4/avatar.js.map +1 -0
- package/dist/modules/v4/barcode.d.ts +27 -0
- package/dist/modules/v4/barcode.js +440 -0
- package/dist/modules/v4/barcode.js.map +1 -0
- package/dist/modules/v4/captcha.d.ts +22 -0
- package/dist/modules/v4/captcha.js +79 -0
- package/dist/modules/v4/captcha.js.map +1 -0
- package/dist/modules/v4/chat.d.ts +21 -0
- package/dist/modules/v4/chat.js +100 -0
- package/dist/modules/v4/chat.js.map +1 -0
- package/dist/modules/v4/color.d.ts +16 -0
- package/dist/modules/v4/color.js +59 -0
- package/dist/modules/v4/color.js.map +1 -0
- package/dist/modules/v4/convert.d.ts +15 -0
- package/dist/modules/v4/convert.js +116 -0
- package/dist/modules/v4/convert.js.map +1 -0
- package/dist/modules/v4/credit.d.ts +22 -0
- package/dist/modules/v4/credit.js +104 -0
- package/dist/modules/v4/credit.js.map +1 -0
- package/dist/modules/v4/cron.d.ts +17 -0
- package/dist/modules/v4/cron.js +202 -0
- package/dist/modules/v4/cron.js.map +1 -0
- package/dist/modules/v4/dice.d.ts +16 -0
- package/dist/modules/v4/dice.js +37 -0
- package/dist/modules/v4/dice.js.map +1 -0
- package/dist/modules/v4/domain.d.ts +6 -0
- package/dist/modules/v4/domain.js +83 -0
- package/dist/modules/v4/domain.js.map +1 -0
- package/dist/modules/v4/encode.d.ts +81 -0
- package/dist/modules/v4/encode.js +236 -0
- package/dist/modules/v4/encode.js.map +1 -0
- package/dist/modules/v4/geo.d.ts +30 -0
- package/dist/modules/v4/geo.js +51 -0
- package/dist/modules/v4/geo.js.map +1 -0
- package/dist/modules/v4/hash.d.ts +15 -0
- package/dist/modules/v4/hash.js +25 -0
- package/dist/modules/v4/hash.js.map +1 -0
- package/dist/modules/v4/hyperplanning.d.ts +19 -0
- package/dist/modules/v4/hyperplanning.js +80 -0
- package/dist/modules/v4/hyperplanning.js.map +1 -0
- package/dist/modules/v4/ip.d.ts +19 -0
- package/dist/modules/v4/ip.js +132 -0
- package/dist/modules/v4/ip.js.map +1 -0
- package/dist/modules/v4/levenshtein.d.ts +13 -0
- package/dist/modules/v4/levenshtein.js +37 -0
- package/dist/modules/v4/levenshtein.js.map +1 -0
- package/dist/modules/v4/palette.d.ts +19 -0
- package/dist/modules/v4/palette.js +56 -0
- package/dist/modules/v4/palette.js.map +1 -0
- package/dist/modules/v4/password.d.ts +25 -0
- package/dist/modules/v4/password.js +343 -0
- package/dist/modules/v4/password.js.map +1 -0
- package/dist/modules/v4/personal.d.ts +6 -0
- package/dist/modules/v4/personal.js +121 -0
- package/dist/modules/v4/personal.js.map +1 -0
- package/dist/modules/v4/placeholder.d.ts +30 -0
- package/dist/modules/v4/placeholder.js +160 -0
- package/dist/modules/v4/placeholder.js.map +1 -0
- package/dist/modules/v4/qrcode.d.ts +25 -0
- package/dist/modules/v4/qrcode.js +92 -0
- package/dist/modules/v4/qrcode.js.map +1 -0
- package/dist/modules/v4/regex.d.ts +23 -0
- package/dist/modules/v4/regex.js +48 -0
- package/dist/modules/v4/regex.js.map +1 -0
- package/dist/modules/v4/statistics.d.ts +20 -0
- package/dist/modules/v4/statistics.js +48 -0
- package/dist/modules/v4/statistics.js.map +1 -0
- package/dist/modules/v4/text.d.ts +43 -0
- package/dist/modules/v4/text.js +323 -0
- package/dist/modules/v4/text.js.map +1 -0
- package/dist/modules/v4/tic_tac_toe.d.ts +19 -0
- package/dist/modules/v4/tic_tac_toe.js +214 -0
- package/dist/modules/v4/tic_tac_toe.js.map +1 -0
- package/dist/modules/v4/time.d.ts +15 -0
- package/dist/modules/v4/time.js +124 -0
- package/dist/modules/v4/time.js.map +1 -0
- package/dist/modules/v4/token.d.ts +9 -0
- package/dist/modules/v4/token.js +45 -0
- package/dist/modules/v4/token.js.map +1 -0
- package/dist/modules/v4/username.d.ts +6 -0
- package/dist/modules/v4/username.js +92 -0
- package/dist/modules/v4/username.js.map +1 -0
- package/dist/modules/v4/validate.d.ts +34 -0
- package/dist/modules/v4/validate.js +75 -0
- package/dist/modules/v4/validate.js.map +1 -0
- package/dist/modules/v4.d.ts +32 -0
- package/dist/modules/v4.js +33 -0
- package/dist/modules/v4.js.map +1 -0
- package/dist/modules/v5/address.d.ts +5 -0
- package/dist/modules/v5/address.js +20 -0
- package/dist/modules/v5/address.js.map +1 -0
- package/dist/modules/v5/algorithms.d.ts +9 -0
- package/dist/modules/v5/algorithms.js +39 -0
- package/dist/modules/v5/algorithms.js.map +1 -0
- package/dist/modules/v5/asymmetric.d.ts +26 -0
- package/dist/modules/v5/asymmetric.js +74 -0
- package/dist/modules/v5/asymmetric.js.map +1 -0
- package/dist/modules/v5/barcode.d.ts +27 -0
- package/dist/modules/v5/barcode.js +424 -0
- package/dist/modules/v5/barcode.js.map +1 -0
- package/dist/modules/v5/base.d.ts +16 -0
- package/dist/modules/v5/base.js +41 -0
- package/dist/modules/v5/base.js.map +1 -0
- package/dist/modules/v5/captcha.d.ts +27 -0
- package/dist/modules/v5/captcha.js +136 -0
- package/dist/modules/v5/captcha.js.map +1 -0
- package/dist/modules/v5/case.d.ts +10 -0
- package/dist/modules/v5/case.js +57 -0
- package/dist/modules/v5/case.js.map +1 -0
- package/dist/modules/v5/chart.d.ts +53 -0
- package/dist/modules/v5/chart.js +385 -0
- package/dist/modules/v5/chart.js.map +1 -0
- package/dist/modules/v5/chat.d.ts +21 -0
- package/dist/modules/v5/chat.js +107 -0
- package/dist/modules/v5/chat.js.map +1 -0
- package/dist/modules/v5/csv.d.ts +29 -0
- package/dist/modules/v5/csv.js +143 -0
- package/dist/modules/v5/csv.js.map +1 -0
- package/dist/modules/v5/diff.d.ts +20 -0
- package/dist/modules/v5/diff.js +81 -0
- package/dist/modules/v5/diff.js.map +1 -0
- package/dist/modules/v5/evaluate.d.ts +14 -0
- package/dist/modules/v5/evaluate.js +284 -0
- package/dist/modules/v5/evaluate.js.map +1 -0
- package/dist/modules/v5/jwt.d.ts +11 -0
- package/dist/modules/v5/jwt.js +42 -0
- package/dist/modules/v5/jwt.js.map +1 -0
- package/dist/modules/v5/matrix.d.ts +77 -0
- package/dist/modules/v5/matrix.js +239 -0
- package/dist/modules/v5/matrix.js.map +1 -0
- package/dist/modules/v5/otp.d.ts +30 -0
- package/dist/modules/v5/otp.js +117 -0
- package/dist/modules/v5/otp.js.map +1 -0
- package/dist/modules/v5/pow.d.ts +29 -0
- package/dist/modules/v5/pow.js +49 -0
- package/dist/modules/v5/pow.js.map +1 -0
- package/dist/modules/v5/read.d.ts +20 -0
- package/dist/modules/v5/read.js +59 -0
- package/dist/modules/v5/read.js.map +1 -0
- package/dist/modules/v5/semver.d.ts +33 -0
- package/dist/modules/v5/semver.js +99 -0
- package/dist/modules/v5/semver.js.map +1 -0
- package/dist/modules/v5/symmetric.d.ts +15 -0
- package/dist/modules/v5/symmetric.js +88 -0
- package/dist/modules/v5/symmetric.js.map +1 -0
- package/dist/modules/v5/text.d.ts +5 -0
- package/dist/modules/v5/text.js +12 -0
- package/dist/modules/v5/text.js.map +1 -0
- package/dist/modules/v5/tic_tac_toe.d.ts +19 -0
- package/dist/modules/v5/tic_tac_toe.js +226 -0
- package/dist/modules/v5/tic_tac_toe.js.map +1 -0
- package/dist/modules/v5/url.d.ts +18 -0
- package/dist/modules/v5/url.js +51 -0
- package/dist/modules/v5/url.js.map +1 -0
- package/dist/modules/v5/uuid.d.ts +25 -0
- package/dist/modules/v5/uuid.js +40 -0
- package/dist/modules/v5/uuid.js.map +1 -0
- package/dist/modules/v5.d.ts +24 -0
- package/dist/modules/v5.js +25 -0
- package/dist/modules/v5.js.map +1 -0
- package/dist/modules/v6.d.ts +1 -0
- package/dist/modules/v6.js +2 -0
- package/dist/modules/v6.js.map +1 -0
- package/dist/routes/delete.d.ts +2 -0
- package/dist/routes/delete.js +73 -0
- package/dist/routes/delete.js.map +1 -0
- package/dist/routes/get.d.ts +2 -0
- package/dist/routes/get.js +857 -0
- package/dist/routes/get.js.map +1 -0
- package/dist/routes/index.d.ts +2 -0
- package/dist/routes/index.js +95 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/patch.d.ts +2 -0
- package/dist/routes/patch.js +45 -0
- package/dist/routes/patch.js.map +1 -0
- package/dist/routes/post.d.ts +2 -0
- package/dist/routes/post.js +604 -0
- package/dist/routes/post.js.map +1 -0
- package/dist/storage/index.d.ts +5 -0
- package/dist/storage/index.js +14 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types/storage.d.ts +52 -0
- package/dist/types/storage.js +2 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/utils/challenge.d.ts +40 -0
- package/dist/utils/challenge.js +75 -0
- package/dist/utils/challenge.js.map +1 -0
- package/dist/utils/colors.d.ts +44 -0
- package/dist/utils/colors.js +93 -0
- package/dist/utils/colors.js.map +1 -0
- package/dist/utils/helpers.d.ts +55 -0
- package/dist/utils/helpers.js +82 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/response.d.ts +9 -0
- package/dist/utils/response.js +24 -0
- package/dist/utils/response.js.map +1 -0
- package/package.json +90 -0
- package/robots.txt +74 -0
- package/src/favicon.ico +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type AvatarShape = 'circle' | 'rounded' | 'square';
|
|
2
|
+
type AnimateMode = 'shimmer' | 'pulse' | 'none';
|
|
3
|
+
export interface PlaceholderOptions {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
bg?: string;
|
|
7
|
+
color?: string;
|
|
8
|
+
text?: string;
|
|
9
|
+
rows?: number;
|
|
10
|
+
avatar?: AvatarShape;
|
|
11
|
+
lines?: number;
|
|
12
|
+
animate?: AnimateMode;
|
|
13
|
+
speed?: number;
|
|
14
|
+
radius?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface PlaceholderResult {
|
|
17
|
+
type: string;
|
|
18
|
+
contentType: string;
|
|
19
|
+
body: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Generates an SVG placeholder image or skeleton loader with configurable dimensions and style.
|
|
23
|
+
*
|
|
24
|
+
* @param type - Placeholder type: "image" or "skeleton"
|
|
25
|
+
* @param query - Query parameters including width, height, bg, color, text, rows, avatar, animate, speed, and radius
|
|
26
|
+
* @returns Object containing the SVG body, content type, and placeholder type
|
|
27
|
+
* @throws Error if any parameter is invalid or out of range
|
|
28
|
+
*/
|
|
29
|
+
export default function placeholder(type: string, query: Record<string, string | undefined>): PlaceholderResult;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { normalizeColor } from '../../utils/colors.js';
|
|
2
|
+
function parseSize(value, name, def) {
|
|
3
|
+
if (value === undefined)
|
|
4
|
+
return def;
|
|
5
|
+
const n = Number(value);
|
|
6
|
+
if (isNaN(n))
|
|
7
|
+
throw new Error(`${name} must be a number`);
|
|
8
|
+
if (n < 1 || n > 4000)
|
|
9
|
+
throw new Error(`${name} must be between 1 and 4000`);
|
|
10
|
+
return Math.floor(n);
|
|
11
|
+
}
|
|
12
|
+
function escapeXml(str) {
|
|
13
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
14
|
+
}
|
|
15
|
+
function generateImage(opts) {
|
|
16
|
+
const { width, height } = opts;
|
|
17
|
+
const bg = normalizeColor(opts.bg, '#cccccc');
|
|
18
|
+
const color = normalizeColor(opts.color, '#333333');
|
|
19
|
+
const text = escapeXml(opts.text ?? `${width}\u00d7${height}`);
|
|
20
|
+
const fontSize = Math.max(12, Math.min(width, height) / 8);
|
|
21
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
22
|
+
<rect width="${width}" height="${height}" fill="${bg}" rx="4" />
|
|
23
|
+
<text x="50%" y="50%" dominant-baseline="central" text-anchor="middle" font-family="system-ui,-apple-system,sans-serif" font-weight="600" font-size="${fontSize}" fill="${color}">${text}</text>
|
|
24
|
+
</svg>`;
|
|
25
|
+
}
|
|
26
|
+
function avatarShape(shape, x, y, size) {
|
|
27
|
+
const r = size / 2;
|
|
28
|
+
switch (shape) {
|
|
29
|
+
case 'circle':
|
|
30
|
+
return `<circle cx="${x + r}" cy="${y + r}" r="${r}" />`;
|
|
31
|
+
case 'rounded':
|
|
32
|
+
return `<rect x="${x}" y="${y}" width="${size}" height="${size}" rx="${Math.round(size * 0.25)}" />`;
|
|
33
|
+
case 'square':
|
|
34
|
+
return `<rect x="${x}" y="${y}" width="${size}" height="${size}" rx="2" />`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
function animationDefs(mode, bg, highlight, speed) {
|
|
38
|
+
if (mode === 'none')
|
|
39
|
+
return '';
|
|
40
|
+
if (mode === 'pulse') {
|
|
41
|
+
return `<style>
|
|
42
|
+
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
|
|
43
|
+
.sk { animation: pulse ${speed}s cubic-bezier(0.4, 0, 0.6, 1) infinite; }
|
|
44
|
+
</style>`;
|
|
45
|
+
}
|
|
46
|
+
return `<linearGradient id="g">
|
|
47
|
+
<stop offset="0.1" stop-color="${bg}" />
|
|
48
|
+
<stop offset="0.5" stop-color="${highlight}" />
|
|
49
|
+
<stop offset="0.9" stop-color="${bg}" />
|
|
50
|
+
<animateTransform attributeName="gradientTransform" type="translate" values="-2 0; 2 0" dur="${speed}s" repeatCount="indefinite" />
|
|
51
|
+
</linearGradient>`;
|
|
52
|
+
}
|
|
53
|
+
function generateSkeleton(opts) {
|
|
54
|
+
const { width, height } = opts;
|
|
55
|
+
const bg = normalizeColor(opts.bg, '#e5e5e5');
|
|
56
|
+
const highlight = normalizeColor(opts.color, '#f5f5f5');
|
|
57
|
+
const rows = Math.max(0, Math.min(20, opts.rows ?? 3));
|
|
58
|
+
const avatar = opts.avatar;
|
|
59
|
+
const animate = opts.animate ?? 'shimmer';
|
|
60
|
+
const speed = opts.speed ?? 1.5;
|
|
61
|
+
const rx = opts.radius ?? 4;
|
|
62
|
+
const pad = Math.round(width * 0.06);
|
|
63
|
+
const slots = rows + (avatar ? 4 : 0);
|
|
64
|
+
const available = height - pad * 2;
|
|
65
|
+
const lineH = Math.round(Math.max(8, (available / Math.max(1, slots)) * 0.65));
|
|
66
|
+
const gap = Math.round(Math.max(6, (available / Math.max(1, slots)) * 0.35));
|
|
67
|
+
const shapes = [];
|
|
68
|
+
let y = pad;
|
|
69
|
+
if (avatar) {
|
|
70
|
+
const size = Math.round(Math.min(width * 0.14, height * 0.24, 48));
|
|
71
|
+
shapes.push(avatarShape(avatar, pad, y, size));
|
|
72
|
+
const lx = pad + size + gap;
|
|
73
|
+
const lw = width - lx - pad;
|
|
74
|
+
const count = Math.max(0, Math.min(2, opts.lines ?? 2));
|
|
75
|
+
if (count === 2) {
|
|
76
|
+
const nameY = Math.max(pad, Math.round(y + size / 2 - (lineH * 2 + gap) / 2));
|
|
77
|
+
shapes.push(`<rect x="${lx}" y="${nameY}" width="${lw * 0.55}" height="${lineH}" rx="${rx}" />`);
|
|
78
|
+
shapes.push(`<rect x="${lx}" y="${nameY + lineH + gap}" width="${lw * 0.35}" height="${lineH}" rx="${rx}" />`);
|
|
79
|
+
}
|
|
80
|
+
else if (count === 1) {
|
|
81
|
+
const nameY = Math.max(pad, Math.round(y + size / 2 - lineH / 2));
|
|
82
|
+
shapes.push(`<rect x="${lx}" y="${nameY}" width="${lw * 0.55}" height="${lineH}" rx="${rx}" />`);
|
|
83
|
+
}
|
|
84
|
+
y += size + gap * 2;
|
|
85
|
+
}
|
|
86
|
+
for (let i = 0; i < rows; i++) {
|
|
87
|
+
const ratio = i === rows - 1 && rows > 1 ? 0.55 : i % 2 === 0 ? 0.92 : 0.78;
|
|
88
|
+
const w = Math.round((width - pad * 2) * ratio);
|
|
89
|
+
shapes.push(`<rect x="${pad}" y="${y}" width="${w}" height="${lineH}" rx="${rx}" />`);
|
|
90
|
+
y += lineH + gap;
|
|
91
|
+
}
|
|
92
|
+
const defs = animationDefs(animate, bg, highlight, speed);
|
|
93
|
+
const fill = animate === 'shimmer' ? 'url(#g)' : bg;
|
|
94
|
+
const cls = animate === 'pulse' ? ' class="sk"' : '';
|
|
95
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
|
96
|
+
<defs>
|
|
97
|
+
<clipPath id="c">
|
|
98
|
+
${shapes.join('\n ')}
|
|
99
|
+
</clipPath>
|
|
100
|
+
${defs}
|
|
101
|
+
</defs>
|
|
102
|
+
<rect width="${width}" height="${height}" clip-path="url(#c)" fill="${fill}"${cls} />
|
|
103
|
+
</svg>`;
|
|
104
|
+
}
|
|
105
|
+
const AVATAR_SHAPES = new Set(['circle', 'rounded', 'square']);
|
|
106
|
+
const ANIMATE_MODES = new Set(['shimmer', 'pulse', 'none']);
|
|
107
|
+
function parseAvatar(value) {
|
|
108
|
+
if (!value)
|
|
109
|
+
return undefined;
|
|
110
|
+
if (value === 'true' || value === '1')
|
|
111
|
+
return 'circle';
|
|
112
|
+
if (AVATAR_SHAPES.has(value))
|
|
113
|
+
return value;
|
|
114
|
+
throw new Error('Avatar must be one of: circle, rounded, square');
|
|
115
|
+
}
|
|
116
|
+
function parseAnimate(value) {
|
|
117
|
+
if (!value)
|
|
118
|
+
return 'shimmer';
|
|
119
|
+
if (ANIMATE_MODES.has(value))
|
|
120
|
+
return value;
|
|
121
|
+
throw new Error('Animate must be one of: shimmer, pulse, none');
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Generates an SVG placeholder image or skeleton loader with configurable dimensions and style.
|
|
125
|
+
*
|
|
126
|
+
* @param type - Placeholder type: "image" or "skeleton"
|
|
127
|
+
* @param query - Query parameters including width, height, bg, color, text, rows, avatar, animate, speed, and radius
|
|
128
|
+
* @returns Object containing the SVG body, content type, and placeholder type
|
|
129
|
+
* @throws Error if any parameter is invalid or out of range
|
|
130
|
+
*/
|
|
131
|
+
export default function placeholder(type, query) {
|
|
132
|
+
const speed = query.speed ? parseFloat(query.speed) : 1.5;
|
|
133
|
+
if (isNaN(speed) || speed < 0.1 || speed > 10)
|
|
134
|
+
throw new Error('Speed must be between 0.1 and 10');
|
|
135
|
+
const radius = query.radius ? parseInt(query.radius, 10) : 4;
|
|
136
|
+
if (isNaN(radius) || radius < 0 || radius > 50)
|
|
137
|
+
throw new Error('Radius must be between 0 and 50');
|
|
138
|
+
const opts = {
|
|
139
|
+
width: parseSize(query.width, 'width', 800),
|
|
140
|
+
height: parseSize(query.height, 'height', 600),
|
|
141
|
+
bg: query.bg,
|
|
142
|
+
color: query.color,
|
|
143
|
+
text: query.text,
|
|
144
|
+
rows: query.rows ? parseInt(query.rows, 10) : undefined,
|
|
145
|
+
avatar: parseAvatar(query.avatar),
|
|
146
|
+
lines: query.lines ? parseInt(query.lines, 10) : 2,
|
|
147
|
+
animate: parseAnimate(query.animate),
|
|
148
|
+
speed,
|
|
149
|
+
radius,
|
|
150
|
+
};
|
|
151
|
+
switch (type) {
|
|
152
|
+
case 'image':
|
|
153
|
+
return { type, contentType: 'image/svg+xml', body: generateImage(opts) };
|
|
154
|
+
case 'skeleton':
|
|
155
|
+
return { type, contentType: 'image/svg+xml', body: generateSkeleton(opts) };
|
|
156
|
+
default:
|
|
157
|
+
throw new Error('Type must be one of: image, skeleton');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=placeholder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"placeholder.js","sourceRoot":"","sources":["../../../src/modules/v4/placeholder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface QRCodeOptions {
|
|
2
|
+
url: string;
|
|
3
|
+
size?: number;
|
|
4
|
+
margin?: number;
|
|
5
|
+
correction?: 'L' | 'M' | 'Q' | 'H';
|
|
6
|
+
dark?: string;
|
|
7
|
+
light?: string;
|
|
8
|
+
icon?: string;
|
|
9
|
+
iconSize?: number;
|
|
10
|
+
iconPadding?: number;
|
|
11
|
+
iconRadius?: number;
|
|
12
|
+
format?: 'png' | 'base64';
|
|
13
|
+
}
|
|
14
|
+
export interface QRCodeResult {
|
|
15
|
+
contentType: string;
|
|
16
|
+
body: Buffer | string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generates a QR code image for a given URL, with optional icon overlay and color customization.
|
|
20
|
+
*
|
|
21
|
+
* @param options - QR code generation options including URL, size, margin, correction level, colors, and optional icon
|
|
22
|
+
* @returns Object containing the QR code as a PNG buffer or Base64 string, and the content type
|
|
23
|
+
* @throws Error if the URL is missing, any option is invalid, or the icon URL cannot be fetched
|
|
24
|
+
*/
|
|
25
|
+
export default function qrcode(options: QRCodeOptions): Promise<QRCodeResult>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createCanvas, loadImage } from 'canvas';
|
|
2
|
+
import { toBuffer, toCanvas as qrToCanvas, toDataURL } from 'qrcode';
|
|
3
|
+
import { MAX_QRCODE_LOGO_BYTES } from '../../constants.js';
|
|
4
|
+
import { normalizeColor } from '../../utils/colors.js';
|
|
5
|
+
const CORRECTIONS = new Set(['L', 'M', 'Q', 'H']);
|
|
6
|
+
const FORMATS = new Set(['png', 'base64']);
|
|
7
|
+
function clamp(value, name, def, min, max) {
|
|
8
|
+
if (value === undefined)
|
|
9
|
+
return def;
|
|
10
|
+
if (isNaN(value))
|
|
11
|
+
throw new Error(`${name} must be a number`);
|
|
12
|
+
if (value < min || value > max)
|
|
13
|
+
throw new Error(`${name} must be between ${min} and ${max}`);
|
|
14
|
+
return Math.floor(value);
|
|
15
|
+
}
|
|
16
|
+
async function fetchIcon(url) {
|
|
17
|
+
if (!/^https:\/\//i.test(url))
|
|
18
|
+
throw new Error('Icon URL must use HTTPS');
|
|
19
|
+
const response = await fetch(url, { signal: AbortSignal.timeout(5000) });
|
|
20
|
+
if (!response.ok)
|
|
21
|
+
throw new Error(`Failed to fetch icon: HTTP ${response.status}`);
|
|
22
|
+
const contentType = response.headers.get('content-type') ?? '';
|
|
23
|
+
if (!contentType.startsWith('image/'))
|
|
24
|
+
throw new Error('Icon URL must point to an image');
|
|
25
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
26
|
+
if (buffer.length > MAX_QRCODE_LOGO_BYTES)
|
|
27
|
+
throw new Error('Icon must be under 2MB');
|
|
28
|
+
return buffer;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generates a QR code image for a given URL, with optional icon overlay and color customization.
|
|
32
|
+
*
|
|
33
|
+
* @param options - QR code generation options including URL, size, margin, correction level, colors, and optional icon
|
|
34
|
+
* @returns Object containing the QR code as a PNG buffer or Base64 string, and the content type
|
|
35
|
+
* @throws Error if the URL is missing, any option is invalid, or the icon URL cannot be fetched
|
|
36
|
+
*/
|
|
37
|
+
export default async function qrcode(options) {
|
|
38
|
+
const { url } = options;
|
|
39
|
+
if (!url || typeof url !== 'string')
|
|
40
|
+
throw new Error('Please provide a valid URL');
|
|
41
|
+
const format = options.format ?? 'png';
|
|
42
|
+
if (!FORMATS.has(format))
|
|
43
|
+
throw new Error('Format must be one of: png, base64');
|
|
44
|
+
const size = clamp(options.size, 'size', 200, 50, 2000);
|
|
45
|
+
const margin = clamp(options.margin, 'margin', 4, 0, 10);
|
|
46
|
+
const dark = normalizeColor(options.dark, '#000000');
|
|
47
|
+
const light = normalizeColor(options.light, '#ffffff');
|
|
48
|
+
let correction = options.correction ?? 'M';
|
|
49
|
+
if (!CORRECTIONS.has(correction))
|
|
50
|
+
throw new Error('Correction must be one of: L, M, Q, H');
|
|
51
|
+
if (options.icon)
|
|
52
|
+
correction = 'H';
|
|
53
|
+
const qrOpts = {
|
|
54
|
+
width: size,
|
|
55
|
+
margin,
|
|
56
|
+
errorCorrectionLevel: correction,
|
|
57
|
+
color: { dark, light },
|
|
58
|
+
};
|
|
59
|
+
if (!options.icon) {
|
|
60
|
+
if (format === 'base64') {
|
|
61
|
+
return { contentType: 'application/json', body: await toDataURL(url, qrOpts) };
|
|
62
|
+
}
|
|
63
|
+
return { contentType: 'image/png', body: await toBuffer(url, qrOpts) };
|
|
64
|
+
}
|
|
65
|
+
const canvas = createCanvas(size, size);
|
|
66
|
+
await qrToCanvas(canvas, url, qrOpts);
|
|
67
|
+
const iconBuffer = await fetchIcon(options.icon);
|
|
68
|
+
const iconImg = await loadImage(iconBuffer);
|
|
69
|
+
const iconSize = clamp(options.iconSize, 'iconSize', Math.round(size * 0.2), 10, Math.round(size * 0.4));
|
|
70
|
+
const iconPadding = clamp(options.iconPadding, 'iconPadding', 5, 0, 50);
|
|
71
|
+
const maxRadius = Math.floor((iconSize + iconPadding * 2) / 2);
|
|
72
|
+
const iconRadius = clamp(options.iconRadius, 'iconRadius', 0, 0, maxRadius);
|
|
73
|
+
const ctx = canvas.getContext('2d');
|
|
74
|
+
const totalSize = iconSize + iconPadding * 2;
|
|
75
|
+
const x = (canvas.width - totalSize) / 2;
|
|
76
|
+
const y = (canvas.height - totalSize) / 2;
|
|
77
|
+
ctx.beginPath();
|
|
78
|
+
ctx.roundRect(x, y, totalSize, totalSize, iconRadius);
|
|
79
|
+
ctx.fillStyle = light;
|
|
80
|
+
ctx.fill();
|
|
81
|
+
ctx.save();
|
|
82
|
+
ctx.beginPath();
|
|
83
|
+
ctx.roundRect(x + iconPadding, y + iconPadding, iconSize, iconSize, Math.max(0, iconRadius - iconPadding));
|
|
84
|
+
ctx.clip();
|
|
85
|
+
ctx.drawImage(iconImg, x + iconPadding, y + iconPadding, iconSize, iconSize);
|
|
86
|
+
ctx.restore();
|
|
87
|
+
if (format === 'base64') {
|
|
88
|
+
return { contentType: 'application/json', body: canvas.toDataURL('image/png') };
|
|
89
|
+
}
|
|
90
|
+
return { contentType: 'image/png', body: canvas.toBuffer('image/png') };
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=qrcode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrcode.js","sourceRoot":"","sources":["../../../src/modules/v4/qrcode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface RegexMatch {
|
|
2
|
+
match: string;
|
|
3
|
+
index: number;
|
|
4
|
+
groups: string[];
|
|
5
|
+
namedGroups: Record<string, string>;
|
|
6
|
+
}
|
|
7
|
+
export interface RegexResult {
|
|
8
|
+
valid: boolean;
|
|
9
|
+
pattern: string;
|
|
10
|
+
flags: string;
|
|
11
|
+
matches: RegexMatch[];
|
|
12
|
+
count: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Tests a regular expression pattern against a text and returns structured match results.
|
|
16
|
+
*
|
|
17
|
+
* @param pattern - The regex pattern to test (max 200 characters)
|
|
18
|
+
* @param text - The text to match against (max 1000 characters)
|
|
19
|
+
* @param flags - Optional regex flags; only g, i, m, s, u are accepted (g is always forced)
|
|
20
|
+
* @returns Match results with groups and named groups, or { valid: false } if the pattern is invalid
|
|
21
|
+
* @throws Error if pattern or text is missing or exceeds the maximum length
|
|
22
|
+
*/
|
|
23
|
+
export default function regex(pattern: string, text: string, flags?: string): RegexResult;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { MAX_PATTERN_LENGTH, MAX_REGEX_MATCHES, MAX_STRING_LENGTH } from '../../constants.js';
|
|
2
|
+
const VALID_FLAGS = new Set(['g', 'i', 'm', 's', 'u']);
|
|
3
|
+
/**
|
|
4
|
+
* Tests a regular expression pattern against a text and returns structured match results.
|
|
5
|
+
*
|
|
6
|
+
* @param pattern - The regex pattern to test (max 200 characters)
|
|
7
|
+
* @param text - The text to match against (max 1000 characters)
|
|
8
|
+
* @param flags - Optional regex flags; only g, i, m, s, u are accepted (g is always forced)
|
|
9
|
+
* @returns Match results with groups and named groups, or { valid: false } if the pattern is invalid
|
|
10
|
+
* @throws Error if pattern or text is missing or exceeds the maximum length
|
|
11
|
+
*/
|
|
12
|
+
export default function regex(pattern, text, flags = 'g') {
|
|
13
|
+
if (!pattern) {
|
|
14
|
+
throw new Error('Please provide a pattern (?pattern={regex})');
|
|
15
|
+
}
|
|
16
|
+
if (!text) {
|
|
17
|
+
throw new Error('Please provide a text (&text={string})');
|
|
18
|
+
}
|
|
19
|
+
if (pattern.length > MAX_PATTERN_LENGTH) {
|
|
20
|
+
throw new Error(`Pattern must be under ${MAX_PATTERN_LENGTH} characters`);
|
|
21
|
+
}
|
|
22
|
+
if (text.length > MAX_STRING_LENGTH) {
|
|
23
|
+
throw new Error(`Text must be under ${MAX_STRING_LENGTH} characters`);
|
|
24
|
+
}
|
|
25
|
+
const cleanedFlags = [...new Set(['g', ...flags.split('').filter((f) => VALID_FLAGS.has(f))])].join('');
|
|
26
|
+
let re;
|
|
27
|
+
try {
|
|
28
|
+
re = new RegExp(pattern, cleanedFlags);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return { valid: false, pattern, flags: cleanedFlags, matches: [], count: 0 };
|
|
32
|
+
}
|
|
33
|
+
const matches = [];
|
|
34
|
+
let result;
|
|
35
|
+
while ((result = re.exec(text)) !== null && matches.length < MAX_REGEX_MATCHES) {
|
|
36
|
+
matches.push({
|
|
37
|
+
match: result[0],
|
|
38
|
+
index: result.index,
|
|
39
|
+
groups: result.slice(1).map((g) => g ?? ''),
|
|
40
|
+
namedGroups: result.groups ? { ...result.groups } : {},
|
|
41
|
+
});
|
|
42
|
+
// Prevent infinite loop on zero-length matches
|
|
43
|
+
if (result[0].length === 0)
|
|
44
|
+
re.lastIndex++;
|
|
45
|
+
}
|
|
46
|
+
return { valid: true, pattern, flags: cleanedFlags, matches, count: matches.length };
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=regex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"regex.js","sourceRoot":"","sources":["../../../src/modules/v4/regex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAE9F,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAiBvD;;;;;;;;GAQG;AACH,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,OAAe,EAAE,IAAY,EAAE,QAAgB,GAAG;IAC5E,IAAI,CAAC,OAAO,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACnE,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACR,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC9D,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,yBAAyB,kBAAkB,aAAa,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,sBAAsB,iBAAiB,aAAa,CAAC,CAAC;IAC1E,CAAC;IAED,MAAM,YAAY,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAExG,IAAI,EAAU,CAAC;IACf,IAAI,CAAC;QACD,EAAE,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACjF,CAAC;IAED,MAAM,OAAO,GAAiB,EAAE,CAAC;IACjC,IAAI,MAA8B,CAAC;IAEnC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI,OAAO,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC;YACT,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;YAChB,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;YAC3C,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE;SACzD,CAAC,CAAC;QACH,+CAA+C;QAC/C,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC;YAAE,EAAE,CAAC,SAAS,EAAE,CAAC;IAC/C,CAAC;IAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;AACzF,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface StatisticsResult {
|
|
2
|
+
count: number;
|
|
3
|
+
sum: number;
|
|
4
|
+
min: number;
|
|
5
|
+
max: number;
|
|
6
|
+
range: number;
|
|
7
|
+
mean: number;
|
|
8
|
+
median: number;
|
|
9
|
+
mode: number[];
|
|
10
|
+
variance: number;
|
|
11
|
+
stddev: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Computes descriptive statistics for a comma-separated list of numbers.
|
|
15
|
+
*
|
|
16
|
+
* @param values - Comma-separated numeric string (e.g. "1,2,3,4,5")
|
|
17
|
+
* @returns Object containing count, sum, min, max, range, mean, median, mode, variance, and standard deviation
|
|
18
|
+
* @throws Error if values is missing, contains non-numeric entries, or exceeds the maximum count
|
|
19
|
+
*/
|
|
20
|
+
export default function statistics(values: string): StatisticsResult;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { MAX_STRING_LENGTH } from '../../constants.js';
|
|
2
|
+
/**
|
|
3
|
+
* Computes descriptive statistics for a comma-separated list of numbers.
|
|
4
|
+
*
|
|
5
|
+
* @param values - Comma-separated numeric string (e.g. "1,2,3,4,5")
|
|
6
|
+
* @returns Object containing count, sum, min, max, range, mean, median, mode, variance, and standard deviation
|
|
7
|
+
* @throws Error if values is missing, contains non-numeric entries, or exceeds the maximum count
|
|
8
|
+
*/
|
|
9
|
+
export default function statistics(values) {
|
|
10
|
+
if (!values)
|
|
11
|
+
throw new Error('A list of values is required');
|
|
12
|
+
if (typeof values !== 'string')
|
|
13
|
+
throw new Error('Values must be a comma-separated string');
|
|
14
|
+
const arr = values.split(',').map((v) => Number(v.trim()));
|
|
15
|
+
if (arr.some(isNaN))
|
|
16
|
+
throw new Error('Values must contain only numbers');
|
|
17
|
+
if (arr.length < 1)
|
|
18
|
+
throw new Error('At least one value is required');
|
|
19
|
+
if (arr.length > MAX_STRING_LENGTH)
|
|
20
|
+
throw new Error(`Cannot process more than ${MAX_STRING_LENGTH} values`);
|
|
21
|
+
const count = arr.length;
|
|
22
|
+
const sum = arr.reduce((a, b) => a + b, 0);
|
|
23
|
+
const min = Math.min(...arr);
|
|
24
|
+
const max = Math.max(...arr);
|
|
25
|
+
const mean = sum / count;
|
|
26
|
+
const sorted = [...arr].sort((a, b) => a - b);
|
|
27
|
+
const median = count % 2 === 0 ? (sorted[count / 2 - 1] + sorted[count / 2]) / 2 : sorted[Math.floor(count / 2)];
|
|
28
|
+
const counts = new Map();
|
|
29
|
+
for (const n of arr)
|
|
30
|
+
counts.set(n, (counts.get(n) ?? 0) + 1);
|
|
31
|
+
const maxCount = Math.max(...counts.values());
|
|
32
|
+
const mode = maxCount === 1 ? [] : [...counts.entries()].filter(([, c]) => c === maxCount).map(([n]) => n);
|
|
33
|
+
const variance = arr.reduce((acc, n) => acc + (n - mean) ** 2, 0) / count;
|
|
34
|
+
const stddev = Math.sqrt(variance);
|
|
35
|
+
return {
|
|
36
|
+
count,
|
|
37
|
+
sum: +sum.toFixed(6),
|
|
38
|
+
min,
|
|
39
|
+
max,
|
|
40
|
+
range: max - min,
|
|
41
|
+
mean: +mean.toFixed(6),
|
|
42
|
+
median: +median.toFixed(6),
|
|
43
|
+
mode,
|
|
44
|
+
variance: +variance.toFixed(6),
|
|
45
|
+
stddev: +stddev.toFixed(6),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=statistics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"statistics.js","sourceRoot":"","sources":["../../../src/modules/v4/statistics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAevD;;;;;;GAMG;AACH,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,MAAc;IAC7C,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC7D,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAE3F,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAE3D,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACzE,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtE,IAAI,GAAG,CAAC,MAAM,GAAG,iBAAiB;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,iBAAiB,SAAS,CAAC,CAAC;IAE5G,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC;IACzB,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,GAAG,GAAG,KAAK,CAAC;IAEzB,MAAM,MAAM,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAE,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAE,CAAC;IAEpH,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,CAAC,IAAI,GAAG;QAAE,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAE3G,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC;IAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEnC,OAAO;QACH,KAAK;QACL,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;QACpB,GAAG;QACH,GAAG;QACH,KAAK,EAAE,GAAG,GAAG,GAAG;QAChB,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACtB,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAC1B,IAAI;QACJ,QAAQ,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAC9B,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;KAC7B,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export interface TextStats {
|
|
2
|
+
characters: number;
|
|
3
|
+
charactersNoSpaces: number;
|
|
4
|
+
words: number;
|
|
5
|
+
sentences: number;
|
|
6
|
+
paragraphs: number;
|
|
7
|
+
readingTime: string;
|
|
8
|
+
mostFrequentChar: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Analyzes a text string and returns character, word, sentence, and reading time statistics.
|
|
12
|
+
*
|
|
13
|
+
* @param value - The text to analyze
|
|
14
|
+
* @returns Object containing character counts, word/sentence/paragraph counts, reading time, and most frequent character
|
|
15
|
+
* @throws Error if value is missing, not a string, or too long
|
|
16
|
+
*/
|
|
17
|
+
export declare function stats(value: string): TextStats;
|
|
18
|
+
/**
|
|
19
|
+
* Converts a string to a URL-friendly slug.
|
|
20
|
+
*
|
|
21
|
+
* @param value - The string to slugify
|
|
22
|
+
* @returns Lowercase hyphenated slug with diacritics and special characters removed
|
|
23
|
+
* @throws Error if value is missing, not a string, or too long
|
|
24
|
+
*/
|
|
25
|
+
export declare function slug(value: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Generates Lorem Ipsum placeholder text.
|
|
28
|
+
*
|
|
29
|
+
* @param type - Content type: "words", "sentences", or "paragraphs"
|
|
30
|
+
* @param count - Number of words, sentences, or paragraphs to generate
|
|
31
|
+
* @returns Generated Lorem Ipsum text
|
|
32
|
+
* @throws Error if count is out of range or type is not one of the accepted values
|
|
33
|
+
*/
|
|
34
|
+
export declare function lorem(type: string, count: string): string;
|
|
35
|
+
/**
|
|
36
|
+
* Converts an integer to its written-out word form in French or English.
|
|
37
|
+
*
|
|
38
|
+
* @param value - The integer to convert (must be less than 1 billion)
|
|
39
|
+
* @param lang - Language: "fr" for French or "en" for English
|
|
40
|
+
* @returns The number written out in words
|
|
41
|
+
* @throws Error if value is not an integer, exceeds the maximum, or lang is not supported
|
|
42
|
+
*/
|
|
43
|
+
export declare function number(value: string, lang: string): string;
|