@arsedizioni/ars-utils 22.0.14 → 22.0.16
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/fesm2022/arsedizioni-ars-utils-clipper.common.mjs +6 -6
- package/fesm2022/arsedizioni-ars-utils-clipper.ui.mjs +48 -48
- package/fesm2022/arsedizioni-ars-utils-core.mjs +555 -404
- package/fesm2022/arsedizioni-ars-utils-core.mjs.map +1 -1
- package/fesm2022/arsedizioni-ars-utils-evolution.common.mjs +6 -6
- package/fesm2022/arsedizioni-ars-utils-help.mjs +9 -9
- package/fesm2022/arsedizioni-ars-utils-support.common.mjs +3 -3
- package/fesm2022/arsedizioni-ars-utils-support.ui.mjs +6 -6
- package/fesm2022/arsedizioni-ars-utils-tinymce.mjs +3 -3
- package/fesm2022/arsedizioni-ars-utils-ui.application.mjs +60 -60
- package/fesm2022/arsedizioni-ars-utils-ui.mjs +97 -97
- package/fesm2022/arsedizioni-ars-utils-ui.oauth.mjs +6 -6
- package/package.json +1 -1
- package/types/arsedizioni-ars-utils-clipper.ui.d.ts +1 -1
- package/types/arsedizioni-ars-utils-core.d.ts +27 -43
|
@@ -2,7 +2,6 @@ import * as i0 from '@angular/core';
|
|
|
2
2
|
import { Pipe, inject, makeEnvironmentProviders, Injectable, ElementRef, afterNextRender, Directive, input, DestroyRef, HostListener, output, forwardRef, EventEmitter, signal, computed, Service, RendererFactory2 } from '@angular/core';
|
|
3
3
|
import { parseISO, parse, format, getYear, getMonth, getDate, getDay, getDaysInMonth, addYears, addMonths, addDays, formatISO, isDate, isValid, endOfDay } from 'date-fns';
|
|
4
4
|
import { it } from 'date-fns/locale';
|
|
5
|
-
import { HttpParams } from '@angular/common/http';
|
|
6
5
|
import { TZDate } from '@date-fns/tz';
|
|
7
6
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
8
7
|
import { DateAdapter, MAT_DATE_LOCALE, MAT_DATE_FORMATS } from '@angular/material/core';
|
|
@@ -12,6 +11,376 @@ import { debounceTime } from 'rxjs/operators';
|
|
|
12
11
|
import { NG_VALIDATORS } from '@angular/forms';
|
|
13
12
|
import { SelectionModel } from '@angular/cdk/collections';
|
|
14
13
|
|
|
14
|
+
/**
|
|
15
|
+
* Zero-dependency Markdown to HTML converter.
|
|
16
|
+
*
|
|
17
|
+
* Design goals:
|
|
18
|
+
* - Single line-based pass over blocks (no repeated full-string regex passes).
|
|
19
|
+
* - Inline formatting never touches code spans / code blocks (stash & restore).
|
|
20
|
+
* - No HTML entity escaping by default in normal text: the source passes as-is.
|
|
21
|
+
* Exception: the content of code spans / code blocks is ALWAYS escaped, so
|
|
22
|
+
* things like List<string> render correctly (the browser displays the
|
|
23
|
+
* original characters; entities never reach the user or the clipboard).
|
|
24
|
+
* Opt-in full escaping via { escapeHtml: true } for untrusted input.
|
|
25
|
+
* - URL sanitization on links/images (javascript:, vbscript:, data: are dropped).
|
|
26
|
+
* - Bounded result cache for repeated renders (Angular change detection friendly).
|
|
27
|
+
*
|
|
28
|
+
* Supported syntax: headings, paragraphs, hard/soft breaks, hr, blockquotes
|
|
29
|
+
* (nested), fenced code blocks, inline code, bold/italic/strikethrough, links
|
|
30
|
+
* (with title), images, autolinked bare URLs, ordered/unordered lists (nested,
|
|
31
|
+
* task lists, ordered start offset), GFM tables with alignment.
|
|
32
|
+
*
|
|
33
|
+
* Known simplifications (documented, by design):
|
|
34
|
+
* - A blank line terminates a list.
|
|
35
|
+
* - Setext headings (=== / ---) are not supported, use # syntax.
|
|
36
|
+
* - Reference-style links [text][ref] are not supported.
|
|
37
|
+
*/
|
|
38
|
+
class MarkdownUtils {
|
|
39
|
+
// #region Cache
|
|
40
|
+
static { this.cache = new Map(); }
|
|
41
|
+
static { this.CACHE_MAX = 200; }
|
|
42
|
+
/** Clears the internal result cache. */
|
|
43
|
+
static clearCache() {
|
|
44
|
+
this.cache.clear();
|
|
45
|
+
}
|
|
46
|
+
// #endregion
|
|
47
|
+
// #region Public API
|
|
48
|
+
/**
|
|
49
|
+
* Convert markdown to HTML.
|
|
50
|
+
* @param markdown : the markdown source
|
|
51
|
+
* @param options : conversion options
|
|
52
|
+
* @returns : the HTML string ('' when input is falsy)
|
|
53
|
+
*/
|
|
54
|
+
static toHtml(markdown, options) {
|
|
55
|
+
if (!markdown)
|
|
56
|
+
return '';
|
|
57
|
+
const opts = { escapeHtml: false, breaks: true, ...options };
|
|
58
|
+
const key = `${opts.escapeHtml ? 1 : 0}${opts.breaks ? 1 : 0}|${markdown}`;
|
|
59
|
+
const hit = this.cache.get(key);
|
|
60
|
+
if (hit !== undefined)
|
|
61
|
+
return hit;
|
|
62
|
+
// Normalize line endings and fix glued sentence punctuation ("dettaglio!Ecco")
|
|
63
|
+
const source = markdown
|
|
64
|
+
.replace(/\r\n?/g, '\n')
|
|
65
|
+
.replace(/([A-Za-zÀ-ÿ][!?])([A-Za-zÀ-ÿ])/g, '$1 $2');
|
|
66
|
+
const html = this.parseBlocks(source.split('\n'), opts).trim();
|
|
67
|
+
if (this.cache.size >= this.CACHE_MAX) {
|
|
68
|
+
this.cache.delete(this.cache.keys().next().value); // FIFO eviction
|
|
69
|
+
}
|
|
70
|
+
this.cache.set(key, html);
|
|
71
|
+
return html;
|
|
72
|
+
}
|
|
73
|
+
// #endregion
|
|
74
|
+
// #region Block parser (single pass)
|
|
75
|
+
static parseBlocks(lines, opts) {
|
|
76
|
+
const out = [];
|
|
77
|
+
let paragraph = [];
|
|
78
|
+
const flush = () => {
|
|
79
|
+
if (paragraph.length > 0) {
|
|
80
|
+
const sep = opts.breaks ? '<br>' : ' ';
|
|
81
|
+
out.push(`<p>${paragraph.map(l => this.inline(l, opts)).join(sep)}</p>`);
|
|
82
|
+
paragraph = [];
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
for (let i = 0; i < lines.length; i++) {
|
|
86
|
+
const line = lines[i];
|
|
87
|
+
const trimmed = line.trim();
|
|
88
|
+
// --- Fenced code block -------------------------------------------------
|
|
89
|
+
const fence = trimmed.match(/^```([\w+-]+)?\s*$/);
|
|
90
|
+
if (fence) {
|
|
91
|
+
flush();
|
|
92
|
+
const lang = fence[1] ? ` class="language-${fence[1]}"` : '';
|
|
93
|
+
const code = [];
|
|
94
|
+
i++;
|
|
95
|
+
while (i < lines.length && !/^```\s*$/.test(lines[i].trim())) {
|
|
96
|
+
code.push(lines[i]);
|
|
97
|
+
i++;
|
|
98
|
+
}
|
|
99
|
+
out.push(`<pre><code${lang}>${this.escape(code.join('\n'))}</code></pre>`);
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
// --- Blank line --------------------------------------------------------
|
|
103
|
+
if (!trimmed) {
|
|
104
|
+
flush();
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
// --- ATX heading -------------------------------------------------------
|
|
108
|
+
const heading = trimmed.match(/^(#{1,6})\s+(.+?)\s*#*\s*$/);
|
|
109
|
+
if (heading) {
|
|
110
|
+
flush();
|
|
111
|
+
const level = heading[1].length;
|
|
112
|
+
out.push(`<h${level}>${this.inline(heading[2], opts)}</h${level}>`);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// --- Horizontal rule ---------------------------------------------------
|
|
116
|
+
if (/^(?:-{3,}|\*{3,}|_{3,})$/.test(trimmed)) {
|
|
117
|
+
flush();
|
|
118
|
+
out.push('<hr>');
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
// --- Blockquote (consecutive lines, one level stripped, recursive) ------
|
|
122
|
+
if (/^>\s?/.test(trimmed)) {
|
|
123
|
+
flush();
|
|
124
|
+
const quoted = [];
|
|
125
|
+
while (i < lines.length && /^>\s?/.test(lines[i].trim())) {
|
|
126
|
+
quoted.push(lines[i].trim().replace(/^>\s?/, ''));
|
|
127
|
+
i++;
|
|
128
|
+
}
|
|
129
|
+
i--;
|
|
130
|
+
out.push(`<blockquote>${this.parseBlocks(quoted, opts)}</blockquote>`);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
// --- Table (header row + separator row) ---------------------------------
|
|
134
|
+
if (trimmed.includes('|') &&
|
|
135
|
+
i + 1 < lines.length &&
|
|
136
|
+
lines[i + 1].includes('-') &&
|
|
137
|
+
/^\|?[\s:\-|]+\|?$/.test(lines[i + 1].trim())) {
|
|
138
|
+
flush();
|
|
139
|
+
const aligns = this.tableAligns(lines[i + 1].trim());
|
|
140
|
+
const head = this.tableRow(trimmed, 'th', aligns, opts);
|
|
141
|
+
const body = [];
|
|
142
|
+
i += 2;
|
|
143
|
+
while (i < lines.length && lines[i].trim().includes('|')) {
|
|
144
|
+
body.push(this.tableRow(lines[i].trim(), 'td', aligns, opts));
|
|
145
|
+
i++;
|
|
146
|
+
}
|
|
147
|
+
i--;
|
|
148
|
+
out.push(`<table>\n<thead>\n${head}\n</thead>` +
|
|
149
|
+
(body.length > 0 ? `\n<tbody>\n${body.join('\n')}\n</tbody>` : '') +
|
|
150
|
+
`\n</table>`);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
// --- List ---------------------------------------------------------------
|
|
154
|
+
if (MarkdownUtils.listItemRe.test(line)) {
|
|
155
|
+
flush();
|
|
156
|
+
const [html, last] = this.parseList(lines, i, opts);
|
|
157
|
+
out.push(html);
|
|
158
|
+
i = last;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
// --- Plain text: accumulate into current paragraph ----------------------
|
|
162
|
+
paragraph.push(trimmed);
|
|
163
|
+
}
|
|
164
|
+
flush();
|
|
165
|
+
return out.join('\n');
|
|
166
|
+
}
|
|
167
|
+
// #endregion
|
|
168
|
+
// #region Lists
|
|
169
|
+
/** Matches "- item", "* item", "+ item", "1. item", "1) item" with leading indent. */
|
|
170
|
+
static { this.listItemRe = /^(\s*)([-*+]|\d+[.)])\s+(.*)$/; }
|
|
171
|
+
/**
|
|
172
|
+
* Gathers the contiguous list block starting at `start`, builds it (with
|
|
173
|
+
* nesting) and returns [html, indexOfLastConsumedLine].
|
|
174
|
+
*/
|
|
175
|
+
static parseList(lines, start, opts) {
|
|
176
|
+
const block = [];
|
|
177
|
+
let i = start;
|
|
178
|
+
while (i < lines.length) {
|
|
179
|
+
const l = lines[i];
|
|
180
|
+
if (!l.trim())
|
|
181
|
+
break; // blank line ends the list
|
|
182
|
+
if (this.listItemRe.test(l) || /^\s{2,}\S/.test(l)) {
|
|
183
|
+
block.push(l);
|
|
184
|
+
i++;
|
|
185
|
+
}
|
|
186
|
+
else
|
|
187
|
+
break;
|
|
188
|
+
}
|
|
189
|
+
return [this.buildList(block, opts), i - 1];
|
|
190
|
+
}
|
|
191
|
+
static buildList(block, opts) {
|
|
192
|
+
const first = block[0].match(this.listItemRe);
|
|
193
|
+
const baseIndent = first[1].length;
|
|
194
|
+
const ordered = /^\d/.test(first[2]);
|
|
195
|
+
const startNum = ordered ? parseInt(first[2], 10) : 1;
|
|
196
|
+
const items = [];
|
|
197
|
+
for (const l of block) {
|
|
198
|
+
const m = l.match(this.listItemRe);
|
|
199
|
+
if (m && m[1].length <= baseIndent) {
|
|
200
|
+
items.push({ text: m[3], childLines: [] });
|
|
201
|
+
}
|
|
202
|
+
else if (items.length > 0) {
|
|
203
|
+
// Continuation or nested content: strip one nesting level of indent
|
|
204
|
+
items[items.length - 1].childLines.push(l.length > baseIndent + 2 ? l.slice(baseIndent + 2) : l.trim());
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
const lis = items.map(item => {
|
|
208
|
+
let inner;
|
|
209
|
+
// GFM task list: - [ ] / - [x]
|
|
210
|
+
const task = item.text.match(/^\[([ xX])\]\s+(.*)$/);
|
|
211
|
+
if (task) {
|
|
212
|
+
const checked = task[1] !== ' ' ? ' checked' : '';
|
|
213
|
+
inner = `<input type="checkbox" disabled${checked}> ${this.inline(task[2], opts)}`;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
inner = this.inline(item.text, opts);
|
|
217
|
+
}
|
|
218
|
+
if (item.childLines.length > 0) {
|
|
219
|
+
inner += '\n' + this.parseBlocks(item.childLines, opts);
|
|
220
|
+
}
|
|
221
|
+
return `<li>${inner}</li>`;
|
|
222
|
+
});
|
|
223
|
+
const tag = ordered ? 'ol' : 'ul';
|
|
224
|
+
const startAttr = ordered && startNum > 1 ? ` start="${startNum}"` : '';
|
|
225
|
+
return `<${tag}${startAttr}>\n${lis.join('\n')}\n</${tag}>`;
|
|
226
|
+
}
|
|
227
|
+
// #endregion
|
|
228
|
+
// #region Tables
|
|
229
|
+
static tableAligns(separator) {
|
|
230
|
+
return separator
|
|
231
|
+
.replace(/^\||\|$/g, '')
|
|
232
|
+
.split('|')
|
|
233
|
+
.map(cell => {
|
|
234
|
+
const t = cell.trim();
|
|
235
|
+
if (t.startsWith(':') && t.endsWith(':'))
|
|
236
|
+
return 'center';
|
|
237
|
+
if (t.endsWith(':'))
|
|
238
|
+
return 'right';
|
|
239
|
+
if (t.startsWith(':'))
|
|
240
|
+
return 'left';
|
|
241
|
+
return undefined;
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
static tableRow(row, tag, aligns, opts) {
|
|
245
|
+
const cells = row.replace(/^\||\|$/g, '').split('|').map(c => c.trim());
|
|
246
|
+
const cellsHtml = cells
|
|
247
|
+
.map((cell, j) => {
|
|
248
|
+
const align = aligns[j] ? ` align="${aligns[j]}"` : '';
|
|
249
|
+
return `<${tag}${align}>${this.inline(cell, opts)}</${tag}>`;
|
|
250
|
+
})
|
|
251
|
+
.join('');
|
|
252
|
+
return `<tr>${cellsHtml}</tr>`;
|
|
253
|
+
}
|
|
254
|
+
// #endregion
|
|
255
|
+
// #region Inline formatting
|
|
256
|
+
/**
|
|
257
|
+
* Applies inline markdown to a single text segment.
|
|
258
|
+
* Generated HTML (code, links, images, autolinks) is stashed behind \u0000
|
|
259
|
+
* placeholders so later regex passes can never corrupt it.
|
|
260
|
+
*/
|
|
261
|
+
static inline(text, opts) {
|
|
262
|
+
const store = [];
|
|
263
|
+
const stash = (html) => `\u0000${store.push(html) - 1}\u0000`;
|
|
264
|
+
// 1. Inline code: stash first so later passes can't touch it.
|
|
265
|
+
// Content is ALWAYS escaped so <, >, & inside code survive in the DOM
|
|
266
|
+
// (the browser renders entities back to the original characters).
|
|
267
|
+
let s = text.replace(/`([^`]+)`/g, (_m, code) => stash(`<code>${this.escape(code)}</code>`));
|
|
268
|
+
// 2. Escape raw HTML as entities (opt-in only)
|
|
269
|
+
if (opts.escapeHtml)
|
|
270
|
+
s = this.escape(s);
|
|
271
|
+
// 3. Images: 
|
|
272
|
+
s = s.replace(/!\[([^\]]*)\]\(\s*([^)\s]+)(?:\s+(?:"|")(.+?)(?:"|"))?\s*\)/g, (_m, alt, src, title) => {
|
|
273
|
+
const url = this.safeUrl(src);
|
|
274
|
+
if (!url)
|
|
275
|
+
return alt;
|
|
276
|
+
const t = title ? ` title="${title}"` : '';
|
|
277
|
+
return stash(`<img src="${url}" alt="${alt}"${t} loading="lazy">`);
|
|
278
|
+
});
|
|
279
|
+
// 4. Links: [text](url "title")
|
|
280
|
+
s = s.replace(/\[([^\]]+)\]\(\s*([^)\s]+)(?:\s+(?:"|")(.+?)(?:"|"))?\s*\)/g, (_m, txt, href, title) => {
|
|
281
|
+
const url = this.safeUrl(href);
|
|
282
|
+
if (!url)
|
|
283
|
+
return txt;
|
|
284
|
+
const t = title ? ` title="${title}"` : '';
|
|
285
|
+
return stash(`<a href="${url}"${t} target="_blank" rel="noopener noreferrer">${txt}</a>`);
|
|
286
|
+
});
|
|
287
|
+
// 5. Autolink remaining bare URLs (markdown links are already stashed)
|
|
288
|
+
s = s.replace(/https?:\/\/[^\s<>"']+/g, url => stash(`<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`));
|
|
289
|
+
// 6. Bold / italic / strikethrough.
|
|
290
|
+
// Delimiters must hug the text; underscore emphasis only at word
|
|
291
|
+
// boundaries so identifiers like snake_case are left untouched.
|
|
292
|
+
s = s.replace(/\*\*\*(?=\S)([\s\S]*?\S)\*\*\*/g, '<strong><em>$1</em></strong>');
|
|
293
|
+
s = s.replace(/(?<![\w*])___(?=\S)([\s\S]*?\S)___(?![\w*])/g, '<strong><em>$1</em></strong>');
|
|
294
|
+
s = s.replace(/\*\*(?=\S)([\s\S]*?\S)\*\*/g, '<strong>$1</strong>');
|
|
295
|
+
s = s.replace(/(?<![\w*])__(?=\S)([\s\S]*?\S)__(?![\w*])/g, '<strong>$1</strong>');
|
|
296
|
+
s = s.replace(/\*(?=\S)([^*\n]*?\S)\*/g, '<em>$1</em>');
|
|
297
|
+
s = s.replace(/(?<![\w_])_(?=\S)([^_\n]*?\S)_(?![\w_])/g, '<em>$1</em>');
|
|
298
|
+
s = s.replace(/~~(?=\S)([\s\S]*?\S)~~/g, '<del>$1</del>');
|
|
299
|
+
// 7. Restore stashed HTML
|
|
300
|
+
return s.replace(/\u0000(\d+)\u0000/g, (_m, idx) => store[Number(idx)] ?? '');
|
|
301
|
+
}
|
|
302
|
+
// #endregion
|
|
303
|
+
// #region Security helpers
|
|
304
|
+
/** Escapes &, <, > and " for safe HTML interpolation. */
|
|
305
|
+
static escape(s) {
|
|
306
|
+
return s
|
|
307
|
+
.replace(/&/g, '&')
|
|
308
|
+
.replace(/</g, '<')
|
|
309
|
+
.replace(/>/g, '>')
|
|
310
|
+
.replace(/"/g, '"');
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Returns a sanitized URL or undefined when the scheme is dangerous.
|
|
314
|
+
* Blocks javascript:, vbscript: and data: (also when obfuscated with
|
|
315
|
+
* whitespace/control characters, e.g. "java\tscript:").
|
|
316
|
+
*/
|
|
317
|
+
static safeUrl(url) {
|
|
318
|
+
const compact = url.replace(/[\s\u0000-\u001f]/g, '');
|
|
319
|
+
if (/^(javascript|vbscript|data):/i.test(compact))
|
|
320
|
+
return undefined;
|
|
321
|
+
return url.replace(/"/g, '%22');
|
|
322
|
+
}
|
|
323
|
+
// #endregion
|
|
324
|
+
// #region Clipboard
|
|
325
|
+
/**
|
|
326
|
+
* Copies markdown content to the clipboard in two flavors:
|
|
327
|
+
* - text/html : the rendered HTML (rich paste into Word, Outlook, Gmail...)
|
|
328
|
+
* - text/plain : the original markdown source (paste into editors, IDEs...)
|
|
329
|
+
* @param markdown : the markdown source
|
|
330
|
+
* @param options : conversion options for the HTML flavor
|
|
331
|
+
* @returns : true on success
|
|
332
|
+
*/
|
|
333
|
+
static async copyToClipboard(markdown, options) {
|
|
334
|
+
if (!markdown || typeof navigator === 'undefined' || !navigator.clipboard)
|
|
335
|
+
return false;
|
|
336
|
+
try {
|
|
337
|
+
if (typeof ClipboardItem !== 'undefined') {
|
|
338
|
+
const html = this.toHtml(markdown, options);
|
|
339
|
+
await navigator.clipboard.write([
|
|
340
|
+
new ClipboardItem({
|
|
341
|
+
'text/html': new Blob([html], { type: 'text/html' }),
|
|
342
|
+
'text/plain': new Blob([markdown], { type: 'text/plain' }),
|
|
343
|
+
}),
|
|
344
|
+
]);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
// Older engines: plain text only
|
|
348
|
+
await navigator.clipboard.writeText(markdown);
|
|
349
|
+
}
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
// Clipboard API requires a secure context and user activation
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Copies plain text (e.g. the content of a single code block) to the clipboard.
|
|
359
|
+
* @param text : the text to copy
|
|
360
|
+
* @returns : true on success
|
|
361
|
+
*/
|
|
362
|
+
static async copyText(text) {
|
|
363
|
+
if (!text || typeof navigator === 'undefined' || !navigator.clipboard)
|
|
364
|
+
return false;
|
|
365
|
+
try {
|
|
366
|
+
await navigator.clipboard.writeText(text);
|
|
367
|
+
return true;
|
|
368
|
+
}
|
|
369
|
+
catch {
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Extracts the visible plain text from a rendered element
|
|
375
|
+
* (what the user sees, entities already decoded by the browser).
|
|
376
|
+
* @param element : the element hosting the rendered markdown
|
|
377
|
+
* @returns : the plain text
|
|
378
|
+
*/
|
|
379
|
+
static elementToText(element) {
|
|
380
|
+
return element.innerText ?? element.textContent ?? '';
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
15
384
|
var DateFormat;
|
|
16
385
|
(function (DateFormat) {
|
|
17
386
|
DateFormat[DateFormat["Short"] = 1] = "Short";
|
|
@@ -28,6 +397,8 @@ var DateFormat;
|
|
|
28
397
|
DateFormat[DateFormat["ShortISO8601"] = 12] = "ShortISO8601"; // yyyy-mm-dd
|
|
29
398
|
})(DateFormat || (DateFormat = {}));
|
|
30
399
|
class SystemUtils {
|
|
400
|
+
/** Shared collator for locale-aware, case-insensitive string comparison. */
|
|
401
|
+
static { this.collator = new Intl.Collator('it', { sensitivity: 'base', numeric: true }); }
|
|
31
402
|
/**
|
|
32
403
|
* Array find by key
|
|
33
404
|
* @param array : the array to scan
|
|
@@ -108,21 +479,23 @@ class SystemUtils {
|
|
|
108
479
|
* Comparator factory for sorting arrays of objects by a given property key.
|
|
109
480
|
* @param key - Name of the property to sort by.
|
|
110
481
|
* @param order - Sort direction: `'asc'` (default) or `'desc'`.
|
|
111
|
-
* @returns A comparator function that returns
|
|
482
|
+
* @returns A comparator function that returns a negative, zero, or positive number.
|
|
112
483
|
*/
|
|
113
484
|
static arraySortCompare(key, order = 'asc') {
|
|
114
|
-
|
|
115
|
-
|
|
485
|
+
const dir = order === 'desc' ? -1 : 1;
|
|
486
|
+
return (a, b) => {
|
|
487
|
+
const varA = a[key];
|
|
488
|
+
const varB = b[key];
|
|
489
|
+
if (varA === varB)
|
|
116
490
|
return 0;
|
|
491
|
+
if (varA === undefined || varA === null)
|
|
492
|
+
return -1 * dir;
|
|
493
|
+
if (varB === undefined || varB === null)
|
|
494
|
+
return 1 * dir;
|
|
495
|
+
if (typeof varA === 'string' && typeof varB === 'string') {
|
|
496
|
+
return SystemUtils.collator.compare(varA, varB) * dir;
|
|
117
497
|
}
|
|
118
|
-
|
|
119
|
-
const varB = typeof b[key] === 'string' ? b[key].toUpperCase() : b[key];
|
|
120
|
-
let comparison = 0;
|
|
121
|
-
if (varA > varB)
|
|
122
|
-
comparison = 1;
|
|
123
|
-
else if (varA < varB)
|
|
124
|
-
comparison = -1;
|
|
125
|
-
return order === 'desc' ? comparison * -1 : comparison;
|
|
498
|
+
return (varA > varB ? 1 : varA < varB ? -1 : 0) * dir;
|
|
126
499
|
};
|
|
127
500
|
}
|
|
128
501
|
/**
|
|
@@ -153,17 +526,13 @@ class SystemUtils {
|
|
|
153
526
|
return `${bytes} byte`;
|
|
154
527
|
}
|
|
155
528
|
/**
|
|
156
|
-
* Compare two
|
|
529
|
+
* Compare two strings (case-insensitive, locale-aware, accent-insensitive).
|
|
157
530
|
* @param a : string a
|
|
158
531
|
* @param b : string b
|
|
159
532
|
* @returns : 0 if equals, 1 if bigger, -1 if lower
|
|
160
533
|
*/
|
|
161
534
|
static compareString(a, b) {
|
|
162
|
-
|
|
163
|
-
return 1;
|
|
164
|
-
if ((a ?? "").toLowerCase() < (b ?? "").toLowerCase())
|
|
165
|
-
return -1;
|
|
166
|
-
return 0;
|
|
535
|
+
return this.collator.compare(a ?? '', b ?? '');
|
|
167
536
|
}
|
|
168
537
|
/**
|
|
169
538
|
* Capitalize a string
|
|
@@ -191,7 +560,7 @@ class SystemUtils {
|
|
|
191
560
|
return b;
|
|
192
561
|
}
|
|
193
562
|
/**
|
|
194
|
-
* Truncate a string
|
|
563
|
+
* Truncate a string at the last word boundary before `max`.
|
|
195
564
|
* @param s : the string to truncate
|
|
196
565
|
* @param max : the max number of chars
|
|
197
566
|
* @returns : the truncated string
|
|
@@ -201,13 +570,8 @@ class SystemUtils {
|
|
|
201
570
|
return undefined;
|
|
202
571
|
if (s.length < max)
|
|
203
572
|
return s;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
if (s[i] === ' ')
|
|
207
|
-
return s.slice(0, i);
|
|
208
|
-
i--;
|
|
209
|
-
}
|
|
210
|
-
return s;
|
|
573
|
+
const i = s.lastIndexOf(' ', max - 1);
|
|
574
|
+
return i > 0 ? s.slice(0, i) : s;
|
|
211
575
|
}
|
|
212
576
|
/**
|
|
213
577
|
* Join a list of strings
|
|
@@ -280,247 +644,16 @@ class SystemUtils {
|
|
|
280
644
|
static replaceAsHtml(s) {
|
|
281
645
|
if (!s)
|
|
282
646
|
return '';
|
|
283
|
-
|
|
284
|
-
const m = regex.exec(s);
|
|
285
|
-
if (!m || m.length === 0)
|
|
286
|
-
return s;
|
|
287
|
-
let result = s;
|
|
288
|
-
for (const v of m) {
|
|
289
|
-
result = result.replace(v, `<a href="${v}" target="_blank">${v}</a>`);
|
|
290
|
-
}
|
|
291
|
-
return result;
|
|
647
|
+
return s.replace(/https?:\/\/[^\s<]+/gi, v => `<a href="${v}" target="_blank" rel="noopener">${v}</a>`);
|
|
292
648
|
}
|
|
293
649
|
/**
|
|
294
650
|
* Convert markdown to html
|
|
295
651
|
* @param markdown : the markdown data
|
|
296
|
-
* @param
|
|
652
|
+
* @param escapeHtml : true to escape HTML. Default is false
|
|
297
653
|
* @returns the html
|
|
298
654
|
*/
|
|
299
|
-
static markdownToHtml(markdown,
|
|
300
|
-
|
|
301
|
-
return '';
|
|
302
|
-
let html = markdown;
|
|
303
|
-
// 1. Escape HTML entities
|
|
304
|
-
if (escapeEntities) {
|
|
305
|
-
html = html.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
306
|
-
}
|
|
307
|
-
// 2. Protect code from inline formatting by replacing it with placeholders.
|
|
308
|
-
// Placeholders are HTML-comment shaped so block detection treats them correctly.
|
|
309
|
-
const codeStore = [];
|
|
310
|
-
const stash = (content) => `<!--C${codeStore.push(content) - 1}-->`;
|
|
311
|
-
// 2a. Fenced code blocks
|
|
312
|
-
html = html.replace(/```(\w+)?\n([\s\S]*?)```/g, (_match, lang, code) => {
|
|
313
|
-
const langClass = lang ? ` class="language-${lang}"` : '';
|
|
314
|
-
return stash(`<pre><code${langClass}>${code.trim()}</code></pre>`);
|
|
315
|
-
});
|
|
316
|
-
// 2b. Inline code
|
|
317
|
-
html = html.replace(/`([^`]+)`/g, (_match, code) => stash(`<code>${code}</code>`));
|
|
318
|
-
// 2c. Ensure a space between two letters separated by sentence punctuation
|
|
319
|
-
// (! or ?), e.g. "dettaglio!Ecco" becomes "dettaglio! Ecco".
|
|
320
|
-
// Period, comma, colon and semicolon are ignored.
|
|
321
|
-
html = html.replace(/([A-Za-zÀ-ÿ][!?])([A-Za-zÀ-ÿ])/g, '$1 $2');
|
|
322
|
-
// 3. Headers
|
|
323
|
-
html = html.replace(/^##### (.*$)/gim, '<h5>$1</h5>');
|
|
324
|
-
html = html.replace(/^#### (.*$)/gim, '<h4>$1</h4>');
|
|
325
|
-
html = html.replace(/^### (.*$)/gim, '<h3>$1</h3>');
|
|
326
|
-
html = html.replace(/^## (.*$)/gim, '<h2>$1</h2>');
|
|
327
|
-
html = html.replace(/^# (.*$)/gim, '<h1>$1</h1>');
|
|
328
|
-
// 4. Horizontal rules
|
|
329
|
-
html = html.replace(/^---+$/gim, '<hr>');
|
|
330
|
-
html = html.replace(/^\*\*\*+$/gim, '<hr>');
|
|
331
|
-
// 5. Links
|
|
332
|
-
html = html.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
|
|
333
|
-
// 6. Images
|
|
334
|
-
html = html.replace(/!\[([^\]]*)\]\(([^)]+)\)/g, '<img src="$2" alt="$1">');
|
|
335
|
-
// 7. Bold and Italic.
|
|
336
|
-
// Delimiters must hug the text (no inner spaces) so spacing between
|
|
337
|
-
// separate styled spans is preserved. Underscore emphasis only applies at
|
|
338
|
-
// word boundaries, so identifiers like snake_case are left untouched.
|
|
339
|
-
html = html.replace(/\*\*\*(?=\S)([\s\S]*?\S)\*\*\*/g, '<strong><em>$1</em></strong>');
|
|
340
|
-
html = html.replace(/(?<![\w*])___(?=\S)([\s\S]*?\S)___(?![\w*])/g, '<strong><em>$1</em></strong>');
|
|
341
|
-
html = html.replace(/\*\*(?=\S)([\s\S]*?\S)\*\*/g, '<strong>$1</strong>');
|
|
342
|
-
html = html.replace(/(?<![\w*])__(?=\S)([\s\S]*?\S)__(?![\w*])/g, '<strong>$1</strong>');
|
|
343
|
-
html = html.replace(/\*(?=\S)([^*\n]*?\S)\*/g, '<em>$1</em>');
|
|
344
|
-
html = html.replace(/(?<![\w_])_(?=\S)([^_\n]*?\S)_(?![\w_])/g, '<em>$1</em>');
|
|
345
|
-
// 8. Strikethrough
|
|
346
|
-
html = html.replace(/~~(?=\S)([\s\S]*?\S)~~/g, '<del>$1</del>');
|
|
347
|
-
// 9. Blockquotes
|
|
348
|
-
html = html.replace(/^> (.*$)/gim, '<blockquote>$1</blockquote>');
|
|
349
|
-
// 10. Tables
|
|
350
|
-
html = this.markdownConvertTables(html);
|
|
351
|
-
// 11. Lists
|
|
352
|
-
html = this.markdownConvertLists(html);
|
|
353
|
-
// 12. Line breaks (two trailing spaces)
|
|
354
|
-
html = html.replace(/ {2}$/gm, '<br>');
|
|
355
|
-
// 13. Paragraphs (last block step, to avoid interfering with other elements)
|
|
356
|
-
html = this.markdownConvertParagraphs(html);
|
|
357
|
-
// 14. Collapse extra blank lines
|
|
358
|
-
html = html.replace(/\n{3,}/g, '\n\n');
|
|
359
|
-
// 15. Restore protected code placeholders
|
|
360
|
-
html = html.replace(/<!--C(\d+)-->/g, (_match, index) => codeStore[Number(index)] ?? '');
|
|
361
|
-
return html.trim();
|
|
362
|
-
}
|
|
363
|
-
/**
|
|
364
|
-
* Convert markdown table to html
|
|
365
|
-
* @param markdown: the markdown string
|
|
366
|
-
* @returns : the html
|
|
367
|
-
*/
|
|
368
|
-
static markdownConvertTables(markdown) {
|
|
369
|
-
const lines = markdown.split('\n');
|
|
370
|
-
const result = [];
|
|
371
|
-
let inTable = false;
|
|
372
|
-
let tableRows = [];
|
|
373
|
-
let headerProcessed = false;
|
|
374
|
-
for (let i = 0; i < lines.length; i++) {
|
|
375
|
-
const line = lines[i].trim();
|
|
376
|
-
if (line.includes('|') && line.length > 1) {
|
|
377
|
-
const nextLine = i + 1 < lines.length ? lines[i + 1].trim() : '';
|
|
378
|
-
const isHeaderSeparator = /^\|?[\s\-:|]+\|?$/.test(nextLine);
|
|
379
|
-
if (!inTable) {
|
|
380
|
-
inTable = true;
|
|
381
|
-
headerProcessed = false;
|
|
382
|
-
tableRows = [];
|
|
383
|
-
}
|
|
384
|
-
if (isHeaderSeparator && !headerProcessed) {
|
|
385
|
-
tableRows.push(this.markdownConvertTableRow(line, true));
|
|
386
|
-
headerProcessed = true;
|
|
387
|
-
i++;
|
|
388
|
-
}
|
|
389
|
-
else if (!isHeaderSeparator) {
|
|
390
|
-
tableRows.push(this.markdownConvertTableRow(line, false));
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
else {
|
|
394
|
-
if (inTable && tableRows.length > 0) {
|
|
395
|
-
result.push('<table>');
|
|
396
|
-
result.push(...tableRows);
|
|
397
|
-
result.push('</table>');
|
|
398
|
-
tableRows = [];
|
|
399
|
-
inTable = false;
|
|
400
|
-
}
|
|
401
|
-
result.push(line);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
if (inTable && tableRows.length > 0) {
|
|
405
|
-
result.push('<table>');
|
|
406
|
-
result.push(...tableRows);
|
|
407
|
-
result.push('</table>');
|
|
408
|
-
}
|
|
409
|
-
return result.join('\n');
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Convert a markdown table row to html
|
|
413
|
-
* @param row : the markdown row
|
|
414
|
-
* @param isHeader : true if is header
|
|
415
|
-
* @returns the html
|
|
416
|
-
*/
|
|
417
|
-
static markdownConvertTableRow(row, isHeader) {
|
|
418
|
-
const cells = row.split('|').map(cell => cell.trim()).filter(cell => cell !== '');
|
|
419
|
-
const tag = isHeader ? 'th' : 'td';
|
|
420
|
-
const cellsHtml = cells.map(cell => ` <${tag}>${cell}</${tag}>`).join('\n');
|
|
421
|
-
return ` <tr>\n${cellsHtml}\n </tr>`;
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Convert a markdown list to html
|
|
425
|
-
* @param markdown : the markdown list
|
|
426
|
-
* @returns the html
|
|
427
|
-
*/
|
|
428
|
-
static markdownConvertLists(markdown) {
|
|
429
|
-
markdown = markdown.replace(/^\* (.*$)/gim, '<li data-type="ul">$1</li>');
|
|
430
|
-
markdown = markdown.replace(/^- (.*$)/gim, '<li data-type="ul">$1</li>');
|
|
431
|
-
markdown = markdown.replace(/^\+ (.*$)/gim, '<li data-type="ul">$1</li>');
|
|
432
|
-
markdown = markdown.replace(/^\d+\. (.*$)/gim, '<li data-type="ol">$1</li>');
|
|
433
|
-
const lines = markdown.split('\n');
|
|
434
|
-
const result = [];
|
|
435
|
-
let currentList = { type: null, items: [] };
|
|
436
|
-
for (const line of lines) {
|
|
437
|
-
const ulMatch = line.match(/^<li data-type="ul">(.*)<\/li>$/);
|
|
438
|
-
const olMatch = line.match(/^<li data-type="ol">(.*)<\/li>$/);
|
|
439
|
-
if (ulMatch) {
|
|
440
|
-
if (currentList.type !== 'ul') {
|
|
441
|
-
if (currentList.type && currentList.items.length > 0) {
|
|
442
|
-
result.push(this.markdownWrapList(currentList.type, currentList.items));
|
|
443
|
-
}
|
|
444
|
-
currentList = { type: 'ul', items: [ulMatch[1]] };
|
|
445
|
-
}
|
|
446
|
-
else {
|
|
447
|
-
currentList.items.push(ulMatch[1]);
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
else if (olMatch) {
|
|
451
|
-
if (currentList.type !== 'ol') {
|
|
452
|
-
if (currentList.type && currentList.items.length > 0) {
|
|
453
|
-
result.push(this.markdownWrapList(currentList.type, currentList.items));
|
|
454
|
-
}
|
|
455
|
-
currentList = { type: 'ol', items: [olMatch[1]] };
|
|
456
|
-
}
|
|
457
|
-
else {
|
|
458
|
-
currentList.items.push(olMatch[1]);
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
else {
|
|
462
|
-
if (currentList.type && currentList.items.length > 0) {
|
|
463
|
-
result.push(this.markdownWrapList(currentList.type, currentList.items));
|
|
464
|
-
currentList = { type: null, items: [] };
|
|
465
|
-
}
|
|
466
|
-
result.push(line);
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
if (currentList.type && currentList.items.length > 0) {
|
|
470
|
-
result.push(this.markdownWrapList(currentList.type, currentList.items));
|
|
471
|
-
}
|
|
472
|
-
return result.join('\n');
|
|
473
|
-
}
|
|
474
|
-
/**
|
|
475
|
-
* Wrap a list
|
|
476
|
-
* @param type: the list type
|
|
477
|
-
* @param items : the item list
|
|
478
|
-
* @returns the html
|
|
479
|
-
*/
|
|
480
|
-
static markdownWrapList(type, items) {
|
|
481
|
-
const listItems = items.map(item => ` <li>${item}</li>`).join('\n');
|
|
482
|
-
return `<${type}>\n${listItems}\n</${type}>`;
|
|
483
|
-
}
|
|
484
|
-
/**
|
|
485
|
-
* Convert markdown paragraphs to html
|
|
486
|
-
* @param markdown : the markdown paragraphs
|
|
487
|
-
* @returns the html
|
|
488
|
-
*/
|
|
489
|
-
static markdownConvertParagraphs(markdown) {
|
|
490
|
-
// Block-level tags that must not be wrapped in a paragraph.
|
|
491
|
-
const blockTag = /^<\/?(h[1-6]|ul|ol|li|table|thead|tbody|tfoot|tr|td|th|pre|blockquote|hr|p|div)\b/i;
|
|
492
|
-
// A line consisting solely of a protected code placeholder is block-level.
|
|
493
|
-
const codePlaceholder = /^<!--C\d+-->$/;
|
|
494
|
-
const lines = markdown.split('\n');
|
|
495
|
-
const result = [];
|
|
496
|
-
// Buffer of consecutive plain-text lines that belong to the same paragraph.
|
|
497
|
-
let paragraph = [];
|
|
498
|
-
// Flush the buffered lines as a single paragraph, joining soft line breaks
|
|
499
|
-
// (single newlines) with a <br> so each source line keeps its own visual row.
|
|
500
|
-
const flushParagraph = () => {
|
|
501
|
-
if (paragraph.length > 0) {
|
|
502
|
-
result.push(`<p>${paragraph.join('<br>')}</p>`);
|
|
503
|
-
paragraph = [];
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
for (const line of lines) {
|
|
507
|
-
const trimmed = line.trim();
|
|
508
|
-
if (!trimmed) {
|
|
509
|
-
flushParagraph();
|
|
510
|
-
result.push('');
|
|
511
|
-
continue;
|
|
512
|
-
}
|
|
513
|
-
if (blockTag.test(trimmed) || codePlaceholder.test(trimmed)) {
|
|
514
|
-
flushParagraph();
|
|
515
|
-
result.push(line);
|
|
516
|
-
continue;
|
|
517
|
-
}
|
|
518
|
-
// Plain text or inline-level content (strong, em, a, code, ...) becomes a paragraph.
|
|
519
|
-
// Lines separated by a single newline are merged into the same paragraph.
|
|
520
|
-
paragraph.push(trimmed);
|
|
521
|
-
}
|
|
522
|
-
flushParagraph();
|
|
523
|
-
return result.join('\n');
|
|
655
|
+
static markdownToHtml(markdown, escapeHtml = false) {
|
|
656
|
+
return MarkdownUtils.toHtml(markdown, { escapeHtml: escapeHtml });
|
|
524
657
|
}
|
|
525
658
|
/**
|
|
526
659
|
* Compare two names
|
|
@@ -560,51 +693,44 @@ class SystemUtils {
|
|
|
560
693
|
* @returns :the ciphered text
|
|
561
694
|
*/
|
|
562
695
|
static cipher(text, key, reverse = false) {
|
|
696
|
+
if (!text || !key)
|
|
697
|
+
return undefined;
|
|
563
698
|
// Surrogate pair limit
|
|
564
699
|
const bound = 0x10000;
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
// Get rotation from key
|
|
570
|
-
let rotation = key.charCodeAt(i % key.length);
|
|
571
|
-
// Are we decrypting?
|
|
700
|
+
const keyLen = key.length;
|
|
701
|
+
let result = '';
|
|
702
|
+
for (let i = 0; i < text.length; i++) {
|
|
703
|
+
let rotation = key.charCodeAt(i % keyLen);
|
|
572
704
|
if (reverse)
|
|
573
705
|
rotation = -rotation;
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
706
|
+
result += String.fromCharCode((text.charCodeAt(i) + rotation + bound) % bound);
|
|
707
|
+
}
|
|
708
|
+
return result;
|
|
577
709
|
}
|
|
578
710
|
/**
|
|
579
|
-
* Clone an object
|
|
580
|
-
*
|
|
711
|
+
* Clone an object (deep copy).
|
|
712
|
+
* Uses native structuredClone: handles Date, Map, Set, typed arrays and circular references.
|
|
713
|
+
* @param obj : the object to clone
|
|
581
714
|
* @returns : a new object
|
|
582
715
|
*/
|
|
583
716
|
static clone(obj) {
|
|
584
717
|
if (!obj)
|
|
585
718
|
return {};
|
|
586
|
-
return
|
|
719
|
+
return structuredClone(obj);
|
|
587
720
|
}
|
|
588
721
|
/**
|
|
589
|
-
* Creates a deep clone of an object
|
|
722
|
+
* Creates a deep clone of an object.
|
|
590
723
|
* @param obj - The source object to clone.
|
|
591
|
-
* @param dest - Optional pre-allocated destination object
|
|
724
|
+
* @param dest - Optional pre-allocated destination object to merge the clone into.
|
|
592
725
|
* @returns A deep copy of `obj`.
|
|
593
726
|
*/
|
|
594
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
595
727
|
static deepClone(obj, dest) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
if (typeof property === 'object' && property !== null) {
|
|
601
|
-
cloneObj[attribute] = this.deepClone(property);
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
604
|
-
cloneObj[attribute] = property;
|
|
605
|
-
}
|
|
728
|
+
const cloned = structuredClone(obj);
|
|
729
|
+
if (dest) {
|
|
730
|
+
Object.assign(dest, cloned);
|
|
731
|
+
return dest;
|
|
606
732
|
}
|
|
607
|
-
return
|
|
733
|
+
return cloned;
|
|
608
734
|
}
|
|
609
735
|
/**
|
|
610
736
|
* Returns `true` when `value` is a syntactically valid UUID string.
|
|
@@ -633,6 +759,10 @@ class SystemUtils {
|
|
|
633
759
|
* @returns : the string UUID
|
|
634
760
|
*/
|
|
635
761
|
static generateUUID() {
|
|
762
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
763
|
+
return crypto.randomUUID();
|
|
764
|
+
}
|
|
765
|
+
// Fallback (non-secure contexts)
|
|
636
766
|
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
637
767
|
const r = (Math.random() * 16) | 0;
|
|
638
768
|
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
@@ -650,27 +780,46 @@ class SystemUtils {
|
|
|
650
780
|
return s;
|
|
651
781
|
return `${s.slice(0, 8)}-${s.slice(8, 12)}-${s.slice(12, 16)}-${s.slice(16, 20)}-${s.slice(20)}`;
|
|
652
782
|
}
|
|
783
|
+
/** Precompiled validation patterns. */
|
|
784
|
+
static { this.emailRegex = /^(?:[a-z0-9+!#$%&'*+\/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+\/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?: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]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/i; }
|
|
785
|
+
static { this.urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)\/?$/i; }
|
|
653
786
|
/**
|
|
654
|
-
* Parse a text and return true if is a valid email or
|
|
787
|
+
* Parse a text and return true if it is a valid email (or empty)
|
|
655
788
|
* @param value : email
|
|
656
789
|
* @returns : true if the email is valid or empty
|
|
657
790
|
*/
|
|
658
791
|
static parseEmail(value) {
|
|
659
792
|
if (!value)
|
|
660
793
|
return true;
|
|
661
|
-
|
|
662
|
-
|
|
794
|
+
return this.emailRegex.test(value.trim().toLowerCase());
|
|
795
|
+
}
|
|
796
|
+
/**
|
|
797
|
+
* Parse a text containing one or more email addresses separated by `;` or `,`
|
|
798
|
+
* and return true if all of them are valid (or the text is empty).
|
|
799
|
+
* Empty items caused by double or trailing separators are ignored.
|
|
800
|
+
* @param value : the email list to parse (e.g. "a@b.it; c@d.it")
|
|
801
|
+
* @returns : true if all emails are valid or the value is empty
|
|
802
|
+
*/
|
|
803
|
+
static parseEmails(value) {
|
|
804
|
+
if (!value || value.trim().length === 0)
|
|
805
|
+
return true;
|
|
806
|
+
const items = value
|
|
807
|
+
.split(/[;,]/)
|
|
808
|
+
.map(e => e.trim().toLowerCase())
|
|
809
|
+
.filter(e => e.length > 0);
|
|
810
|
+
if (items.length === 0)
|
|
811
|
+
return false; // only separators, no addresses
|
|
812
|
+
return items.every(e => this.emailRegex.test(e));
|
|
663
813
|
}
|
|
664
814
|
/**
|
|
665
|
-
* Parse a text and return true if is a valid url or
|
|
815
|
+
* Parse a text and return true if it is a valid url (or empty)
|
|
666
816
|
* @param value : the url to parse
|
|
667
817
|
* @returns : true if the url is valid or empty
|
|
668
818
|
*/
|
|
669
819
|
static parseUrl(value) {
|
|
670
820
|
if (!value)
|
|
671
821
|
return true;
|
|
672
|
-
|
|
673
|
-
return regex.test(value.trim().toLowerCase());
|
|
822
|
+
return this.urlRegex.test(value.trim().toLowerCase());
|
|
674
823
|
}
|
|
675
824
|
/**
|
|
676
825
|
* Get date parts from a string value
|
|
@@ -874,16 +1023,8 @@ class SystemUtils {
|
|
|
874
1023
|
static getQueryStringValueByName(name) {
|
|
875
1024
|
if (!this.isBrowser())
|
|
876
1025
|
return undefined;
|
|
877
|
-
const
|
|
878
|
-
|
|
879
|
-
const httpParams = new HttpParams({ fromString: url.split('?')[1] });
|
|
880
|
-
const raw = httpParams.get(name);
|
|
881
|
-
if (!raw)
|
|
882
|
-
return undefined;
|
|
883
|
-
const v = decodeURIComponent(raw);
|
|
884
|
-
return v && v !== 'null' ? v : undefined;
|
|
885
|
-
}
|
|
886
|
-
return undefined;
|
|
1026
|
+
const v = new URLSearchParams(window.location.search).get(name);
|
|
1027
|
+
return v && v !== 'null' ? v : undefined;
|
|
887
1028
|
}
|
|
888
1029
|
/**
|
|
889
1030
|
* Generate a password
|
|
@@ -1061,6 +1202,8 @@ class SystemUtils {
|
|
|
1061
1202
|
else
|
|
1062
1203
|
return [];
|
|
1063
1204
|
}
|
|
1205
|
+
/** Cache for resolved color luminance results. */
|
|
1206
|
+
static { this.colorLightCache = new Map(); }
|
|
1064
1207
|
/**
|
|
1065
1208
|
* Check if a color is light or dark
|
|
1066
1209
|
* @param color : the color
|
|
@@ -1068,19 +1211,27 @@ class SystemUtils {
|
|
|
1068
1211
|
* @returns true if the color is light
|
|
1069
1212
|
*/
|
|
1070
1213
|
static isColorLight(color, minimumLuminance = 186) {
|
|
1214
|
+
if (!this.isBrowser())
|
|
1215
|
+
return true; // SSR fallback
|
|
1216
|
+
const cacheKey = `${color}|${minimumLuminance}`;
|
|
1217
|
+
const cached = this.colorLightCache.get(cacheKey);
|
|
1218
|
+
if (cached !== undefined)
|
|
1219
|
+
return cached;
|
|
1071
1220
|
const tempDiv = document.createElement('div');
|
|
1072
1221
|
tempDiv.style.color = color;
|
|
1073
1222
|
document.body.appendChild(tempDiv);
|
|
1074
1223
|
const rgb = getComputedStyle(tempDiv).color;
|
|
1075
1224
|
document.body.removeChild(tempDiv);
|
|
1076
1225
|
const result = rgb.match(/\d+/g);
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1226
|
+
let light = true; // fallback
|
|
1227
|
+
if (result && result.length >= 3) {
|
|
1228
|
+
const r = parseInt(result[0], 10);
|
|
1229
|
+
const g = parseInt(result[1], 10);
|
|
1230
|
+
const b = parseInt(result[2], 10);
|
|
1231
|
+
light = (0.299 * r + 0.587 * g + 0.114 * b) > minimumLuminance;
|
|
1232
|
+
}
|
|
1233
|
+
this.colorLightCache.set(cacheKey, light);
|
|
1234
|
+
return light;
|
|
1084
1235
|
}
|
|
1085
1236
|
}
|
|
1086
1237
|
|
|
@@ -1128,10 +1279,10 @@ class FormatPipe {
|
|
|
1128
1279
|
}
|
|
1129
1280
|
return undefined;
|
|
1130
1281
|
}
|
|
1131
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1132
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1282
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FormatPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1283
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: FormatPipe, isStandalone: true, name: "format" }); }
|
|
1133
1284
|
}
|
|
1134
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1285
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FormatPipe, decorators: [{
|
|
1135
1286
|
type: Pipe,
|
|
1136
1287
|
args: [{
|
|
1137
1288
|
name: 'format',
|
|
@@ -1164,10 +1315,10 @@ class ReplacePipe {
|
|
|
1164
1315
|
const replacement = (regexValue === '\n' && !replaceValue) ? '<br>' : replaceValue;
|
|
1165
1316
|
return this.sanitizer.bypassSecurityTrustHtml(value.replace(new RegExp(regexValue, 'g'), replacement));
|
|
1166
1317
|
}
|
|
1167
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1168
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1318
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ReplacePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1319
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: ReplacePipe, isStandalone: true, name: "replace" }); }
|
|
1169
1320
|
}
|
|
1170
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1321
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ReplacePipe, decorators: [{
|
|
1171
1322
|
type: Pipe,
|
|
1172
1323
|
args: [{
|
|
1173
1324
|
name: 'replace',
|
|
@@ -1193,10 +1344,10 @@ class SafeHtmlPipe {
|
|
|
1193
1344
|
transform(value) {
|
|
1194
1345
|
return this.sanitizer.bypassSecurityTrustHtml(value ?? '');
|
|
1195
1346
|
}
|
|
1196
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1197
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1347
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SafeHtmlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1348
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: SafeHtmlPipe, isStandalone: true, name: "safeHtml" }); }
|
|
1198
1349
|
}
|
|
1199
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1350
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SafeHtmlPipe, decorators: [{
|
|
1200
1351
|
type: Pipe,
|
|
1201
1352
|
args: [{
|
|
1202
1353
|
name: 'safeHtml',
|
|
@@ -1222,10 +1373,10 @@ class SafeUrlPipe {
|
|
|
1222
1373
|
transform(value) {
|
|
1223
1374
|
return this.sanitizer.bypassSecurityTrustResourceUrl(value ?? '');
|
|
1224
1375
|
}
|
|
1225
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1226
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1376
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SafeUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1377
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: SafeUrlPipe, isStandalone: true, name: "safeUrl" }); }
|
|
1227
1378
|
}
|
|
1228
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1379
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SafeUrlPipe, decorators: [{
|
|
1229
1380
|
type: Pipe,
|
|
1230
1381
|
args: [{
|
|
1231
1382
|
name: 'safeUrl',
|
|
@@ -1254,10 +1405,10 @@ class SearchCallbackPipe {
|
|
|
1254
1405
|
return items;
|
|
1255
1406
|
return items.filter(item => callback(item));
|
|
1256
1407
|
}
|
|
1257
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1258
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1408
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SearchCallbackPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1409
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: SearchCallbackPipe, isStandalone: true, name: "callback", pure: false }); }
|
|
1259
1410
|
}
|
|
1260
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1411
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SearchCallbackPipe, decorators: [{
|
|
1261
1412
|
type: Pipe,
|
|
1262
1413
|
args: [{
|
|
1263
1414
|
name: 'callback',
|
|
@@ -1305,10 +1456,10 @@ class SearchFilterPipe {
|
|
|
1305
1456
|
metadata.count = result.length;
|
|
1306
1457
|
return result;
|
|
1307
1458
|
}
|
|
1308
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1309
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1459
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SearchFilterPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1460
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: SearchFilterPipe, isStandalone: true, name: "search" }); }
|
|
1310
1461
|
}
|
|
1311
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1462
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SearchFilterPipe, decorators: [{
|
|
1312
1463
|
type: Pipe,
|
|
1313
1464
|
args: [{
|
|
1314
1465
|
name: 'search',
|
|
@@ -1335,10 +1486,10 @@ class FormatHtmlPipe {
|
|
|
1335
1486
|
transform(value) {
|
|
1336
1487
|
return this.sanitizer.bypassSecurityTrustHtml((value ?? '').replaceAll(/(?:\r\n|\r|\n)/g, '<br>'));
|
|
1337
1488
|
}
|
|
1338
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1339
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
1489
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FormatHtmlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
1490
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: FormatHtmlPipe, isStandalone: true, name: "formatHtml" }); }
|
|
1340
1491
|
}
|
|
1341
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1492
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FormatHtmlPipe, decorators: [{
|
|
1342
1493
|
type: Pipe,
|
|
1343
1494
|
args: [{
|
|
1344
1495
|
name: 'formatHtml',
|
|
@@ -1660,10 +1811,10 @@ class DateFnsAdapter extends DateAdapter {
|
|
|
1660
1811
|
invalid() {
|
|
1661
1812
|
return new Date(NaN);
|
|
1662
1813
|
}
|
|
1663
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1664
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.
|
|
1814
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: DateFnsAdapter, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
1815
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: DateFnsAdapter }); }
|
|
1665
1816
|
}
|
|
1666
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1817
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: DateFnsAdapter, decorators: [{
|
|
1667
1818
|
type: Injectable
|
|
1668
1819
|
}], ctorParameters: () => [] });
|
|
1669
1820
|
/**
|
|
@@ -1699,10 +1850,10 @@ class AutoFocusDirective {
|
|
|
1699
1850
|
this.elementRef.nativeElement?.focus();
|
|
1700
1851
|
});
|
|
1701
1852
|
}
|
|
1702
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1703
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
1853
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: AutoFocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1854
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: AutoFocusDirective, isStandalone: true, selector: "[autoFocus]", ngImport: i0 }); }
|
|
1704
1855
|
}
|
|
1705
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1856
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: AutoFocusDirective, decorators: [{
|
|
1706
1857
|
type: Directive,
|
|
1707
1858
|
args: [{
|
|
1708
1859
|
selector: '[autoFocus]',
|
|
@@ -1800,10 +1951,10 @@ class DateIntervalChangeDirective {
|
|
|
1800
1951
|
}
|
|
1801
1952
|
this.subject.next(e);
|
|
1802
1953
|
}
|
|
1803
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1804
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
1954
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: DateIntervalChangeDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
1955
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: DateIntervalChangeDirective, isStandalone: true, selector: "[dateIntervalChange]", inputs: { dateIntervalChange: { classPropertyName: "dateIntervalChange", publicName: "dateIntervalChange", isSignal: true, isRequired: false, transformFunction: null }, end: { classPropertyName: "end", publicName: "end", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keyup": "onKeyup($event)" } }, ngImport: i0 }); }
|
|
1805
1956
|
}
|
|
1806
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
1957
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: DateIntervalChangeDirective, decorators: [{
|
|
1807
1958
|
type: Directive,
|
|
1808
1959
|
args: [{
|
|
1809
1960
|
selector: '[dateIntervalChange]',
|
|
@@ -1846,10 +1997,10 @@ class CopyClipboardDirective {
|
|
|
1846
1997
|
document.removeEventListener('copy', listener, false);
|
|
1847
1998
|
}
|
|
1848
1999
|
}
|
|
1849
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1850
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2000
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: CopyClipboardDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2001
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: CopyClipboardDirective, isStandalone: true, selector: "[copyClipboard]", inputs: { payload: { classPropertyName: "payload", publicName: "copyClipboard", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { copied: "copied" }, host: { listeners: { "click": "onClick($event)" } }, ngImport: i0 }); }
|
|
1851
2002
|
}
|
|
1852
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2003
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: CopyClipboardDirective, decorators: [{
|
|
1853
2004
|
type: Directive,
|
|
1854
2005
|
args: [{
|
|
1855
2006
|
selector: '[copyClipboard]',
|
|
@@ -1878,8 +2029,8 @@ class EmailsValidatorDirective {
|
|
|
1878
2029
|
const isValid = parts.every(part => part.length === 0 || !!SystemUtils.parseEmail(part));
|
|
1879
2030
|
return isValid ? null : { emails: "Elenco non valido." };
|
|
1880
2031
|
}
|
|
1881
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1882
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2032
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: EmailsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2033
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: EmailsValidatorDirective, isStandalone: true, selector: "[emails]", providers: [
|
|
1883
2034
|
{
|
|
1884
2035
|
provide: NG_VALIDATORS,
|
|
1885
2036
|
useExisting: forwardRef(() => EmailsValidatorDirective),
|
|
@@ -1887,7 +2038,7 @@ class EmailsValidatorDirective {
|
|
|
1887
2038
|
},
|
|
1888
2039
|
], ngImport: i0 }); }
|
|
1889
2040
|
}
|
|
1890
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2041
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: EmailsValidatorDirective, decorators: [{
|
|
1891
2042
|
type: Directive,
|
|
1892
2043
|
args: [{
|
|
1893
2044
|
selector: "[emails]",
|
|
@@ -1923,8 +2074,8 @@ class EqualsValidatorDirective {
|
|
|
1923
2074
|
return null;
|
|
1924
2075
|
return eq.value === control.value ? null : { equals: "Non valido." };
|
|
1925
2076
|
}
|
|
1926
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1927
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2077
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: EqualsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2078
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: EqualsValidatorDirective, isStandalone: true, selector: "[equals]", inputs: { equals: { classPropertyName: "equals", publicName: "equals", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
1928
2079
|
{
|
|
1929
2080
|
provide: NG_VALIDATORS,
|
|
1930
2081
|
useExisting: forwardRef(() => EqualsValidatorDirective),
|
|
@@ -1932,7 +2083,7 @@ class EqualsValidatorDirective {
|
|
|
1932
2083
|
},
|
|
1933
2084
|
], ngImport: i0 }); }
|
|
1934
2085
|
}
|
|
1935
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2086
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: EqualsValidatorDirective, decorators: [{
|
|
1936
2087
|
type: Directive,
|
|
1937
2088
|
args: [{
|
|
1938
2089
|
selector: "[equals]",
|
|
@@ -1976,8 +2127,8 @@ class FileSizeValidatorDirective {
|
|
|
1976
2127
|
const isValid = s <= this.maxSizeMb() && s >= this.minSizeMb();
|
|
1977
2128
|
return isValid ? null : { fileSize: "Non valido." };
|
|
1978
2129
|
}
|
|
1979
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
1980
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2130
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FileSizeValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2131
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: FileSizeValidatorDirective, isStandalone: true, selector: "[fileSize]", inputs: { maxSizeMb: { classPropertyName: "maxSizeMb", publicName: "maxSizeMb", isSignal: true, isRequired: false, transformFunction: null }, minSizeMb: { classPropertyName: "minSizeMb", publicName: "minSizeMb", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
1981
2132
|
{
|
|
1982
2133
|
provide: NG_VALIDATORS,
|
|
1983
2134
|
useExisting: forwardRef(() => FileSizeValidatorDirective),
|
|
@@ -1985,7 +2136,7 @@ class FileSizeValidatorDirective {
|
|
|
1985
2136
|
},
|
|
1986
2137
|
], ngImport: i0 }); }
|
|
1987
2138
|
}
|
|
1988
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2139
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FileSizeValidatorDirective, decorators: [{
|
|
1989
2140
|
type: Directive,
|
|
1990
2141
|
args: [{
|
|
1991
2142
|
selector: "[fileSize]",
|
|
@@ -2016,8 +2167,8 @@ class GuidValidatorDirective {
|
|
|
2016
2167
|
return null;
|
|
2017
2168
|
return SystemUtils.parseUUID(input) ? null : { guid: "Non valido." };
|
|
2018
2169
|
}
|
|
2019
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2020
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2170
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: GuidValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2171
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: GuidValidatorDirective, isStandalone: true, selector: "[guid]", providers: [
|
|
2021
2172
|
{
|
|
2022
2173
|
provide: NG_VALIDATORS,
|
|
2023
2174
|
useExisting: forwardRef(() => GuidValidatorDirective),
|
|
@@ -2025,7 +2176,7 @@ class GuidValidatorDirective {
|
|
|
2025
2176
|
},
|
|
2026
2177
|
], ngImport: i0 }); }
|
|
2027
2178
|
}
|
|
2028
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2179
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: GuidValidatorDirective, decorators: [{
|
|
2029
2180
|
type: Directive,
|
|
2030
2181
|
args: [{
|
|
2031
2182
|
selector: "[guid]",
|
|
@@ -2062,8 +2213,8 @@ class MaxTermsValidatorDirective {
|
|
|
2062
2213
|
const terms = input.match(/\S+/g)?.length ?? 0;
|
|
2063
2214
|
return terms <= this.maxTerms() ? null : { maxTerms: "Non valido." };
|
|
2064
2215
|
}
|
|
2065
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2066
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2216
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: MaxTermsValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2217
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: MaxTermsValidatorDirective, isStandalone: true, selector: "[maxTerms]", inputs: { maxTerms: { classPropertyName: "maxTerms", publicName: "maxTerms", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
2067
2218
|
{
|
|
2068
2219
|
provide: NG_VALIDATORS,
|
|
2069
2220
|
useExisting: forwardRef(() => MaxTermsValidatorDirective),
|
|
@@ -2071,7 +2222,7 @@ class MaxTermsValidatorDirective {
|
|
|
2071
2222
|
},
|
|
2072
2223
|
], ngImport: i0 }); }
|
|
2073
2224
|
}
|
|
2074
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2225
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: MaxTermsValidatorDirective, decorators: [{
|
|
2075
2226
|
type: Directive,
|
|
2076
2227
|
args: [{
|
|
2077
2228
|
selector: "[maxTerms]",
|
|
@@ -2102,8 +2253,8 @@ class NotEmptyValidatorDirective {
|
|
|
2102
2253
|
return null;
|
|
2103
2254
|
return input.trim().length > 0 ? null : { notEmpty: true };
|
|
2104
2255
|
}
|
|
2105
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2106
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2256
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: NotEmptyValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2257
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: NotEmptyValidatorDirective, isStandalone: true, selector: "[notEmpty]", providers: [
|
|
2107
2258
|
{
|
|
2108
2259
|
provide: NG_VALIDATORS,
|
|
2109
2260
|
useExisting: forwardRef(() => NotEmptyValidatorDirective),
|
|
@@ -2111,7 +2262,7 @@ class NotEmptyValidatorDirective {
|
|
|
2111
2262
|
},
|
|
2112
2263
|
], ngImport: i0 }); }
|
|
2113
2264
|
}
|
|
2114
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2265
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: NotEmptyValidatorDirective, decorators: [{
|
|
2115
2266
|
type: Directive,
|
|
2116
2267
|
args: [{
|
|
2117
2268
|
selector: "[notEmpty]",
|
|
@@ -2159,8 +2310,8 @@ class NotEqualValidatorDirective {
|
|
|
2159
2310
|
}
|
|
2160
2311
|
return errors;
|
|
2161
2312
|
}
|
|
2162
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2163
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2313
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: NotEqualValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2314
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: NotEqualValidatorDirective, isStandalone: true, selector: "[notEqual]", inputs: { notEqual: { classPropertyName: "notEqual", publicName: "notEqual", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
2164
2315
|
{
|
|
2165
2316
|
provide: NG_VALIDATORS,
|
|
2166
2317
|
useExisting: forwardRef(() => NotEqualValidatorDirective),
|
|
@@ -2168,7 +2319,7 @@ class NotEqualValidatorDirective {
|
|
|
2168
2319
|
},
|
|
2169
2320
|
], ngImport: i0 }); }
|
|
2170
2321
|
}
|
|
2171
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2322
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: NotEqualValidatorDirective, decorators: [{
|
|
2172
2323
|
type: Directive,
|
|
2173
2324
|
args: [{
|
|
2174
2325
|
selector: "[notEqual]",
|
|
@@ -2201,8 +2352,8 @@ class NotFutureValidatorDirective {
|
|
|
2201
2352
|
const d = endOfDay(SystemUtils.parseDate(input));
|
|
2202
2353
|
return d <= today ? null : { notFuture: "Non valido." };
|
|
2203
2354
|
}
|
|
2204
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2205
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2355
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: NotFutureValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2356
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: NotFutureValidatorDirective, isStandalone: true, selector: "[notFuture]", providers: [
|
|
2206
2357
|
{
|
|
2207
2358
|
provide: NG_VALIDATORS,
|
|
2208
2359
|
useExisting: forwardRef(() => NotFutureValidatorDirective),
|
|
@@ -2210,7 +2361,7 @@ class NotFutureValidatorDirective {
|
|
|
2210
2361
|
},
|
|
2211
2362
|
], ngImport: i0 }); }
|
|
2212
2363
|
}
|
|
2213
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2364
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: NotFutureValidatorDirective, decorators: [{
|
|
2214
2365
|
type: Directive,
|
|
2215
2366
|
args: [{
|
|
2216
2367
|
selector: "[notFuture]",
|
|
@@ -2239,8 +2390,8 @@ class PasswordValidatorDirective {
|
|
|
2239
2390
|
const strength = SystemUtils.calculatePasswordStrength(input);
|
|
2240
2391
|
return strength.isValid ? null : { password: "Non valido." };
|
|
2241
2392
|
}
|
|
2242
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2243
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2393
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: PasswordValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2394
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: PasswordValidatorDirective, isStandalone: true, selector: "[password]", providers: [
|
|
2244
2395
|
{
|
|
2245
2396
|
provide: NG_VALIDATORS,
|
|
2246
2397
|
useExisting: forwardRef(() => PasswordValidatorDirective),
|
|
@@ -2248,7 +2399,7 @@ class PasswordValidatorDirective {
|
|
|
2248
2399
|
},
|
|
2249
2400
|
], ngImport: i0 }); }
|
|
2250
2401
|
}
|
|
2251
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2402
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: PasswordValidatorDirective, decorators: [{
|
|
2252
2403
|
type: Directive,
|
|
2253
2404
|
args: [{
|
|
2254
2405
|
selector: "[password]",
|
|
@@ -2282,10 +2433,10 @@ class RemoveFocusDirective {
|
|
|
2282
2433
|
setTimeout(() => el.blur(), 0);
|
|
2283
2434
|
}
|
|
2284
2435
|
}
|
|
2285
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2286
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2436
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: RemoveFocusDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2437
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: RemoveFocusDirective, isStandalone: true, selector: "[removeFocus]", host: { listeners: { "click": "onClick()" } }, ngImport: i0 }); }
|
|
2287
2438
|
}
|
|
2288
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2439
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: RemoveFocusDirective, decorators: [{
|
|
2289
2440
|
type: Directive,
|
|
2290
2441
|
args: [{
|
|
2291
2442
|
selector: '[removeFocus]',
|
|
@@ -2313,8 +2464,8 @@ class SqlDateValidatorDirective {
|
|
|
2313
2464
|
const d = endOfDay(SystemUtils.parseDate(input));
|
|
2314
2465
|
return d.getFullYear() > 1750 ? null : { sqlDate: "Non valido." };
|
|
2315
2466
|
}
|
|
2316
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2317
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2467
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SqlDateValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2468
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: SqlDateValidatorDirective, isStandalone: true, selector: "[sqlDate]", providers: [
|
|
2318
2469
|
{
|
|
2319
2470
|
provide: NG_VALIDATORS,
|
|
2320
2471
|
useExisting: forwardRef(() => SqlDateValidatorDirective),
|
|
@@ -2322,7 +2473,7 @@ class SqlDateValidatorDirective {
|
|
|
2322
2473
|
},
|
|
2323
2474
|
], ngImport: i0 }); }
|
|
2324
2475
|
}
|
|
2325
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2476
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: SqlDateValidatorDirective, decorators: [{
|
|
2326
2477
|
type: Directive,
|
|
2327
2478
|
args: [{
|
|
2328
2479
|
selector: "[sqlDate]",
|
|
@@ -2388,8 +2539,8 @@ class TimeValidatorDirective {
|
|
|
2388
2539
|
}
|
|
2389
2540
|
return null;
|
|
2390
2541
|
}
|
|
2391
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2392
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2542
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: TimeValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2543
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: TimeValidatorDirective, isStandalone: true, selector: "[time]", inputs: { slots: { classPropertyName: "slots", publicName: "slots", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
2393
2544
|
{
|
|
2394
2545
|
provide: NG_VALIDATORS,
|
|
2395
2546
|
useExisting: forwardRef(() => TimeValidatorDirective),
|
|
@@ -2397,7 +2548,7 @@ class TimeValidatorDirective {
|
|
|
2397
2548
|
},
|
|
2398
2549
|
], ngImport: i0 }); }
|
|
2399
2550
|
}
|
|
2400
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2551
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: TimeValidatorDirective, decorators: [{
|
|
2401
2552
|
type: Directive,
|
|
2402
2553
|
args: [{
|
|
2403
2554
|
selector: "[time]",
|
|
@@ -2428,8 +2579,8 @@ class UrlValidatorDirective {
|
|
|
2428
2579
|
return null;
|
|
2429
2580
|
return SystemUtils.parseUrl(input) ? null : { url: "Non valido." };
|
|
2430
2581
|
}
|
|
2431
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2432
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.
|
|
2582
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UrlValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2583
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.1", type: UrlValidatorDirective, isStandalone: true, selector: "[url]", providers: [
|
|
2433
2584
|
{
|
|
2434
2585
|
provide: NG_VALIDATORS,
|
|
2435
2586
|
useExisting: forwardRef(() => UrlValidatorDirective),
|
|
@@ -2437,7 +2588,7 @@ class UrlValidatorDirective {
|
|
|
2437
2588
|
},
|
|
2438
2589
|
], ngImport: i0 }); }
|
|
2439
2590
|
}
|
|
2440
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2591
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: UrlValidatorDirective, decorators: [{
|
|
2441
2592
|
type: Directive,
|
|
2442
2593
|
args: [{
|
|
2443
2594
|
selector: "[url]",
|
|
@@ -2480,8 +2631,8 @@ class ValidIfDirective {
|
|
|
2480
2631
|
}
|
|
2481
2632
|
return isValid ? null : { validIf: "Non valido." };
|
|
2482
2633
|
}
|
|
2483
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2484
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2634
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ValidIfDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2635
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: ValidIfDirective, isStandalone: true, selector: "[validIf]", inputs: { validIf: { classPropertyName: "validIf", publicName: "validIf", isSignal: true, isRequired: false, transformFunction: null } }, providers: [
|
|
2485
2636
|
{
|
|
2486
2637
|
provide: NG_VALIDATORS,
|
|
2487
2638
|
useExisting: forwardRef(() => ValidIfDirective),
|
|
@@ -2489,7 +2640,7 @@ class ValidIfDirective {
|
|
|
2489
2640
|
},
|
|
2490
2641
|
], ngImport: i0 }); }
|
|
2491
2642
|
}
|
|
2492
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2643
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ValidIfDirective, decorators: [{
|
|
2493
2644
|
type: Directive,
|
|
2494
2645
|
args: [{
|
|
2495
2646
|
selector: "[validIf]",
|
|
@@ -2523,10 +2674,10 @@ class ValidatorDirective {
|
|
|
2523
2674
|
const fn = this.validator();
|
|
2524
2675
|
return fn ? fn(control) : null;
|
|
2525
2676
|
}
|
|
2526
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2527
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.
|
|
2677
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ValidatorDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
2678
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.1", type: ValidatorDirective, isStandalone: true, selector: "[validator]", inputs: { validator: { classPropertyName: "validator", publicName: "validator", isSignal: true, isRequired: false, transformFunction: null } }, providers: [{ provide: NG_VALIDATORS, useExisting: ValidatorDirective, multi: true }], ngImport: i0 }); }
|
|
2528
2679
|
}
|
|
2529
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2680
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ValidatorDirective, decorators: [{
|
|
2530
2681
|
type: Directive,
|
|
2531
2682
|
args: [{
|
|
2532
2683
|
selector: '[validator]',
|
|
@@ -2552,10 +2703,10 @@ class FormatMarkdownPipe {
|
|
|
2552
2703
|
transform(value) {
|
|
2553
2704
|
return this.sanitizer.bypassSecurityTrustHtml(SystemUtils.markdownToHtml(value ?? ''));
|
|
2554
2705
|
}
|
|
2555
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2556
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.
|
|
2706
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FormatMarkdownPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
2707
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "22.0.1", ngImport: i0, type: FormatMarkdownPipe, isStandalone: true, name: "formatMarkdown" }); }
|
|
2557
2708
|
}
|
|
2558
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
2709
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: FormatMarkdownPipe, decorators: [{
|
|
2559
2710
|
type: Pipe,
|
|
2560
2711
|
args: [{
|
|
2561
2712
|
name: 'formatMarkdown',
|
|
@@ -2906,10 +3057,10 @@ class BroadcastService {
|
|
|
2906
3057
|
getMessage() {
|
|
2907
3058
|
return this.subject.asObservable();
|
|
2908
3059
|
}
|
|
2909
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2910
|
-
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.
|
|
3060
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: BroadcastService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
|
|
3061
|
+
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.1", ngImport: i0, type: BroadcastService }); }
|
|
2911
3062
|
}
|
|
2912
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
3063
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: BroadcastService, decorators: [{
|
|
2913
3064
|
type: Service
|
|
2914
3065
|
}] });
|
|
2915
3066
|
|
|
@@ -2967,10 +3118,10 @@ class EnvironmentService {
|
|
|
2967
3118
|
get appServiceLoginUri() { return this._effectiveServiceLoginUri(); }
|
|
2968
3119
|
/** @param value - The login endpoint URI of the backend service. */
|
|
2969
3120
|
set appServiceLoginUri(value) { this.appServiceLoginUriSignal.set(value); }
|
|
2970
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
2971
|
-
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.
|
|
3121
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: EnvironmentService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
|
|
3122
|
+
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.1", ngImport: i0, type: EnvironmentService }); }
|
|
2972
3123
|
}
|
|
2973
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
3124
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: EnvironmentService, decorators: [{
|
|
2974
3125
|
type: Service
|
|
2975
3126
|
}] });
|
|
2976
3127
|
|
|
@@ -3001,10 +3152,10 @@ class ScreenService {
|
|
|
3001
3152
|
get isIEOrEdge() {
|
|
3002
3153
|
return /msie\s|trident\/|edge\//i.test(window.navigator.userAgent);
|
|
3003
3154
|
}
|
|
3004
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
3005
|
-
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.
|
|
3155
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ScreenService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
|
|
3156
|
+
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.1", ngImport: i0, type: ScreenService }); }
|
|
3006
3157
|
}
|
|
3007
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
3158
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ScreenService, decorators: [{
|
|
3008
3159
|
type: Service
|
|
3009
3160
|
}] });
|
|
3010
3161
|
|
|
@@ -3123,10 +3274,10 @@ class ThemeService {
|
|
|
3123
3274
|
this.themeChanged.next(this.getTheme());
|
|
3124
3275
|
this.broadcastChannel.sendMessage(this.broadcastMessage, theme);
|
|
3125
3276
|
}
|
|
3126
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.
|
|
3127
|
-
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.
|
|
3277
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Service }); }
|
|
3278
|
+
static { this.ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.1", ngImport: i0, type: ThemeService }); }
|
|
3128
3279
|
}
|
|
3129
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.
|
|
3280
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: ThemeService, decorators: [{
|
|
3130
3281
|
type: Service
|
|
3131
3282
|
}], ctorParameters: () => [] });
|
|
3132
3283
|
|