idiotikmethods 0.1.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.
- package/IdiotikMethods.js +779 -0
- package/package.json +10 -0
- package/sw.js +267 -0
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
// ================================================================
|
|
2
|
+
// IDIOTIK METHODS — v0.1
|
|
3
|
+
// Single bundled trust loader. Loads every library under its roof,
|
|
4
|
+
// initializes each one so pipelines are live, registers all to
|
|
5
|
+
// window.idiotik.methods.*, and boots the SW stack.
|
|
6
|
+
// ================================================================
|
|
7
|
+
|
|
8
|
+
(function (root) {
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
// ----------------------------------------------------------------
|
|
12
|
+
// GUARD — only run once
|
|
13
|
+
// ----------------------------------------------------------------
|
|
14
|
+
if (root.__IdiotikMethods) return;
|
|
15
|
+
root.__IdiotikMethods = true;
|
|
16
|
+
|
|
17
|
+
// ----------------------------------------------------------------
|
|
18
|
+
// WAIT FOR IDIOTIK CORE
|
|
19
|
+
// ----------------------------------------------------------------
|
|
20
|
+
function _waitForIdiotik(cb) {
|
|
21
|
+
if (root.idiotik) return cb(root.idiotik);
|
|
22
|
+
let attempts = 0;
|
|
23
|
+
const t = setInterval(() => {
|
|
24
|
+
if (root.idiotik) { clearInterval(t); cb(root.idiotik); }
|
|
25
|
+
else if (++attempts > 100) { clearInterval(t); console.warn("[IdiotikMethods] idiotik core not found after 10s"); }
|
|
26
|
+
}, 100);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ----------------------------------------------------------------
|
|
30
|
+
// LIBRARY REGISTRY
|
|
31
|
+
// ----------------------------------------------------------------
|
|
32
|
+
const _methods = {};
|
|
33
|
+
const _loadedUrls = new Set();
|
|
34
|
+
|
|
35
|
+
// ----------------------------------------------------------------
|
|
36
|
+
// FULL LIBRARY MANIFEST
|
|
37
|
+
// Every library the project could ever need — loaded under this roof.
|
|
38
|
+
// cdnjs preferred, unpkg fallback.
|
|
39
|
+
// ----------------------------------------------------------------
|
|
40
|
+
const LIBRARIES = [
|
|
41
|
+
// ── PDF / DOC ──────────────────────────────────────────────
|
|
42
|
+
{
|
|
43
|
+
key: "pdfjs",
|
|
44
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.min.js",
|
|
45
|
+
fallback: "https://unpkg.com/pdfjs-dist@4.2.67/build/pdf.min.js",
|
|
46
|
+
init: () => _initPdfJs(),
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// ── GESTURE / INPUT ────────────────────────────────────────
|
|
50
|
+
{
|
|
51
|
+
key: "hammer",
|
|
52
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js",
|
|
53
|
+
fallback: "https://unpkg.com/hammerjs@2.0.8/hammer.min.js",
|
|
54
|
+
init: () => _initHammer(),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
key: "interact",
|
|
58
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.27/interact.min.js",
|
|
59
|
+
fallback: "https://unpkg.com/interactjs@1.10.27/dist/interact.min.js",
|
|
60
|
+
init: () => _register("interact", root.interact),
|
|
61
|
+
},
|
|
62
|
+
|
|
63
|
+
// ── MAPS ───────────────────────────────────────────────────
|
|
64
|
+
{
|
|
65
|
+
key: "leaflet",
|
|
66
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/leaflet.js",
|
|
67
|
+
fallback: "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js",
|
|
68
|
+
init: () => _initLeaflet(),
|
|
69
|
+
},
|
|
70
|
+
|
|
71
|
+
// ── 3D / CANVAS / GRAPHICS ─────────────────────────────────
|
|
72
|
+
{
|
|
73
|
+
key: "three",
|
|
74
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js",
|
|
75
|
+
fallback: "https://unpkg.com/three@0.128.0/build/three.min.js",
|
|
76
|
+
init: () => _register("three", root.THREE),
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
key: "pixijs",
|
|
80
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/pixi.js/7.4.2/pixi.min.js",
|
|
81
|
+
fallback: "https://unpkg.com/pixi.js@7.4.2/dist/pixi.min.js",
|
|
82
|
+
init: () => _register("pixijs", root.PIXI),
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
key: "fabric",
|
|
86
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.0/fabric.min.js",
|
|
87
|
+
fallback: "https://unpkg.com/fabric@5.3.0/dist/fabric.min.js",
|
|
88
|
+
init: () => _register("fabric", root.fabric),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
key: "konva",
|
|
92
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/konva/9.3.3/konva.min.js",
|
|
93
|
+
fallback: "https://unpkg.com/konva@9.3.3/konva.min.js",
|
|
94
|
+
init: () => _register("konva", root.Konva),
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
key: "p5",
|
|
98
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.4/p5.min.js",
|
|
99
|
+
fallback: "https://unpkg.com/p5@1.9.4/lib/p5.min.js",
|
|
100
|
+
init: () => _register("p5", root.p5),
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
key: "d3",
|
|
104
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/d3/7.9.0/d3.min.js",
|
|
105
|
+
fallback: "https://unpkg.com/d3@7.9.0/dist/d3.min.js",
|
|
106
|
+
init: () => _register("d3", root.d3),
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
key: "chartjs",
|
|
110
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.3/chart.umd.min.js",
|
|
111
|
+
fallback: "https://unpkg.com/chart.js@4.4.3/dist/chart.umd.min.js",
|
|
112
|
+
init: () => _register("chartjs", root.Chart),
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
key: "echarts",
|
|
116
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/echarts/5.5.0/echarts.min.js",
|
|
117
|
+
fallback: "https://unpkg.com/echarts@5.5.0/dist/echarts.min.js",
|
|
118
|
+
init: () => _register("echarts", root.echarts),
|
|
119
|
+
},
|
|
120
|
+
|
|
121
|
+
// ── AUDIO ──────────────────────────────────────────────────
|
|
122
|
+
{
|
|
123
|
+
key: "tone",
|
|
124
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/tone/14.8.49/Tone.js",
|
|
125
|
+
fallback: "https://unpkg.com/tone@14.8.49/build/Tone.js",
|
|
126
|
+
init: () => _register("tone", root.Tone),
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
key: "howler",
|
|
130
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/howler/2.2.4/howler.min.js",
|
|
131
|
+
fallback: "https://unpkg.com/howler@2.2.4/dist/howler.min.js",
|
|
132
|
+
init: () => _register("howler", root.Howl ? { Howl: root.Howl, Howler: root.Howler } : null),
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
key: "wavesurfer",
|
|
136
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/wavesurfer.js/7.8.2/wavesurfer.js",
|
|
137
|
+
fallback: "https://unpkg.com/wavesurfer.js@7.8.2/dist/wavesurfer.js",
|
|
138
|
+
init: () => _register("wavesurfer", root.WaveSurfer),
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
// ── ANIMATION ──────────────────────────────────────────────
|
|
142
|
+
{
|
|
143
|
+
key: "gsap",
|
|
144
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.5/gsap.min.js",
|
|
145
|
+
fallback: "https://unpkg.com/gsap@3.12.5/dist/gsap.min.js",
|
|
146
|
+
init: () => _register("gsap", root.gsap),
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
key: "anime",
|
|
150
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.2/anime.min.js",
|
|
151
|
+
fallback: "https://unpkg.com/animejs@3.2.2/lib/anime.min.js",
|
|
152
|
+
init: () => _register("anime", root.anime),
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
key: "lottie",
|
|
156
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.12.2/lottie.min.js",
|
|
157
|
+
fallback: "https://unpkg.com/lottie-web@5.12.2/build/player/lottie.min.js",
|
|
158
|
+
init: () => _register("lottie", root.lottie),
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
key: "velocity",
|
|
162
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/velocity/2.0.6/velocity.min.js",
|
|
163
|
+
fallback: "https://unpkg.com/velocity-animate@2.0.6/velocity.min.js",
|
|
164
|
+
init: () => _register("velocity", root.Velocity),
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
// ── NETWORK / REALTIME ─────────────────────────────────────
|
|
168
|
+
{
|
|
169
|
+
key: "socketio",
|
|
170
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.7.5/socket.io.min.js",
|
|
171
|
+
fallback: "https://unpkg.com/socket.io-client@4.7.5/dist/socket.io.min.js",
|
|
172
|
+
init: () => _register("socketio", root.io),
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
key: "axios",
|
|
176
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/axios/1.7.2/axios.min.js",
|
|
177
|
+
fallback: "https://unpkg.com/axios@1.7.2/dist/axios.min.js",
|
|
178
|
+
init: () => _register("axios", root.axios),
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
key: "signalr",
|
|
182
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/8.0.7/signalr.min.js",
|
|
183
|
+
fallback: "https://unpkg.com/@microsoft/signalr@8.0.7/dist/browser/signalr.min.js",
|
|
184
|
+
init: () => _register("signalr", root.signalR),
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
// ── UTILITY ────────────────────────────────────────────────
|
|
188
|
+
{
|
|
189
|
+
key: "lodash",
|
|
190
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js",
|
|
191
|
+
fallback: "https://unpkg.com/lodash@4.17.21/lodash.min.js",
|
|
192
|
+
init: () => _register("lodash", root._),
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
key: "dayjs",
|
|
196
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.11/dayjs.min.js",
|
|
197
|
+
fallback: "https://unpkg.com/dayjs@1.11.11/dayjs.min.js",
|
|
198
|
+
init: () => _register("dayjs", root.dayjs),
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
key: "moment",
|
|
202
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.30.1/moment.min.js",
|
|
203
|
+
fallback: "https://unpkg.com/moment@2.30.1/moment.min.js",
|
|
204
|
+
init: () => _register("moment", root.moment),
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
key: "mathjs",
|
|
208
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/mathjs/13.0.3/math.min.js",
|
|
209
|
+
fallback: "https://unpkg.com/mathjs@13.0.3/lib/browser/math.js",
|
|
210
|
+
init: () => _register("mathjs", root.math),
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
key: "rxjs",
|
|
214
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/rxjs/7.8.1/rxjs.umd.min.js",
|
|
215
|
+
fallback: "https://unpkg.com/rxjs@7.8.1/dist/bundles/rxjs.umd.min.js",
|
|
216
|
+
init: () => _register("rxjs", root.rxjs),
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
key: "ramda",
|
|
220
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/ramda/0.30.1/ramda.min.js",
|
|
221
|
+
fallback: "https://unpkg.com/ramda@0.30.1/dist/ramda.min.js",
|
|
222
|
+
init: () => _register("ramda", root.R),
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
// ── DOM / UI ───────────────────────────────────────────────
|
|
226
|
+
{
|
|
227
|
+
key: "jquery",
|
|
228
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js",
|
|
229
|
+
fallback: "https://unpkg.com/jquery@3.7.1/dist/jquery.min.js",
|
|
230
|
+
init: () => _register("jquery", root.jQuery),
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
key: "alpine",
|
|
234
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/alpinejs/3.14.1/cdn.min.js",
|
|
235
|
+
fallback: "https://unpkg.com/alpinejs@3.14.1/dist/cdn.min.js",
|
|
236
|
+
init: () => _register("alpine", root.Alpine),
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
key: "htmx",
|
|
240
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/htmx/2.0.1/htmx.min.js",
|
|
241
|
+
fallback: "https://unpkg.com/htmx.org@2.0.1/dist/htmx.min.js",
|
|
242
|
+
init: () => _register("htmx", root.htmx),
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
key: "sortablejs",
|
|
246
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.2/Sortable.min.js",
|
|
247
|
+
fallback: "https://unpkg.com/sortablejs@1.15.2/Sortable.min.js",
|
|
248
|
+
init: () => _register("sortablejs", root.Sortable),
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
key: "popper",
|
|
252
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/popper.js/2.11.8/umd/popper.min.js",
|
|
253
|
+
fallback: "https://unpkg.com/@popperjs/core@2.11.8/dist/umd/popper.min.js",
|
|
254
|
+
init: () => _register("popper", root.Popper),
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
key: "tippy",
|
|
258
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/tippy.js/6.3.7/tippy.umd.min.js",
|
|
259
|
+
fallback: "https://unpkg.com/tippy.js@6.3.7/dist/tippy.umd.min.js",
|
|
260
|
+
init: () => _register("tippy", root.tippy),
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
key: "notyf",
|
|
264
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/notyf/3.10.0/notyf.min.js",
|
|
265
|
+
fallback: "https://unpkg.com/notyf@3.10.0/notyf.min.js",
|
|
266
|
+
init: () => _register("notyf", root.Notyf),
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
key: "sweetalert2",
|
|
270
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/limonte-sweetalert2/11.12.2/sweetalert2.min.js",
|
|
271
|
+
fallback: "https://unpkg.com/sweetalert2@11.12.2/dist/sweetalert2.min.js",
|
|
272
|
+
init: () => _register("sweetalert2", root.Swal),
|
|
273
|
+
},
|
|
274
|
+
|
|
275
|
+
// ── DATA / PARSING ─────────────────────────────────────────
|
|
276
|
+
{
|
|
277
|
+
key: "papaparse",
|
|
278
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js",
|
|
279
|
+
fallback: "https://unpkg.com/papaparse@5.4.1/papaparse.min.js",
|
|
280
|
+
init: () => _register("papaparse", root.Papa),
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
key: "xlsx",
|
|
284
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.5/xlsx.full.min.js",
|
|
285
|
+
fallback: "https://unpkg.com/xlsx@0.18.5/dist/xlsx.full.min.js",
|
|
286
|
+
init: () => _register("xlsx", root.XLSX),
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
key: "marked",
|
|
290
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/marked/13.0.2/marked.min.js",
|
|
291
|
+
fallback: "https://unpkg.com/marked@13.0.2/marked.min.js",
|
|
292
|
+
init: () => _register("marked", root.marked),
|
|
293
|
+
},
|
|
294
|
+
{
|
|
295
|
+
key: "dompurify",
|
|
296
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.1.6/purify.min.js",
|
|
297
|
+
fallback: "https://unpkg.com/dompurify@3.1.6/dist/purify.min.js",
|
|
298
|
+
init: () => _register("dompurify", root.DOMPurify),
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
key: "fuse",
|
|
302
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/fuse.js/7.0.0/fuse.min.js",
|
|
303
|
+
fallback: "https://unpkg.com/fuse.js@7.0.0/dist/fuse.min.js",
|
|
304
|
+
init: () => _register("fuse", root.Fuse),
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
key: "lunr",
|
|
308
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/lunr.js/2.3.9/lunr.min.js",
|
|
309
|
+
fallback: "https://unpkg.com/lunr@2.3.9/lunr.min.js",
|
|
310
|
+
init: () => _register("lunr", root.lunr),
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
// ── CRYPTO / SECURITY ──────────────────────────────────────
|
|
314
|
+
{
|
|
315
|
+
key: "cryptojs",
|
|
316
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.2.0/crypto-js.min.js",
|
|
317
|
+
fallback: "https://unpkg.com/crypto-js@4.2.0/crypto-js.js",
|
|
318
|
+
init: () => _register("cryptojs", root.CryptoJS),
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
key: "forge",
|
|
322
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/forge/1.3.1/forge.min.js",
|
|
323
|
+
fallback: "https://unpkg.com/node-forge@1.3.1/dist/forge.min.js",
|
|
324
|
+
init: () => _register("forge", root.forge),
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
// ── MEDIA / STREAM ─────────────────────────────────────────
|
|
328
|
+
{
|
|
329
|
+
key: "videojs",
|
|
330
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/video.js/8.12.0/video.min.js",
|
|
331
|
+
fallback: "https://unpkg.com/video.js@8.12.0/dist/video.min.js",
|
|
332
|
+
init: () => _register("videojs", root.videojs),
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
key: "recordrtc",
|
|
336
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/RecordRTC/5.6.2/RecordRTC.min.js",
|
|
337
|
+
fallback: "https://unpkg.com/recordrtc@5.6.2/RecordRTC.js",
|
|
338
|
+
init: () => _register("recordrtc", root.RecordRTC),
|
|
339
|
+
},
|
|
340
|
+
|
|
341
|
+
// ── PHYSICS / SIMULATION ───────────────────────────────────
|
|
342
|
+
{
|
|
343
|
+
key: "matterjs",
|
|
344
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js",
|
|
345
|
+
fallback: "https://unpkg.com/matter-js@0.19.0/build/matter.min.js",
|
|
346
|
+
init: () => _register("matterjs", root.Matter),
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
key: "planck",
|
|
350
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/planck/1.0.0/planck.min.js",
|
|
351
|
+
fallback: "https://unpkg.com/planck@1.0.0/dist/planck.min.js",
|
|
352
|
+
init: () => _register("planck", root.planck),
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
// ── ROUTING / SPA ──────────────────────────────────────────
|
|
356
|
+
{
|
|
357
|
+
key: "navigo",
|
|
358
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/navigo/8.11.1/navigo.min.js",
|
|
359
|
+
fallback: "https://unpkg.com/navigo@8.11.1/lib/navigo.min.js",
|
|
360
|
+
init: () => _register("navigo", root.Navigo),
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
key: "pagejs",
|
|
364
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/page.js/1.11.6/page.min.js",
|
|
365
|
+
fallback: "https://unpkg.com/page@1.11.6/page.js",
|
|
366
|
+
init: () => _register("pagejs", root.page),
|
|
367
|
+
},
|
|
368
|
+
|
|
369
|
+
// ── WORKER / PARALLEL ──────────────────────────────────────
|
|
370
|
+
{
|
|
371
|
+
key: "comlink",
|
|
372
|
+
url: "https://unpkg.com/comlink@4.4.1/dist/umd/comlink.js",
|
|
373
|
+
fallback: "https://cdn.jsdelivr.net/npm/comlink@4.4.1/dist/umd/comlink.js",
|
|
374
|
+
init: () => _register("comlink", root.Comlink),
|
|
375
|
+
},
|
|
376
|
+
|
|
377
|
+
// ── MISC POWER TOOLS ───────────────────────────────────────
|
|
378
|
+
{
|
|
379
|
+
key: "idb",
|
|
380
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/idb/8.0.0/idb.min.js",
|
|
381
|
+
fallback: "https://unpkg.com/idb@8.0.0/build/umd.js",
|
|
382
|
+
init: () => _register("idb", root.idb),
|
|
383
|
+
},
|
|
384
|
+
{
|
|
385
|
+
key: "localforage",
|
|
386
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js",
|
|
387
|
+
fallback: "https://unpkg.com/localforage@1.10.0/dist/localforage.min.js",
|
|
388
|
+
init: () => _register("localforage", root.localforage),
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
key: "fingerprintjs",
|
|
392
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/fingerprintjs2/2.1.4/fingerprint2.min.js",
|
|
393
|
+
fallback: "https://unpkg.com/fingerprintjs2@2.1.4/dist/fingerprint2.min.js",
|
|
394
|
+
init: () => _register("fingerprintjs", root.Fingerprint2),
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
key: "qrcode",
|
|
398
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js",
|
|
399
|
+
fallback: "https://unpkg.com/qrcodejs@1.0.0/qrcode.min.js",
|
|
400
|
+
init: () => _register("qrcode", root.QRCode),
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
key: "zxing",
|
|
404
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/zxing-js/0.21.3/index.min.js",
|
|
405
|
+
fallback: "https://unpkg.com/@zxing/library@0.21.3/umd/index.min.js",
|
|
406
|
+
init: () => _register("zxing", root.ZXing),
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
key: "tesseract",
|
|
410
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/tesseract.js/5.1.0/tesseract.min.js",
|
|
411
|
+
fallback: "https://unpkg.com/tesseract.js@5.1.0/dist/tesseract.min.js",
|
|
412
|
+
init: () => _register("tesseract", root.Tesseract),
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
key: "ml5",
|
|
416
|
+
url: "https://unpkg.com/ml5@1.2.1/dist/ml5.min.js",
|
|
417
|
+
fallback: "https://cdn.jsdelivr.net/npm/ml5@1.2.1/dist/ml5.min.js",
|
|
418
|
+
init: () => _register("ml5", root.ml5),
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
key: "tensorflow",
|
|
422
|
+
url: "https://cdnjs.cloudflare.com/ajax/libs/tensorflow/4.20.0/tf.min.js",
|
|
423
|
+
fallback: "https://unpkg.com/@tensorflow/tfjs@4.20.0/dist/tf.min.js",
|
|
424
|
+
init: () => _register("tensorflow", root.tf),
|
|
425
|
+
},
|
|
426
|
+
];
|
|
427
|
+
|
|
428
|
+
// ----------------------------------------------------------------
|
|
429
|
+
// REGISTER — wrap a library ref into window.idiotik.methods.*
|
|
430
|
+
// ----------------------------------------------------------------
|
|
431
|
+
function _register(key, ref) {
|
|
432
|
+
if (!ref) {
|
|
433
|
+
console.warn(`[IdiotikMethods] ${key} — global not found after load, skipping register`);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
_methods[key] = ref;
|
|
437
|
+
// expose on window.idiotik.methods if idiotik is present
|
|
438
|
+
if (root.idiotik) {
|
|
439
|
+
root.idiotik.methods = root.idiotik.methods || {};
|
|
440
|
+
root.idiotik.methods[key] = ref;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// ----------------------------------------------------------------
|
|
445
|
+
// LIBRARY-SPECIFIC INITIALIZERS
|
|
446
|
+
// Each one: initialize, run minimum viable activity, leave pipeline live.
|
|
447
|
+
// ----------------------------------------------------------------
|
|
448
|
+
|
|
449
|
+
function _initPdfJs() {
|
|
450
|
+
const pdfjsLib = root.pdfjsLib || root["pdfjs-dist"] || root.pdfjsLib;
|
|
451
|
+
if (!pdfjsLib) { console.warn("[IdiotikMethods] pdf.js global not found"); return; }
|
|
452
|
+
|
|
453
|
+
// set worker src (use CDN worker)
|
|
454
|
+
if (pdfjsLib.GlobalWorkerOptions) {
|
|
455
|
+
pdfjsLib.GlobalWorkerOptions.workerSrc =
|
|
456
|
+
"https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.2.67/pdf.worker.min.js";
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// spin up a minimal invisible container to get the trusted event pipeline live
|
|
460
|
+
const container = document.createElement("div");
|
|
461
|
+
container.style.cssText = "position:fixed;width:1px;height:1px;top:-9999px;left:-9999px;overflow:hidden;pointer-events:none;";
|
|
462
|
+
document.body.appendChild(container);
|
|
463
|
+
|
|
464
|
+
// render a blank 1-page PDF to initialize pdf.js's trusted click + interaction channels
|
|
465
|
+
const blankPdfBase64 =
|
|
466
|
+
"JVBERi0xLjQKMSAwIG9iago8PCAvVHlwZSAvQ2F0YWxvZyAvUGFnZXMgMiAwIFIgPj4KZW5kb2JqCjIgMCBvYmoKPDwgL1R5cGUgL1BhZ2VzIC9LaWRzIFszIDAgUl0gL0NvdW50IDEgPj4KZW5kb2JqCjMgMCBvYmoKPDwgL1R5cGUgL1BhZ2UgL1BhcmVudCAyIDAgUiAvTWVkaWFCb3ggWzAgMCAxIDFdID4+CmVuZG9iagp4cmVmCjAgNAowMDAwMDAwMDAwIDY1NTM1IGYgCjAwMDAwMDAwMDkgMDAwMDAgbiAKMDAwMDAwMDA1OCAwMDAwMCBuIAowMDAwMDAwMTE1IDAwMDAwIG4gCnRyYWlsZXIKPDwgL1NpemUgNCAvUm9vdCAxIDAgUiA+PgpzdGFydHhyZWYKMTkwCiUlRU9G";
|
|
467
|
+
|
|
468
|
+
const pdfData = atob(blankPdfBase64);
|
|
469
|
+
const pdfArray = new Uint8Array(pdfData.length);
|
|
470
|
+
for (let i = 0; i < pdfData.length; i++) pdfArray[i] = pdfData.charCodeAt(i);
|
|
471
|
+
|
|
472
|
+
pdfjsLib.getDocument({ data: pdfArray }).promise.then((pdf) => {
|
|
473
|
+
return pdf.getPage(1);
|
|
474
|
+
}).then((page) => {
|
|
475
|
+
const canvas = document.createElement("canvas");
|
|
476
|
+
canvas.style.cssText = "position:absolute;width:1px;height:1px;pointer-events:none;";
|
|
477
|
+
container.appendChild(canvas);
|
|
478
|
+
const ctx = canvas.getContext("2d");
|
|
479
|
+
const viewport = page.getViewport({ scale: 0.01 });
|
|
480
|
+
canvas.width = viewport.width;
|
|
481
|
+
canvas.height = viewport.height;
|
|
482
|
+
page.render({ canvasContext: ctx, viewport });
|
|
483
|
+
}).catch(() => {});
|
|
484
|
+
|
|
485
|
+
_register("pdfjs", pdfjsLib);
|
|
486
|
+
|
|
487
|
+
// expose the trusted container for bypass hooks
|
|
488
|
+
_methods.pdfjsContainer = container;
|
|
489
|
+
if (root.idiotik) {
|
|
490
|
+
root.idiotik.methods = root.idiotik.methods || {};
|
|
491
|
+
root.idiotik.methods.pdfjsContainer = container;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function _initHammer() {
|
|
496
|
+
if (!root.Hammer) { console.warn("[IdiotikMethods] Hammer.js not found"); return; }
|
|
497
|
+
// create a hidden target and register ALL recognizers so the gesture pipeline is live
|
|
498
|
+
const target = document.createElement("div");
|
|
499
|
+
target.style.cssText = "position:fixed;width:1px;height:1px;top:-9999px;left:-9999px;touch-action:none;pointer-events:all;";
|
|
500
|
+
document.body.appendChild(target);
|
|
501
|
+
|
|
502
|
+
const mc = new root.Hammer.Manager(target, {
|
|
503
|
+
recognizers: [
|
|
504
|
+
[root.Hammer.Tap],
|
|
505
|
+
[root.Hammer.DoubleTap],
|
|
506
|
+
[root.Hammer.Press],
|
|
507
|
+
[root.Hammer.Pan, { direction: root.Hammer.DIRECTION_ALL }],
|
|
508
|
+
[root.Hammer.Swipe, { direction: root.Hammer.DIRECTION_ALL }],
|
|
509
|
+
[root.Hammer.Pinch],
|
|
510
|
+
[root.Hammer.Rotate],
|
|
511
|
+
],
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// fire noop listeners so the pipeline actually activates
|
|
515
|
+
["tap", "doubletap", "press", "pan", "swipe", "pinch", "rotate"].forEach((ev) => {
|
|
516
|
+
mc.on(ev, () => {});
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
_register("hammer", root.Hammer);
|
|
520
|
+
_methods.hammerManager = mc;
|
|
521
|
+
if (root.idiotik) {
|
|
522
|
+
root.idiotik.methods = root.idiotik.methods || {};
|
|
523
|
+
root.idiotik.methods.hammerManager = mc;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function _initLeaflet() {
|
|
528
|
+
if (!root.L) { console.warn("[IdiotikMethods] Leaflet not found"); return; }
|
|
529
|
+
// spin up a hidden map instance so tile/event pipeline is live
|
|
530
|
+
const container = document.createElement("div");
|
|
531
|
+
container.style.cssText = "position:fixed;width:1px;height:1px;top:-9999px;left:-9999px;overflow:hidden;";
|
|
532
|
+
document.body.appendChild(container);
|
|
533
|
+
|
|
534
|
+
try {
|
|
535
|
+
const map = root.L.map(container, {
|
|
536
|
+
center: [0, 0],
|
|
537
|
+
zoom: 1,
|
|
538
|
+
zoomControl: false,
|
|
539
|
+
attributionControl: false,
|
|
540
|
+
});
|
|
541
|
+
// register pointer + gesture listeners so the pipeline fires
|
|
542
|
+
map.on("click mousemove", () => {});
|
|
543
|
+
_register("leaflet", root.L);
|
|
544
|
+
_methods.leafletMap = map;
|
|
545
|
+
if (root.idiotik) {
|
|
546
|
+
root.idiotik.methods = root.idiotik.methods || {};
|
|
547
|
+
root.idiotik.methods.leafletMap = map;
|
|
548
|
+
}
|
|
549
|
+
} catch (e) {
|
|
550
|
+
// container not ready or headless env
|
|
551
|
+
_register("leaflet", root.L);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// ----------------------------------------------------------------
|
|
556
|
+
// SCRIPT LOADER — load as classic <script> (no type=module)
|
|
557
|
+
// so everything lands on the shared window. with cdnjs/unpkg fallback.
|
|
558
|
+
// ----------------------------------------------------------------
|
|
559
|
+
function _loadScript(url, fallback) {
|
|
560
|
+
return new Promise((resolve) => {
|
|
561
|
+
if (_loadedUrls.has(url)) return resolve(true);
|
|
562
|
+
_loadedUrls.add(url);
|
|
563
|
+
|
|
564
|
+
const tryLoad = (src, isFallback) => {
|
|
565
|
+
const s = document.createElement("script");
|
|
566
|
+
s.src = src;
|
|
567
|
+
// NO type="module" — forces classic script so globals land on window
|
|
568
|
+
s.async = false;
|
|
569
|
+
s.onload = () => resolve(true);
|
|
570
|
+
s.onerror = () => {
|
|
571
|
+
if (!isFallback && fallback) {
|
|
572
|
+
tryLoad(fallback, true);
|
|
573
|
+
} else {
|
|
574
|
+
console.warn(`[IdiotikMethods] failed to load: ${src}`);
|
|
575
|
+
resolve(false);
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
document.head.appendChild(s);
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
tryLoad(url, false);
|
|
582
|
+
});
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// ----------------------------------------------------------------
|
|
586
|
+
// MAIN BOOT — load all libraries, init, register
|
|
587
|
+
// ----------------------------------------------------------------
|
|
588
|
+
async function _boot(idiotik) {
|
|
589
|
+
// set up methods namespace immediately
|
|
590
|
+
idiotik.methods = idiotik.methods || {};
|
|
591
|
+
|
|
592
|
+
// register SW before loading libraries
|
|
593
|
+
// (SW needs to be up to intercept library requests)
|
|
594
|
+
await _bootSW(idiotik);
|
|
595
|
+
|
|
596
|
+
// load all libraries concurrently — they're independent
|
|
597
|
+
await Promise.allSettled(
|
|
598
|
+
LIBRARIES.map(async (lib) => {
|
|
599
|
+
const ok = await _loadScript(lib.url, lib.fallback);
|
|
600
|
+
if (ok) {
|
|
601
|
+
try {
|
|
602
|
+
lib.init();
|
|
603
|
+
} catch (e) {
|
|
604
|
+
console.warn(`[IdiotikMethods] init error for ${lib.key}:`, e);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
})
|
|
608
|
+
);
|
|
609
|
+
|
|
610
|
+
// final sync — make sure idiotik.methods is fully populated
|
|
611
|
+
Object.assign(idiotik.methods, _methods);
|
|
612
|
+
|
|
613
|
+
console.info(
|
|
614
|
+
`[IdiotikMethods] loaded ${Object.keys(_methods).length}/${LIBRARIES.length} libraries. ` +
|
|
615
|
+
`registry: window.idiotik.methods.*`
|
|
616
|
+
);
|
|
617
|
+
|
|
618
|
+
// signal to IdiotikScript that methods are live
|
|
619
|
+
root.__IdiotikMethodsReady = true;
|
|
620
|
+
root.dispatchEvent && root.dispatchEvent(new Event("idiotik:methods:ready"));
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
// ----------------------------------------------------------------
|
|
624
|
+
// SW BOOT — register service workers + window Proxy fallback
|
|
625
|
+
// Injected into IdiotikMethods so this file owns the SW lifecycle.
|
|
626
|
+
// ----------------------------------------------------------------
|
|
627
|
+
async function _bootSW(idiotik) {
|
|
628
|
+
if (!("serviceWorker" in navigator)) {
|
|
629
|
+
console.warn("[IdiotikMethods] SW not supported — falling back to window Proxy");
|
|
630
|
+
_installWindowProxy(idiotik);
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// determine SW script URL — look for sw.js next to IdiotikMethods.js
|
|
635
|
+
const swUrl = _resolveSwUrl();
|
|
636
|
+
|
|
637
|
+
try {
|
|
638
|
+
const reg = await navigator.serviceWorker.register(swUrl, { scope: "/" });
|
|
639
|
+
console.info("[IdiotikMethods] SW registered:", reg.scope);
|
|
640
|
+
|
|
641
|
+
// wait for the SW to be active
|
|
642
|
+
await _waitForSWActive(reg);
|
|
643
|
+
|
|
644
|
+
// signal the SW that IdiotikMethods is live and share the VFS
|
|
645
|
+
_syncVfsToSW();
|
|
646
|
+
|
|
647
|
+
} catch (primaryErr) {
|
|
648
|
+
console.warn("[IdiotikMethods] primary SW failed:", primaryErr.message, "— trying fallback");
|
|
649
|
+
|
|
650
|
+
// try fallback SW (different internal strategy)
|
|
651
|
+
try {
|
|
652
|
+
const fallbackUrl = _resolveSwUrl("fallback");
|
|
653
|
+
const fallbackReg = await navigator.serviceWorker.register(fallbackUrl, { scope: "/" });
|
|
654
|
+
await _waitForSWActive(fallbackReg);
|
|
655
|
+
console.info("[IdiotikMethods] fallback SW active");
|
|
656
|
+
_syncVfsToSW();
|
|
657
|
+
} catch (fallbackErr) {
|
|
658
|
+
console.warn("[IdiotikMethods] fallback SW also failed:", fallbackErr.message, "— installing window Proxy");
|
|
659
|
+
_installWindowProxy(idiotik);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
function _resolveSwUrl(type) {
|
|
665
|
+
// look for sw.js in the same directory as the current script
|
|
666
|
+
const scripts = document.querySelectorAll("script[src]");
|
|
667
|
+
for (const s of scripts) {
|
|
668
|
+
if (s.src && (s.src.includes("IdiotikMethods") || s.src.includes("idiotik"))) {
|
|
669
|
+
const base = s.src.substring(0, s.src.lastIndexOf("/") + 1);
|
|
670
|
+
return type === "fallback" ? `${base}sw-fallback.js` : `${base}sw.js`;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
return type === "fallback" ? "/sw-fallback.js" : "/sw.js";
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function _waitForSWActive(reg) {
|
|
677
|
+
return new Promise((resolve) => {
|
|
678
|
+
if (reg.active) return resolve();
|
|
679
|
+
const sw = reg.installing || reg.waiting;
|
|
680
|
+
if (!sw) return resolve();
|
|
681
|
+
sw.addEventListener("statechange", function handler() {
|
|
682
|
+
if (sw.state === "activated") {
|
|
683
|
+
sw.removeEventListener("statechange", handler);
|
|
684
|
+
resolve();
|
|
685
|
+
}
|
|
686
|
+
});
|
|
687
|
+
// timeout after 5s — don't block library loading indefinitely
|
|
688
|
+
setTimeout(resolve, 5000);
|
|
689
|
+
});
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function _syncVfsToSW() {
|
|
693
|
+
// send VFS contents to active SW so it can serve .idiotik.js files from it
|
|
694
|
+
if (!navigator.serviceWorker.controller) return;
|
|
695
|
+
const vfsKeys = root.idiotik && root.idiotik.script
|
|
696
|
+
? root.idiotik.script.vfs.keys()
|
|
697
|
+
: [];
|
|
698
|
+
const vfsEntries = vfsKeys.map((k) => ({
|
|
699
|
+
path: k,
|
|
700
|
+
source: root.idiotik.script.vfs.get(k),
|
|
701
|
+
}));
|
|
702
|
+
navigator.serviceWorker.controller.postMessage({
|
|
703
|
+
type: "IDIOTIK_VFS_SYNC",
|
|
704
|
+
vfs: vfsEntries,
|
|
705
|
+
});
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// ----------------------------------------------------------------
|
|
709
|
+
// WINDOW PROXY FALLBACK
|
|
710
|
+
// Sits on window before libraries load, intercepts their writes
|
|
711
|
+
// the moment they happen. Last resort if both SWs fail.
|
|
712
|
+
// ----------------------------------------------------------------
|
|
713
|
+
function _installWindowProxy(idiotik) {
|
|
714
|
+
// globals we care about wrapping
|
|
715
|
+
const WATCH_KEYS = [
|
|
716
|
+
"pdfjsLib", "Hammer", "L", "THREE", "PIXI", "fabric", "Konva",
|
|
717
|
+
"p5", "d3", "Chart", "echarts", "Tone", "Howl", "WaveSurfer",
|
|
718
|
+
"gsap", "anime", "lottie", "Velocity", "io", "axios", "signalR",
|
|
719
|
+
"_", "dayjs", "moment", "math", "rxjs", "R", "jQuery", "$",
|
|
720
|
+
"Alpine", "htmx", "Sortable", "Popper", "tippy", "Notyf", "Swal",
|
|
721
|
+
"Papa", "XLSX", "marked", "DOMPurify", "Fuse", "lunr",
|
|
722
|
+
"CryptoJS", "forge", "videojs", "RecordRTC", "Matter", "planck",
|
|
723
|
+
"Navigo", "page", "Comlink", "idb", "localforage",
|
|
724
|
+
"Fingerprint2", "QRCode", "ZXing", "Tesseract", "ml5", "tf",
|
|
725
|
+
];
|
|
726
|
+
|
|
727
|
+
// map from global key → methods key
|
|
728
|
+
const KEY_MAP = {
|
|
729
|
+
pdfjsLib: "pdfjs", L: "leaflet", THREE: "three", PIXI: "pixijs",
|
|
730
|
+
Chart: "chartjs", Tone: "tone", Howl: "howler", WaveSurfer: "wavesurfer",
|
|
731
|
+
io: "socketio", _: "lodash", math: "mathjs", R: "ramda",
|
|
732
|
+
jQuery: "jquery", $: "jquery", Swal: "sweetalert2", Papa: "papaparse",
|
|
733
|
+
ZXing: "zxing", Fingerprint2: "fingerprintjs", tf: "tensorflow",
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
WATCH_KEYS.forEach((key) => {
|
|
737
|
+
if (Object.prototype.hasOwnProperty.call(root, key)) {
|
|
738
|
+
// already set — wrap immediately
|
|
739
|
+
const val = root[key];
|
|
740
|
+
const methodKey = KEY_MAP[key] || key.toLowerCase();
|
|
741
|
+
_register(methodKey, val);
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
// not set yet — intercept the set
|
|
745
|
+
let _val;
|
|
746
|
+
try {
|
|
747
|
+
Object.defineProperty(root, key, {
|
|
748
|
+
configurable: true,
|
|
749
|
+
enumerable: true,
|
|
750
|
+
get() { return _val; },
|
|
751
|
+
set(v) {
|
|
752
|
+
_val = v;
|
|
753
|
+
const methodKey = KEY_MAP[key] || key.toLowerCase();
|
|
754
|
+
_register(methodKey, v);
|
|
755
|
+
// restore to plain value so library works normally
|
|
756
|
+
try {
|
|
757
|
+
Object.defineProperty(root, key, {
|
|
758
|
+
configurable: true,
|
|
759
|
+
enumerable: true,
|
|
760
|
+
writable: true,
|
|
761
|
+
value: v,
|
|
762
|
+
});
|
|
763
|
+
} catch (_) {}
|
|
764
|
+
},
|
|
765
|
+
});
|
|
766
|
+
} catch (_) {
|
|
767
|
+
// defineProperty failed (e.g. non-configurable) — skip
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
|
|
771
|
+
idiotik._proxyInstalled = true;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
// ----------------------------------------------------------------
|
|
775
|
+
// BOOT SEQUENCE
|
|
776
|
+
// ----------------------------------------------------------------
|
|
777
|
+
_waitForIdiotik(_boot);
|
|
778
|
+
|
|
779
|
+
}(typeof window !== "undefined" ? window : (typeof global !== "undefined" ? global : this)));
|
package/package.json
ADDED
package/sw.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// ================================================================
|
|
2
|
+
// IDIOTIK SERVICE WORKER — v0.1
|
|
3
|
+
// Single file. Primary strategy: response rewrite.
|
|
4
|
+
// If primary intercept fails: blob respondWith fallback.
|
|
5
|
+
// Owns the VFS — serves .idiotik.js files as CDN-origin dependencies.
|
|
6
|
+
// ================================================================
|
|
7
|
+
|
|
8
|
+
"use strict";
|
|
9
|
+
|
|
10
|
+
// ----------------------------------------------------------------
|
|
11
|
+
// STATE
|
|
12
|
+
// ----------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
// in-memory VFS — path → auto-wrapped source
|
|
15
|
+
const VFS = new Map();
|
|
16
|
+
|
|
17
|
+
// which CDN hosts we intercept library requests from
|
|
18
|
+
const CDN_ORIGINS = [
|
|
19
|
+
"cdnjs.cloudflare.com",
|
|
20
|
+
"unpkg.com",
|
|
21
|
+
"cdn.jsdelivr.net",
|
|
22
|
+
"ajax.googleapis.com",
|
|
23
|
+
"raw.githubusercontent.com",
|
|
24
|
+
"gist.githubusercontent.com",
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
// idiotik wrapper injected into every intercepted library source
|
|
28
|
+
// this is appended after the library source — registers it into window.idiotik.methods
|
|
29
|
+
const IDIOTIK_WRAPPER_TEMPLATE = (key) => `
|
|
30
|
+
;(function(){
|
|
31
|
+
try {
|
|
32
|
+
if (typeof self !== 'undefined' && self.__idiotikMethodsQueue) {
|
|
33
|
+
self.__idiotikMethodsQueue.push("${key}");
|
|
34
|
+
}
|
|
35
|
+
if (typeof window !== 'undefined' && window.idiotik) {
|
|
36
|
+
window.idiotik.methods = window.idiotik.methods || {};
|
|
37
|
+
// the actual global assignment happens in IdiotikMethods.js init()
|
|
38
|
+
// this wrapper just signals that the library executed inside our context
|
|
39
|
+
window.idiotik.__swWrapped = window.idiotik.__swWrapped || [];
|
|
40
|
+
window.idiotik.__swWrapped.push("${key}");
|
|
41
|
+
}
|
|
42
|
+
} catch(e) {}
|
|
43
|
+
})();
|
|
44
|
+
`;
|
|
45
|
+
|
|
46
|
+
// ----------------------------------------------------------------
|
|
47
|
+
// INSTALL + ACTIVATE — take control immediately
|
|
48
|
+
// ----------------------------------------------------------------
|
|
49
|
+
|
|
50
|
+
self.addEventListener("install", (event) => {
|
|
51
|
+
event.waitUntil(self.skipWaiting());
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
self.addEventListener("activate", (event) => {
|
|
55
|
+
event.waitUntil(self.clients.claim());
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// ----------------------------------------------------------------
|
|
59
|
+
// MESSAGE — receive VFS sync from IdiotikMethods.js
|
|
60
|
+
// ----------------------------------------------------------------
|
|
61
|
+
|
|
62
|
+
self.addEventListener("message", (event) => {
|
|
63
|
+
const data = event.data;
|
|
64
|
+
if (!data || !data.type) return;
|
|
65
|
+
|
|
66
|
+
if (data.type === "IDIOTIK_VFS_SYNC") {
|
|
67
|
+
// populate VFS from the main thread's idiotik.script.vfs
|
|
68
|
+
if (Array.isArray(data.vfs)) {
|
|
69
|
+
for (const entry of data.vfs) {
|
|
70
|
+
if (entry.path && entry.source) {
|
|
71
|
+
VFS.set(entry.path, entry.source);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// acknowledge
|
|
76
|
+
if (event.source) {
|
|
77
|
+
event.source.postMessage({ type: "IDIOTIK_VFS_ACK", count: VFS.size });
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (data.type === "IDIOTIK_VFS_SET") {
|
|
83
|
+
// single entry upsert
|
|
84
|
+
if (data.path && data.source) {
|
|
85
|
+
VFS.set(data.path, data.source);
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (data.type === "IDIOTIK_VFS_DELETE") {
|
|
91
|
+
if (data.path) VFS.delete(data.path);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (data.type === "IDIOTIK_VFS_CLEAR") {
|
|
96
|
+
VFS.clear();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// ----------------------------------------------------------------
|
|
102
|
+
// FETCH — main intercept logic
|
|
103
|
+
// Strategy A (primary): fetch real source, inject wrapper, respond
|
|
104
|
+
// Strategy B (fallback): blob URL respondWith
|
|
105
|
+
// ----------------------------------------------------------------
|
|
106
|
+
|
|
107
|
+
self.addEventListener("fetch", (event) => {
|
|
108
|
+
const url = new URL(event.request.url);
|
|
109
|
+
|
|
110
|
+
// ── VFS lookup — serve .idiotik.js files as if CDN-origin ──
|
|
111
|
+
// check VFS by full URL and by pathname
|
|
112
|
+
if (VFS.has(event.request.url) || VFS.has(url.pathname)) {
|
|
113
|
+
const source = VFS.get(event.request.url) || VFS.get(url.pathname);
|
|
114
|
+
event.respondWith(_serveFromVfs(source, event.request.url));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// check if this is a .idiotik.js file served from a CDN path that matches VFS
|
|
119
|
+
if (url.pathname.endsWith(".idiotik.js")) {
|
|
120
|
+
// try VFS by filename
|
|
121
|
+
const filename = url.pathname.split("/").pop();
|
|
122
|
+
for (const [vfsPath, source] of VFS.entries()) {
|
|
123
|
+
if (vfsPath.endsWith(filename) || vfsPath.includes(filename)) {
|
|
124
|
+
event.respondWith(_serveFromVfs(source, event.request.url));
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ── CDN library interception ────────────────────────────────
|
|
131
|
+
if (_isCdnRequest(url)) {
|
|
132
|
+
event.respondWith(_interceptCdnRequest(event.request, url));
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// everything else — pass through untouched
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// ----------------------------------------------------------------
|
|
140
|
+
// VFS SERVER — serve auto-wrapped .idiotik.js as valid JS
|
|
141
|
+
// The browser believes this is a real CDN-origin file.
|
|
142
|
+
// ----------------------------------------------------------------
|
|
143
|
+
|
|
144
|
+
function _serveFromVfs(source, originalUrl) {
|
|
145
|
+
const headers = new Headers({
|
|
146
|
+
"Content-Type": "application/javascript; charset=utf-8",
|
|
147
|
+
"Cache-Control": "no-store",
|
|
148
|
+
"X-Idiotik-VFS": "true",
|
|
149
|
+
});
|
|
150
|
+
return new Response(source, { status: 200, headers });
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ----------------------------------------------------------------
|
|
154
|
+
// CDN INTERCEPT — primary strategy: response rewrite
|
|
155
|
+
// Fetches real source, injects idiotik wrapper, serves modified response.
|
|
156
|
+
// Trust fully intact because library still originates from real CDN.
|
|
157
|
+
// ----------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
async function _interceptCdnRequest(request, url) {
|
|
160
|
+
// derive a library key from the URL
|
|
161
|
+
const libKey = _keyFromUrl(url);
|
|
162
|
+
|
|
163
|
+
// ── PRIMARY: response rewrite ────────────────────────────────
|
|
164
|
+
try {
|
|
165
|
+
const realResponse = await fetch(request.url, {
|
|
166
|
+
cache: "force-cache",
|
|
167
|
+
credentials: "omit",
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
if (!realResponse.ok) throw new Error(`CDN responded ${realResponse.status}`);
|
|
171
|
+
|
|
172
|
+
const originalSource = await realResponse.text();
|
|
173
|
+
|
|
174
|
+
// inject wrapper at end of library source
|
|
175
|
+
const patchedSource = originalSource + "\n" + IDIOTIK_WRAPPER_TEMPLATE(libKey);
|
|
176
|
+
|
|
177
|
+
const headers = new Headers(realResponse.headers);
|
|
178
|
+
headers.set("Content-Type", "application/javascript; charset=utf-8");
|
|
179
|
+
headers.set("X-Idiotik-Wrapped", libKey);
|
|
180
|
+
|
|
181
|
+
return new Response(patchedSource, {
|
|
182
|
+
status: realResponse.status,
|
|
183
|
+
statusText: realResponse.statusText,
|
|
184
|
+
headers,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
} catch (primaryErr) {
|
|
188
|
+
// ── FALLBACK: blob respondWith ───────────────────────────
|
|
189
|
+
// Different internal strategy — clone into blob, attach wrapper in blob context
|
|
190
|
+
try {
|
|
191
|
+
return await _blobFallbackStrategy(request, url, libKey);
|
|
192
|
+
} catch (fallbackErr) {
|
|
193
|
+
// both failed — pass through unmodified
|
|
194
|
+
console.warn(`[IdiotikSW] both strategies failed for ${url.href}:`, fallbackErr.message);
|
|
195
|
+
return fetch(request);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ----------------------------------------------------------------
|
|
201
|
+
// FALLBACK STRATEGY — blob respondWith
|
|
202
|
+
// Fetches real source, clones into blob URL, attaches wrapper hooks.
|
|
203
|
+
// Different internal path — may succeed where response rewrite was blocked.
|
|
204
|
+
// ----------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
async function _blobFallbackStrategy(request, url, libKey) {
|
|
207
|
+
const realResponse = await fetch(request.url, {
|
|
208
|
+
cache: "force-cache",
|
|
209
|
+
credentials: "omit",
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
if (!realResponse.ok) throw new Error(`CDN blob fallback: ${realResponse.status}`);
|
|
213
|
+
|
|
214
|
+
const originalSource = await realResponse.text();
|
|
215
|
+
const patchedSource = originalSource + "\n" + IDIOTIK_WRAPPER_TEMPLATE(libKey);
|
|
216
|
+
|
|
217
|
+
// create a blob with correct JS MIME type
|
|
218
|
+
const blob = new Blob([patchedSource], { type: "application/javascript" });
|
|
219
|
+
|
|
220
|
+
// serve from blob — browser receives a valid JS response with wrapper baked in
|
|
221
|
+
const headers = new Headers();
|
|
222
|
+
headers.set("Content-Type", "application/javascript; charset=utf-8");
|
|
223
|
+
headers.set("X-Idiotik-BlobWrapped", libKey);
|
|
224
|
+
|
|
225
|
+
return new Response(blob, {
|
|
226
|
+
status: 200,
|
|
227
|
+
headers,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// ----------------------------------------------------------------
|
|
232
|
+
// HELPERS
|
|
233
|
+
// ----------------------------------------------------------------
|
|
234
|
+
|
|
235
|
+
function _isCdnRequest(url) {
|
|
236
|
+
return CDN_ORIGINS.some((origin) => url.hostname === origin || url.hostname.endsWith("." + origin));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function _keyFromUrl(url) {
|
|
240
|
+
// derive a short stable key from the CDN URL
|
|
241
|
+
// e.g. cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js → hammer
|
|
242
|
+
const path = url.pathname.toLowerCase();
|
|
243
|
+
|
|
244
|
+
// try /ajax/libs/LIBNAME/... (cdnjs)
|
|
245
|
+
const cdnjsMatch = path.match(/\/ajax\/libs\/([^/]+)/);
|
|
246
|
+
if (cdnjsMatch) {
|
|
247
|
+
return _sanitizeKey(cdnjsMatch[1]);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// try unpkg / jsdelivr: /LIBNAME@version or /LIBNAME/...
|
|
251
|
+
const unpkgMatch = path.match(/^\/(?:npm\/)?(@[^/]+\/[^/@]+|[^/@]+)/);
|
|
252
|
+
if (unpkgMatch) {
|
|
253
|
+
return _sanitizeKey(unpkgMatch[1]);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// fallback — use hostname + first path segment
|
|
257
|
+
const parts = path.split("/").filter(Boolean);
|
|
258
|
+
return _sanitizeKey(parts[0] || "unknown");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function _sanitizeKey(raw) {
|
|
262
|
+
return raw
|
|
263
|
+
.replace(/[@.]/g, "_")
|
|
264
|
+
.replace(/[^a-z0-9_]/g, "")
|
|
265
|
+
.replace(/^_+|_+$/g, "")
|
|
266
|
+
.slice(0, 32);
|
|
267
|
+
}
|