@regardio/js 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,126 +0,0 @@
1
- // src/http/cookie.ts
2
- function setCookieValue(name, value, options = {}) {
3
- if (typeof window === "undefined") {
4
- console.warn("Cannot set cookie on server side");
5
- return;
6
- }
7
- let cookieString = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
8
- if (options.expires) {
9
- cookieString += `; expires=${options.expires.toUTCString()}`;
10
- }
11
- if (options.path) {
12
- cookieString += `; path=${options.path}`;
13
- }
14
- if (options.sameSite) {
15
- cookieString += `; SameSite=${options.sameSite}`;
16
- }
17
- if (options.secure) {
18
- cookieString += "; Secure";
19
- }
20
- if (options.domain) {
21
- cookieString += `; domain=${options.domain}`;
22
- }
23
- try {
24
- document.cookie = cookieString;
25
- } catch (error) {
26
- if (error instanceof Error) {
27
- console.error(`Failed to set cookie '${name}':`, error.message);
28
- } else {
29
- console.error(`Failed to set cookie '${name}': Unknown error`);
30
- }
31
- }
32
- }
33
- function getCookieValue(name) {
34
- if (typeof window === "undefined") {
35
- console.warn("Cannot get cookie on server side");
36
- return null;
37
- }
38
- const value = `; ${document.cookie}`;
39
- const parts = value.split(`; ${name}=`);
40
- if (parts.length === 2) {
41
- const cookieValue = parts.pop()?.split(";").shift();
42
- return cookieValue ? decodeURIComponent(cookieValue) : null;
43
- }
44
- return null;
45
- }
46
-
47
- // src/http/domain.ts
48
- var createDomain = (request) => {
49
- const headers = request.headers;
50
- const maybeProto = headers.get("x-forwarded-proto");
51
- const maybeHost = headers.get("host");
52
- const url = new URL(request.url);
53
- if (maybeProto) {
54
- return `${maybeProto}://${maybeHost ?? url.host}`;
55
- }
56
- if (url.hostname === "localhost") {
57
- return `http://${url.host}`;
58
- }
59
- return `https://${url.host}`;
60
- };
61
-
62
- // src/http/is-route-active.ts
63
- var ROOT_PATH = "/";
64
- function isRouteActive(path, currentPath, end) {
65
- if (path === currentPath) {
66
- return true;
67
- }
68
- if (typeof end === "function") {
69
- return !end(currentPath);
70
- }
71
- const defaultEnd = end ?? true;
72
- const oneLevelDeep = 1;
73
- const threeLevelsDeep = 3;
74
- const depth = defaultEnd ? oneLevelDeep : threeLevelsDeep;
75
- return checkIfRouteIsActive(path, currentPath, depth);
76
- }
77
- function checkIfRouteIsActive(targetLink, currentRoute, depth = 1) {
78
- const currentRoutePath = currentRoute.split("?")[0] ?? "";
79
- if (!isRoot(currentRoutePath) && isRoot(targetLink)) {
80
- return false;
81
- }
82
- if (!currentRoutePath.includes(targetLink)) {
83
- return false;
84
- }
85
- const isSameRoute = targetLink === currentRoutePath;
86
- if (isSameRoute) {
87
- return true;
88
- }
89
- return hasMatchingSegments(targetLink, currentRoutePath, depth);
90
- }
91
- function splitIntoSegments(href) {
92
- return href.split("/").filter(Boolean);
93
- }
94
- function hasMatchingSegments(targetLink, currentRoute, depth) {
95
- const segments = splitIntoSegments(targetLink);
96
- const matchingSegments = numberOfMatchingSegments(currentRoute, segments);
97
- if (targetLink === currentRoute) {
98
- return true;
99
- }
100
- return matchingSegments > segments.length - (depth - 1);
101
- }
102
- function numberOfMatchingSegments(href, segments) {
103
- let count = 0;
104
- for (const segment of splitIntoSegments(href)) {
105
- if (segments.includes(segment)) {
106
- count += 1;
107
- } else {
108
- return count;
109
- }
110
- }
111
- return count;
112
- }
113
- function isRoot(path) {
114
- return path === ROOT_PATH;
115
- }
116
-
117
- // src/http/request-helpers.ts
118
- function getCleanUrl(request) {
119
- const url = new URL(request.url);
120
- url.searchParams.forEach((_, key) => {
121
- url.searchParams.delete(key);
122
- });
123
- return url.toString();
124
- }
125
-
126
- export { checkIfRouteIsActive, createDomain, getCleanUrl, getCookieValue, isRouteActive, setCookieValue };
@@ -1,91 +0,0 @@
1
- import { Cookie, SessionStorage } from 'react-router';
2
-
3
- interface LanguageDetectorOption {
4
- /**
5
- * Define the list of supported languages, this is used to determine if one of
6
- * the languages requested by the user is supported by the application.
7
- * This should be be same as the supportedLngs in the i18next options.
8
- */
9
- supportedLanguages: string[];
10
- /**
11
- * Define the fallback language that it's going to be used in the case user
12
- * expected language is not supported.
13
- * This should be be same as the fallbackLng in the i18next options.
14
- */
15
- fallbackLanguage: string;
16
- /**
17
- * If you want to use a cookie to store the user preferred language, you can
18
- * pass the Cookie object here.
19
- */
20
- cookie?: Cookie;
21
- /**
22
- * If you want to use a session to store the user preferred language, you can
23
- * pass the SessionStorage object here.
24
- * When this is not defined, getting the locale will ignore the session.
25
- */
26
- sessionStorage?: SessionStorage;
27
- /**
28
- * If defined a sessionStorage and want to change the default key used to
29
- * store the user preferred language, you can pass the key here.
30
- * @default "lng"
31
- */
32
- sessionKey?: string;
33
- /**
34
- * If you want to use search parameters for language detection and want to
35
- * change the default key used to for the parameter name,
36
- * you can pass the key here.
37
- * @default "lng"
38
- */
39
- searchParamKey?: string;
40
- /**
41
- * The order the library will use to detect the user preferred language.
42
- * By default the order is
43
- * - urlPath (first segment like /de/ or /en/)
44
- * - cookie
45
- * - session
46
- * - searchParams
47
- * - header
48
- * And finally the fallback language.
49
- */
50
- order?: Array<'urlPath' | 'searchParams' | 'cookie' | 'session' | 'header'>;
51
- }
52
- interface LanguageDetectorLinguiOptions {
53
- detection: LanguageDetectorOption;
54
- }
55
- declare class LanguageDetectorLingui {
56
- private detector;
57
- private options;
58
- constructor(options: LanguageDetectorLinguiOptions);
59
- /**
60
- * Detect the current locale by following the order defined in the
61
- * `detection.order` option.
62
- * By default the order is
63
- * - urlPath (first segment like /de/ or /en/)
64
- * - cookie
65
- * - session
66
- * - searchParams
67
- * - header
68
- * And finally the fallback language.
69
- */
70
- getLocale(request: Request): Promise<string>;
71
- }
72
- /**
73
- * The LanguageDetector contains the logic to detect the user preferred language
74
- * fully server-side by using a SessionStorage, Cookie, URLSearchParams, or
75
- * Headers.
76
- */
77
- declare class LanguageDetector {
78
- private options;
79
- constructor(options: LanguageDetectorOption);
80
- detect(request: Request): Promise<string>;
81
- private isSessionOnly;
82
- private isCookieOnly;
83
- private fromUrlPath;
84
- private fromSearchParams;
85
- private fromCookie;
86
- private fromSessionStorage;
87
- private fromHeader;
88
- private fromSupported;
89
- }
90
-
91
- export { LanguageDetector, LanguageDetectorLingui, type LanguageDetectorLinguiOptions, type LanguageDetectorOption };
@@ -1,139 +0,0 @@
1
- import { parseAcceptLanguage } from 'intl-parse-accept-language';
2
-
3
- // src/intl/language-detector.ts
4
- var LanguageDetectorLingui = class {
5
- detector;
6
- options;
7
- constructor(options) {
8
- this.options = options;
9
- this.detector = new LanguageDetector(this.options.detection);
10
- }
11
- /**
12
- * Detect the current locale by following the order defined in the
13
- * `detection.order` option.
14
- * By default the order is
15
- * - urlPath (first segment like /de/ or /en/)
16
- * - cookie
17
- * - session
18
- * - searchParams
19
- * - header
20
- * And finally the fallback language.
21
- */
22
- async getLocale(request) {
23
- return await this.detector.detect(request);
24
- }
25
- };
26
- var LanguageDetector = class {
27
- options;
28
- constructor(options) {
29
- this.options = options;
30
- this.isSessionOnly(this.options);
31
- this.isCookieOnly(this.options);
32
- }
33
- async detect(request) {
34
- const order = this.options.order ?? ["urlPath", "cookie", "session", "searchParams", "header"];
35
- for (const method of order) {
36
- let locale = null;
37
- if (method === "urlPath") {
38
- locale = this.fromUrlPath(request);
39
- }
40
- if (method === "searchParams") {
41
- locale = this.fromSearchParams(request);
42
- }
43
- if (method === "cookie") {
44
- locale = await this.fromCookie(request);
45
- }
46
- if (method === "session") {
47
- locale = await this.fromSessionStorage(request);
48
- }
49
- if (method === "header") {
50
- locale = this.fromHeader(request);
51
- }
52
- if (locale) return locale;
53
- }
54
- return this.options.fallbackLanguage;
55
- }
56
- isSessionOnly(options) {
57
- if (options.order?.length === 1 && options.order[0] === "session" && !options.sessionStorage) {
58
- throw new Error(
59
- "You need a sessionStorage if you want to only get the locale from the session"
60
- );
61
- }
62
- }
63
- isCookieOnly(options) {
64
- if (options.order?.length === 1 && options.order[0] === "cookie" && !options.cookie) {
65
- throw new Error("You need a cookie if you want to only get the locale from the cookie");
66
- }
67
- }
68
- fromUrlPath(request) {
69
- const url = new URL(request.url);
70
- const pathSegments = url.pathname.split("/").filter(Boolean);
71
- if (pathSegments.length > 0) {
72
- const firstSegment = pathSegments[0];
73
- if (firstSegment) {
74
- return this.fromSupported(firstSegment);
75
- }
76
- }
77
- return null;
78
- }
79
- fromSearchParams(request) {
80
- const url = new URL(request.url);
81
- if (!url.searchParams.has(this.options.searchParamKey ?? "lng")) {
82
- return null;
83
- }
84
- return this.fromSupported(url.searchParams.get(this.options.searchParamKey ?? "lng"));
85
- }
86
- async fromCookie(request) {
87
- if (!this.options.cookie) return null;
88
- const cookie = this.options.cookie;
89
- try {
90
- const lng = await cookie.parse(request.headers.get("Cookie"));
91
- if (typeof lng !== "string" || !lng) return null;
92
- return this.fromSupported(lng);
93
- } catch (_error) {
94
- return null;
95
- }
96
- }
97
- async fromSessionStorage(request) {
98
- if (!this.options.sessionStorage) return null;
99
- const session = await this.options.sessionStorage.getSession(request.headers.get("Cookie"));
100
- const lng = session.get(this.options.sessionKey ?? "lng");
101
- if (!lng) return null;
102
- return this.fromSupported(lng);
103
- }
104
- fromHeader(request) {
105
- const locales = getClientLocales(request);
106
- if (!locales) return null;
107
- if (Array.isArray(locales)) return this.fromSupported(locales.join(","));
108
- return this.fromSupported(locales);
109
- }
110
- fromSupported(language) {
111
- if (!language) return this.options.fallbackLanguage;
112
- const languageStr = Array.isArray(language) ? language.join(",") : language;
113
- const parsed = parseAcceptLanguage(languageStr, {
114
- ignoreWildcard: true,
115
- validate: (locale) => this.options.supportedLanguages.includes(locale) ? locale : null
116
- });
117
- return parsed[0] || this.options.fallbackLanguage;
118
- }
119
- };
120
- function getClientLocales(requestOrHeaders) {
121
- const headers = getHeaders(requestOrHeaders);
122
- const acceptLanguage = headers.get("Accept-Language");
123
- if (!acceptLanguage) return void 0;
124
- const locales = parseAcceptLanguage(acceptLanguage, {
125
- ignoreWildcard: true,
126
- validate: Intl.DateTimeFormat.supportedLocalesOf
127
- });
128
- if (locales.length === 0) return void 0;
129
- if (locales.length === 1) return locales[0];
130
- return locales;
131
- }
132
- function getHeaders(requestOrHeaders) {
133
- if (requestOrHeaders instanceof Request) {
134
- return requestOrHeaders.headers;
135
- }
136
- return requestOrHeaders;
137
- }
138
-
139
- export { LanguageDetector, LanguageDetectorLingui };
@@ -1,46 +0,0 @@
1
- declare function formatBytes(bytes: number, decimals?: number): string;
2
-
3
- /**
4
- * Replace straight quotes with typographically correct quotes for the given locale.
5
- *
6
- * @param text - The text containing straight quotes
7
- * @param locale - The locale to use for quote style (e.g., 'en', 'de', 'fr')
8
- * @returns Text with typographic quotes
9
- *
10
- * @example
11
- * typographicQuotes('"Hello"', 'en') // → '"Hello"'
12
- * typographicQuotes('"Hello"', 'de') // → '„Hello"'
13
- * typographicQuotes('"Hello"', 'fr') // → '« Hello »'
14
- */
15
- declare function typographicQuotes(text: string, locale: string): string;
16
- declare function toBoolean(value: string | boolean | null | undefined): boolean;
17
- /**
18
- * Replace &shy; HTML entity with Unicode soft hyphen
19
- */
20
- declare function replaceShyInString(input: string): string;
21
- /**
22
- * Split text into sentences
23
- */
24
- declare function splitIntoSentences(text: string): string[];
25
- /**
26
- * Split text into words
27
- */
28
- declare function splitIntoWords(text: string): string[];
29
- /**
30
- * Truncate text to a maximum length
31
- */
32
- declare function truncateText(text: string, maxLength: number, suffix?: string): string;
33
- /**
34
- * Author info parsed from a string like "Name <email> (url)"
35
- */
36
- type AuthorInfo = {
37
- name?: string;
38
- email?: string;
39
- url?: string;
40
- };
41
- /**
42
- * Parse an author string in the format "Name <email> (url)"
43
- */
44
- declare function parseAuthorString(input: string): AuthorInfo;
45
-
46
- export { type AuthorInfo, formatBytes, parseAuthorString, replaceShyInString, splitIntoSentences, splitIntoWords, toBoolean, truncateText, typographicQuotes };
@@ -1,109 +0,0 @@
1
- // src/text/bytes.ts
2
- function formatBytes(bytes, decimals = 2) {
3
- if (!+bytes) {
4
- return "0 Bytes";
5
- }
6
- const k = 1e3;
7
- const dm = decimals < 0 ? 0 : decimals;
8
- const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
9
- const i = Math.floor(Math.log(bytes) / Math.log(k));
10
- return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
11
- }
12
-
13
- // src/text/text.ts
14
- var quoteStyles = {
15
- cs: { close: "\u201D", closeSingle: "\u2019", open: "\u201E", openSingle: "\u201A" },
16
- // Danish, Norwegian - » « › ‹
17
- da: { close: "\xAB", closeSingle: "\u203A", open: "\xBB", openSingle: "\u2039" },
18
- // German (Germany, Austria) - „ " ‚ '
19
- de: { close: "\u201D", closeSingle: "\u2019", open: "\u201E", openSingle: "\u201A" },
20
- // German (Switzerland) - « » ‹ ›
21
- "de-ch": { close: "\xBB", closeSingle: "\u203A", open: "\xAB", openSingle: "\u2039" },
22
- // English (US, UK, etc.) - " " ' '
23
- en: { close: "\u201D", closeSingle: "\u2019", open: "\u201C", openSingle: "\u2018" },
24
- // Spanish, Italian, Portuguese - « » " "
25
- es: { close: "\xBB", closeSingle: "\u201D", open: "\xAB", openSingle: "\u201C" },
26
- fi: { close: "\u201D", closeSingle: "\u2019", open: "\u201D", openSingle: "\u2019" },
27
- // French - « » ‹ › (with spaces)
28
- fr: { close: " \xBB", closeSingle: " \u203A", open: "\xAB ", openSingle: "\u2039 " },
29
- hu: { close: "\u201D", closeSingle: "\u2019", open: "\u201E", openSingle: "\u201A" },
30
- it: { close: "\xBB", closeSingle: "\u201D", open: "\xAB", openSingle: "\u201C" },
31
- // Japanese - 「 」 『 』
32
- ja: { close: "\u300D", closeSingle: "\u300F", open: "\u300C", openSingle: "\u300E" },
33
- // Dutch - ' ' ' '
34
- nl: { close: "\u2019", closeSingle: "\u2019", open: "\u2018", openSingle: "\u2018" },
35
- no: { close: "\xAB", closeSingle: "\u203A", open: "\xBB", openSingle: "\u2039" },
36
- // Polish, Czech, Hungarian - „ " ‚ '
37
- pl: { close: "\u201D", closeSingle: "\u2019", open: "\u201E", openSingle: "\u201A" },
38
- pt: { close: "\xBB", closeSingle: "\u201D", open: "\xAB", openSingle: "\u201C" },
39
- // Russian - « » ‚ '
40
- ru: { close: "\xBB", closeSingle: "\u2019", open: "\xAB", openSingle: "\u201A" },
41
- // Swedish, Finnish - " " ' '
42
- sv: { close: "\u201D", closeSingle: "\u2019", open: "\u201D", openSingle: "\u2019" },
43
- // Chinese - 「 」 『 』
44
- zh: { close: "\u300D", closeSingle: "\u300F", open: "\u300C", openSingle: "\u300E" }
45
- };
46
- function getQuoteStyle(locale) {
47
- const normalized = locale.toLowerCase();
48
- const exactMatch = quoteStyles[normalized];
49
- if (exactMatch) {
50
- return exactMatch;
51
- }
52
- const baseLanguage = normalized.split("-")[0];
53
- if (baseLanguage) {
54
- const baseMatch = quoteStyles[baseLanguage];
55
- if (baseMatch) {
56
- return baseMatch;
57
- }
58
- }
59
- return quoteStyles.en;
60
- }
61
- function typographicQuotes(text, locale) {
62
- const style = getQuoteStyle(locale);
63
- let result = text.replace(/"([^"]*)"/g, `${style.open}$1${style.close}`);
64
- result = result.replace(/'([^']*)'/g, `${style.openSingle}$1${style.closeSingle}`);
65
- return result;
66
- }
67
- function toBoolean(value) {
68
- if (typeof value === "boolean") {
69
- return value;
70
- }
71
- return value === "true" || value === "1";
72
- }
73
- function replaceShyInString(input) {
74
- return input.replace(/&shy;/g, "\xAD");
75
- }
76
- function splitIntoSentences(text) {
77
- return text.split(/(?<=[.!?])\s+/);
78
- }
79
- function splitIntoWords(text) {
80
- return text.split(/\s+/);
81
- }
82
- function truncateText(text, maxLength, suffix = "...") {
83
- if (text.length <= maxLength) {
84
- return text;
85
- }
86
- return text.slice(0, maxLength - suffix.length) + suffix;
87
- }
88
- var authorRegex = /^(.*?)\s*(?:<([^>]+)>)?\s*(?:\(([^)]+)\))?$/;
89
- function parseAuthorString(input) {
90
- const match = input.match(authorRegex);
91
- if (match) {
92
- const [, name, email, url] = match;
93
- const result = {};
94
- if (email) {
95
- result.email = email;
96
- }
97
- const trimmedName = name?.trim();
98
- if (trimmedName) {
99
- result.name = trimmedName;
100
- }
101
- if (url) {
102
- result.url = url;
103
- }
104
- return result;
105
- }
106
- return {};
107
- }
108
-
109
- export { formatBytes, parseAuthorString, replaceShyInString, splitIntoSentences, splitIntoWords, toBoolean, truncateText, typographicQuotes };
@@ -1,48 +0,0 @@
1
- /** Delays using a promise
2
- * @param ms Milisecods of delay
3
- * @return Promise
4
- */
5
- declare function delay(ms: number): Promise<unknown>;
6
-
7
- declare function measure<Result>(key: string, callback: () => Result | Promise<Result>): Promise<Result>;
8
-
9
- declare function timeAgo(input: Date | string): string;
10
- declare const oneWeekFromNow: () => Date;
11
- declare const oneDayFromNow: () => Date;
12
- declare const oneMinuteFromNow: () => Date;
13
- declare function friendlyDuration(minutes: number | null, locale: string, short?: boolean): {
14
- key: string;
15
- vars: {
16
- hours: string;
17
- minutes: string;
18
- count?: undefined;
19
- value?: undefined;
20
- };
21
- } | {
22
- key: string;
23
- vars: {
24
- hours: string;
25
- minutes?: undefined;
26
- count?: undefined;
27
- value?: undefined;
28
- };
29
- } | {
30
- key: string;
31
- vars: {
32
- minutes: string;
33
- hours?: undefined;
34
- count?: undefined;
35
- value?: undefined;
36
- };
37
- } | {
38
- key: string;
39
- vars: {
40
- count: number;
41
- value: string;
42
- hours?: undefined;
43
- minutes?: undefined;
44
- };
45
- } | null;
46
- declare const dateTimeInUnix: (date: number) => number;
47
-
48
- export { dateTimeInUnix, delay, friendlyDuration, measure, oneDayFromNow, oneMinuteFromNow, oneWeekFromNow, timeAgo };