PageSourceSearch

https://website-cms-prod.fly.dev/modules/App/assets/js/app/utils.js

js website-cms-prod.fly.dev collected 2026-10-03 08:28:13 UTC 5,028 bytes, 176 lines download raw bytes

1import { Engine as JSLiteEngine } from "../../vendor/jslite.esm.js";
2
3let formatSize = function(bytes) {
4    if (bytes == 0) { return "0.00 B"; }
5    let e = Math.floor(Math.log(bytes) / Math.log(1024));
6    return ((bytes / Math.pow(1024, e)).toFixed(2) + ' ' + ' KMGTP'.charAt(e) + 'B').replace('.00', '');
7}
8
9let formatNumber = function(num, round = 2) {
10    return (new Intl.NumberFormat(navigator.language, { style: 'decimal', maximumFractionDigits: round})).format(num);
11}
12
13let formatDuration = function(time) {
14    // Hours, minutes and seconds
15    let hrs = ~~(time / 3600);
16    let mins = ~~((time % 3600) / 60);
17    let secs = ~~time % 60;
18
19    // Output like "1:01" or "4:03:59" or "123:03:59"
20    let ret = '';
21
22    if (hrs > 0) {
23        ret += `${hrs}:${(mins < 10 ? '0' : '')}`;
24    }
25
26    ret += `${mins}:${(secs < 10 ? '0' : '')}`;
27    ret += `${secs}`;
28    return ret;
29}
30
31let isNumeric = function(n) { return !isNaN(parseFloat(n)) && isFinite(n); }
32
33let on = function(element, name, delegate, fn) {
34
35    if (!fn) {
36        element.addEventListener(name, arguments[2]);
37    } else {
38        element.addEventListener(name, function(e) {
39
40            let target = e.target;
41
42            while (target !== element) {
43
44                if (!target) {
45                    break;
46                }
47
48                if (target.matches(delegate)) {
49                    return fn.apply(target, arguments);
50                }
51
52                target = target.parentNode;
53            }
54        });
55    }
56
57    return element;
58};
59
60let toKebabCase = function(str) {
61    return str.replace(/([a-z])([A-Z])/g, '$1-$2').replace(/\s+/g, '-').toLowerCase();
62};
63
64let copyText = function(text, cb) {
65    let inp = document.createElement('textarea');
66    document.body.appendChild(inp)
67    inp.value = text
68    inp.select();
69    try { document.execCommand('copy', false); } catch (e) { }
70    inp.remove();
71    if (cb) cb();
72}
73
74let interpolateEngine = new JSLiteEngine();
75
76let interpolate = function(str, params) {
77    const source = `return \`${str}\`;`;
78    return interpolateEngine.run(interpolateEngine.compile(source), Object.assign({}, params));
79}
80
81let uuid = function() {
82
83    if (typeof(crypto) !== 'undefined' && typeof(crypto.randomUUID) === 'function') {
84        return crypto.randomUUID();
85    }
86
87    return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
88        (c ^ (typeof(crypto) !== 'undefined' && typeof(crypto.getRandomValues) === 'function' ? crypto.getRandomValues(new Uint8Array(1))[0] : Math.floor(Math.random() * 255)) & 15 >> c / 4).toString(16)
89    );
90}
91
92let nanoid = function(size = 10) {
93
94    const alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
95    let id = '';
96
97    if (typeof(crypto) !== 'undefined' && typeof(crypto.getRandomValues) === 'function') {
98        const bytes = new Uint8Array(size);
99        crypto.getRandomValues(bytes);
100        for (let i = 0; i < size; i++) id += alphabet[bytes[i] % alphabet.length];
101        return id;
102    }
103
104    for (let i = 0; i < size; i++) id += alphabet.charAt(Math.floor(Math.random() * alphabet.length));
105    return id;
106}
107
108
109let truncate = function(text, length, clamp = '...') {
110    let content = text || '';
111    return content.length > length ? content.slice(0, length) + clamp : content;
112};
113
114let stripTags = function(input, allowed) {
115
116    if (Array.isArray(allowed)) {
117        let tags = '';
118        allowed.forEach(tag => tags += `<${tag}>`);
119        allowed = tags;
120    }
121
122    // making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)
123    allowed = (((allowed || '') + '').toLowerCase().match(/<[a-z][a-z0-9\-]*>/g) || []).join('');
124    const tags = /<\/?([a-z0-9\-]*)\b[^>]*>?/gi;
125    const commentsAndPhpTags = /<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi;
126    let after = input;
127
128    after = (after.substring(after.length - 1) === '<') ? after.substring(0, after.length - 1) : after;
129
130    while (true) {
131        const before = after
132        after = before.replace(commentsAndPhpTags, '').replace(tags, ($0, $1) => {
133            return allowed.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''
134        });
135        if (before === after) {
136            return after
137        }
138    }
139};
140
141let base64encode = function(str) {
142    return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) =>
142  String.fromCharCode('0x' + p1)));
143};
144
145let base64decode = function(str) {
146    return decodeURIComponent(atob(str).split('').map((c) => {
147        return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2)
148    }).join(''));
149};
150
151let escape = function(html) {
152    return String(html)
153        .replace(/&/g, "&amp;")
154        .replace(/</g, "&lt;")
155        .replace(/>/g, "&gt;")
156        .replace(/"/g, "&quot;")
157        .replace(/'/g, "&#039;");
158};
159
160export default {
161    base64encode,
162    base64decode,
163    copyText,
164    escape,
165    formatSize,
166    formatDuration,
167    formatNumber,
168    interpolate,
169    isNumeric,
170    nanoid,
171    on,
172    toKebabCase,
173    uuid,
174    truncate,
175    stripTags
176}

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.