@environment-safe/file 0.0.1

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/dist/index.cjs ADDED
@@ -0,0 +1,599 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.save = exports.remove = exports.pathJoin = exports.load = exports.listFiles = exports.list = exports.info = exports.handle = exports.fileBody = exports.exists = exports.File = void 0;
7
+ var _browserOrNode = require("browser-or-node");
8
+ var _buffer = require("./buffer.cjs");
9
+ var fs = _interopRequireWildcard(require("fs"));
10
+ var path = _interopRequireWildcard(require("path"));
11
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
12
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
13
+ /*
14
+ import { isBrowser, isJsDom } from 'browser-or-node';
15
+ import * as mod from 'module';
16
+ import * as path from 'path';
17
+ let internalRequire = null;
18
+ if(typeof require !== 'undefined') internalRequire = require;
19
+ const ensureRequire = ()=> (!internalRequire) && (internalRequire = mod.createRequire(import.meta.url));
20
+ //*/
21
+
22
+ /**
23
+ * A JSON object
24
+ * @typedef { object } JSON
25
+ */
26
+
27
+ const inputQueue = [];
28
+ const attachInputGenerator = eventType => {
29
+ const handler = event => {
30
+ if (inputQueue.length) {
31
+ const input = inputQueue.shift();
32
+ try {
33
+ input.handler(event, input.resolve, input.reject);
34
+ } catch (ex) {
35
+ inputQueue.unshift(input);
36
+ }
37
+ }
38
+ };
39
+ window.addEventListener('load', event => {
40
+ document.body.addEventListener(eventType, handler, false);
41
+ });
42
+ //document.body.addEventListener(eventType, handler, false);
43
+ };
44
+
45
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
46
+ attachInputGenerator('mousedown');
47
+ // mousemove is cleanest, but seems unreliable
48
+ // attachInputGenerator('mousemove');
49
+ }
50
+
51
+ const wantInput = async (id, handler, cache) => {
52
+ const promise = new Promise((resolve, reject) => {
53
+ inputQueue.push({
54
+ resolve,
55
+ reject,
56
+ handler
57
+ });
58
+ });
59
+ const input = await promise;
60
+ return await input;
61
+ };
62
+ const getFilePickerOptions = (name, path) => {
63
+ let suffix = name.split('.').pop();
64
+ if (suffix.length > 6) suffix = '';
65
+ const options = {
66
+ suggestedName: name
67
+ };
68
+ if (path) options.startIn = path;
69
+ if (suffix) {
70
+ const accept = {};
71
+ accept[mimesBySuffix[suffix]] = '.' + suffix;
72
+ options.types = [{
73
+ description: suffix,
74
+ accept
75
+ }];
76
+ options.excludeAcceptAllOption = true;
77
+ }
78
+ return options;
79
+ };
80
+ const makeLocation = (path, dir) => {
81
+ if (dir && dir[0] === '.') {
82
+ if (dir[1] === '.') {
83
+ if (dir[2] === '/' && dir[3]) {
84
+ return pathJoin(File.directory.current, '..', dir.substring(3), path);
85
+ } else {
86
+ if (dir[2]) {
87
+ return pathJoin(File.directory.current, '..', dir.substring(3), path);
88
+ } else {
89
+ return pathJoin(File.directory.current, '..', path);
90
+ }
91
+ }
92
+ } else {
93
+ if (dir[1] === '/') {
94
+ return pathJoin(File.directory.current, dir.substring(2), path);
95
+ } else {
96
+ if (dir[1]) {
97
+ return pathJoin(File.directory.current, dir, path);
98
+ } else {
99
+ return pathJoin(File.directory.current, path);
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return dir ? handleCanonicalPath(dir, File.os, File.user) + '/' + path : path;
105
+ };
106
+ const save = async (name, dir, buffer, meta = {}) => {
107
+ const location = makeLocation(name, dir);
108
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
109
+ const options = getFilePickerOptions(name, dir);
110
+ const newHandle = await wantInput(location, (event, resolve, reject) => {
111
+ try {
112
+ window.showSaveFilePicker(options).then(thisHandle => {
113
+ resolve(thisHandle);
114
+ }).catch(ex => {
115
+ reject(ex);
116
+ });
117
+ } catch (ex) {
118
+ reject(ex);
119
+ }
120
+ }, meta.cache);
121
+ const writableStream = await newHandle.createWritable();
122
+ // write our file
123
+ await writableStream.write(buffer);
124
+ // close the file and write the contents to disk.
125
+ await writableStream.close();
126
+ } else {
127
+ return await new Promise((resolve, reject) => {
128
+ fs.writeFile(location, buffer, err => {
129
+ if (err) return reject(err);
130
+ resolve();
131
+ });
132
+ });
133
+ }
134
+ };
135
+ exports.save = save;
136
+ const mimesBySuffix = {
137
+ json: 'application/json',
138
+ jpg: 'image/jpeg',
139
+ jpeg: 'image/jpeg',
140
+ gif: 'image/gif',
141
+ png: 'image/png',
142
+ svg: 'image/sxg+xml',
143
+ webp: 'image/webp',
144
+ csv: 'text/csv',
145
+ tsv: 'text/tsv',
146
+ ssv: 'text/ssv',
147
+ js: 'text/javascript',
148
+ mjs: 'text/javascript',
149
+ cjs: 'text/javascript',
150
+ css: 'text/css'
151
+ };
152
+ const pathJoin = (...parts) => {
153
+ //returns buffer, eventually stream
154
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
155
+ return parts.join('/');
156
+ } else {
157
+ return path.join.apply(path, parts);
158
+ }
159
+ };
160
+
161
+ //todo: should I remove export (no one should use this)?
162
+ exports.pathJoin = pathJoin;
163
+ const fileBody = async (path, dir, baseDir, allowRedirect, forceReturn) => {
164
+ try {
165
+ //let location = dir?dir+ '/' + path:path; //todo: looser handling
166
+ let location = makeLocation(path, dir);
167
+ if (canonicalLocationToPath['darwin'][dir]) {
168
+ if (baseDir) {
169
+ throw new Error('custom directories unsupported');
170
+ } else {
171
+ location = 'file://' + handleCanonicalPath(dir, File.os, File.user) + '/' + path;
172
+ }
173
+ }
174
+ const response = await fetch(location);
175
+ const text = await response.text();
176
+ if (!(response.ok || allowRedirect && response.redirected || forceReturn)) {
177
+ return null;
178
+ }
179
+ return text;
180
+ } catch (ex) {
181
+ //console.log(location, ex);
182
+ return null;
183
+ }
184
+ };
185
+ exports.fileBody = fileBody;
186
+ const handle = async (path, dir, writable, cache = {}) => {
187
+ //returns buffer, eventually stream
188
+ let suffix = path.split('.').pop();
189
+ if (suffix.length > 6) suffix = '';
190
+ const location = makeLocation(path, dir);
191
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
192
+ if (cache && cache[path]) return cache[path];
193
+ const options = getFilePickerOptions(path);
194
+ try {
195
+ const response = await fileBody(path, dir);
196
+ if (response === null) throw new Error('File not found');
197
+ } catch (ex) {
198
+ const newHandle = await wantInput(location, (event, resolve, reject) => {
199
+ try {
200
+ window.showSaveFilePicker(options).then(thisHandle => {
201
+ resolve(thisHandle);
202
+ }).catch(ex => {
203
+ reject(ex);
204
+ });
205
+ } catch (ex) {
206
+ reject(ex);
207
+ }
208
+ });
209
+ return newHandle;
210
+ }
211
+ const fileHandle = await wantInput(location, (event, resolve, reject) => {
212
+ try {
213
+ window.showOpenFilePicker(options).then(([handle]) => {
214
+ resolve(handle);
215
+ }).catch(ex => {
216
+ reject(ex);
217
+ });
218
+ } catch (ex) {
219
+ reject(ex);
220
+ }
221
+ }, cache);
222
+ // eslint-disable-next-line no-undef
223
+ if (cache) cache[location] = fileHandle;
224
+ // eslint-disable-next-line no-undef
225
+ return fileHandle;
226
+ } else {
227
+ // todo: impl
228
+ }
229
+ };
230
+ exports.handle = handle;
231
+ const load = async (path, dir, cache) => {
232
+ //returns buffer, eventually stream
233
+ const location = makeLocation(path, dir);
234
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
235
+ try {
236
+ const response = await fetch(location);
237
+ if (!response) {
238
+ return new ArrayBuffer();
239
+ }
240
+ const buffer = await response.arrayBuffer();
241
+ buffer;
242
+ return buffer;
243
+ } catch (ex) {
244
+ return new ArrayBuffer();
245
+ }
246
+ } else {
247
+ return await new Promise((resolve, reject) => {
248
+ fs.readFile(location, (err, body) => {
249
+ if (err) return reject(err);
250
+ resolve(body);
251
+ });
252
+ });
253
+ }
254
+ };
255
+ exports.load = load;
256
+ const exists = async (path, dir, cache, incomingHandle) => {
257
+ //returns buffer, eventually stream
258
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
259
+ if (incomingHandle) {
260
+ const fileHandle = incomingHandle;
261
+ const file = await fileHandle.getFile();
262
+ const buffer = await file.arrayBuffer();
263
+ return !!buffer;
264
+ } else {
265
+ const body = await fileBody(path, dir);
266
+ return body !== null;
267
+ }
268
+ } else {
269
+ return await new Promise((resolve, reject) => {
270
+ const location = makeLocation(path, dir);
271
+ fs.stat(location, (err, res) => {
272
+ if (err) resolve(false);
273
+ resolve(true);
274
+ });
275
+ });
276
+ }
277
+ };
278
+ exports.exists = exists;
279
+ const remove = async (path, dir, cache) => {
280
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
281
+ const fileHandle = await handle(path, dir, true, cache);
282
+ if (fileHandle.remove) fileHandle.remove(); //non-standard, but supported
283
+ } else {
284
+ // todo: impl
285
+ }
286
+ };
287
+ exports.remove = remove;
288
+ const info = async (path, dir, cache) => {
289
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
290
+ // todo: impl
291
+ } else {
292
+ // todo: impl
293
+ }
294
+ };
295
+ exports.info = info;
296
+ const list = async (path, options = {}) => {
297
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
298
+ // todo: impl
299
+ switch (File.agent.name) {
300
+ case 'chrome':
301
+ {
302
+ const page = await fileBody('', path, null, null, true);
303
+ let rows = page && page.match(/<script>addRow\((.*)\);<\/script>/g) || [];
304
+ rows = rows.map(row => {
305
+ return row.match(/<script>addRow\((.*)\);<\/script>/)[1];
306
+ });
307
+ const jsonData = `[[${rows.join('], [')}]]`;
308
+ const data = JSON.parse(jsonData);
309
+ let results = data.map(meta => {
310
+ return {
311
+ name: meta[0],
312
+ isFile: () => {
313
+ return !!meta[2];
314
+ }
315
+ };
316
+ });
317
+ if (Object.keys(options).length) {
318
+ if (options.files === false) {
319
+ results = results.filter(file => {
320
+ return !file.isFile();
321
+ });
322
+ }
323
+ if (options.directories === false) {
324
+ results = results.filter(file => {
325
+ return file.isFile();
326
+ });
327
+ }
328
+ if (!options.hidden) {
329
+ results = results.filter(file => {
330
+ return file !== '.' && file !== '..';
331
+ });
332
+ }
333
+ }
334
+ return results.map(file => {
335
+ return file.name;
336
+ });
337
+ //TODO: apache fallback
338
+ //break;
339
+ }
340
+
341
+ default:
342
+ throw new Error(`Usupported Browser: ${File.os}`);
343
+ }
344
+ } else {
345
+ //todo: platform safe separator
346
+ const target = path.indexOf('/') === -1 ? makeLocation('', path) : path;
347
+ return await new Promise((resolve, reject) => {
348
+ fs.readdir(target, {
349
+ withFileTypes: true
350
+ }, (err, files) => {
351
+ if (err) return reject(err);
352
+ let results = files;
353
+ if (Object.keys(options).length) {
354
+ if (options.files === false) {
355
+ results = results.filter(file => {
356
+ return !file.isFile();
357
+ });
358
+ }
359
+ if (options.directories === false) {
360
+ results = results.filter(file => {
361
+ return file.isFile();
362
+ });
363
+ }
364
+ if (!options.hidden) {
365
+ results = results.filter(file => {
366
+ return file !== '.' && file !== '..';
367
+ });
368
+ }
369
+ }
370
+ resolve(results.map(file => {
371
+ return file.name;
372
+ }));
373
+ });
374
+ });
375
+ }
376
+ };
377
+ exports.list = list;
378
+ const internalCache = {};
379
+ const listFiles = path => {
380
+ return list(path).map(src => {
381
+ const url = src.indexOf('://') !== -1 ? src : `file://${src}`;
382
+ return new File(url);
383
+ });
384
+ };
385
+ exports.listFiles = listFiles;
386
+ class File {
387
+ constructor(path, options = {}) {
388
+ //todo: clean this rats nest up
389
+ const location = (path && path[0] === '/' ? `file:${path}` : path) || !path && options.directory && handleCanonicalPath(options.directory, File.os, File.user) || '/tmp/' + Math.floor(Math.random() * 10000);
390
+ if (options.cache === true) options.cache = internalCache;
391
+ this.options = options;
392
+ //one of: desktop, documents, downloads, music, pictures, videos
393
+ this.directory = options.directory || '.';
394
+ this.path = location;
395
+ this.buffer = new _buffer.FileBuffer();
396
+ }
397
+ async save() {
398
+ await save(this.path, this.directory, this.buffer, this.options);
399
+ return this;
400
+ }
401
+ async load() {
402
+ const dir = this.path.indexOf('/') === -1 ? this.directory : '';
403
+ this.buffer = await load(this.path, dir, this.options);
404
+ this.buffer.cast = type => {
405
+ return _buffer.FileBuffer.to(type, this.buffer);
406
+ };
407
+ return this;
408
+ }
409
+ body(value) {
410
+ if (value === null || value === undefined) return this.buffer;
411
+ this.buffer = _buffer.FileBuffer.from(value);
412
+ this.buffer.cast = type => {
413
+ return _buffer.FileBuffer.to(type, this.buffer);
414
+ };
415
+ if (value) return this;
416
+ return this.buffer;
417
+ }
418
+ async info() {
419
+ return await info(this.path, this.directory);
420
+ }
421
+ async 'delete'() {
422
+ await remove(this.path, this.directory, this.options);
423
+ return this;
424
+ }
425
+ static exists(path, directory) {
426
+ return exists(path, directory);
427
+ }
428
+ static list(path, options) {
429
+ return list(path, options);
430
+ }
431
+ }
432
+ exports.File = File;
433
+ let user = '';
434
+ Object.defineProperty(File, 'user', {
435
+ get() {
436
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
437
+ return user || 'khrome'; //todo: something real;
438
+ } else {
439
+ return user || 'khrome'; //todo: something real;
440
+ }
441
+ },
442
+
443
+ set(newValue) {
444
+ user = newValue;
445
+ },
446
+ enumerable: true,
447
+ configurable: true
448
+ });
449
+ Object.defineProperty(File, 'os', {
450
+ get() {
451
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
452
+ return 'darwin'; //todo: something real;
453
+ } else {
454
+ return 'darwin';
455
+ }
456
+ },
457
+ set(newValue) {
458
+ //do nothing
459
+ },
460
+ enumerable: true,
461
+ configurable: true
462
+ });
463
+ const canonicalLocationToPath = {
464
+ darwin: {
465
+ 'desktop': '~/Desktop',
466
+ 'documents': '~/Documents',
467
+ 'downloads': '~/Downloads',
468
+ 'music': '~/Music',
469
+ 'pictures': '~/Pictures',
470
+ 'home': '~/Pictures',
471
+ 'videos': '~/Movies'
472
+ },
473
+ win: {},
474
+ linux: {}
475
+ };
476
+ const osToHome = {
477
+ darwin: '/Users/${user}',
478
+ win: 'C:/',
479
+ linux: '/Users/${user}'
480
+ };
481
+
482
+ /*const handlePath = (path, os, username)=>{
483
+ return path.replace('~', osToHome[os].replace('${user}', username));
484
+ };*/
485
+
486
+ const handleCanonicalPath = (name, os, username) => {
487
+ const path = canonicalLocationToPath[os][name];
488
+ return path.replace('~', osToHome[os].replace('${user}', username));
489
+ };
490
+ File.directory = {};
491
+ Object.defineProperty(File.directory, 'current', {
492
+ get() {
493
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
494
+ const base = document.getElementsByTagName('base')[0];
495
+ let basedir = null;
496
+ if (base && (basedir = base.getAttribute('href'))) {
497
+ return basedir;
498
+ } else {
499
+ let path = window.location.pathname;
500
+ path = path.split('/');
501
+ path.pop(); // drop the top one
502
+ return path.join('/');
503
+ }
504
+ } else {
505
+ return process.cwd();
506
+ }
507
+ },
508
+ set(newValue) {
509
+ //do nothing
510
+ },
511
+ enumerable: true,
512
+ configurable: true
513
+ });
514
+ Object.defineProperty(File, 'agent', {
515
+ get() {
516
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
517
+ //var nVer = navigator.appVersion;
518
+ var nAgt = navigator.userAgent;
519
+ var browserName = navigator.appName;
520
+ var fullVersion = '' + parseFloat(navigator.appVersion);
521
+ var majorVersion = parseInt(navigator.appVersion, 10);
522
+ var nameOffset, verOffset, ix;
523
+
524
+ // In Opera, the true version is after "Opera" or after "Version"
525
+ if ((verOffset = nAgt.indexOf('Opera')) != -1) {
526
+ browserName = 'Opera';
527
+ fullVersion = nAgt.substring(verOffset + 6);
528
+ if ((verOffset = nAgt.indexOf('Version')) != -1) fullVersion = nAgt.substring(verOffset + 8);
529
+ }
530
+ // In MSIE, the true version is after 'MSIE' in userAgent
531
+ else if ((verOffset = nAgt.indexOf('MSIE')) != -1) {
532
+ browserName = 'Microsoft Internet Explorer';
533
+ fullVersion = nAgt.substring(verOffset + 5);
534
+ }
535
+ // In Chrome, the true version is after 'Chrome'
536
+ else if ((verOffset = nAgt.indexOf('Chrome')) != -1) {
537
+ browserName = 'Chrome';
538
+ fullVersion = nAgt.substring(verOffset + 7);
539
+ }
540
+ // In Safari, the true version is after 'Safari' or after 'Version'
541
+ else if ((verOffset = nAgt.indexOf('Safari')) != -1) {
542
+ browserName = 'Safari';
543
+ fullVersion = nAgt.substring(verOffset + 7);
544
+ if ((verOffset = nAgt.indexOf('Version')) != -1) fullVersion = nAgt.substring(verOffset + 8);
545
+ }
546
+ // In Firefox, the true version is after 'Firefox'
547
+ else if ((verOffset = nAgt.indexOf('Firefox')) != -1) {
548
+ browserName = 'Firefox';
549
+ fullVersion = nAgt.substring(verOffset + 8);
550
+ }
551
+ // In most other browsers, 'name/version' is at the end of userAgent
552
+ else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) {
553
+ browserName = nAgt.substring(nameOffset, verOffset);
554
+ fullVersion = nAgt.substring(verOffset + 1);
555
+ if (browserName.toLowerCase() == browserName.toUpperCase()) {
556
+ browserName = navigator.appName;
557
+ }
558
+ }
559
+ // trim the fullVersion string at semicolon/space if present
560
+ if ((ix = fullVersion.indexOf(';')) != -1) fullVersion = fullVersion.substring(0, ix);
561
+ if ((ix = fullVersion.indexOf(' ')) != -1) fullVersion = fullVersion.substring(0, ix);
562
+ majorVersion = parseInt('' + fullVersion, 10);
563
+ if (isNaN(majorVersion)) {
564
+ fullVersion = '' + parseFloat(navigator.appVersion);
565
+ majorVersion = parseInt(navigator.appVersion, 10);
566
+ }
567
+ return {
568
+ name: browserName.toLowerCase(),
569
+ version: fullVersion,
570
+ major: majorVersion
571
+ };
572
+ } else {
573
+ return {};
574
+ }
575
+ },
576
+ set(newValue) {
577
+ //do nothing
578
+ },
579
+ enumerable: true,
580
+ configurable: true
581
+ });
582
+ const directoryGet = type => {
583
+ if (_browserOrNode.isBrowser || _browserOrNode.isJsDom) {
584
+ return handleCanonicalPath('home', File.os, File.user);
585
+ } else {
586
+ return process.cwd();
587
+ }
588
+ };
589
+ Object.keys(canonicalLocationToPath['darwin']).forEach(key => {
590
+ // register all available keys
591
+ Object.defineProperty(File.directory, key, {
592
+ enumerable: true,
593
+ configurable: true,
594
+ get() {
595
+ return directoryGet(key);
596
+ },
597
+ set(newValue) {}
598
+ });
599
+ });
package/index.html ADDED
@@ -0,0 +1,74 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <link rel="icon" href="/favicon.ico">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>Loading...</title>
8
+ <style>
9
+ body{
10
+ padding: 0px;
11
+ margin: 0px;
12
+ width:100%;
13
+ height: 100%;
14
+ overflow: hidden;
15
+ }
16
+ #forkme{
17
+ position: absolute;
18
+ top: 0px;
19
+ right: 0px;
20
+ display: block;
21
+ }
22
+ </style>
23
+ <script type="importmap">{ "imports" :{
24
+ "browser-or-node":"https://unpkg.com/browser-or-node@2.1.1/src/index.js",
25
+ "@environment-safe/package" : "https://unpkg.com/@environment-safe/package@0.1.3/src/index.mjs",
26
+ "module": "https://unpkg.com/browser-or-node@2.1.1/src/index.js",
27
+ "node:events": "https://unpkg.com/extended-emitter@1.3.2/node-events.mjs",
28
+ "path": "https://unpkg.com/browser-or-node@2.1.1/src/index.js"
29
+ }}</script>
30
+ <script
31
+ type="module"
32
+ src="https://cdn.jsdelivr.net/gh/zerodevx/zero-md@2/dist/zero-md.min.js"
33
+ ></script>
34
+ <script type="module">
35
+ import { getPackage } from '@environment-safe/package';
36
+ const pkgReady = getPackage();
37
+ const ready = Promise.all([
38
+ pkgReady,
39
+ new Promise((resolve)=>{
40
+ window.pkgDone = resolve;
41
+ })
42
+ ]);
43
+ const getUrl = (repository)=>{
44
+ if(repository.url && repository.url.indexOf('://') !==-1) return repository.url;
45
+ if(repository.url){
46
+ if(repository.url.indexOf('git@') === 0){
47
+ const parts = repository.url.substring(4).split(':');
48
+ if(parts[1].indexOf('.git') !== -1){
49
+ parts[1] = parts[1].substring(0, parts[1].length-4);
50
+ }
51
+ switch(parts[0]){
52
+ case 'github.com' : return `https://github.com/${parts[1]}`;
53
+ default: throw new Error(`Unknown source`);
54
+ }
55
+ console.log(parts);
56
+ }
57
+ }
58
+ }
59
+ const pkg = await pkgReady;
60
+ window.pkg = pkg;
61
+ console.log(pkg);
62
+ await ready;
63
+ document.title = pkg.name;
64
+ document.write(`<a style="position: absolute; top: 0px; right: 0px; display: block;" id="forkme" href="${getUrl(pkg.repository)}" class="ribbon"><img decoding="async" loading="lazy" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" alt="Fork me on GitHub" data-recalc-dims="1"></a>`)
65
+ document.write(`<h1>${pkg.name}@${pkg.version}</h1>`);
66
+ document.write(`<table><tr>`);
67
+ document.write(`<td><a href="docs/">Documentation</a><a href="test/">Tests</a></td>`);
68
+ document.write(`</tr></table>`);
69
+ document.write(`<p>${pkg.description}</p>`);
70
+ document.write(`<zero-md src="README.md"></zero-md>`)
71
+ </script>
72
+ </head>
73
+ <body onload="window.pkgDone()"></body>
74
+ </html>