arcadible 0.1.4 → 0.1.6

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/src/util/dom.js CHANGED
@@ -7,12 +7,12 @@ const jsdom = require("jsdom");
7
7
 
8
8
  // [use]
9
9
 
10
- const DOM = jsdom.JSDOM;
10
+ const JSDOM = jsdom.JSDOM;
11
11
 
12
12
  // [function]
13
13
 
14
14
  const sanitize = function (str, cfg) {
15
- const dom = dompurify(new DOM().window);
15
+ const dom = dompurify(new JSDOM().window);
16
16
  if (cfg) {
17
17
  return dom.sanitize(str, {
18
18
  ALLOWED_ATTR: cfg.ALLOWED_ATTR,
@@ -24,4 +24,4 @@ const sanitize = function (str, cfg) {
24
24
 
25
25
  // [export]
26
26
 
27
- module.exports = { DOM, sanitize };
27
+ module.exports = { DOM: JSDOM, sanitize };
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const fs = require("fs-extra");
6
+ const imageSize = require("image-size").imageSize;
7
+
8
+ // [use]
9
+
10
+ const readFileSync = fs.readFileSync; // eslint-disable-line no-sync
11
+ const statSync = fs.statSync; // eslint-disable-line no-sync
12
+
13
+ // [function]
14
+
15
+ const checkAspect = function (width, height, aspect) {
16
+ if (!aspect) {
17
+ return true;
18
+ }
19
+ const parts = aspect.split(":");
20
+ if (parts.length !== 2) {
21
+ return false;
22
+ }
23
+ const aspectWidth = Number(parts[0]);
24
+ const aspectHeight = Number(parts[1]);
25
+ if (!aspectWidth || !aspectHeight) {
26
+ return false;
27
+ }
28
+ return width * aspectHeight === height * aspectWidth;
29
+ };
30
+
31
+ // [function]
32
+
33
+ const checkSize = function (file, maxSize) {
34
+ if (!maxSize) {
35
+ return true;
36
+ }
37
+ return statSync(file).size <= maxSize;
38
+ };
39
+
40
+ // [function]
41
+
42
+ const checkPng = function (file, { aspect, maxSize, minHeight, minWidth }) {
43
+ if (!checkSize(file, maxSize)) {
44
+ return false;
45
+ }
46
+ const buffer = readFileSync(file);
47
+ const { height, width } = imageSize(buffer);
48
+ if (minWidth && width < minWidth) {
49
+ return false;
50
+ }
51
+ if (minHeight && height < minHeight) {
52
+ return false;
53
+ }
54
+ if (!checkAspect(width, height, aspect)) {
55
+ return false;
56
+ }
57
+ return true;
58
+ };
59
+
60
+ // [function]
61
+
62
+ const checkSvg = function (file, { maxSize }) {
63
+ if (!checkSize(file, maxSize)) {
64
+ return false;
65
+ }
66
+ return true;
67
+ };
68
+
69
+ // [function]
70
+
71
+ const check = function (file, { type, ...opts }) {
72
+ switch (type) {
73
+ case "image/png":
74
+ return checkPng(file, opts);
75
+ case "image/svg+xml":
76
+ return checkSvg(file, opts);
77
+ default:
78
+ return false;
79
+ }
80
+ };
81
+
82
+ // [export]
83
+
84
+ module.exports = { check };
package/src/util/log.js CHANGED
@@ -73,25 +73,25 @@ const pdnl = function (message) {
73
73
  // [function]
74
74
 
75
75
  const hw = function (message) {
76
- log(console.log, message, { bold: true, color: "yellow" });
76
+ log(console.warn, message, { bold: true, color: "yellow" });
77
77
  };
78
78
 
79
79
  // [function]
80
80
 
81
81
  const hwnl = function (message) {
82
- log(console.log, message, { bold: true, color: "yellow", nl: true });
82
+ log(console.warn, message, { bold: true, color: "yellow", nl: true });
83
83
  };
84
84
 
85
85
  // [function]
86
86
 
87
87
  const pw = function (message) {
88
- log(console.log, message, { color: "yellow" });
88
+ log(console.warn, message, { color: "yellow" });
89
89
  };
90
90
 
91
91
  // [function]
92
92
 
93
93
  const pwnl = function (message) {
94
- log(console.log, message, { color: "yellow", nl: true });
94
+ log(console.warn, message, { color: "yellow", nl: true });
95
95
  };
96
96
 
97
97
  // [function]
package/src/util/objs.js CHANGED
@@ -6,33 +6,33 @@ const stringify = require("fast-json-stable-stringify");
6
6
 
7
7
  // [function]
8
8
 
9
- const compact = function (value) {
9
+ const deepCompact = function (obj) {
10
10
  /* eslint-disable no-undefined */
11
- if (value === null || value === undefined) {
11
+ if (obj === null || obj === undefined) {
12
12
  return undefined;
13
13
  }
14
- if (Array.isArray(value)) {
15
- const cleaned = value.map(compact).filter((v) => v !== undefined);
14
+ if (Array.isArray(obj)) {
15
+ const cleaned = obj.map(deepCompact).filter((v) => v !== undefined);
16
16
  return cleaned.length ? cleaned : undefined;
17
17
  }
18
- if (typeof value === "object") {
18
+ if (typeof obj === "object") {
19
19
  const cleaned = Object.fromEntries(
20
- Object.entries(value)
21
- .map(([k, v]) => [k, compact(v)])
20
+ Object.entries(obj)
21
+ .map(([k, v]) => [k, deepCompact(v)])
22
22
  .filter(([, v]) => v !== undefined),
23
23
  );
24
24
  return Object.keys(cleaned).length ? cleaned : undefined;
25
25
  }
26
- return value;
26
+ return obj;
27
27
  /* eslint-enable no-undefined */
28
28
  };
29
29
 
30
30
  // [function]
31
31
 
32
- const sort = function (value) {
33
- return JSON.parse(stringify(value));
32
+ const deepSort = function (obj) {
33
+ return JSON.parse(stringify(obj));
34
34
  };
35
35
 
36
36
  // [export]
37
37
 
38
- module.exports = { compact, sort };
38
+ module.exports = { deepCompact, deepSort };
@@ -10,7 +10,7 @@ const objs = require("./objs");
10
10
 
11
11
  // [use]
12
12
 
13
- const sortObjs = objs.sort;
13
+ const deepSort = objs.deepSort;
14
14
 
15
15
  // [function]
16
16
 
@@ -21,7 +21,7 @@ const write = function (data) {
21
21
  // [function]
22
22
 
23
23
  const printJson = function (data) {
24
- write(JSON.stringify(sortObjs(data), null, 2));
24
+ write(JSON.stringify(deepSort(data), null, 2));
25
25
  };
26
26
 
27
27
  // [function]
@@ -33,7 +33,7 @@ const printToml = function (data, key = "value") {
33
33
  return;
34
34
  }
35
35
  try {
36
- write(TOML.stringify(sortObjs(data)));
36
+ write(TOML.stringify(deepSort(data)));
37
37
  } catch (ex) {
38
38
  write(TOML.stringify({ [field]: data }));
39
39
  }
@@ -2,9 +2,9 @@
2
2
 
3
3
  // [function]
4
4
 
5
- const format = function (name, error) {
6
- return error.issues.map(
7
- (issue) => `${name}.${issue.path.join(".") || "value"}: ${issue.message}`,
5
+ const format = function (name, { issues }) {
6
+ return issues.map(
7
+ ({ message, path }) => `${name}.${path.join(".") || "value"}: ${message}`,
8
8
  );
9
9
  };
10
10
 
@@ -12,9 +12,9 @@ const format = function (name, error) {
12
12
 
13
13
  const validator = function (name, schema) {
14
14
  return (value, conf) => {
15
- const result = schema(value, conf).safeParse(value);
16
- if (!result.success) {
17
- return { issues: format(name, result.error) };
15
+ const { error, success } = schema(value, conf).safeParse(value);
16
+ if (!success) {
17
+ return { issues: format(name, error) };
18
18
  }
19
19
  return { issues: [] };
20
20
  };
package/src/util/strs.js CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  // [function]
4
4
 
5
+ const indentLines = function (strs, spaces = 2) {
6
+ const pad = " ".repeat(spaces);
7
+ return strs
8
+ .split("\n")
9
+ .map((str) => pad + str)
10
+ .join("\n");
11
+ };
12
+
13
+ // [function]
14
+
5
15
  const stripLeadingInvisible = function (str) {
6
16
  return String(str).replace(
7
17
  // eslint-disable-next-line no-misleading-character-class
@@ -18,4 +28,4 @@ const trimWhitespace = function (str) {
18
28
 
19
29
  // [export]
20
30
 
21
- module.exports = { stripLeadingInvisible, trimWhitespace };
31
+ module.exports = { indentLines, stripLeadingInvisible, trimWhitespace };
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+
3
+ // [import]
4
+
5
+ const createFile = require("mp4box").createFile;
6
+ const fs = require("fs-extra");
7
+
8
+ // [use]
9
+
10
+ const readFileSync = fs.readFileSync; // eslint-disable-line no-sync
11
+ const statSync = fs.statSync; // eslint-disable-line no-sync
12
+
13
+ // [function]
14
+
15
+ const checkAspect = function (width, height, aspect) {
16
+ if (!aspect) {
17
+ return true;
18
+ }
19
+ const parts = aspect.split(":");
20
+ if (parts.length !== 2) {
21
+ return false;
22
+ }
23
+ const aspectWidth = Number(parts[0]);
24
+ const aspectHeight = Number(parts[1]);
25
+ if (!aspectWidth || !aspectHeight) {
26
+ return false;
27
+ }
28
+ return width * aspectHeight === height * aspectWidth;
29
+ };
30
+
31
+ // [function]
32
+
33
+ const checkSize = function (file, maxSize) {
34
+ if (!maxSize) {
35
+ return true;
36
+ }
37
+ return statSync(file).size <= maxSize;
38
+ };
39
+
40
+ // [function]
41
+
42
+ const readMp4 = function (file) {
43
+ const data = readFileSync(file);
44
+ const mp4 = createFile();
45
+ let error = null;
46
+ let video = null;
47
+ mp4.onReady = function (info) {
48
+ const track = info.tracks.find((t) => t.video);
49
+ if (!track || !track.video) {
50
+ error = new Error("No video track found.");
51
+ return;
52
+ }
53
+ video = {
54
+ duration: info.duration / info.timescale,
55
+ height: track.video.height,
56
+ width: track.video.width,
57
+ };
58
+ };
59
+ mp4.onError = function (mod, msg) {
60
+ error = new Error(`MP4Box(${mod}): ${msg}`);
61
+ };
62
+ const buffer = data.buffer.slice(
63
+ data.byteOffset,
64
+ data.byteOffset + data.byteLength,
65
+ );
66
+ buffer.fileStart = 0;
67
+ mp4.appendBuffer(buffer);
68
+ mp4.flush();
69
+ if (error) {
70
+ throw error;
71
+ }
72
+ if (!video) {
73
+ throw new Error("MP4 metadata not available.");
74
+ }
75
+ return video;
76
+ };
77
+
78
+ // [function]
79
+
80
+ const checkMp4 = function (
81
+ file,
82
+ { aspect, maxDuration, maxSize, minHeight, minWidth },
83
+ ) {
84
+ if (!checkSize(file, maxSize)) {
85
+ return false;
86
+ }
87
+ let video = null;
88
+ try {
89
+ video = readMp4(file);
90
+ } catch {
91
+ return false;
92
+ }
93
+ const { duration, height, width } = video;
94
+ if (minWidth && width < minWidth) {
95
+ return false;
96
+ }
97
+ if (minHeight && height < minHeight) {
98
+ return false;
99
+ }
100
+ if (maxDuration && duration > maxDuration) {
101
+ return false;
102
+ }
103
+ if (!checkAspect(width, height, aspect)) {
104
+ return false;
105
+ }
106
+ return true;
107
+ };
108
+
109
+ // [function]
110
+
111
+ const check = function (file, { type, ...opts }) {
112
+ switch (type) {
113
+ case "video/mp4":
114
+ return checkMp4(file, opts);
115
+ default:
116
+ return false;
117
+ }
118
+ };
119
+
120
+ // [export]
121
+
122
+ module.exports = { check };
package/src/util/zip.js CHANGED
@@ -16,8 +16,8 @@ const objs = require("./objs");
16
16
  // [use]
17
17
 
18
18
  const createHash = crypto.createHash;
19
+ const deepSort = objs.deepSort;
19
20
  const join = path.join;
20
- const sortObjs = objs.sort;
21
21
 
22
22
  // [class]
23
23
 
@@ -41,7 +41,7 @@ const Main = class {
41
41
  addJson(name, value) {
42
42
  const entry = join(this.prefix, name);
43
43
  const content = Buffer.from(
44
- JSON.stringify(sortObjs(value), null, 2),
44
+ JSON.stringify(deepSort(value), null, 2),
45
45
  "utf8",
46
46
  );
47
47
  this.zip.addFile(entry, content);