usemods-nuxt 0.0.8
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 +91 -0
- package/dist/module.cjs +5 -0
- package/dist/module.d.mts +8 -0
- package/dist/module.d.ts +8 -0
- package/dist/module.json +5 -0
- package/dist/module.mjs +971 -0
- package/dist/runtime/plugin.d.ts +2 -0
- package/dist/runtime/plugin.mjs +4 -0
- package/dist/types.d.mts +16 -0
- package/dist/types.d.ts +16 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Get your module up and running quickly.
|
|
3
|
+
|
|
4
|
+
Find and replace all on all files (CMD+SHIFT+F):
|
|
5
|
+
- Name: My Module
|
|
6
|
+
- Package name: mods-module
|
|
7
|
+
- Description: My new Nuxt module
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
# My Module
|
|
11
|
+
|
|
12
|
+
[![npm version][npm-version-src]][npm-version-href]
|
|
13
|
+
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
14
|
+
[![License][license-src]][license-href]
|
|
15
|
+
[![Nuxt][nuxt-src]][nuxt-href]
|
|
16
|
+
|
|
17
|
+
My new Nuxt module for doing amazing things.
|
|
18
|
+
|
|
19
|
+
- [✨ Release Notes](/CHANGELOG.md)
|
|
20
|
+
<!-- - [🏀 Online playground](https://stackblitz.com/github/your-org/mods-module?file=playground%2Fapp.vue) -->
|
|
21
|
+
<!-- - [📖 Documentation](https://example.com) -->
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
<!-- Highlight some of the features your module provide here -->
|
|
26
|
+
|
|
27
|
+
- ⛰ Foo
|
|
28
|
+
- 🚠 Bar
|
|
29
|
+
- 🌲 Baz
|
|
30
|
+
|
|
31
|
+
## Quick Setup
|
|
32
|
+
|
|
33
|
+
1. Add `mods-module` dependency to your project
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
# Using pnpm
|
|
37
|
+
pnpm add -D mods-module
|
|
38
|
+
|
|
39
|
+
# Using yarn
|
|
40
|
+
yarn add --dev mods-module
|
|
41
|
+
|
|
42
|
+
# Using npm
|
|
43
|
+
npm install --save-dev mods-module
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. Add `mods-module` to the `modules` section of `nuxt.config.ts`
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
export default defineNuxtConfig({
|
|
50
|
+
modules: ["mods-module"],
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
That's it! You can now use My Module in your Nuxt app ✨
|
|
55
|
+
|
|
56
|
+
## Development
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Install dependencies
|
|
60
|
+
npm install
|
|
61
|
+
|
|
62
|
+
# Generate type stubs
|
|
63
|
+
npm run dev:prepare
|
|
64
|
+
|
|
65
|
+
# Develop with the playground
|
|
66
|
+
npm run dev
|
|
67
|
+
|
|
68
|
+
# Build the playground
|
|
69
|
+
npm run dev:build
|
|
70
|
+
|
|
71
|
+
# Run ESLint
|
|
72
|
+
npm run lint
|
|
73
|
+
|
|
74
|
+
# Run Vitest
|
|
75
|
+
npm run test
|
|
76
|
+
npm run test:watch
|
|
77
|
+
|
|
78
|
+
# Release new version
|
|
79
|
+
npm run release
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
<!-- Badges -->
|
|
83
|
+
|
|
84
|
+
[npm-version-src]: https://img.shields.io/npm/v/mods-module/latest.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
85
|
+
[npm-version-href]: https://npmjs.com/package/mods-module
|
|
86
|
+
[npm-downloads-src]: https://img.shields.io/npm/dm/mods-module.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
87
|
+
[npm-downloads-href]: https://npmjs.com/package/mods-module
|
|
88
|
+
[license-src]: https://img.shields.io/npm/l/mods-module.svg?style=flat&colorA=18181B&colorB=28CF8D
|
|
89
|
+
[license-href]: https://npmjs.com/package/mods-module
|
|
90
|
+
[nuxt-src]: https://img.shields.io/badge/Nuxt-18181B?logo=nuxt.js
|
|
91
|
+
[nuxt-href]: https://nuxt.com
|
package/dist/module.cjs
ADDED
package/dist/module.d.ts
ADDED
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,971 @@
|
|
|
1
|
+
import { defineNuxtModule, createResolver, addImports, addPlugin } from '@nuxt/kit';
|
|
2
|
+
|
|
3
|
+
function scrollToAnchor(id) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
setTimeout(() => {
|
|
6
|
+
const selector = `#${id}`, element = document.querySelector(selector);
|
|
7
|
+
if (!element) {
|
|
8
|
+
reject(`Element with id '${id}' not found.`);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
element.scrollIntoView({ behavior: "smooth", block: "start" }), resolve();
|
|
12
|
+
}, 180);
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
function toggleBodyScroll(className = "fixed") {
|
|
16
|
+
return new Promise((resolve, reject) => {
|
|
17
|
+
try {
|
|
18
|
+
const body = document.body, isFixed = body.classList.contains(className), scrollY = isFixed ? parseInt(body.style.top, 10) : window.scrollY;
|
|
19
|
+
if (body.style.top = isFixed ? "" : `-${scrollY}px`, body.classList.toggle(className, !isFixed), isFixed)
|
|
20
|
+
window.scrollTo(0, -scrollY);
|
|
21
|
+
resolve();
|
|
22
|
+
} catch (error) {
|
|
23
|
+
reject(error);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function toggleElementScroll(element) {
|
|
28
|
+
return new Promise((resolve, reject) => {
|
|
29
|
+
if (element.dataset.isScrollLocked === "true")
|
|
30
|
+
element.style.overflow = "", delete element.dataset.isScrollLocked;
|
|
31
|
+
else
|
|
32
|
+
element.style.overflow = "hidden", element.dataset.isScrollLocked = "true";
|
|
33
|
+
resolve();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function copyToClipboard(value) {
|
|
37
|
+
if (!navigator.clipboard || !navigator.clipboard.writeText)
|
|
38
|
+
return Promise.reject("Clipboard API is not available");
|
|
39
|
+
return navigator.clipboard.writeText(String(value)).catch((error) => {
|
|
40
|
+
throw console.error("Failed to copy text: ", error), error;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function toggleFullScreen() {
|
|
44
|
+
return new Promise((resolve, reject) => {
|
|
45
|
+
if (document.fullscreenElement)
|
|
46
|
+
document.exitFullscreen().then(resolve).catch(reject);
|
|
47
|
+
else
|
|
48
|
+
document.documentElement.requestFullscreen().then(resolve).catch(reject);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function resetForm(form) {
|
|
52
|
+
return new Promise((resolve, reject) => {
|
|
53
|
+
try {
|
|
54
|
+
form.reset(), resolve();
|
|
55
|
+
} catch (error) {
|
|
56
|
+
reject(error);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function focusOnInvalid(container) {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
try {
|
|
63
|
+
const input = container.querySelector("input:invalid, select:invalid, textarea:invalid");
|
|
64
|
+
if (input)
|
|
65
|
+
input.focus(), input.scrollIntoView({ behavior: "smooth", block: "center" });
|
|
66
|
+
resolve();
|
|
67
|
+
} catch (error) {
|
|
68
|
+
reject(error);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
function focusOnNth(container, index = 0) {
|
|
73
|
+
return new Promise((resolve, reject) => {
|
|
74
|
+
const elements = container.querySelectorAll("input, textarea, select"), elementIndex = index === -1 ? elements.length - 1 : index;
|
|
75
|
+
if (elementIndex < 0 || elementIndex >= elements.length)
|
|
76
|
+
return reject(new Error(`Element at index ${index} is out of bounds.`));
|
|
77
|
+
const element = elements[elementIndex];
|
|
78
|
+
if (!element || typeof element.focus !== "function")
|
|
79
|
+
return reject(new Error("Failed to focus on the element."));
|
|
80
|
+
try {
|
|
81
|
+
element.focus({ preventScroll: true }), element.scrollIntoView({ behavior: "smooth", block: "center" }), resolve();
|
|
82
|
+
} catch (error) {
|
|
83
|
+
reject(new Error("Failed to focus on the element."));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
function focusTrap(container) {
|
|
88
|
+
const focusableElements = container.querySelectorAll('a[href], button, textarea, input[type="text"], input[type="radio"], input[type="checkbox"], select'), firstFocusableElement = focusableElements[0], lastFocusableElement = focusableElements[focusableElements.length - 1];
|
|
89
|
+
container.addEventListener("keydown", (event) => {
|
|
90
|
+
if (!(event.key === "Tab" || event.keyCode === 9))
|
|
91
|
+
return;
|
|
92
|
+
if (event.shiftKey) {
|
|
93
|
+
if (document.activeElement === firstFocusableElement)
|
|
94
|
+
lastFocusableElement.focus(), event.preventDefault();
|
|
95
|
+
} else if (document.activeElement === lastFocusableElement)
|
|
96
|
+
firstFocusableElement.focus(), event.preventDefault();
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function formatNumber(value, decimals = 2, locale = "en-US") {
|
|
100
|
+
const safeDecimals = Math.max(0, Math.min(decimals, 20));
|
|
101
|
+
let config = { style: "decimal", minimumFractionDigits: safeDecimals === 0 ? 0 : safeDecimals === 1 ? 1 : 2, maximumFractionDigits: safeDecimals };
|
|
102
|
+
return new Intl.NumberFormat(locale, config).format(value);
|
|
103
|
+
}
|
|
104
|
+
function formatCurrency(value, decimals = 2, locale = "en-US") {
|
|
105
|
+
const safeDecimals = Math.max(0, Math.min(decimals, 20));
|
|
106
|
+
let config = { style: "currency", currencyDisplay: "narrowSymbol", minimumFractionDigits: safeDecimals === 0 ? 0 : safeDecimals === 1 ? 1 : 2, maximumFractionDigits: safeDecimals, currency: currencySymbols.get(locale) || "USD" };
|
|
107
|
+
return new Intl.NumberFormat(locale, config).format(value);
|
|
108
|
+
}
|
|
109
|
+
function formatValuation(value, decimals = 2, locale = "en-US") {
|
|
110
|
+
const safeDecimals = Math.max(0, Math.min(decimals, 20));
|
|
111
|
+
let config = { style: "currency", currencyDisplay: "narrowSymbol", notation: "compact", compactDisplay: "short", minimumFractionDigits: safeDecimals === 0 ? 0 : safeDecimals === 1 ? 1 : 2, maximumFractionDigits: safeDecimals, currency: currencySymbols.get(locale) || "USD" };
|
|
112
|
+
return new Intl.NumberFormat(locale, config).format(value);
|
|
113
|
+
}
|
|
114
|
+
function formatPercentage(value, decimals = 2, locale = "en-US") {
|
|
115
|
+
const safeDecimals = Math.max(0, Math.min(decimals, 20));
|
|
116
|
+
let config = { style: "percent", minimumFractionDigits: safeDecimals === 0 ? 0 : safeDecimals === 1 ? 1 : 2, maximumFractionDigits: safeDecimals };
|
|
117
|
+
return new Intl.NumberFormat(locale, config).format(value);
|
|
118
|
+
}
|
|
119
|
+
function formatDurationLabels(seconds, labels = "long", round = false) {
|
|
120
|
+
const time = [{ unit: labels === "short" ? "yr" : " year", secondsInUnit: 31536e3 }, { unit: labels === "short" ? "mo" : " month", secondsInUnit: 2628e3 }, { unit: labels === "short" ? "wk" : " week", secondsInUnit: 604800 }, { unit: labels === "short" ? "d" : " day", secondsInUnit: 86400 }, { unit: labels === "short" ? "hr" : " hour", secondsInUnit: 3600 }, { unit: labels === "short" ? "min" : " minute", secondsInUnit: 60 }, { unit: labels === "short" ? "s" : " second", secondsInUnit: 1 }];
|
|
121
|
+
if (seconds == 0)
|
|
122
|
+
return `0${labels === "short" ? "s" : " seconds"}`;
|
|
123
|
+
if (round) {
|
|
124
|
+
for (let { secondsInUnit } of time)
|
|
125
|
+
if (seconds >= secondsInUnit) {
|
|
126
|
+
seconds = seconds - seconds % secondsInUnit;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let remainingSeconds = seconds, formattedTime = "";
|
|
131
|
+
for (let { unit, secondsInUnit } of time) {
|
|
132
|
+
const count = Math.floor(remainingSeconds / secondsInUnit);
|
|
133
|
+
if (count > 0)
|
|
134
|
+
formattedTime += `${count}${count === 1 || labels === "short" ? unit : unit + "s"} `, remainingSeconds -= count * secondsInUnit;
|
|
135
|
+
}
|
|
136
|
+
return formattedTime.trim();
|
|
137
|
+
}
|
|
138
|
+
function formatDurationNumbers(seconds) {
|
|
139
|
+
const hours = Math.floor(seconds / 3600), minutes = Math.floor((seconds - hours * 3600) / 60), remainingSeconds = seconds - hours * 3600 - minutes * 60;
|
|
140
|
+
return [hours, minutes, remainingSeconds].map((value) => value.toString().padStart(2, "0")).join(":");
|
|
141
|
+
}
|
|
142
|
+
function formatNumberToWords(value) {
|
|
143
|
+
const underTwenty = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen"], tens = ["twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"];
|
|
144
|
+
if (value < 20)
|
|
145
|
+
return underTwenty[value];
|
|
146
|
+
if (value < 100)
|
|
147
|
+
return `${tens[Math.floor(value / 10) - 2]}${value % 10 ? "-" + underTwenty[value % 10] : ""}`;
|
|
148
|
+
const formatGroup = (number) => {
|
|
149
|
+
if (number >= 100) {
|
|
150
|
+
const remainder = number % 100;
|
|
151
|
+
return `${underTwenty[Math.floor(number / 100)]} hundred${remainder ? ` and ${formatGroup(remainder)}` : ""}`;
|
|
152
|
+
} else if (number >= 20)
|
|
153
|
+
return `${tens[Math.floor(number / 10) - 2]}${number % 10 ? "-" + underTwenty[number % 10] : ""}`;
|
|
154
|
+
else
|
|
155
|
+
return underTwenty[number];
|
|
156
|
+
}, scales = ["", " thousand", " million", " billion", " trillion", " quadrillion", " quintillion"];
|
|
157
|
+
let scaleIndex = 0, result = "";
|
|
158
|
+
while (value > 0) {
|
|
159
|
+
const groupValue = value % 1e3;
|
|
160
|
+
if (groupValue > 0)
|
|
161
|
+
result = formatGroup(groupValue) + scales[scaleIndex] + (result ? ", " + result : "");
|
|
162
|
+
value = Math.floor(value / 1e3), scaleIndex++;
|
|
163
|
+
}
|
|
164
|
+
return result.trim();
|
|
165
|
+
}
|
|
166
|
+
function formatInitials(text, length = 2) {
|
|
167
|
+
return text = text.replace(/(Mr|Mrs|Ms|Dr|Jr|Sr|Prof|Hon|Snr|Jnr|St)\.?/g, "").trim(), text.split(" ").filter((word) => !["the", "third"].includes(word.toLowerCase())).map((word) => word.charAt(0).toUpperCase()).join("").substring(0, length);
|
|
168
|
+
}
|
|
169
|
+
function formatUnixTime(timestamp) {
|
|
170
|
+
return new Date(timestamp * 1e3).toISOString().replace("T", " ").replace("Z", "");
|
|
171
|
+
}
|
|
172
|
+
function formatList(items, limit = Infinity, conjunction = "and") {
|
|
173
|
+
if (typeof items === "string")
|
|
174
|
+
items = items.split(",").map((item) => item.trim());
|
|
175
|
+
if (typeof items === "object" && !Array.isArray(items))
|
|
176
|
+
items = Object.values(items);
|
|
177
|
+
if (!Array.isArray(items) || items.length === 0)
|
|
178
|
+
return "";
|
|
179
|
+
if (items.length <= 2)
|
|
180
|
+
return items.join(items.length === 2 ? ` ${conjunction} ` : "");
|
|
181
|
+
if (items.length <= limit)
|
|
182
|
+
return items.slice(0, -1).join(", ") + ` ${conjunction} ` + items.slice(-1);
|
|
183
|
+
const listedItems = items.slice(0, limit).join(", "), remaining = items.length - limit;
|
|
184
|
+
return `${listedItems} ${conjunction} ${remaining} more`;
|
|
185
|
+
}
|
|
186
|
+
function formatTitle(text) {
|
|
187
|
+
const exceptions = /* @__PURE__ */ new Set(["a", "an", "to", "the", "for", "and", "nor", "but", "or", "yet", "so", "in", "is", "it", "than", "on", "at", "with", "under", "above", "from", "of", "although", "because", "since", "unless"]);
|
|
188
|
+
return text.split(" ").map((word, index, wordsArray) => {
|
|
189
|
+
const lowerWord = word.toLowerCase();
|
|
190
|
+
if (index === 0 || index === wordsArray.length - 1 || !exceptions.has(lowerWord))
|
|
191
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
192
|
+
return lowerWord;
|
|
193
|
+
}).join(" ");
|
|
194
|
+
}
|
|
195
|
+
function formatSentenceCase(text) {
|
|
196
|
+
return text.split("\n\n").map((paragraph) => paragraph.split(". ").map((sentence) => sentence.charAt(0).toUpperCase() + sentence.slice(1)).join(". ")).join("\n\n");
|
|
197
|
+
}
|
|
198
|
+
function formatTextWrap(value) {
|
|
199
|
+
const space = value.lastIndexOf(" ");
|
|
200
|
+
if (space !== -1)
|
|
201
|
+
return value.substring(0, space) + " " + value.substring(space + 1);
|
|
202
|
+
return value;
|
|
203
|
+
}
|
|
204
|
+
var currencySymbols = /* @__PURE__ */ new Map([["en-US", "USD"], ["en-GB", "GBP"], ["en-AU", "AUD"], ["en-CA", "CAD"], ["en-NZ", "NZD"], ["en-ZA", "ZAR"], ["de-DE", "EUR"], ["fr-FR", "EUR"], ["es-ES", "EUR"], ["it-IT", "EUR"], ["pt-PT", "EUR"], ["nl-NL", "EUR"], ["da-DK", "DKK"], ["sv-SE", "SEK"], ["nb-NO", "NOK"], ["fi-FI", "EUR"], ["pl-PL", "PLN"], ["tr-TR", "TRY"], ["ru-RU", "RUB"], ["ja-JP", "JPY"], ["zh-CN", "CNY"], ["ko-KR", "KRW"], ["ar-SA", "SAR"], ["he-IL", "ILS"], ["id-ID", "IDR"], ["ms-MY", "MYR"], ["th-TH", "THB"], ["vi-VN", "VND"], ["hi-IN", "INR"], ["bn-IN", "INR"], ["pa-IN", "INR"], ["gu-IN", "INR"], ["or-IN", "INR"], ["ta-IN", "INR"], ["te-IN", "INR"], ["kn-IN", "INR"], ["ml-IN", "INR"]]);
|
|
205
|
+
function startWith(value, start) {
|
|
206
|
+
if (value.startsWith(start))
|
|
207
|
+
return value;
|
|
208
|
+
return start + value;
|
|
209
|
+
}
|
|
210
|
+
function startWithout(value, start) {
|
|
211
|
+
if (value.startsWith(start))
|
|
212
|
+
return value.substring(start.length);
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
function endWith(text, end) {
|
|
216
|
+
if (text.endsWith(end))
|
|
217
|
+
return text;
|
|
218
|
+
return text + end;
|
|
219
|
+
}
|
|
220
|
+
function endWithout(text, end) {
|
|
221
|
+
if (text.endsWith(end))
|
|
222
|
+
return text.substring(0, text.length - end.length);
|
|
223
|
+
return text;
|
|
224
|
+
}
|
|
225
|
+
function surroundWith(text, start, end) {
|
|
226
|
+
if (text.startsWith(start) && text.endsWith(end))
|
|
227
|
+
return text;
|
|
228
|
+
if (text.startsWith(start))
|
|
229
|
+
return text + end;
|
|
230
|
+
if (text.endsWith(end))
|
|
231
|
+
return start + text;
|
|
232
|
+
return start + text + end;
|
|
233
|
+
}
|
|
234
|
+
function pluralize(value, count) {
|
|
235
|
+
if (!value)
|
|
236
|
+
return "";
|
|
237
|
+
if (value = value.trim().toLowerCase(), count === 1)
|
|
238
|
+
return value;
|
|
239
|
+
if (unchangingPlurals.has(value))
|
|
240
|
+
return value;
|
|
241
|
+
if (irregularPlurals.has(value))
|
|
242
|
+
return irregularPlurals.get(value) || value;
|
|
243
|
+
if (value.endsWith("f"))
|
|
244
|
+
return value.slice(0, -1) + "ves";
|
|
245
|
+
if (value.endsWith("fe"))
|
|
246
|
+
return value.slice(0, -2) + "ves";
|
|
247
|
+
if (value.endsWith("y"))
|
|
248
|
+
return value.slice(0, -1) + "ies";
|
|
249
|
+
if (value.endsWith("s"))
|
|
250
|
+
return value;
|
|
251
|
+
if (value.endsWith("x"))
|
|
252
|
+
return value + "es";
|
|
253
|
+
if (value.endsWith("ch"))
|
|
254
|
+
return value + "es";
|
|
255
|
+
if (value.endsWith("sh"))
|
|
256
|
+
return value + "es";
|
|
257
|
+
return value + "s";
|
|
258
|
+
}
|
|
259
|
+
function singularize(value) {
|
|
260
|
+
if (value = value.trim().toLowerCase(), unchangingPlurals.has(value))
|
|
261
|
+
return value;
|
|
262
|
+
if (irregularPlurals.has(value))
|
|
263
|
+
return irregularPlurals.get(value) || value;
|
|
264
|
+
if (value.endsWith("ives"))
|
|
265
|
+
return value.slice(0, -4) + "ife";
|
|
266
|
+
if (value.endsWith("ves"))
|
|
267
|
+
return value.slice(0, -3) + "f";
|
|
268
|
+
if (value.endsWith("ies"))
|
|
269
|
+
return value.slice(0, -3) + "y";
|
|
270
|
+
if (value.endsWith("ches") || value.endsWith("shes") || value.endsWith("xes"))
|
|
271
|
+
return value.slice(0, -2);
|
|
272
|
+
if (value.endsWith("oes"))
|
|
273
|
+
return value.slice(0, -2);
|
|
274
|
+
if (value.endsWith("us") || value.endsWith("ss"))
|
|
275
|
+
return value;
|
|
276
|
+
if (value.endsWith("i"))
|
|
277
|
+
return value.slice(0, -1) + "us";
|
|
278
|
+
if (value.endsWith("a"))
|
|
279
|
+
return value.slice(0, -1) + "on";
|
|
280
|
+
if (value.endsWith("s") && value.length > 1)
|
|
281
|
+
return value.slice(0, -1);
|
|
282
|
+
return value;
|
|
283
|
+
}
|
|
284
|
+
function ordinalize(value) {
|
|
285
|
+
const suffixes = ["th", "st", "nd", "rd"], remainder = value % 100;
|
|
286
|
+
return value + (suffixes[(remainder - 20) % 10] || suffixes[remainder] || suffixes[0]);
|
|
287
|
+
}
|
|
288
|
+
function stripHtml(text) {
|
|
289
|
+
return text.replace(/<[^>]*>?/gm, "");
|
|
290
|
+
}
|
|
291
|
+
function stripWhitespace(text) {
|
|
292
|
+
return text.replace(/\s+/g, "");
|
|
293
|
+
}
|
|
294
|
+
function stripNumbers(text) {
|
|
295
|
+
return text.replace(/[0-9]/g, "");
|
|
296
|
+
}
|
|
297
|
+
function stripPunctuation(text) {
|
|
298
|
+
return text.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, "");
|
|
299
|
+
}
|
|
300
|
+
function stripSymbols(text) {
|
|
301
|
+
return text.replace(/[^\w\s]|_/g, "");
|
|
302
|
+
}
|
|
303
|
+
function stripEmojis(text) {
|
|
304
|
+
return text.replace(/[\p{Emoji_Presentation}\p{Emoji}\uFE0F\u200D\u20E3]/gu, "");
|
|
305
|
+
}
|
|
306
|
+
function slugify(text) {
|
|
307
|
+
return text.toLowerCase().replace(/[^\w ]+/g, "").replace(/ +/g, "-");
|
|
308
|
+
}
|
|
309
|
+
function deslugify(text) {
|
|
310
|
+
return text.toLowerCase().replace(/-/g, " ");
|
|
311
|
+
}
|
|
312
|
+
function camelCase(text) {
|
|
313
|
+
return text.trim().split(/[-\s]/).map((word, index) => {
|
|
314
|
+
if (index === 0)
|
|
315
|
+
return word.toLowerCase();
|
|
316
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
317
|
+
}).join("");
|
|
318
|
+
}
|
|
319
|
+
function pascalCase(text) {
|
|
320
|
+
return text.trim().split(/[-\s]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join("");
|
|
321
|
+
}
|
|
322
|
+
function snakeCase(text) {
|
|
323
|
+
return text.trim().replace(/\s+/g, "_").toLowerCase();
|
|
324
|
+
}
|
|
325
|
+
function kebabCase(text) {
|
|
326
|
+
return text.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
|
|
327
|
+
return index === 0 ? word.toLowerCase() : "-" + word.toLowerCase();
|
|
328
|
+
}).replace(/\s+/g, "");
|
|
329
|
+
}
|
|
330
|
+
function titleCase(text) {
|
|
331
|
+
return text.replace(/(?:^\w|[A-Z]|\b\w)/g, (word, index) => {
|
|
332
|
+
return word.toUpperCase();
|
|
333
|
+
}).replace(/\s+/g, " ");
|
|
334
|
+
}
|
|
335
|
+
function escapeHtml(text) {
|
|
336
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
337
|
+
}
|
|
338
|
+
function unescapeHtml(text) {
|
|
339
|
+
return text.replace(/</g, "<").replace(/>/g, ">");
|
|
340
|
+
}
|
|
341
|
+
var unchangingPlurals = /* @__PURE__ */ new Set(["sheep", "fish", "deer", "hay", "moose", "series", "species", "aircraft", "bison", "buffalo", "cod", "elk", "halibut", "hovercraft", "lego", "mackerel", "salmon", "spacecraft", "swine", "trout", "tuna"]), irregularPlurals = /* @__PURE__ */ new Map([["child", "children"], ["person", "people"], ["man", "men"], ["woman", "women"], ["tooth", "teeth"], ["foot", "feet"], ["mouse", "mice"], ["goose", "geese"], ["ox", "oxen"], ["leaf", "leaves"], ["life", "lives"], ["knife", "knives"], ["wife", "wives"], ["half", "halves"], ["elf", "elves"], ["loaf", "loaves"], ["potato", "potatoes"], ["tomato", "tomatoes"], ["cactus", "cacti"], ["focus", "foci"], ["fungus", "fungi"], ["nucleus", "nuclei"], ["syllabus", "syllabi"], ["analysis", "analyses"], ["diagnosis", "diagnoses"], ["oasis", "oases"], ["thesis", "theses"], ["crisis", "crises"]]);
|
|
342
|
+
function detectDevice() {
|
|
343
|
+
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) ? "Mobile" : "Desktop";
|
|
344
|
+
}
|
|
345
|
+
function detectOS() {
|
|
346
|
+
const userAgent = navigator.userAgent.toLowerCase();
|
|
347
|
+
if (userAgent.includes("win"))
|
|
348
|
+
return "Windows";
|
|
349
|
+
if (userAgent.includes("mac"))
|
|
350
|
+
return "Mac";
|
|
351
|
+
if (userAgent.includes("linux"))
|
|
352
|
+
return "Linux";
|
|
353
|
+
if (userAgent.includes("x11"))
|
|
354
|
+
return "UNIX";
|
|
355
|
+
if (userAgent.includes("android"))
|
|
356
|
+
return "Android";
|
|
357
|
+
if (userAgent.includes("iphone"))
|
|
358
|
+
return "iOS";
|
|
359
|
+
return "Unknown";
|
|
360
|
+
}
|
|
361
|
+
function detectActiveBrowser() {
|
|
362
|
+
return !document.hidden;
|
|
363
|
+
}
|
|
364
|
+
function detectColorScheme() {
|
|
365
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
366
|
+
}
|
|
367
|
+
function detectUserTimezone() {
|
|
368
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
369
|
+
}
|
|
370
|
+
function detectDeviceOrientation() {
|
|
371
|
+
return window.screen.orientation.type;
|
|
372
|
+
}
|
|
373
|
+
function detectWindowSize() {
|
|
374
|
+
return { width: window.innerWidth, height: window.innerHeight };
|
|
375
|
+
}
|
|
376
|
+
function detectScreenSize() {
|
|
377
|
+
return { width: window.screen.width, height: window.screen.height };
|
|
378
|
+
}
|
|
379
|
+
function detectBreakpoint() {
|
|
380
|
+
const width = window.innerWidth;
|
|
381
|
+
if (width < 640)
|
|
382
|
+
return "xs";
|
|
383
|
+
if (width < 768)
|
|
384
|
+
return "sm";
|
|
385
|
+
if (width < 1024)
|
|
386
|
+
return "md";
|
|
387
|
+
if (width < 1280)
|
|
388
|
+
return "lg";
|
|
389
|
+
if (width < 1536)
|
|
390
|
+
return "xl";
|
|
391
|
+
return "2xl";
|
|
392
|
+
}
|
|
393
|
+
function detectContainerBreakpoint(element) {
|
|
394
|
+
const width = element.getBoundingClientRect().width;
|
|
395
|
+
if (width < 320)
|
|
396
|
+
return "@xs";
|
|
397
|
+
if (width < 384)
|
|
398
|
+
return "@sm";
|
|
399
|
+
if (width < 448)
|
|
400
|
+
return "@md";
|
|
401
|
+
if (width < 512)
|
|
402
|
+
return "@lg";
|
|
403
|
+
if (width < 576)
|
|
404
|
+
return "@xl";
|
|
405
|
+
if (width < 672)
|
|
406
|
+
return "@2xl";
|
|
407
|
+
if (width < 768)
|
|
408
|
+
return "@3xl";
|
|
409
|
+
if (width < 896)
|
|
410
|
+
return "@4xl";
|
|
411
|
+
if (width < 1024)
|
|
412
|
+
return "@5xl";
|
|
413
|
+
if (width < 1152)
|
|
414
|
+
return "@6xl";
|
|
415
|
+
if (width < 1280)
|
|
416
|
+
return "@7xl";
|
|
417
|
+
return "@7xl";
|
|
418
|
+
}
|
|
419
|
+
function detectScrollPosition() {
|
|
420
|
+
return { x: window.scrollX, y: window.scrollY };
|
|
421
|
+
}
|
|
422
|
+
function detectMousePosition(event) {
|
|
423
|
+
return { x: event.pageX, y: event.pageY };
|
|
424
|
+
}
|
|
425
|
+
function detectRelativeMousePosition(event) {
|
|
426
|
+
const { innerWidth, innerHeight } = window;
|
|
427
|
+
return { x: event.clientX / innerWidth, y: event.clientY / innerHeight };
|
|
428
|
+
}
|
|
429
|
+
function detectNetworkStatus() {
|
|
430
|
+
return navigator.onLine ? "Online" : "Offline";
|
|
431
|
+
}
|
|
432
|
+
function detectUrl() {
|
|
433
|
+
return window.location.href;
|
|
434
|
+
}
|
|
435
|
+
function detectUrlPath() {
|
|
436
|
+
return window.location.pathname.split("/").filter((p) => p);
|
|
437
|
+
}
|
|
438
|
+
function detectUrlParams() {
|
|
439
|
+
const searchParams = new URLSearchParams(window.location.search), paramsArray = [];
|
|
440
|
+
for (let [key, value] of searchParams.entries())
|
|
441
|
+
paramsArray.push({ [key]: value });
|
|
442
|
+
return paramsArray.length > 0 ? paramsArray : null;
|
|
443
|
+
}
|
|
444
|
+
function detectUrlHash() {
|
|
445
|
+
return window.location.hash.replace("#", "");
|
|
446
|
+
}
|
|
447
|
+
function detectHost() {
|
|
448
|
+
return window.location.host;
|
|
449
|
+
}
|
|
450
|
+
function detectHostName() {
|
|
451
|
+
return window.location.hostname;
|
|
452
|
+
}
|
|
453
|
+
function detectPort() {
|
|
454
|
+
return window.location.port;
|
|
455
|
+
}
|
|
456
|
+
function generateNumber(length) {
|
|
457
|
+
return Math.floor(Math.random() * Math.pow(10, length));
|
|
458
|
+
}
|
|
459
|
+
function generateNumberBetween(min2, max2) {
|
|
460
|
+
if (min2 > max2)
|
|
461
|
+
console.warn("[MODS] Warning: min value is higher than max value");
|
|
462
|
+
return Math.floor(Math.random() * (max2 - min2 + 1) + min2);
|
|
463
|
+
}
|
|
464
|
+
function generateUuid() {
|
|
465
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
466
|
+
const r = Math.random() * 16 | 0;
|
|
467
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
function generateShortId(length = 36) {
|
|
471
|
+
const timestampPart = Math.floor(Date.now()).toString(length).toUpperCase(), randomPart = Math.random().toString(length).slice(2).toUpperCase();
|
|
472
|
+
return (timestampPart + randomPart).slice(0, length);
|
|
473
|
+
}
|
|
474
|
+
function generatePassword(length = 8) {
|
|
475
|
+
if (length < 8)
|
|
476
|
+
length = 8;
|
|
477
|
+
const uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ", lowercase = uppercase.toLowerCase(), numbers = "0123456789", symbols = "!@#$%^&*", allChars = uppercase + lowercase + numbers + symbols, passwordArray = [uppercase[Math.floor(Math.random() * uppercase.length)], lowercase[Math.floor(Math.random() * lowercase.length)], numbers[Math.floor(Math.random() * numbers.length)], symbols[Math.floor(Math.random() * symbols.length)]];
|
|
478
|
+
for (let i = passwordArray.length; i < length; i++)
|
|
479
|
+
passwordArray.push(allChars[Math.floor(Math.random() * allChars.length)]);
|
|
480
|
+
for (let i = passwordArray.length - 1; i > 0; i--) {
|
|
481
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
482
|
+
[passwordArray[i], passwordArray[j]] = [passwordArray[j], passwordArray[i]];
|
|
483
|
+
}
|
|
484
|
+
return passwordArray.join("");
|
|
485
|
+
}
|
|
486
|
+
function generateLoremIpsum(count = 5, format = "words") {
|
|
487
|
+
const lorem = "lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod tempor incididunt ut labore et dolore magna aliqua".split(" "), generateSentence = () => {
|
|
488
|
+
const words = Array.from({ length: Math.floor(Math.random() * 10) + 5 }, () => lorem[Math.floor(Math.random() * lorem.length)]).join(" ");
|
|
489
|
+
return formatSentence(words);
|
|
490
|
+
}, formatSentence = (sentence) => {
|
|
491
|
+
return sentence.charAt(0).toUpperCase() + sentence.slice(1) + ".";
|
|
492
|
+
};
|
|
493
|
+
if (format === "sentences")
|
|
494
|
+
return Array.from({ length: count }, generateSentence).join(" ");
|
|
495
|
+
else if (format === "paragraphs")
|
|
496
|
+
return Array.from({ length: count }, () => Array.from({ length: Math.floor(Math.random() * 3) + 2 }, generateSentence).join(" ")).join("\n\n");
|
|
497
|
+
else
|
|
498
|
+
return lorem.slice(0, count).join(" ");
|
|
499
|
+
}
|
|
500
|
+
function sum(numbers) {
|
|
501
|
+
return numbers.reduce((a, b) => a + b, 0);
|
|
502
|
+
}
|
|
503
|
+
function mean(numbers) {
|
|
504
|
+
return sum(numbers) / numbers.length;
|
|
505
|
+
}
|
|
506
|
+
function average(numbers) {
|
|
507
|
+
return mean(numbers);
|
|
508
|
+
}
|
|
509
|
+
function margin(value, percentage) {
|
|
510
|
+
return value * percentage / 100;
|
|
511
|
+
}
|
|
512
|
+
function addMargin(value, percentage) {
|
|
513
|
+
return value + margin(value, percentage);
|
|
514
|
+
}
|
|
515
|
+
function subtractMargin(value, percentage) {
|
|
516
|
+
return value - margin(value, percentage);
|
|
517
|
+
}
|
|
518
|
+
function subtractMarkup(value, percentage) {
|
|
519
|
+
return value / (1 + percentage / 100);
|
|
520
|
+
}
|
|
521
|
+
function addMarkup(value, percentage) {
|
|
522
|
+
return value + subtractMarkup(value, percentage);
|
|
523
|
+
}
|
|
524
|
+
function median(numbers) {
|
|
525
|
+
const sorted = numbers.sort((a, b) => a - b), middle = Math.floor(sorted.length / 2);
|
|
526
|
+
if (sorted.length % 2 === 0)
|
|
527
|
+
return (sorted[middle - 1] + sorted[middle]) / 2;
|
|
528
|
+
return sorted[middle];
|
|
529
|
+
}
|
|
530
|
+
function mode(numbers) {
|
|
531
|
+
if (numbers.length === 0)
|
|
532
|
+
return null;
|
|
533
|
+
if (numbers.length === 1)
|
|
534
|
+
return numbers[0];
|
|
535
|
+
const frequencyMap = /* @__PURE__ */ new Map();
|
|
536
|
+
numbers.forEach((num) => frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1));
|
|
537
|
+
const maxEntry = [...frequencyMap.entries()].reduce((a, b) => a[1] > b[1] ? a : b);
|
|
538
|
+
if (maxEntry[1] > 1)
|
|
539
|
+
return maxEntry[0];
|
|
540
|
+
return null;
|
|
541
|
+
}
|
|
542
|
+
function min(numbers) {
|
|
543
|
+
return Math.min(...numbers);
|
|
544
|
+
}
|
|
545
|
+
function max(numbers) {
|
|
546
|
+
return Math.max(...numbers);
|
|
547
|
+
}
|
|
548
|
+
function minMax(numbers) {
|
|
549
|
+
return [min(numbers), max(numbers)];
|
|
550
|
+
}
|
|
551
|
+
function range(numbers) {
|
|
552
|
+
return max(numbers) - min(numbers);
|
|
553
|
+
}
|
|
554
|
+
function standardDeviation(numbers) {
|
|
555
|
+
return Math.sqrt(mean(numbers.map((num) => Math.pow(num - mean(numbers), 2))));
|
|
556
|
+
}
|
|
557
|
+
function skewness(numbers) {
|
|
558
|
+
const n = numbers.length, meanValue = mean(numbers);
|
|
559
|
+
if (standardDeviation(numbers) === 0)
|
|
560
|
+
return;
|
|
561
|
+
let sum2 = 0;
|
|
562
|
+
for (let num of numbers)
|
|
563
|
+
sum2 += (num - meanValue) ** 3;
|
|
564
|
+
return n / ((n - 1) * (n - 2)) * (sum2 / standardDeviation(numbers) ** 3);
|
|
565
|
+
}
|
|
566
|
+
function isEmail(value) {
|
|
567
|
+
return /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6}$/.test(value);
|
|
568
|
+
}
|
|
569
|
+
function isNumber(value) {
|
|
570
|
+
if (typeof value === "number")
|
|
571
|
+
return true;
|
|
572
|
+
return console.warn("[MODS] Non-numeric value passed to isNumber validator."), false;
|
|
573
|
+
}
|
|
574
|
+
function isUrl(value) {
|
|
575
|
+
return /^(?:\w+:)?\/\/([^\s\.]+\.\S{2,}|localhost[\:?\d]*(?:[^\:?\d]\S*)?)$/.test(value);
|
|
576
|
+
}
|
|
577
|
+
function isEmpty(value) {
|
|
578
|
+
if (value === null || value === void 0)
|
|
579
|
+
return true;
|
|
580
|
+
if (typeof value === "string")
|
|
581
|
+
return value === "";
|
|
582
|
+
if (Array.isArray(value))
|
|
583
|
+
return value.length === 0;
|
|
584
|
+
if (typeof value === "object")
|
|
585
|
+
return Object.keys(value).length === 0;
|
|
586
|
+
return true;
|
|
587
|
+
}
|
|
588
|
+
function isUuid(value) {
|
|
589
|
+
return /^[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}$/i.test(value);
|
|
590
|
+
}
|
|
591
|
+
function isJson(value) {
|
|
592
|
+
try {
|
|
593
|
+
return JSON.parse(value), true;
|
|
594
|
+
} catch (error) {
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
function isObject(value) {
|
|
599
|
+
return value && typeof value === "object" && value.constructor === Object;
|
|
600
|
+
}
|
|
601
|
+
function isArray(value) {
|
|
602
|
+
return Array.isArray(value);
|
|
603
|
+
}
|
|
604
|
+
function isHex(value) {
|
|
605
|
+
return /^#?([0-9A-Fa-f]{3,4}|[0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})$/.test(value);
|
|
606
|
+
}
|
|
607
|
+
function isAlphabetic(value) {
|
|
608
|
+
return /^[a-zA-Z]+$/.test(value);
|
|
609
|
+
}
|
|
610
|
+
function isAlphanumeric(value) {
|
|
611
|
+
return /^[a-zA-Z0-9]+$/.test(value);
|
|
612
|
+
}
|
|
613
|
+
function isBoolean(value) {
|
|
614
|
+
return typeof value === "boolean" || value === "false" || value === "true";
|
|
615
|
+
}
|
|
616
|
+
function isUndefined(value) {
|
|
617
|
+
return value === void 0;
|
|
618
|
+
}
|
|
619
|
+
function isNull(value) {
|
|
620
|
+
return value === null;
|
|
621
|
+
}
|
|
622
|
+
function isDate(value) {
|
|
623
|
+
if (value instanceof Date)
|
|
624
|
+
return !isNaN(value.getTime());
|
|
625
|
+
else if (typeof value === "string" || typeof value === "number") {
|
|
626
|
+
const date = new Date(value);
|
|
627
|
+
return !isNaN(date.getTime());
|
|
628
|
+
}
|
|
629
|
+
return false;
|
|
630
|
+
}
|
|
631
|
+
function isTime(value) {
|
|
632
|
+
return /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/.test(value);
|
|
633
|
+
}
|
|
634
|
+
function isLeapYear(value) {
|
|
635
|
+
return value % 4 === 0 && value % 100 !== 0 || value % 400 === 0;
|
|
636
|
+
}
|
|
637
|
+
function isEven(value) {
|
|
638
|
+
return value % 2 === 0;
|
|
639
|
+
}
|
|
640
|
+
function isOdd(value) {
|
|
641
|
+
return Math.abs(value % 2) === 1;
|
|
642
|
+
}
|
|
643
|
+
function isPositive(value) {
|
|
644
|
+
return Math.sign(value) === 1;
|
|
645
|
+
}
|
|
646
|
+
function isNegative(value) {
|
|
647
|
+
return Math.sign(value) === -1;
|
|
648
|
+
}
|
|
649
|
+
function isZero(value) {
|
|
650
|
+
return value === 0;
|
|
651
|
+
}
|
|
652
|
+
function isOver9000(value) {
|
|
653
|
+
return value > 9e3;
|
|
654
|
+
}
|
|
655
|
+
function isPrime(value) {
|
|
656
|
+
const boundary = Math.floor(Math.sqrt(value));
|
|
657
|
+
for (let i = 2; i <= boundary; i++)
|
|
658
|
+
if (value % i === 0)
|
|
659
|
+
return false;
|
|
660
|
+
return value >= 2;
|
|
661
|
+
}
|
|
662
|
+
function isInteger(value) {
|
|
663
|
+
if (!isNumber(value))
|
|
664
|
+
return false;
|
|
665
|
+
return value % 1 === 0;
|
|
666
|
+
}
|
|
667
|
+
function isFloat(value) {
|
|
668
|
+
if (!isNumber(value))
|
|
669
|
+
return false;
|
|
670
|
+
return !isInteger(value);
|
|
671
|
+
}
|
|
672
|
+
function isBetween(value, min2, max2) {
|
|
673
|
+
if (min2 > max2)
|
|
674
|
+
[min2, max2] = [max2, min2];
|
|
675
|
+
return value >= min2 && value <= max2;
|
|
676
|
+
}
|
|
677
|
+
function isDivisibleBy(value, divisor) {
|
|
678
|
+
return value % divisor === 0;
|
|
679
|
+
}
|
|
680
|
+
function isCreditCard(value) {
|
|
681
|
+
return /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11})$/.test(value);
|
|
682
|
+
}
|
|
683
|
+
function isLatLng(value) {
|
|
684
|
+
return /^([-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)),\s*([-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?))$/.test(value);
|
|
685
|
+
}
|
|
686
|
+
function isLatitude(value) {
|
|
687
|
+
return /^[-+]?([1-8]?\d(\.\d{1,6})?|90(\.0{1,6})?)$/.test(value);
|
|
688
|
+
}
|
|
689
|
+
function isLongitude(value) {
|
|
690
|
+
return /^[-+]?(180(\.0{1,6})?|((1[0-7]\d)|([1-9]?\d))(\.\d{1,6})?)$/.test(value);
|
|
691
|
+
}
|
|
692
|
+
function isIpAddress(value) {
|
|
693
|
+
return /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)((?::\d+)?|)$/.test(value);
|
|
694
|
+
}
|
|
695
|
+
function isPort(value) {
|
|
696
|
+
return value > 0 && value <= 65535;
|
|
697
|
+
}
|
|
698
|
+
function isMacAddress(value) {
|
|
699
|
+
return /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/.test(value);
|
|
700
|
+
}
|
|
701
|
+
function dataShuffle(items) {
|
|
702
|
+
if (!items || !(isObject(items) || isArray(items)))
|
|
703
|
+
return console.warn("[MODS] Warning: dataShuffle() expects an object or array as the first argument."), items;
|
|
704
|
+
const shuffleArray = (array) => {
|
|
705
|
+
for (let i = array.length - 1; i > 0; i--) {
|
|
706
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
707
|
+
[array[i], array[j]] = [array[j], array[i]];
|
|
708
|
+
}
|
|
709
|
+
return array;
|
|
710
|
+
};
|
|
711
|
+
if (isObject(items)) {
|
|
712
|
+
const entries = Object.entries(items);
|
|
713
|
+
return Object.fromEntries(shuffleArray(entries));
|
|
714
|
+
} else
|
|
715
|
+
return shuffleArray([...items]);
|
|
716
|
+
}
|
|
717
|
+
function dataReverse(items) {
|
|
718
|
+
if (!items || !(isObject(items) || isArray(items)))
|
|
719
|
+
return console.warn("[MODS] Warning: dataReverse() expects an object or array as the first argument."), items;
|
|
720
|
+
if (isObject(items)) {
|
|
721
|
+
const entries = Object.entries(items);
|
|
722
|
+
return Object.fromEntries(entries.reverse());
|
|
723
|
+
} else
|
|
724
|
+
return items.reverse();
|
|
725
|
+
}
|
|
726
|
+
function dataSortBy(items, property, order = "asc") {
|
|
727
|
+
const comparator = (a, b) => {
|
|
728
|
+
if (a[property] < b[property])
|
|
729
|
+
return order === "asc" ? -1 : 1;
|
|
730
|
+
if (a[property] > b[property])
|
|
731
|
+
return order === "asc" ? 1 : -1;
|
|
732
|
+
return 0;
|
|
733
|
+
};
|
|
734
|
+
if (isObject(items)) {
|
|
735
|
+
const entries = Object.entries(items);
|
|
736
|
+
return Object.fromEntries(entries.sort((a, b) => comparator(a[1], b[1])));
|
|
737
|
+
} else
|
|
738
|
+
return items.sort(comparator);
|
|
739
|
+
}
|
|
740
|
+
function dataRemoveDuplicates(...arrays) {
|
|
741
|
+
const mergedArray = arrays.flat();
|
|
742
|
+
return mergedArray.filter((item, index) => mergedArray.indexOf(item) === index);
|
|
743
|
+
}
|
|
744
|
+
function dataFlatten(items) {
|
|
745
|
+
if (isObject(items)) {
|
|
746
|
+
const flattened = {};
|
|
747
|
+
return Object.keys(items).forEach((key) => {
|
|
748
|
+
const item = items[key];
|
|
749
|
+
flattened[key] = Array.isArray(item) ? item.flat() : item;
|
|
750
|
+
}), flattened;
|
|
751
|
+
} else if (Array.isArray(items))
|
|
752
|
+
return items.flat();
|
|
753
|
+
else
|
|
754
|
+
return items;
|
|
755
|
+
}
|
|
756
|
+
function dataWithout(items, properties) {
|
|
757
|
+
if (isObject(items)) {
|
|
758
|
+
const entries = Object.entries(items);
|
|
759
|
+
return Object.fromEntries(entries.filter(([key]) => !properties.includes(key)));
|
|
760
|
+
} else
|
|
761
|
+
return items.filter((item) => !properties.includes(item));
|
|
762
|
+
}
|
|
763
|
+
function splitByWords(text) {
|
|
764
|
+
const sentences = text.split(/([\.\?\!])\s*/);
|
|
765
|
+
let wordIndex = 0, combinedSentences = [];
|
|
766
|
+
for (let i = 0; i < sentences.length; i += 2) {
|
|
767
|
+
const sentence = sentences[i] + (sentences[i + 1] || "");
|
|
768
|
+
if (sentence.trim() === "")
|
|
769
|
+
continue;
|
|
770
|
+
const words = sentence.split(" ").map((word) => {
|
|
771
|
+
return wordIndex++, `<span class="word"><span class="word-${wordIndex}">${word}</span></span>`;
|
|
772
|
+
}).join(" ");
|
|
773
|
+
combinedSentences.push(`<span class="sentence sentence-${combinedSentences.length + 1}">${words}</span>`);
|
|
774
|
+
}
|
|
775
|
+
return combinedSentences.join(" ");
|
|
776
|
+
}
|
|
777
|
+
function checkPasswordStrength(value, length, uppercase, numbers, special) {
|
|
778
|
+
let strength = 0;
|
|
779
|
+
const counts = { uppercase: (value.match(/[A-Z]/g) || []).length, numbers: (value.match(/[0-9]/g) || []).length, special: (value.match(/[^a-zA-Z0-9]/g) || []).length };
|
|
780
|
+
if (value.length < length)
|
|
781
|
+
return { score: 1, label: `Password must be at least ${length} characters long` };
|
|
782
|
+
if (counts.uppercase < uppercase)
|
|
783
|
+
return { score: 1, label: `Password must contain ${uppercase} uppercase letter` };
|
|
784
|
+
if (counts.numbers < numbers)
|
|
785
|
+
return { score: 1, label: `Password must contain ${numbers} number` };
|
|
786
|
+
if (counts.special < special)
|
|
787
|
+
return { score: 1, label: `Password must contain ${special} special character` };
|
|
788
|
+
if (value.length >= length)
|
|
789
|
+
strength++;
|
|
790
|
+
if (counts.uppercase >= uppercase)
|
|
791
|
+
strength++;
|
|
792
|
+
if (counts.numbers >= numbers)
|
|
793
|
+
strength++;
|
|
794
|
+
if (counts.special >= special)
|
|
795
|
+
strength++;
|
|
796
|
+
if (strength === 4)
|
|
797
|
+
return { score: 4, label: "Very Strong" };
|
|
798
|
+
if (strength === 3)
|
|
799
|
+
return { score: 3, label: "Strong" };
|
|
800
|
+
if (strength === 2)
|
|
801
|
+
return { score: 2, label: "Medium" };
|
|
802
|
+
if (strength === 1)
|
|
803
|
+
return { score: 1, label: "Weak" };
|
|
804
|
+
return { score: 0, label: "Very Weak" };
|
|
805
|
+
}
|
|
806
|
+
function readingTime(text, wordsPerMinute = 200) {
|
|
807
|
+
const words = text.split(" ").length, seconds = Math.floor(words / wordsPerMinute * 60);
|
|
808
|
+
return formatDurationLabels(Math.ceil(seconds));
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
const utils = {
|
|
812
|
+
__proto__: null,
|
|
813
|
+
addMargin: addMargin,
|
|
814
|
+
addMarkup: addMarkup,
|
|
815
|
+
average: average,
|
|
816
|
+
camelCase: camelCase,
|
|
817
|
+
checkPasswordStrength: checkPasswordStrength,
|
|
818
|
+
copyToClipboard: copyToClipboard,
|
|
819
|
+
dataFlatten: dataFlatten,
|
|
820
|
+
dataRemoveDuplicates: dataRemoveDuplicates,
|
|
821
|
+
dataReverse: dataReverse,
|
|
822
|
+
dataShuffle: dataShuffle,
|
|
823
|
+
dataSortBy: dataSortBy,
|
|
824
|
+
dataWithout: dataWithout,
|
|
825
|
+
deslugify: deslugify,
|
|
826
|
+
detectActiveBrowser: detectActiveBrowser,
|
|
827
|
+
detectBreakpoint: detectBreakpoint,
|
|
828
|
+
detectColorScheme: detectColorScheme,
|
|
829
|
+
detectContainerBreakpoint: detectContainerBreakpoint,
|
|
830
|
+
detectDevice: detectDevice,
|
|
831
|
+
detectDeviceOrientation: detectDeviceOrientation,
|
|
832
|
+
detectHost: detectHost,
|
|
833
|
+
detectHostName: detectHostName,
|
|
834
|
+
detectMousePosition: detectMousePosition,
|
|
835
|
+
detectNetworkStatus: detectNetworkStatus,
|
|
836
|
+
detectOS: detectOS,
|
|
837
|
+
detectPort: detectPort,
|
|
838
|
+
detectRelativeMousePosition: detectRelativeMousePosition,
|
|
839
|
+
detectScreenSize: detectScreenSize,
|
|
840
|
+
detectScrollPosition: detectScrollPosition,
|
|
841
|
+
detectUrl: detectUrl,
|
|
842
|
+
detectUrlHash: detectUrlHash,
|
|
843
|
+
detectUrlParams: detectUrlParams,
|
|
844
|
+
detectUrlPath: detectUrlPath,
|
|
845
|
+
detectUserTimezone: detectUserTimezone,
|
|
846
|
+
detectWindowSize: detectWindowSize,
|
|
847
|
+
endWith: endWith,
|
|
848
|
+
endWithout: endWithout,
|
|
849
|
+
escapeHtml: escapeHtml,
|
|
850
|
+
focusOnInvalid: focusOnInvalid,
|
|
851
|
+
focusOnNth: focusOnNth,
|
|
852
|
+
focusTrap: focusTrap,
|
|
853
|
+
formatCurrency: formatCurrency,
|
|
854
|
+
formatDurationLabels: formatDurationLabels,
|
|
855
|
+
formatDurationNumbers: formatDurationNumbers,
|
|
856
|
+
formatInitials: formatInitials,
|
|
857
|
+
formatList: formatList,
|
|
858
|
+
formatNumber: formatNumber,
|
|
859
|
+
formatNumberToWords: formatNumberToWords,
|
|
860
|
+
formatPercentage: formatPercentage,
|
|
861
|
+
formatSentenceCase: formatSentenceCase,
|
|
862
|
+
formatTextWrap: formatTextWrap,
|
|
863
|
+
formatTitle: formatTitle,
|
|
864
|
+
formatUnixTime: formatUnixTime,
|
|
865
|
+
formatValuation: formatValuation,
|
|
866
|
+
generateLoremIpsum: generateLoremIpsum,
|
|
867
|
+
generateNumber: generateNumber,
|
|
868
|
+
generateNumberBetween: generateNumberBetween,
|
|
869
|
+
generatePassword: generatePassword,
|
|
870
|
+
generateShortId: generateShortId,
|
|
871
|
+
generateUuid: generateUuid,
|
|
872
|
+
isAlphabetic: isAlphabetic,
|
|
873
|
+
isAlphanumeric: isAlphanumeric,
|
|
874
|
+
isArray: isArray,
|
|
875
|
+
isBetween: isBetween,
|
|
876
|
+
isBoolean: isBoolean,
|
|
877
|
+
isCreditCard: isCreditCard,
|
|
878
|
+
isDate: isDate,
|
|
879
|
+
isDivisibleBy: isDivisibleBy,
|
|
880
|
+
isEmail: isEmail,
|
|
881
|
+
isEmpty: isEmpty,
|
|
882
|
+
isEven: isEven,
|
|
883
|
+
isFloat: isFloat,
|
|
884
|
+
isHex: isHex,
|
|
885
|
+
isInteger: isInteger,
|
|
886
|
+
isIpAddress: isIpAddress,
|
|
887
|
+
isJson: isJson,
|
|
888
|
+
isLatLng: isLatLng,
|
|
889
|
+
isLatitude: isLatitude,
|
|
890
|
+
isLeapYear: isLeapYear,
|
|
891
|
+
isLongitude: isLongitude,
|
|
892
|
+
isMacAddress: isMacAddress,
|
|
893
|
+
isNegative: isNegative,
|
|
894
|
+
isNull: isNull,
|
|
895
|
+
isNumber: isNumber,
|
|
896
|
+
isObject: isObject,
|
|
897
|
+
isOdd: isOdd,
|
|
898
|
+
isOver9000: isOver9000,
|
|
899
|
+
isPort: isPort,
|
|
900
|
+
isPositive: isPositive,
|
|
901
|
+
isPrime: isPrime,
|
|
902
|
+
isTime: isTime,
|
|
903
|
+
isUndefined: isUndefined,
|
|
904
|
+
isUrl: isUrl,
|
|
905
|
+
isUuid: isUuid,
|
|
906
|
+
isZero: isZero,
|
|
907
|
+
kebabCase: kebabCase,
|
|
908
|
+
margin: margin,
|
|
909
|
+
max: max,
|
|
910
|
+
mean: mean,
|
|
911
|
+
median: median,
|
|
912
|
+
min: min,
|
|
913
|
+
minMax: minMax,
|
|
914
|
+
mode: mode,
|
|
915
|
+
ordinalize: ordinalize,
|
|
916
|
+
pascalCase: pascalCase,
|
|
917
|
+
pluralize: pluralize,
|
|
918
|
+
range: range,
|
|
919
|
+
readingTime: readingTime,
|
|
920
|
+
resetForm: resetForm,
|
|
921
|
+
scrollToAnchor: scrollToAnchor,
|
|
922
|
+
singularize: singularize,
|
|
923
|
+
skewness: skewness,
|
|
924
|
+
slugify: slugify,
|
|
925
|
+
snakeCase: snakeCase,
|
|
926
|
+
splitByWords: splitByWords,
|
|
927
|
+
standardDeviation: standardDeviation,
|
|
928
|
+
startWith: startWith,
|
|
929
|
+
startWithout: startWithout,
|
|
930
|
+
stripEmojis: stripEmojis,
|
|
931
|
+
stripHtml: stripHtml,
|
|
932
|
+
stripNumbers: stripNumbers,
|
|
933
|
+
stripPunctuation: stripPunctuation,
|
|
934
|
+
stripSymbols: stripSymbols,
|
|
935
|
+
stripWhitespace: stripWhitespace,
|
|
936
|
+
subtractMargin: subtractMargin,
|
|
937
|
+
subtractMarkup: subtractMarkup,
|
|
938
|
+
sum: sum,
|
|
939
|
+
surroundWith: surroundWith,
|
|
940
|
+
titleCase: titleCase,
|
|
941
|
+
toggleBodyScroll: toggleBodyScroll,
|
|
942
|
+
toggleElementScroll: toggleElementScroll,
|
|
943
|
+
toggleFullScreen: toggleFullScreen,
|
|
944
|
+
unescapeHtml: unescapeHtml
|
|
945
|
+
};
|
|
946
|
+
|
|
947
|
+
const module = defineNuxtModule({
|
|
948
|
+
meta: {
|
|
949
|
+
name: "mods-module",
|
|
950
|
+
configKey: "modsModule"
|
|
951
|
+
},
|
|
952
|
+
// Default configuration options of the Nuxt module
|
|
953
|
+
defaults: {
|
|
954
|
+
alias: []
|
|
955
|
+
},
|
|
956
|
+
setup(options, nuxt) {
|
|
957
|
+
const { resolve } = createResolver(import.meta.url);
|
|
958
|
+
const aliasMap = new Map(options.alias);
|
|
959
|
+
for (const name of Object.keys(utils)) {
|
|
960
|
+
const alias = aliasMap.has(name) ? aliasMap.get(name) : name;
|
|
961
|
+
addImports({
|
|
962
|
+
name,
|
|
963
|
+
as: alias,
|
|
964
|
+
from: resolve("../../dist/index")
|
|
965
|
+
});
|
|
966
|
+
}
|
|
967
|
+
addPlugin(resolve("./runtime/plugin"));
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
export { module as default };
|
package/dist/types.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import type { ModuleOptions } from './module.js'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
declare module '@nuxt/schema' {
|
|
6
|
+
interface NuxtConfig { ['modsModule']?: Partial<ModuleOptions> }
|
|
7
|
+
interface NuxtOptions { ['modsModule']?: ModuleOptions }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare module 'nuxt/schema' {
|
|
11
|
+
interface NuxtConfig { ['modsModule']?: Partial<ModuleOptions> }
|
|
12
|
+
interface NuxtOptions { ['modsModule']?: ModuleOptions }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export type { ModuleOptions, default } from './module.js'
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
|
|
2
|
+
import type { ModuleOptions } from './module'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
declare module '@nuxt/schema' {
|
|
6
|
+
interface NuxtConfig { ['modsModule']?: Partial<ModuleOptions> }
|
|
7
|
+
interface NuxtOptions { ['modsModule']?: ModuleOptions }
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
declare module 'nuxt/schema' {
|
|
11
|
+
interface NuxtConfig { ['modsModule']?: Partial<ModuleOptions> }
|
|
12
|
+
interface NuxtOptions { ['modsModule']?: ModuleOptions }
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
export type { ModuleOptions, default } from './module'
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "usemods-nuxt",
|
|
3
|
+
"version": "0.0.8",
|
|
4
|
+
"description": "Zippy little modifiers and utilities for your Nuxt app.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/LittleFoxCompany/usemods.git"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"type": "module",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/types.d.ts",
|
|
14
|
+
"import": "./dist/module.mjs",
|
|
15
|
+
"require": "./dist/module.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"main": "./dist/module.cjs",
|
|
19
|
+
"types": "./dist/types.d.ts",
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"prepack": "nuxt-module-build build",
|
|
25
|
+
"prepack:stub": "nuxt-module-build build --stub",
|
|
26
|
+
"dev": "nuxi dev docs",
|
|
27
|
+
"dev:build": "nuxi build docs",
|
|
28
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare docs",
|
|
29
|
+
"release": "npm run test && npm run prepack && npm publish",
|
|
30
|
+
"lint": "eslint .",
|
|
31
|
+
"test": "vitest run",
|
|
32
|
+
"test:watch": "vitest watch"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@nuxt/kit": "^3.10.3"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@nuxt/devtools": "latest",
|
|
39
|
+
"@nuxt/eslint-config": "^0.2.0",
|
|
40
|
+
"@nuxt/module-builder": "^0.5.5",
|
|
41
|
+
"@nuxt/schema": "^3.10.3",
|
|
42
|
+
"@nuxt/test-utils": "^3.11.0",
|
|
43
|
+
"@types/node": "^20.11.19",
|
|
44
|
+
"changelogen": "^0.5.5",
|
|
45
|
+
"eslint": "^8.56.0",
|
|
46
|
+
"nuxt": "^3.10.3",
|
|
47
|
+
"vitest": "^1.3.1",
|
|
48
|
+
"vue": "^3.4.20"
|
|
49
|
+
}
|
|
50
|
+
}
|