@lowlighter/toolbox 1.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.
Files changed (47) hide show
  1. package/README.md +14 -0
  2. package/clone.d.ts +9 -0
  3. package/clone.js +37 -0
  4. package/deno.lock +53 -0
  5. package/env.d.ts +28 -0
  6. package/env.js +28 -0
  7. package/evaluate.d.ts +49 -0
  8. package/evaluate.js +90 -0
  9. package/events.d.ts +8 -0
  10. package/events.js +28 -0
  11. package/filesystem.d.ts +19 -0
  12. package/filesystem.js +40 -0
  13. package/fixtures/filesystem/a/b/foo.txt +1 -0
  14. package/fixtures/filesystem/a/c/bar.txt +1 -0
  15. package/fixtures/filesystem/a/c/baz.txt +1 -0
  16. package/fixtures/filesystem/a/d/qux.ts +1 -0
  17. package/format.d.ts +9 -0
  18. package/format.js +21 -0
  19. package/identicon.d.ts +6 -0
  20. package/identicon.js +32 -0
  21. package/imgb64.d.ts +1 -0
  22. package/imgb64.js +15 -0
  23. package/mod.ts +1 -0
  24. package/noop.d.ts +1 -0
  25. package/noop.js +2 -0
  26. package/package.json +116 -0
  27. package/permissions.d.ts +1 -0
  28. package/permissions.js +31 -0
  29. package/pluralize.d.ts +6 -0
  30. package/pluralize.js +44 -0
  31. package/promises.d.ts +1 -0
  32. package/promises.js +12 -0
  33. package/resolve.d.ts +5 -0
  34. package/resolve.js +18 -0
  35. package/scripts/code_quality.d.ts +0 -0
  36. package/scripts/code_quality.js +210 -0
  37. package/scripts/download_lambda_chromium.d.ts +10 -0
  38. package/scripts/download_lambda_chromium.js +133 -0
  39. package/scripts/highlight_coverage.d.ts +0 -0
  40. package/scripts/highlight_coverage.js +62 -0
  41. package/scripts/publish/_utils.js +95 -0
  42. package/scripts/publish/npm.d.ts +11 -0
  43. package/scripts/publish/npm.js +130 -0
  44. package/scripts/publish/x.d.ts +20 -0
  45. package/scripts/publish/x.js +303 -0
  46. package/timezone.d.ts +2 -0
  47. package/timezone.js +8 -0
package/README.md ADDED
@@ -0,0 +1,14 @@
1
+ # 🧰 Toolbox
2
+
3
+ [![JSR](https://jsr.io/badges/@libs/toolbox)](https://jsr.io/@libs/toolbox) [![JSR Score](https://jsr.io/badges/@libs/toolbox/score)](https://jsr.io/@libs/toolbox)
4
+
5
+ A set of miscellaneous utilities.
6
+
7
+ - [`📚 Documentation`](https://jsr.io/@libs/toolbox/doc)
8
+
9
+ ## 📜 License
10
+
11
+ ```plaintext
12
+ Copyright (c) Simon Lecoq <@lowlighter>. (MIT License)
13
+ https://github.com/lowlighter/libs/blob/main/LICENSE
14
+ ```
package/clone.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Clones a value deeply.
3
+ *
4
+ * If `structuredCloneable` is set, the clone will be compatible with `structuredClone` algorithm, meaning that:
5
+ * - Proxy are unproxyed to plain objects
6
+ * - Incompatible types are ignored
7
+ */ export declare function clone<T>(value: T, options?: {
8
+ structuredCloneable?: boolean;
9
+ }): T;
package/clone.js ADDED
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Clones a value deeply.
3
+ *
4
+ * If `structuredCloneable` is set, the clone will be compatible with `structuredClone` algorithm, meaning that:
5
+ * - Proxy are unproxyed to plain objects
6
+ * - Incompatible types are ignored
7
+ */ export function clone(value, options) {
8
+ return _clone(value, options, new WeakMap());
9
+ }
10
+ /** {@linkcode clone()} implementation. */ function _clone(value, options, seen) {
11
+ if (Array.isArray(value)) {
12
+ if (seen.has(value)) return seen.get(value);
13
+ const cloned = [];
14
+ seen.set(value, cloned);
15
+ for (const item of value)cloned.push(_clone(item, options, seen));
16
+ return cloned;
17
+ }
18
+ if ([
19
+ Date,
20
+ Error,
21
+ Map,
22
+ Set,
23
+ RegExp
24
+ ].some((type)=>value instanceof type)) return structuredClone(value);
25
+ if (typeof value === "object" && value !== null) {
26
+ if (seen.has(value)) return seen.get(value);
27
+ const cloned = {};
28
+ seen.set(value, cloned);
29
+ for (const [k, v] of Object.entries(value)){
30
+ if (options?.structuredCloneable && (typeof v === "symbol" || typeof v === "function")) continue;
31
+ cloned[k] = _clone(v, options, seen);
32
+ }
33
+ return cloned;
34
+ }
35
+ return value;
36
+ }
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9jbG9uZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENsb25lcyBhIHZhbHVlIGRlZXBseS5cbiAqXG4gKiBJZiBgc3RydWN0dXJlZENsb25lYWJsZWAgaXMgc2V0LCB0aGUgY2xvbmUgd2lsbCBiZSBjb21wYXRpYmxlIHdpdGggYHN0cnVjdHVyZWRDbG9uZWAgYWxnb3JpdGhtLCBtZWFuaW5nIHRoYXQ6XG4gKiAtIFByb3h5IGFyZSB1bnByb3h5ZWQgdG8gcGxhaW4gb2JqZWN0c1xuICogLSBJbmNvbXBhdGlibGUgdHlwZXMgYXJlIGlnbm9yZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsb25lPFQ+KHZhbHVlOiBULCBvcHRpb25zPzogeyBzdHJ1Y3R1cmVkQ2xvbmVhYmxlPzogYm9vbGVhbiB9KTogVCB7XG4gIHJldHVybiBfY2xvbmUodmFsdWUsIG9wdGlvbnMsIG5ldyBXZWFrTWFwKCkpIGFzIFRcbn1cblxuLyoqIHtAbGlua2NvZGUgY2xvbmUoKX0gaW1wbGVtZW50YXRpb24uICovXG5mdW5jdGlvbiBfY2xvbmUodmFsdWU6IHVua25vd24sIG9wdGlvbnM6IHsgc3RydWN0dXJlZENsb25lYWJsZT86IGJvb2xlYW4gfSB8IHVuZGVmaW5lZCwgc2VlbjogV2Vha01hcDxvYmplY3QsIHVua25vd24+KTogdW5rbm93biB7XG4gIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkge1xuICAgIGlmIChzZWVuLmhhcyh2YWx1ZSkpXG4gICAgICByZXR1cm4gc2Vlbi5nZXQodmFsdWUpXG4gICAgY29uc3QgY2xvbmVkOiB1bmtub3duW10gPSBbXVxuICAgIHNlZW4uc2V0KHZhbHVlLCBjbG9uZWQpXG4gICAgZm9yIChjb25zdCBpdGVtIG9mIHZhbHVlKVxuICAgICAgY2xvbmVkLnB1c2goX2Nsb25lKGl0ZW0sIG9wdGlvbnMsIHNlZW4pKVxuICAgIHJldHVybiBjbG9uZWRcbiAgfVxuICBpZiAoW0RhdGUsIEVycm9yLCBNYXAsIFNldCwgUmVnRXhwXS5zb21lKCh0eXBlKSA9PiB2YWx1ZSBpbnN0YW5jZW9mIHR5cGUpKVxuICAgIHJldHVybiBzdHJ1Y3R1cmVkQ2xvbmUodmFsdWUpXG4gIGlmICgodHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiKSAmJiAodmFsdWUgIT09IG51bGwpKSB7XG4gICAgaWYgKHNlZW4uaGFzKHZhbHVlKSlcbiAgICAgIHJldHVybiBzZWVuLmdldCh2YWx1ZSlcbiAgICBjb25zdCBjbG9uZWQgPSB7fSBhcyBSZWNvcmQ8UHJvcGVydHlLZXksIHVua25vd24+XG4gICAgc2Vlbi5zZXQodmFsdWUsIGNsb25lZClcbiAgICBmb3IgKGNvbnN0IFtrLCB2XSBvZiBPYmplY3QuZW50cmllcyh2YWx1ZSkpIHtcbiAgICAgIGlmICgob3B0aW9ucz8uc3RydWN0dXJlZENsb25lYWJsZSkgJiYgKHR5cGVvZiB2ID09PSBcInN5bWJvbFwiIHx8IHR5cGVvZiB2ID09PSBcImZ1bmN0aW9uXCIpKVxuICAgICAgICBjb250aW51ZVxuICAgICAgY2xvbmVkW2tdID0gX2Nsb25lKHYsIG9wdGlvbnMsIHNlZW4pXG4gICAgfVxuICAgIHJldHVybiBjbG9uZWRcbiAgfVxuICByZXR1cm4gdmFsdWVcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7O0NBTUMsR0FDRCxPQUFPLFNBQVMsTUFBUyxLQUFRLEVBQUUsT0FBMkM7RUFDNUUsT0FBTyxPQUFPLE9BQU8sU0FBUyxJQUFJO0FBQ3BDO0FBRUEsd0NBQXdDLEdBQ3hDLFNBQVMsT0FBTyxLQUFjLEVBQUUsT0FBc0QsRUFBRSxJQUE4QjtFQUNwSCxJQUFJLE1BQU0sT0FBTyxDQUFDLFFBQVE7SUFDeEIsSUFBSSxLQUFLLEdBQUcsQ0FBQyxRQUNYLE9BQU8sS0FBSyxHQUFHLENBQUM7SUFDbEIsTUFBTSxTQUFvQixFQUFFO0lBQzVCLEtBQUssR0FBRyxDQUFDLE9BQU87SUFDaEIsS0FBSyxNQUFNLFFBQVEsTUFDakIsT0FBTyxJQUFJLENBQUMsT0FBTyxNQUFNLFNBQVM7SUFDcEMsT0FBTztFQUNUO0VBQ0EsSUFBSTtJQUFDO0lBQU07SUFBTztJQUFLO0lBQUs7R0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE9BQVMsaUJBQWlCLE9BQ2xFLE9BQU8sZ0JBQWdCO0VBQ3pCLElBQUksQUFBQyxPQUFPLFVBQVUsWUFBYyxVQUFVLE1BQU87SUFDbkQsSUFBSSxLQUFLLEdBQUcsQ0FBQyxRQUNYLE9BQU8sS0FBSyxHQUFHLENBQUM7SUFDbEIsTUFBTSxTQUFTLENBQUM7SUFDaEIsS0FBSyxHQUFHLENBQUMsT0FBTztJQUNoQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsSUFBSSxPQUFPLE9BQU8sQ0FBQyxPQUFRO01BQzFDLElBQUksQUFBQyxTQUFTLHVCQUF3QixDQUFDLE9BQU8sTUFBTSxZQUFZLE9BQU8sTUFBTSxVQUFVLEdBQ3JGO01BQ0YsTUFBTSxDQUFDLEVBQUUsR0FBRyxPQUFPLEdBQUcsU0FBUztJQUNqQztJQUNBLE9BQU87RUFDVDtFQUNBLE9BQU87QUFDVCJ9
package/deno.lock ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "version": "5",
3
+ "specifiers": {
4
+ "jsr:@std/cli@^1.0.28": "1.0.31",
5
+ "jsr:@std/fs@^1.0.23": "1.0.24",
6
+ "jsr:@std/internal@^1.0.14": "1.0.14",
7
+ "jsr:@std/path@^1.1.4": "1.1.6",
8
+ "jsr:@std/path@^1.1.5": "1.1.6"
9
+ },
10
+ "jsr": {
11
+ "@std/cli@1.0.31": {
12
+ "integrity": "190bb61f809378267c06be3bcd689fcc540f0cfaa5892171144cae787d02e2fd",
13
+ "dependencies": [
14
+ "jsr:@std/internal"
15
+ ]
16
+ },
17
+ "@std/fs@1.0.24": {
18
+ "integrity": "f3061b45b81673a2bece689da041df32d174be064c89eb6397fb5718d3fb7877",
19
+ "dependencies": [
20
+ "jsr:@std/internal",
21
+ "jsr:@std/path@^1.1.5"
22
+ ]
23
+ },
24
+ "@std/internal@1.0.14": {
25
+ "integrity": "291516b3d4c35024d6ffbc0a9df5bf4c64116e05b50012cf846710152d2ffdf7"
26
+ },
27
+ "@std/path@1.1.6": {
28
+ "integrity": "c68485c2a4dfbb5ae3cc74fae4e8c4e5d874cf8a8ed12927917235c758b46cbe",
29
+ "dependencies": [
30
+ "jsr:@std/internal"
31
+ ]
32
+ }
33
+ },
34
+ "workspace": {
35
+ "dependencies": [
36
+ "jsr:@std/cli@^1.0.28",
37
+ "jsr:@std/encoding@^1.0.10",
38
+ "jsr:@std/fs@^1.0.23",
39
+ "jsr:@std/path@^1.1.4",
40
+ "jsr:@std/streams@^1.0.17",
41
+ "jsr:@std/tar@0.1.10"
42
+ ],
43
+ "packageJson": {
44
+ "dependencies": [
45
+ "npm:@jsr/std__cli@^1.0.28",
46
+ "npm:@jsr/std__fs@^1.0.23",
47
+ "npm:@jsr/std__path@^1.1.4",
48
+ "npm:@jsr/std__streams@^1.0.17",
49
+ "npm:@jsr/std__tar@~0.1.10"
50
+ ]
51
+ }
52
+ }
53
+ }
package/env.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Reads an environment variable.
3
+ *
4
+ * An empty string is returned if the variable is unreadable.
5
+ *
6
+ * ```ts
7
+ * env("ENV_VAR", { default: "foo" })
8
+ * ```
9
+ */ export declare function env(key: string, options?: {
10
+ boolean?: false;
11
+ default?: string;
12
+ }): string;
13
+ /**
14
+ * Reads an environment variable and converts it to a boolean.
15
+ *
16
+ * Any non-empty string is considered truthy, except for:
17
+ * - Values matching falsy definition in {@link https://yaml.org/type/bool.html | YAML 1.1 specification}
18
+ * - Zero-valued strings after a number conversion
19
+ *
20
+ * A falsy value is returned if the variable is unreadable.
21
+ *
22
+ * ```ts
23
+ * env("ENV_VAR", { boolean: true, default: "false" })
24
+ * ```
25
+ */ export declare function env(key: string, options: {
26
+ boolean: true;
27
+ default?: string;
28
+ }): boolean;
package/env.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Reads an environment variable.
3
+ *
4
+ * An empty string is returned if the variable is unreadable.
5
+ *
6
+ * ```ts
7
+ * env("ENV_VAR", { default: "foo" })
8
+ * ```
9
+ */ export function env(key, { boolean = false, default: _default = "" } = {}) {
10
+ if (boolean) {
11
+ const value = env(key, {
12
+ boolean: false,
13
+ default: _default
14
+ });
15
+ if (+value === 0) return false;
16
+ return !/^([Nn]o?|NO|[Oo]ff|OFF|[Ff]alse|FALSE)$/.test(value);
17
+ }
18
+ try {
19
+ if (Deno.permissions.querySync({
20
+ name: "env",
21
+ variable: key
22
+ }).state !== "granted") return _default;
23
+ return Deno.env.get(key) || _default;
24
+ } catch {
25
+ return _default;
26
+ }
27
+ }
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9lbnYudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZWFkcyBhbiBlbnZpcm9ubWVudCB2YXJpYWJsZS5cbiAqXG4gKiBBbiBlbXB0eSBzdHJpbmcgaXMgcmV0dXJuZWQgaWYgdGhlIHZhcmlhYmxlIGlzIHVucmVhZGFibGUuXG4gKlxuICogYGBgdHNcbiAqIGVudihcIkVOVl9WQVJcIiwgeyBkZWZhdWx0OiBcImZvb1wiIH0pXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVudihrZXk6IHN0cmluZywgb3B0aW9ucz86IHsgYm9vbGVhbj86IGZhbHNlOyBkZWZhdWx0Pzogc3RyaW5nIH0pOiBzdHJpbmdcbi8qKlxuICogUmVhZHMgYW4gZW52aXJvbm1lbnQgdmFyaWFibGUgYW5kIGNvbnZlcnRzIGl0IHRvIGEgYm9vbGVhbi5cbiAqXG4gKiBBbnkgbm9uLWVtcHR5IHN0cmluZyBpcyBjb25zaWRlcmVkIHRydXRoeSwgZXhjZXB0IGZvcjpcbiAqIC0gVmFsdWVzIG1hdGNoaW5nIGZhbHN5IGRlZmluaXRpb24gaW4ge0BsaW5rIGh0dHBzOi8veWFtbC5vcmcvdHlwZS9ib29sLmh0bWwgfCBZQU1MIDEuMSBzcGVjaWZpY2F0aW9ufVxuICogLSBaZXJvLXZhbHVlZCBzdHJpbmdzIGFmdGVyIGEgbnVtYmVyIGNvbnZlcnNpb25cbiAqXG4gKiBBIGZhbHN5IHZhbHVlIGlzIHJldHVybmVkIGlmIHRoZSB2YXJpYWJsZSBpcyB1bnJlYWRhYmxlLlxuICpcbiAqIGBgYHRzXG4gKiBlbnYoXCJFTlZfVkFSXCIsIHsgYm9vbGVhbjogdHJ1ZSwgZGVmYXVsdDogXCJmYWxzZVwiIH0pXG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVudihrZXk6IHN0cmluZywgb3B0aW9uczogeyBib29sZWFuOiB0cnVlOyBkZWZhdWx0Pzogc3RyaW5nIH0pOiBib29sZWFuXG5leHBvcnQgZnVuY3Rpb24gZW52KGtleTogc3RyaW5nLCB7IGJvb2xlYW4gPSBmYWxzZSwgZGVmYXVsdDogX2RlZmF1bHQgPSBcIlwiIH0gPSB7fSkge1xuICBpZiAoYm9vbGVhbikge1xuICAgIGNvbnN0IHZhbHVlID0gZW52KGtleSwgeyBib29sZWFuOiBmYWxzZSwgZGVmYXVsdDogX2RlZmF1bHQgfSlcbiAgICBpZiAoK3ZhbHVlID09PSAwKVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgcmV0dXJuICEvXihbTm5dbz98Tk98W09vXWZmfE9GRnxbRmZdYWxzZXxGQUxTRSkkLy50ZXN0KHZhbHVlKVxuICB9XG4gIHRyeSB7XG4gICAgaWYgKERlbm8ucGVybWlzc2lvbnMucXVlcnlTeW5jKHsgbmFtZTogXCJlbnZcIiwgdmFyaWFibGU6IGtleSB9KS5zdGF0ZSAhPT0gXCJncmFudGVkXCIpXG4gICAgICByZXR1cm4gX2RlZmF1bHRcbiAgICByZXR1cm4gRGVuby5lbnYuZ2V0KGtleSkgfHwgX2RlZmF1bHRcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIF9kZWZhdWx0XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Q0FRQyxHQWdCRCxPQUFPLFNBQVMsSUFBSSxHQUFXLEVBQUUsRUFBRSxVQUFVLEtBQUssRUFBRSxTQUFTLFdBQVcsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0VBQy9FLElBQUksU0FBUztJQUNYLE1BQU0sUUFBUSxJQUFJLEtBQUs7TUFBRSxTQUFTO01BQU8sU0FBUztJQUFTO0lBQzNELElBQUksQ0FBQyxVQUFVLEdBQ2IsT0FBTztJQUNULE9BQU8sQ0FBQywwQ0FBMEMsSUFBSSxDQUFDO0VBQ3pEO0VBQ0EsSUFBSTtJQUNGLElBQUksS0FBSyxXQUFXLENBQUMsU0FBUyxDQUFDO01BQUUsTUFBTTtNQUFPLFVBQVU7SUFBSSxHQUFHLEtBQUssS0FBSyxXQUN2RSxPQUFPO0lBQ1QsT0FBTyxLQUFLLEdBQUcsQ0FBQyxHQUFHLENBQUMsUUFBUTtFQUM5QixFQUFFLE9BQU07SUFDTixPQUFPO0VBQ1Q7QUFDRiJ9
package/evaluate.d.ts ADDED
@@ -0,0 +1,49 @@
1
+ /** Evaluate an expression and return a string. */ export declare function evaluate(expression: string, context: Readonly<Record<PropertyKey, unknown>>, options: EvaluateOptions & {
2
+ sync: true;
3
+ return: typeof EvaluationReturn.String;
4
+ }): string;
5
+ /** Evaluate an expression and return a boolean. */ export declare function evaluate(expression: string, context: Readonly<Record<PropertyKey, unknown>>, options: EvaluateOptions & {
6
+ sync: true;
7
+ return: typeof EvaluationReturn.Boolean;
8
+ }): boolean;
9
+ /** Evaluate an expression against a context. */ export declare function evaluate(expression: string, context?: Readonly<Record<PropertyKey, unknown>>, options?: EvaluateOptions & {
10
+ sync: true;
11
+ }): unknown;
12
+ /** Evaluate an expression and return a string. */ export declare function evaluate(expression: string, context: Readonly<Record<PropertyKey, unknown>>, options: EvaluateOptions & {
13
+ sync?: false;
14
+ return: typeof EvaluationReturn.String;
15
+ }): Promise<string>;
16
+ /** Evaluate an expression and return a boolean. */ export declare function evaluate(expression: string, context: Readonly<Record<PropertyKey, unknown>>, options: EvaluateOptions & {
17
+ sync?: false;
18
+ return: typeof EvaluationReturn.Boolean;
19
+ }): Promise<boolean>;
20
+ /**
21
+ * Evaluate an expression against a context.
22
+ *
23
+ * The context is exposed to the expression through a `with` scope, meaning its entries can be referenced directly by name.
24
+ *
25
+ * ```ts
26
+ * import { evaluate } from "./evaluate.ts"
27
+ * console.assert(await evaluate("${a + b}", { a: 1, b: 2 }) === 3)
28
+ * console.assert(await evaluate("foo${a}", { a: "bar" }) === "foobar")
29
+ * ```
30
+ */ export declare function evaluate(expression: string, context?: Readonly<Record<PropertyKey, unknown>>, options?: EvaluateOptions & {
31
+ sync?: false;
32
+ }): Promise<unknown>;
33
+ /** Syntaxes supported by {@linkcode evaluate()}. */ export declare enum EvaluationSyntax {
34
+ /** Treat the expression as an implicit template literal: expressions wrapped in `${...}` are evaluated, anything else is returned as-is. */ Template,
35
+ /** Treat the expression as a single JavaScript expression. */ Block,
36
+ /** Treat the expression as an asynchronous function body, where `return` statements yield the result. */ Function
37
+ }
38
+ /** Coercions applicable to an {@linkcode evaluate()} result. */ export declare enum EvaluationReturn {
39
+ /** Return the result as-is. */ Unknown,
40
+ /** Coerce the result to a boolean. */ Boolean,
41
+ /** Coerce the result to a string. */ String
42
+ }
43
+ /** Options for {@linkcode evaluate()}. */ export type EvaluateOptions = {
44
+ /** Code evaluated before the expression, useful to declare constants or helper functions. */ preload?: string;
45
+ /** Syntax used to interpret the expression (defaults to {@linkcode EvaluationSyntax.Template}). */ syntax?: EvaluationSyntax;
46
+ /** Coercion applied to the result (defaults to {@linkcode EvaluationReturn.Unknown}). */ return?: EvaluationReturn;
47
+ /** Abort signal (ignored if running in sync mode). */ signal?: AbortSignal;
48
+ /** Whether to evaluate in a synchronous manner. */ sync?: boolean;
49
+ };
package/evaluate.js ADDED
@@ -0,0 +1,90 @@
1
+ // Imports
2
+ import { AsyncFunction } from "@lowlighter/typing/func";
3
+ /** Reserved identifier used internally by {@linkcode evaluate()} to share state with the evaluated expression. */ const reserved = "__evaluate__";
4
+ export function evaluate(expression, context = {}, { sync = false, preload, syntax = EvaluationSyntax.Template, return: coerce, signal } = {}) {
5
+ // Check whether the expression needs to be executed
6
+ let execute = syntax !== EvaluationSyntax.Template;
7
+ if (syntax === EvaluationSyntax.Template) {
8
+ // Unwrap expressions of the form `${...}`
9
+ if (expression.startsWith("${") && expression.endsWith("}") && coerce !== EvaluationReturn.String) {
10
+ let depth = 1;
11
+ let i = 2;
12
+ for(; i < expression.length && depth > 0; i++)depth += expression[i] === "{" ? 1 : expression[i] === "}" ? -1 : 0;
13
+ if (depth === 0 && i === expression.length) {
14
+ expression = expression.slice(2, -1).trim();
15
+ execute = true;
16
+ }
17
+ }
18
+ // Quote implicit template literals
19
+ if (!execute && /\$\{[\s\S]*\}/.test(expression)) {
20
+ expression = `\`${expression}\``;
21
+ execute = true;
22
+ }
23
+ }
24
+ if (!execute) return sync ? expression : Promise.resolve(expression);
25
+ // Prevent internal state corruption from namespace collisions
26
+ if (reserved in context) {
27
+ const error = new ReferenceError(`"${reserved}" is a reserved variable name`);
28
+ if (sync) throw error;
29
+ return Promise.reject(error);
30
+ }
31
+ // Evaluate the expression
32
+ if (sync) {
33
+ try {
34
+ if (syntax === EvaluationSyntax.Function) expression = `(()=>{${expression}})()`;
35
+ const fn = new Function(reserved, `${preload};with(${reserved}.context){${reserved}.result=${expression}}return ${reserved}.result`);
36
+ const result = fn({
37
+ context,
38
+ result: undefined
39
+ });
40
+ return coerce === EvaluationReturn.String ? `${result}` : coerce === EvaluationReturn.Boolean ? !!result : result;
41
+ } catch (error) {
42
+ if (error instanceof Error) delete error.stack;
43
+ throw error;
44
+ }
45
+ }
46
+ if (syntax === EvaluationSyntax.Function) expression = `await(async()=>{${expression}})()`;
47
+ return (async ()=>{
48
+ const fn = new AsyncFunction(reserved, `${preload};with(${reserved}.context){${reserved}.result=${expression}}return ${reserved}.result`);
49
+ const result = await abortable(fn({
50
+ context,
51
+ result: undefined
52
+ }), signal);
53
+ return coerce === EvaluationReturn.String ? `${result}` : coerce === EvaluationReturn.Boolean ? !!result : result;
54
+ })().catch((error)=>{
55
+ if (error instanceof Error) delete error.stack;
56
+ throw error;
57
+ });
58
+ }
59
+ /** Race a promise against an abort signal, rejecting with the signal reason upon abortion. */ async function abortable(promise, signal) {
60
+ if (!signal) return promise;
61
+ const { promise: aborted, reject } = Promise.withResolvers();
62
+ const onabort = ()=>reject(signal.reason);
63
+ signal.addEventListener("abort", onabort, {
64
+ once: true
65
+ });
66
+ try {
67
+ signal.throwIfAborted();
68
+ return await Promise.race([
69
+ promise,
70
+ aborted
71
+ ]);
72
+ } finally{
73
+ signal.removeEventListener("abort", onabort);
74
+ // Mark a possible late settlement as handled to avoid unhandled rejections after abortion
75
+ promise.catch(()=>{});
76
+ }
77
+ }
78
+ /** Syntaxes supported by {@linkcode evaluate()}. */ export var EvaluationSyntax = /*#__PURE__*/ function(EvaluationSyntax) {
79
+ /** Treat the expression as an implicit template literal: expressions wrapped in `${...}` are evaluated, anything else is returned as-is. */ EvaluationSyntax[EvaluationSyntax["Template"] = 0] = "Template";
80
+ /** Treat the expression as a single JavaScript expression. */ EvaluationSyntax[EvaluationSyntax["Block"] = 1] = "Block";
81
+ /** Treat the expression as an asynchronous function body, where `return` statements yield the result. */ EvaluationSyntax[EvaluationSyntax["Function"] = 2] = "Function";
82
+ return EvaluationSyntax;
83
+ }({});
84
+ /** Coercions applicable to an {@linkcode evaluate()} result. */ export var EvaluationReturn = /*#__PURE__*/ function(EvaluationReturn) {
85
+ /** Return the result as-is. */ EvaluationReturn[EvaluationReturn["Unknown"] = 0] = "Unknown";
86
+ /** Coerce the result to a boolean. */ EvaluationReturn[EvaluationReturn["Boolean"] = 1] = "Boolean";
87
+ /** Coerce the result to a string. */ EvaluationReturn[EvaluationReturn["String"] = 2] = "String";
88
+ return EvaluationReturn;
89
+ }({});
90
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9ldmFsdWF0ZS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBJbXBvcnRzXG5pbXBvcnQgeyBBc3luY0Z1bmN0aW9uIH0gZnJvbSBcIkBsaWJzL3R5cGluZy9mdW5jXCJcblxuLyoqIFJlc2VydmVkIGlkZW50aWZpZXIgdXNlZCBpbnRlcm5hbGx5IGJ5IHtAbGlua2NvZGUgZXZhbHVhdGUoKX0gdG8gc2hhcmUgc3RhdGUgd2l0aCB0aGUgZXZhbHVhdGVkIGV4cHJlc3Npb24uICovXG5jb25zdCByZXNlcnZlZCA9IFwiX19ldmFsdWF0ZV9fXCJcblxuLyoqIEV2YWx1YXRlIGFuIGV4cHJlc3Npb24gYW5kIHJldHVybiBhIHN0cmluZy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBldmFsdWF0ZShleHByZXNzaW9uOiBzdHJpbmcsIGNvbnRleHQ6IFJlYWRvbmx5PFJlY29yZDxQcm9wZXJ0eUtleSwgdW5rbm93bj4+LCBvcHRpb25zOiBFdmFsdWF0ZU9wdGlvbnMgJiB7IHN5bmM6IHRydWU7IHJldHVybjogdHlwZW9mIEV2YWx1YXRpb25SZXR1cm4uU3RyaW5nIH0pOiBzdHJpbmdcbi8qKiBFdmFsdWF0ZSBhbiBleHByZXNzaW9uIGFuZCByZXR1cm4gYSBib29sZWFuLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV2YWx1YXRlKGV4cHJlc3Npb246IHN0cmluZywgY29udGV4dDogUmVhZG9ubHk8UmVjb3JkPFByb3BlcnR5S2V5LCB1bmtub3duPj4sIG9wdGlvbnM6IEV2YWx1YXRlT3B0aW9ucyAmIHsgc3luYzogdHJ1ZTsgcmV0dXJuOiB0eXBlb2YgRXZhbHVhdGlvblJldHVybi5Cb29sZWFuIH0pOiBib29sZWFuXG4vKiogRXZhbHVhdGUgYW4gZXhwcmVzc2lvbiBhZ2FpbnN0IGEgY29udGV4dC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBldmFsdWF0ZShleHByZXNzaW9uOiBzdHJpbmcsIGNvbnRleHQ/OiBSZWFkb25seTxSZWNvcmQ8UHJvcGVydHlLZXksIHVua25vd24+Piwgb3B0aW9ucz86IEV2YWx1YXRlT3B0aW9ucyAmIHsgc3luYzogdHJ1ZSB9KTogdW5rbm93blxuLyoqIEV2YWx1YXRlIGFuIGV4cHJlc3Npb24gYW5kIHJldHVybiBhIHN0cmluZy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBldmFsdWF0ZShleHByZXNzaW9uOiBzdHJpbmcsIGNvbnRleHQ6IFJlYWRvbmx5PFJlY29yZDxQcm9wZXJ0eUtleSwgdW5rbm93bj4+LCBvcHRpb25zOiBFdmFsdWF0ZU9wdGlvbnMgJiB7IHN5bmM/OiBmYWxzZTsgcmV0dXJuOiB0eXBlb2YgRXZhbHVhdGlvblJldHVybi5TdHJpbmcgfSk6IFByb21pc2U8c3RyaW5nPlxuLyoqIEV2YWx1YXRlIGFuIGV4cHJlc3Npb24gYW5kIHJldHVybiBhIGJvb2xlYW4uICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXZhbHVhdGUoZXhwcmVzc2lvbjogc3RyaW5nLCBjb250ZXh0OiBSZWFkb25seTxSZWNvcmQ8UHJvcGVydHlLZXksIHVua25vd24+Piwgb3B0aW9uczogRXZhbHVhdGVPcHRpb25zICYgeyBzeW5jPzogZmFsc2U7IHJldHVybjogdHlwZW9mIEV2YWx1YXRpb25SZXR1cm4uQm9vbGVhbiB9KTogUHJvbWlzZTxib29sZWFuPlxuLyoqXG4gKiBFdmFsdWF0ZSBhbiBleHByZXNzaW9uIGFnYWluc3QgYSBjb250ZXh0LlxuICpcbiAqIFRoZSBjb250ZXh0IGlzIGV4cG9zZWQgdG8gdGhlIGV4cHJlc3Npb24gdGhyb3VnaCBhIGB3aXRoYCBzY29wZSwgbWVhbmluZyBpdHMgZW50cmllcyBjYW4gYmUgcmVmZXJlbmNlZCBkaXJlY3RseSBieSBuYW1lLlxuICpcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBldmFsdWF0ZSB9IGZyb20gXCIuL2V2YWx1YXRlLnRzXCJcbiAqIGNvbnNvbGUuYXNzZXJ0KGF3YWl0IGV2YWx1YXRlKFwiJHthICsgYn1cIiwgeyBhOiAxLCBiOiAyIH0pID09PSAzKVxuICogY29uc29sZS5hc3NlcnQoYXdhaXQgZXZhbHVhdGUoXCJmb28ke2F9XCIsIHsgYTogXCJiYXJcIiB9KSA9PT0gXCJmb29iYXJcIilcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gZXZhbHVhdGUoZXhwcmVzc2lvbjogc3RyaW5nLCBjb250ZXh0PzogUmVhZG9ubHk8UmVjb3JkPFByb3BlcnR5S2V5LCB1bmtub3duPj4sIG9wdGlvbnM/OiBFdmFsdWF0ZU9wdGlvbnMgJiB7IHN5bmM/OiBmYWxzZSB9KTogUHJvbWlzZTx1bmtub3duPlxuZXhwb3J0IGZ1bmN0aW9uIGV2YWx1YXRlKGV4cHJlc3Npb246IHN0cmluZywgY29udGV4dDogUmVhZG9ubHk8UmVjb3JkPFByb3BlcnR5S2V5LCB1bmtub3duPj4gPSB7fSwgeyBzeW5jID0gZmFsc2UsIHByZWxvYWQsIHN5bnRheCA9IEV2YWx1YXRpb25TeW50YXguVGVtcGxhdGUsIHJldHVybjogY29lcmNlLCBzaWduYWwgfTogRXZhbHVhdGVPcHRpb25zID0ge30pIHtcbiAgLy8gQ2hlY2sgd2hldGhlciB0aGUgZXhwcmVzc2lvbiBuZWVkcyB0byBiZSBleGVjdXRlZFxuICBsZXQgZXhlY3V0ZSA9IHN5bnRheCAhPT0gRXZhbHVhdGlvblN5bnRheC5UZW1wbGF0ZVxuICBpZiAoc3ludGF4ID09PSBFdmFsdWF0aW9uU3ludGF4LlRlbXBsYXRlKSB7XG4gICAgLy8gVW53cmFwIGV4cHJlc3Npb25zIG9mIHRoZSBmb3JtIGAkey4uLn1gXG4gICAgaWYgKGV4cHJlc3Npb24uc3RhcnRzV2l0aChcIiR7XCIpICYmIGV4cHJlc3Npb24uZW5kc1dpdGgoXCJ9XCIpICYmIChjb2VyY2UgIT09IEV2YWx1YXRpb25SZXR1cm4uU3RyaW5nKSkge1xuICAgICAgbGV0IGRlcHRoID0gMVxuICAgICAgbGV0IGkgPSAyXG4gICAgICBmb3IgKDsgKGkgPCBleHByZXNzaW9uLmxlbmd0aCkgJiYgKGRlcHRoID4gMCk7IGkrKylcbiAgICAgICAgZGVwdGggKz0gKGV4cHJlc3Npb25baV0gPT09IFwie1wiKSA/IDEgOiAoZXhwcmVzc2lvbltpXSA9PT0gXCJ9XCIpID8gLTEgOiAwXG4gICAgICBpZiAoKGRlcHRoID09PSAwKSAmJiAoaSA9PT0gZXhwcmVzc2lvbi5sZW5ndGgpKSB7XG4gICAgICAgIGV4cHJlc3Npb24gPSBleHByZXNzaW9uLnNsaWNlKDIsIC0xKS50cmltKClcbiAgICAgICAgZXhlY3V0ZSA9IHRydWVcbiAgICAgIH1cbiAgICB9XG4gICAgLy8gUXVvdGUgaW1wbGljaXQgdGVtcGxhdGUgbGl0ZXJhbHNcbiAgICBpZiAoKCFleGVjdXRlKSAmJiAoL1xcJFxce1tcXHNcXFNdKlxcfS8udGVzdChleHByZXNzaW9uKSkpIHtcbiAgICAgIGV4cHJlc3Npb24gPSBgXFxgJHtleHByZXNzaW9ufVxcYGBcbiAgICAgIGV4ZWN1dGUgPSB0cnVlXG4gICAgfVxuICB9XG4gIGlmICghZXhlY3V0ZSlcbiAgICByZXR1cm4gc3luYyA/IGV4cHJlc3Npb24gOiBQcm9taXNlLnJlc29sdmUoZXhwcmVzc2lvbilcblxuICAvLyBQcmV2ZW50IGludGVybmFsIHN0YXRlIGNvcnJ1cHRpb24gZnJvbSBuYW1lc3BhY2UgY29sbGlzaW9uc1xuICBpZiAocmVzZXJ2ZWQgaW4gY29udGV4dCkge1xuICAgIGNvbnN0IGVycm9yID0gbmV3IFJlZmVyZW5jZUVycm9yKGBcIiR7cmVzZXJ2ZWR9XCIgaXMgYSByZXNlcnZlZCB2YXJpYWJsZSBuYW1lYClcbiAgICBpZiAoc3luYylcbiAgICAgIHRocm93IGVycm9yXG4gICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGVycm9yKVxuICB9XG5cbiAgLy8gRXZhbHVhdGUgdGhlIGV4cHJlc3Npb25cbiAgaWYgKHN5bmMpIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHN5bnRheCA9PT0gRXZhbHVhdGlvblN5bnRheC5GdW5jdGlvbilcbiAgICAgICAgZXhwcmVzc2lvbiA9IGAoKCk9Pnske2V4cHJlc3Npb259fSkoKWBcbiAgICAgIGNvbnN0IGZuID0gbmV3IEZ1bmN0aW9uKHJlc2VydmVkLCBgJHtwcmVsb2FkfTt3aXRoKCR7cmVzZXJ2ZWR9LmNvbnRleHQpeyR7cmVzZXJ2ZWR9LnJlc3VsdD0ke2V4cHJlc3Npb259fXJldHVybiAke3Jlc2VydmVkfS5yZXN1bHRgKVxuICAgICAgY29uc3QgcmVzdWx0ID0gZm4oeyBjb250ZXh0LCByZXN1bHQ6IHVuZGVmaW5lZCB9KVxuICAgICAgcmV0dXJuIGNvZXJjZSA9PT0gRXZhbHVhdGlvblJldHVybi5TdHJpbmcgPyBgJHtyZXN1bHR9YCA6IGNvZXJjZSA9PT0gRXZhbHVhdGlvblJldHVybi5Cb29sZWFuID8gISFyZXN1bHQgOiByZXN1bHRcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpXG4gICAgICAgIGRlbGV0ZSBlcnJvci5zdGFja1xuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cbiAgaWYgKHN5bnRheCA9PT0gRXZhbHVhdGlvblN5bnRheC5GdW5jdGlvbilcbiAgICBleHByZXNzaW9uID0gYGF3YWl0KGFzeW5jKCk9Pnske2V4cHJlc3Npb259fSkoKWBcbiAgcmV0dXJuIChhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgZm4gPSBuZXcgQXN5bmNGdW5jdGlvbihyZXNlcnZlZCwgYCR7cHJlbG9hZH07d2l0aCgke3Jlc2VydmVkfS5jb250ZXh0KXske3Jlc2VydmVkfS5yZXN1bHQ9JHtleHByZXNzaW9ufX1yZXR1cm4gJHtyZXNlcnZlZH0ucmVzdWx0YClcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBhYm9ydGFibGUoZm4oeyBjb250ZXh0LCByZXN1bHQ6IHVuZGVmaW5lZCB9KSwgc2lnbmFsKVxuICAgIHJldHVybiBjb2VyY2UgPT09IEV2YWx1YXRpb25SZXR1cm4uU3RyaW5nID8gYCR7cmVzdWx0fWAgOiBjb2VyY2UgPT09IEV2YWx1YXRpb25SZXR1cm4uQm9vbGVhbiA/ICEhcmVzdWx0IDogcmVzdWx0XG4gIH0pKCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2YgRXJyb3IpXG4gICAgICBkZWxldGUgZXJyb3Iuc3RhY2tcbiAgICB0aHJvdyBlcnJvclxuICB9KVxufVxuXG4vKiogUmFjZSBhIHByb21pc2UgYWdhaW5zdCBhbiBhYm9ydCBzaWduYWwsIHJlamVjdGluZyB3aXRoIHRoZSBzaWduYWwgcmVhc29uIHVwb24gYWJvcnRpb24uICovXG5hc3luYyBmdW5jdGlvbiBhYm9ydGFibGU8VD4ocHJvbWlzZTogUHJvbWlzZTxUPiwgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPFQ+IHtcbiAgaWYgKCFzaWduYWwpXG4gICAgcmV0dXJuIHByb21pc2VcbiAgY29uc3QgeyBwcm9taXNlOiBhYm9ydGVkLCByZWplY3QgfSA9IFByb21pc2Uud2l0aFJlc29sdmVyczxuZXZlcj4oKVxuICBjb25zdCBvbmFib3J0ID0gKCkgPT4gcmVqZWN0KHNpZ25hbC5yZWFzb24pXG4gIHNpZ25hbC5hZGRFdmVudExpc3RlbmVyKFwiYWJvcnRcIiwgb25hYm9ydCwgeyBvbmNlOiB0cnVlIH0pXG4gIHRyeSB7XG4gICAgc2lnbmFsLnRocm93SWZBYm9ydGVkKClcbiAgICByZXR1cm4gYXdhaXQgUHJvbWlzZS5yYWNlKFtwcm9taXNlLCBhYm9ydGVkXSlcbiAgfSBmaW5hbGx5IHtcbiAgICBzaWduYWwucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImFib3J0XCIsIG9uYWJvcnQpXG4gICAgLy8gTWFyayBhIHBvc3NpYmxlIGxhdGUgc2V0dGxlbWVudCBhcyBoYW5kbGVkIHRvIGF2b2lkIHVuaGFuZGxlZCByZWplY3Rpb25zIGFmdGVyIGFib3J0aW9uXG4gICAgcHJvbWlzZS5jYXRjaCgoKSA9PiB7fSlcbiAgfVxufVxuXG4vKiogU3ludGF4ZXMgc3VwcG9ydGVkIGJ5IHtAbGlua2NvZGUgZXZhbHVhdGUoKX0uICovXG5leHBvcnQgZW51bSBFdmFsdWF0aW9uU3ludGF4IHtcbiAgLyoqIFRyZWF0IHRoZSBleHByZXNzaW9uIGFzIGFuIGltcGxpY2l0IHRlbXBsYXRlIGxpdGVyYWw6IGV4cHJlc3Npb25zIHdyYXBwZWQgaW4gYCR7Li4ufWAgYXJlIGV2YWx1YXRlZCwgYW55dGhpbmcgZWxzZSBpcyByZXR1cm5lZCBhcy1pcy4gKi9cbiAgVGVtcGxhdGUsXG4gIC8qKiBUcmVhdCB0aGUgZXhwcmVzc2lvbiBhcyBhIHNpbmdsZSBKYXZhU2NyaXB0IGV4cHJlc3Npb24uICovXG4gIEJsb2NrLFxuICAvKiogVHJlYXQgdGhlIGV4cHJlc3Npb24gYXMgYW4gYXN5bmNocm9ub3VzIGZ1bmN0aW9uIGJvZHksIHdoZXJlIGByZXR1cm5gIHN0YXRlbWVudHMgeWllbGQgdGhlIHJlc3VsdC4gKi9cbiAgRnVuY3Rpb24sXG59XG5cbi8qKiBDb2VyY2lvbnMgYXBwbGljYWJsZSB0byBhbiB7QGxpbmtjb2RlIGV2YWx1YXRlKCl9IHJlc3VsdC4gKi9cbmV4cG9ydCBlbnVtIEV2YWx1YXRpb25SZXR1cm4ge1xuICAvKiogUmV0dXJuIHRoZSByZXN1bHQgYXMtaXMuICovXG4gIFVua25vd24sXG4gIC8qKiBDb2VyY2UgdGhlIHJlc3VsdCB0byBhIGJvb2xlYW4uICovXG4gIEJvb2xlYW4sXG4gIC8qKiBDb2VyY2UgdGhlIHJlc3VsdCB0byBhIHN0cmluZy4gKi9cbiAgU3RyaW5nLFxufVxuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rY29kZSBldmFsdWF0ZSgpfS4gKi9cbmV4cG9ydCB0eXBlIEV2YWx1YXRlT3B0aW9ucyA9IHtcbiAgLyoqIENvZGUgZXZhbHVhdGVkIGJlZm9yZSB0aGUgZXhwcmVzc2lvbiwgdXNlZnVsIHRvIGRlY2xhcmUgY29uc3RhbnRzIG9yIGhlbHBlciBmdW5jdGlvbnMuICovXG4gIHByZWxvYWQ/OiBzdHJpbmdcbiAgLyoqIFN5bnRheCB1c2VkIHRvIGludGVycHJldCB0aGUgZXhwcmVzc2lvbiAoZGVmYXVsdHMgdG8ge0BsaW5rY29kZSBFdmFsdWF0aW9uU3ludGF4LlRlbXBsYXRlfSkuICovXG4gIHN5bnRheD86IEV2YWx1YXRpb25TeW50YXhcbiAgLyoqIENvZXJjaW9uIGFwcGxpZWQgdG8gdGhlIHJlc3VsdCAoZGVmYXVsdHMgdG8ge0BsaW5rY29kZSBFdmFsdWF0aW9uUmV0dXJuLlVua25vd259KS4gKi9cbiAgcmV0dXJuPzogRXZhbHVhdGlvblJldHVyblxuICAvKiogQWJvcnQgc2lnbmFsIChpZ25vcmVkIGlmIHJ1bm5pbmcgaW4gc3luYyBtb2RlKS4gKi9cbiAgc2lnbmFsPzogQWJvcnRTaWduYWxcbiAgLyoqIFdoZXRoZXIgdG8gZXZhbHVhdGUgaW4gYSBzeW5jaHJvbm91cyBtYW5uZXIuICovXG4gIHN5bmM/OiBib29sZWFuXG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsVUFBVTtBQUNWLFNBQVMsYUFBYSxRQUFRLG9CQUFtQjtBQUVqRCxnSEFBZ0gsR0FDaEgsTUFBTSxXQUFXO0FBd0JqQixPQUFPLFNBQVMsU0FBUyxVQUFrQixFQUFFLFVBQWtELENBQUMsQ0FBQyxFQUFFLEVBQUUsT0FBTyxLQUFLLEVBQUUsT0FBTyxFQUFFLFNBQVMsaUJBQWlCLFFBQVEsRUFBRSxRQUFRLE1BQU0sRUFBRSxNQUFNLEVBQW1CLEdBQUcsQ0FBQyxDQUFDO0VBQzVNLG9EQUFvRDtFQUNwRCxJQUFJLFVBQVUsV0FBVyxpQkFBaUIsUUFBUTtFQUNsRCxJQUFJLFdBQVcsaUJBQWlCLFFBQVEsRUFBRTtJQUN4QywwQ0FBMEM7SUFDMUMsSUFBSSxXQUFXLFVBQVUsQ0FBQyxTQUFTLFdBQVcsUUFBUSxDQUFDLFFBQVMsV0FBVyxpQkFBaUIsTUFBTSxFQUFHO01BQ25HLElBQUksUUFBUTtNQUNaLElBQUksSUFBSTtNQUNSLE1BQU8sQUFBQyxJQUFJLFdBQVcsTUFBTSxJQUFNLFFBQVEsR0FBSSxJQUM3QyxTQUFTLEFBQUMsVUFBVSxDQUFDLEVBQUUsS0FBSyxNQUFPLElBQUksQUFBQyxVQUFVLENBQUMsRUFBRSxLQUFLLE1BQU8sQ0FBQyxJQUFJO01BQ3hFLElB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
package/events.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /** An event emitter with strongly-typed event data. */ export declare class EventEmitter<T = unknown> {
2
+ /** Registers a listener for the specified event. */ on(event: string, listener: Listener<T>, {}?: {
3
+ }): void;
4
+ /** Unregisters all listeners for the specified event. */ off(event: string): void;
5
+ /** Unregisters a listener for the specified event. */ off(event: string, listener: Listener<T>): void;
6
+ /** Emits an event with the specified data. */ emit(event: string, data: T): void;
7
+ }
8
+ /** A listener invoked with the emitted event data. */ export type Listener<T = unknown> = (data: T) => void;
package/events.js ADDED
@@ -0,0 +1,28 @@
1
+ /** An event emitter with strongly-typed event data. */ export class EventEmitter {
2
+ /** Registered listeners mapped to their wrappers. */ #listeners = new Map();
3
+ /** Registers a listener for the specified event. */ on(event, listener, { once = false } = {}) {
4
+ const listeners = this.#listeners.getOrInsert(event, new Map());
5
+ if (!listeners.has(listener)) listeners.set(listener, once ? (data)=>listener(data) : listener);
6
+ }
7
+ off(event, listener) {
8
+ const listeners = this.#listeners.get(event);
9
+ if (!listener) {
10
+ listeners?.clear();
11
+ return;
12
+ }
13
+ if (listeners?.has(listener)) listeners.delete(listener);
14
+ }
15
+ /** Emits an event with the specified data. */ emit(event, data) {
16
+ const listeners = this.#listeners.get(event);
17
+ if (!listeners) return;
18
+ // Snapshot registered listeners
19
+ for (const [listener, wrapper] of [
20
+ ...listeners
21
+ ]){
22
+ if (listeners.get(listener) !== wrapper) continue;
23
+ if (wrapper !== listener) listeners.delete(listener);
24
+ wrapper(data);
25
+ }
26
+ }
27
+ }
28
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9ldmVudHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIEFuIGV2ZW50IGVtaXR0ZXIgd2l0aCBzdHJvbmdseS10eXBlZCBldmVudCBkYXRhLiAqL1xuZXhwb3J0IGNsYXNzIEV2ZW50RW1pdHRlcjxUID0gdW5rbm93bj4ge1xuICAvKiogUmVnaXN0ZXJlZCBsaXN0ZW5lcnMgbWFwcGVkIHRvIHRoZWlyIHdyYXBwZXJzLiAqL1xuICAjbGlzdGVuZXJzID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxMaXN0ZW5lcjxUPiwgTGlzdGVuZXI8VD4+PigpXG5cbiAgLyoqIFJlZ2lzdGVycyBhIGxpc3RlbmVyIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LiAqL1xuICBvbihldmVudDogc3RyaW5nLCBsaXN0ZW5lcjogTGlzdGVuZXI8VD4sIHsgb25jZSA9IGZhbHNlIH0gPSB7fSk6IHZvaWQge1xuICAgIGNvbnN0IGxpc3RlbmVycyA9IHRoaXMuI2xpc3RlbmVycy5nZXRPckluc2VydChldmVudCwgbmV3IE1hcCgpKVxuICAgIGlmICghbGlzdGVuZXJzLmhhcyhsaXN0ZW5lcikpXG4gICAgICBsaXN0ZW5lcnMuc2V0KGxpc3RlbmVyLCBvbmNlID8gKChkYXRhOiBUKSA9PiBsaXN0ZW5lcihkYXRhKSkgOiBsaXN0ZW5lcilcbiAgfVxuXG4gIC8qKiBVbnJlZ2lzdGVycyBhbGwgbGlzdGVuZXJzIGZvciB0aGUgc3BlY2lmaWVkIGV2ZW50LiAqL1xuICBvZmYoZXZlbnQ6IHN0cmluZyk6IHZvaWRcbiAgLyoqIFVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuICovXG4gIG9mZihldmVudDogc3RyaW5nLCBsaXN0ZW5lcjogTGlzdGVuZXI8VD4pOiB2b2lkXG4gIG9mZihldmVudDogc3RyaW5nLCBsaXN0ZW5lcj86IExpc3RlbmVyPFQ+KSB7XG4gICAgY29uc3QgbGlzdGVuZXJzID0gdGhpcy4jbGlzdGVuZXJzLmdldChldmVudClcbiAgICBpZiAoIWxpc3RlbmVyKSB7XG4gICAgICBsaXN0ZW5lcnM/LmNsZWFyKClcbiAgICAgIHJldHVyblxuICAgIH1cbiAgICBpZiAobGlzdGVuZXJzPy5oYXMobGlzdGVuZXIpKVxuICAgICAgbGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lcilcbiAgfVxuXG4gIC8qKiBFbWl0cyBhbiBldmVudCB3aXRoIHRoZSBzcGVjaWZpZWQgZGF0YS4gKi9cbiAgZW1pdChldmVudDogc3RyaW5nLCBkYXRhOiBUKTogdm9pZCB7XG4gICAgY29uc3QgbGlzdGVuZXJzID0gdGhpcy4jbGlzdGVuZXJzLmdldChldmVudClcbiAgICBpZiAoIWxpc3RlbmVycylcbiAgICAgIHJldHVyblxuICAgIC8vIFNuYXBzaG90IHJlZ2lzdGVyZWQgbGlzdGVuZXJzXG4gICAgZm9yIChjb25zdCBbbGlzdGVuZXIsIHdyYXBwZXJdIG9mIFsuLi5saXN0ZW5lcnNdKSB7XG4gICAgICBpZiAobGlzdGVuZXJzLmdldChsaXN0ZW5lcikgIT09IHdyYXBwZXIpXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICBpZiAod3JhcHBlciAhPT0gbGlzdGVuZXIpXG4gICAgICAgIGxpc3RlbmVycy5kZWxldGUobGlzdGVuZXIpXG4gICAgICB3cmFwcGVyKGRhdGEpXG4gICAgfVxuICB9XG59XG5cbi8qKiBBIGxpc3RlbmVyIGludm9rZWQgd2l0aCB0aGUgZW1pdHRlZCBldmVudCBkYXRhLiAqL1xuZXhwb3J0IHR5cGUgTGlzdGVuZXI8VCA9IHVua25vd24+ID0gKGRhdGE6IFQpID0+IHZvaWRcbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxREFBcUQsR0FDckQsT0FBTyxNQUFNO0VBQ1gsbURBQW1ELEdBQ25ELENBQUEsU0FBVSxHQUFHLElBQUksTUFBNEM7RUFFN0Qsa0RBQWtELEdBQ2xELEdBQUcsS0FBYSxFQUFFLFFBQXFCLEVBQUUsRUFBRSxPQUFPLEtBQUssRUFBRSxHQUFHLENBQUMsQ0FBQyxFQUFRO0lBQ3BFLE1BQU0sWUFBWSxJQUFJLENBQUMsQ0FBQSxTQUFVLENBQUMsV0FBVyxDQUFDLE9BQU8sSUFBSTtJQUN6RCxJQUFJLENBQUMsVUFBVSxHQUFHLENBQUMsV0FDakIsVUFBVSxHQUFHLENBQUMsVUFBVSxPQUFRLENBQUMsT0FBWSxTQUFTLFFBQVM7RUFDbkU7RUFNQSxJQUFJLEtBQWEsRUFBRSxRQUFzQixFQUFFO0lBQ3pDLE1BQU0sWUFBWSxJQUFJLENBQUMsQ0FBQSxTQUFVLENBQUMsR0FBRyxDQUFDO0lBQ3RDLElBQUksQ0FBQyxVQUFVO01BQ2IsV0FBVztNQUNYO0lBQ0Y7SUFDQSxJQUFJLFdBQVcsSUFBSSxXQUNqQixVQUFVLE1BQU0sQ0FBQztFQUNyQjtFQUVBLDRDQUE0QyxHQUM1QyxLQUFLLEtBQWEsRUFBRSxJQUFPLEVBQVE7SUFDakMsTUFBTSxZQUFZLElBQUksQ0FBQyxDQUFBLFNBQVUsQ0FBQyxHQUFHLENBQUM7SUFDdEMsSUFBSSxDQUFDLFdBQ0g7SUFDRixnQ0FBZ0M7SUFDaEMsS0FBSyxNQUFNLENBQUMsVUFBVSxRQUFRLElBQUk7U0FBSTtLQUFVLENBQUU7TUFDaEQsSUFBSSxVQUFVLEdBQUcsQ0FBQyxjQUFjLFNBQzlCO01BQ0YsSUFBSSxZQUFZLFVBQ2QsVUFBVSxNQUFNLENBQUM7TUFDbkIsUUFBUTtJQUNWO0VBQ0Y7QUFDRiJ9
@@ -0,0 +1,19 @@
1
+ import type { Nullable } from "@lowlighter/typing";
2
+ export type { Nullable };
3
+ /** Gets the current working directory. */ export declare function cwd(): string;
4
+ /** Changes the current working directory. */ export declare function chdir(path: string | URL): string;
5
+ /** Gets the file type of a file path. */ export declare function filetype(path: string): Nullable<"file" | "directory">;
6
+ /** Options for {@linkcode list()}. */ export type ListOptions = {
7
+ /** Root directory to search in. Defaults to the current working directory. */ root?: string;
8
+ /** Whether to return relative paths. */ relative?: boolean;
9
+ /** Whether to include files in the results. */ files?: boolean;
10
+ /** Whether to include directories in the results. */ directories?: boolean;
11
+ /** List of glob patterns to be excluded from the expansion. */ exclude?: string[];
12
+ /** Whether globstar should be case-insensitive. */ caseInsensitive?: boolean;
13
+ /** Whether to follow symbolic links. */ followSymlinks?: boolean;
14
+ };
15
+ /**
16
+ * Lists all entries matching the given glob pattern in the specified root directory.
17
+ *
18
+ * Note that `files` and `directories` both default to `false`, at least one of them must be enabled to get any result.
19
+ */ export declare function list(glob: string, {}?: ListOptions): Promise<string[]>;
package/filesystem.js ADDED
@@ -0,0 +1,40 @@
1
+ // Imports
2
+ import { expandGlob } from "@std/fs";
3
+ /** Gets the current working directory. */ export function cwd() {
4
+ return Deno.cwd().replaceAll("\\", "/");
5
+ }
6
+ /** Changes the current working directory. */ export function chdir(path) {
7
+ Deno.chdir(path);
8
+ return cwd();
9
+ }
10
+ /** Gets the file type of a file path. */ export function filetype(path) {
11
+ try {
12
+ const lstat = Deno.lstatSync(path);
13
+ if (lstat.isFile) return "file";
14
+ if (lstat.isDirectory) return "directory";
15
+ } catch {
16
+ // Ignore errors
17
+ }
18
+ return null;
19
+ }
20
+ /**
21
+ * Lists all entries matching the given glob pattern in the specified root directory.
22
+ *
23
+ * Note that `files` and `directories` both default to `false`, at least one of them must be enabled to get any result.
24
+ */ export async function list(glob, { root = cwd(), relative = true, files = false, directories = false, exclude, caseInsensitive, followSymlinks } = {}) {
25
+ root = root.replaceAll("\\", "/");
26
+ if (!root.endsWith("/")) root += "/";
27
+ const entries = await Array.fromAsync(expandGlob(glob, {
28
+ root,
29
+ canonicalize: true,
30
+ includeDirs: directories,
31
+ exclude,
32
+ caseInsensitive,
33
+ followSymlinks
34
+ }));
35
+ return entries.filter((entry)=>files && entry.isFile || directories && entry.isDirectory).map(({ path })=>{
36
+ path = path.replaceAll("\\", "/");
37
+ return relative && path.startsWith(root) ? path.slice(root.length) : path;
38
+ });
39
+ }
40
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9maWxlc3lzdGVtLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIEltcG9ydHNcbmltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiQGxpYnMvdHlwaW5nXCJcbmltcG9ydCB7IGV4cGFuZEdsb2IgfSBmcm9tIFwiQHN0ZC9mc1wiXG5leHBvcnQgdHlwZSB7IE51bGxhYmxlIH1cblxuLyoqIEdldHMgdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkuICovXG5leHBvcnQgZnVuY3Rpb24gY3dkKCk6IHN0cmluZyB7XG4gIHJldHVybiBEZW5vLmN3ZCgpLnJlcGxhY2VBbGwoXCJcXFxcXCIsIFwiL1wiKVxufVxuXG4vKiogQ2hhbmdlcyB0aGUgY3VycmVudCB3b3JraW5nIGRpcmVjdG9yeS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjaGRpcihwYXRoOiBzdHJpbmcgfCBVUkwpOiBzdHJpbmcge1xuICBEZW5vLmNoZGlyKHBhdGgpXG4gIHJldHVybiBjd2QoKVxufVxuXG4vKiogR2V0cyB0aGUgZmlsZSB0eXBlIG9mIGEgZmlsZSBwYXRoLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZpbGV0eXBlKHBhdGg6IHN0cmluZyk6IE51bGxhYmxlPFwiZmlsZVwiIHwgXCJkaXJlY3RvcnlcIj4ge1xuICB0cnkge1xuICAgIGNvbnN0IGxzdGF0ID0gRGVuby5sc3RhdFN5bmMocGF0aClcbiAgICBpZiAobHN0YXQuaXNGaWxlKVxuICAgICAgcmV0dXJuIFwiZmlsZVwiXG4gICAgaWYgKGxzdGF0LmlzRGlyZWN0b3J5KVxuICAgICAgcmV0dXJuIFwiZGlyZWN0b3J5XCJcbiAgfSBjYXRjaCB7XG4gICAgLy8gSWdub3JlIGVycm9yc1xuICB9XG4gIHJldHVybiBudWxsXG59XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmtjb2RlIGxpc3QoKX0uICovXG5leHBvcnQgdHlwZSBMaXN0T3B0aW9ucyA9IHtcbiAgLyoqIFJvb3QgZGlyZWN0b3J5IHRvIHNlYXJjaCBpbi4gRGVmYXVsdHMgdG8gdGhlIGN1cnJlbnQgd29ya2luZyBkaXJlY3RvcnkuICovXG4gIHJvb3Q/OiBzdHJpbmdcbiAgLyoqIFdoZXRoZXIgdG8gcmV0dXJuIHJlbGF0aXZlIHBhdGhzLiAqL1xuICByZWxhdGl2ZT86IGJvb2xlYW5cbiAgLyoqIFdoZXRoZXIgdG8gaW5jbHVkZSBmaWxlcyBpbiB0aGUgcmVzdWx0cy4gKi9cbiAgZmlsZXM/OiBib29sZWFuXG4gIC8qKiBXaGV0aGVyIHRvIGluY2x1ZGUgZGlyZWN0b3JpZXMgaW4gdGhlIHJlc3VsdHMuICovXG4gIGRpcmVjdG9yaWVzPzogYm9vbGVhblxuICAvKiogTGlzdCBvZiBnbG9iIHBhdHRlcm5zIHRvIGJlIGV4Y2x1ZGVkIGZyb20gdGhlIGV4cGFuc2lvbi4gKi9cbiAgZXhjbHVkZT86IHN0cmluZ1tdXG4gIC8qKiBXaGV0aGVyIGdsb2JzdGFyIHNob3VsZCBiZSBjYXNlLWluc2Vuc2l0aXZlLiAqL1xuICBjYXNlSW5zZW5zaXRpdmU/OiBib29sZWFuXG4gIC8qKiBXaGV0aGVyIHRvIGZvbGxvdyBzeW1ib2xpYyBsaW5rcy4gKi9cbiAgZm9sbG93U3ltbGlua3M/OiBib29sZWFuXG59XG5cbi8qKlxuICogTGlzdHMgYWxsIGVudHJpZXMgbWF0Y2hpbmcgdGhlIGdpdmVuIGdsb2IgcGF0dGVybiBpbiB0aGUgc3BlY2lmaWVkIHJvb3QgZGlyZWN0b3J5LlxuICpcbiAqIE5vdGUgdGhhdCBgZmlsZXNgIGFuZCBgZGlyZWN0b3JpZXNgIGJvdGggZGVmYXVsdCB0byBgZmFsc2VgLCBhdCBsZWFzdCBvbmUgb2YgdGhlbSBtdXN0IGJlIGVuYWJsZWQgdG8gZ2V0IGFueSByZXN1bHQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0KGdsb2I6IHN0cmluZywgeyByb290ID0gY3dkKCksIHJlbGF0aXZlID0gdHJ1ZSwgZmlsZXMgPSBmYWxzZSwgZGlyZWN0b3JpZXMgPSBmYWxzZSwgZXhjbHVkZSwgY2FzZUluc2Vuc2l0aXZlLCBmb2xsb3dTeW1saW5rcyB9OiBMaXN0T3B0aW9ucyA9IHt9KTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICByb290ID0gcm9vdC5yZXBsYWNlQWxsKFwiXFxcXFwiLCBcIi9cIilcbiAgaWYgKCFyb290LmVuZHNXaXRoKFwiL1wiKSlcbiAgICByb290ICs9IFwiL1wiXG4gIGNvbnN0IGVudHJpZXMgPSBhd2FpdCBBcnJheS5mcm9tQXN5bmMoZXhwYW5kR2xvYihnbG9iLCB7IHJvb3QsIGNhbm9uaWNhbGl6ZTogdHJ1ZSwgaW5jbHVkZURpcnM6IGRpcmVjdG9yaWVzLCBleGNsdWRlLCBjYXNlSW5zZW5zaXRpdmUsIGZvbGxvd1N5bWxpbmtzIH0pKVxuICByZXR1cm4gZW50cmllc1xuICAgIC5maWx0ZXIoKGVudHJ5KSA9PiAoZmlsZXMgJiYgZW50cnkuaXNGaWxlKSB8fCAoZGlyZWN0b3JpZXMgJiYgZW50cnkuaXNEaXJlY3RvcnkpKVxuICAgIC5tYXAoKHsgcGF0aCB9KSA9PiB7XG4gICAgICBwYXRoID0gcGF0aC5yZXBsYWNlQWxsKFwiXFxcXFwiLCBcIi9cIilcbiAgICAgIHJldHVybiAocmVsYXRpdmUgJiYgcGF0aC5zdGFydHNXaXRoKHJvb3QpKSA/IHBhdGguc2xpY2Uocm9vdC5sZW5ndGgpIDogcGF0aFxuICAgIH0pXG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsVUFBVTtBQUVWLFNBQVMsVUFBVSxRQUFRLFVBQVM7QUFHcEMsd0NBQXdDLEdBQ3hDLE9BQU8sU0FBUztFQUNkLE9BQU8sS0FBSyxHQUFHLEdBQUcsVUFBVSxDQUFDLE1BQU07QUFDckM7QUFFQSwyQ0FBMkMsR0FDM0MsT0FBTyxTQUFTLE1BQU0sSUFBa0I7RUFDdEMsS0FBSyxLQUFLLENBQUM7RUFDWCxPQUFPO0FBQ1Q7QUFFQSx1Q0FBdUMsR0FDdkMsT0FBTyxTQUFTLFNBQVMsSUFBWTtFQUNuQyxJQUFJO0lBQ0YsTUFBTSxRQUFRLEtBQUssU0FBUyxDQUFDO0lBQzdCLElBQUksTUFBTSxNQUFNLEVBQ2QsT0FBTztJQUNULElBQUksTUFBTSxXQUFXLEVBQ25CLE9BQU87RUFDWCxFQUFFLE9BQU07RUFDTixnQkFBZ0I7RUFDbEI7RUFDQSxPQUFPO0FBQ1Q7QUFvQkE7Ozs7Q0FJQyxHQUNELE9BQU8sZUFBZSxLQUFLLElBQVksRUFBRSxFQUFFLE9BQU8sS0FBSyxFQUFFLFdBQVcsSUFBSSxFQUFFLFFBQVEsS0FBSyxFQUFFLGNBQWMsS0FBSyxFQUFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsY0FBYyxFQUFlLEdBQUcsQ0FBQyxDQUFDO0VBQ3hLLE9BQU8sS0FBSyxVQUFVLENBQUMsTUFBTTtFQUM3QixJQUFJLENBQUMsS0FBSyxRQUFRLENBQUMsTUFDakIsUUFBUTtFQUNWLE1BQU0sVUFBVSxNQUFNLE1BQU0sU0FBUyxDQUFDLFdBQVcsTUFBTTtJQUFFO0lBQU0sY0FBYztJQUFNLGFBQWE7SUFBYTtJQUFTO0lBQWlCO0VBQWU7RUFDdEosT0FBTyxRQUNKLE1BQU0sQ0FBQyxDQUFDLFFBQVUsQUFBQyxTQUFTLE1BQU0sTUFBTSxJQUFNLGVBQWUsTUFBTSxXQUFXLEVBQzlFLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFO0lBQ1osT0FBTyxLQUFLLFVBQVUsQ0FBQyxNQUFNO0lBQzdCLE9BQU8sQUFBQyxZQUFZLEtBQUssVUFBVSxDQUFDLFFBQVMsS0FBSyxLQUFLLENBQUMsS0FBSyxNQUFNLElBQUk7RUFDekU7QUFDSiJ9
@@ -0,0 +1 @@
1
+ Lorem ipsum
@@ -0,0 +1 @@
1
+ Lorem ipsum
@@ -0,0 +1 @@
1
+ Lorem ipsum
@@ -0,0 +1 @@
1
+ // Lorem ipsum
package/format.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ /** Format a country code as a flag emoji. */ export declare function countryFlag(code: string): string;
2
+ /** Normalize string to uppercase and remove diacritics. */ export declare function unfd(string: string): string;
3
+ /** Normalize string to lowercase and remove diacritics. */ export declare function lnfd(string: string): string;
4
+ /**
5
+ * Strip emojis from a string.
6
+ *
7
+ * Keycap emojis are converted back to their base character
8
+ * and flag emojis back to their two-letter country code.
9
+ */ export declare function stripEmojis(string: string): string;
package/format.js ADDED
@@ -0,0 +1,21 @@
1
+ /** Format a country code as a flag emoji. */ export function countryFlag(code) {
2
+ const cc = code.trim().toUpperCase();
3
+ if (!/^[A-Z]{2}$/.test(cc)) return code;
4
+ const A = 0x1f1e6;
5
+ return String.fromCodePoint(A + (cc.charCodeAt(0) - 65), A + (cc.charCodeAt(1) - 65));
6
+ }
7
+ /** Normalize string to uppercase and remove diacritics. */ export function unfd(string) {
8
+ return string.toLocaleUpperCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
9
+ }
10
+ /** Normalize string to lowercase and remove diacritics. */ export function lnfd(string) {
11
+ return unfd(string).toLocaleLowerCase();
12
+ }
13
+ /**
14
+ * Strip emojis from a string.
15
+ *
16
+ * Keycap emojis are converted back to their base character
17
+ * and flag emojis back to their two-letter country code.
18
+ */ export function stripEmojis(string) {
19
+ return string.replace(/([#*0-9])\uFE0F?\u20E3/gu, "$1").replace(/\p{Regional_Indicator}/gu, (char)=>String.fromCharCode(char.codePointAt(0) - 0x1f1e6 + 65)).replace(/\p{Extended_Pictographic}(?:\uFE0F|\p{Emoji_Modifier}|\u200D\p{Extended_Pictographic})*/gu, "");
20
+ }
21
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9mb3JtYXQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIEZvcm1hdCBhIGNvdW50cnkgY29kZSBhcyBhIGZsYWcgZW1vamkuICovXG5leHBvcnQgZnVuY3Rpb24gY291bnRyeUZsYWcoY29kZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgY2MgPSBjb2RlLnRyaW0oKS50b1VwcGVyQ2FzZSgpXG4gIGlmICghL15bQS1aXXsyfSQvLnRlc3QoY2MpKVxuICAgIHJldHVybiBjb2RlXG4gIGNvbnN0IEEgPSAweDFmMWU2XG4gIHJldHVybiBTdHJpbmcuZnJvbUNvZGVQb2ludChBICsgKGNjLmNoYXJDb2RlQXQoMCkgLSA2NSksIEEgKyAoY2MuY2hhckNvZGVBdCgxKSAtIDY1KSlcbn1cblxuLyoqIE5vcm1hbGl6ZSBzdHJpbmcgdG8gdXBwZXJjYXNlIGFuZCByZW1vdmUgZGlhY3JpdGljcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmZkKHN0cmluZzogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHN0cmluZy50b0xvY2FsZVVwcGVyQ2FzZSgpLm5vcm1hbGl6ZShcIk5GRFwiKS5yZXBsYWNlKC9bXFx1MDMwMC1cXHUwMzZmXS9nLCBcIlwiKVxufVxuXG4vKiogTm9ybWFsaXplIHN0cmluZyB0byBsb3dlcmNhc2UgYW5kIHJlbW92ZSBkaWFjcml0aWNzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxuZmQoc3RyaW5nOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gdW5mZChzdHJpbmcpLnRvTG9jYWxlTG93ZXJDYXNlKClcbn1cblxuLyoqXG4gKiBTdHJpcCBlbW9qaXMgZnJvbSBhIHN0cmluZy5cbiAqXG4gKiBLZXljYXAgZW1vamlzIGFyZSBjb252ZXJ0ZWQgYmFjayB0byB0aGVpciBiYXNlIGNoYXJhY3RlclxuICogYW5kIGZsYWcgZW1vamlzIGJhY2sgdG8gdGhlaXIgdHdvLWxldHRlciBjb3VudHJ5IGNvZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzdHJpcEVtb2ppcyhzdHJpbmc6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBzdHJpbmdcbiAgICAucmVwbGFjZSgvKFsjKjAtOV0pXFx1RkUwRj9cXHUyMEUzL2d1LCBcIiQxXCIpXG4gICAgLnJlcGxhY2UoL1xccHtSZWdpb25hbF9JbmRpY2F0b3J9L2d1LCAoY2hhcikgPT4gU3RyaW5nLmZyb21DaGFyQ29kZShjaGFyLmNvZGVQb2ludEF0KDApISAtIDB4MWYxZTYgKyA2NSkpXG4gICAgLnJlcGxhY2UoL1xccHtFeHRlbmRlZF9QaWN0b2dyYXBoaWN9KD86XFx1RkUwRnxcXHB7RW1vamlfTW9kaWZpZXJ9fFxcdTIwMERcXHB7RXh0ZW5kZWRfUGljdG9ncmFwaGljfSkqL2d1LCBcIlwiKVxufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDJDQUEyQyxHQUMzQyxPQUFPLFNBQVMsWUFBWSxJQUFZO0VBQ3RDLE1BQU0sS0FBSyxLQUFLLElBQUksR0FBRyxXQUFXO0VBQ2xDLElBQUksQ0FBQyxhQUFhLElBQUksQ0FBQyxLQUNyQixPQUFPO0VBQ1QsTUFBTSxJQUFJO0VBQ1YsT0FBTyxPQUFPLGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxVQUFVLENBQUMsS0FBSyxFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsVUFBVSxDQUFDLEtBQUssRUFBRTtBQUNyRjtBQUVBLHlEQUF5RCxHQUN6RCxPQUFPLFNBQVMsS0FBSyxNQUFjO0VBQ2pDLE9BQU8sT0FBTyxpQkFBaUIsR0FBRyxTQUFTLENBQUMsT0FBTyxPQUFPLENBQUMsb0JBQW9CO0FBQ2pGO0FBRUEseURBQXlELEdBQ3pELE9BQU8sU0FBUyxLQUFLLE1BQWM7RUFDakMsT0FBTyxLQUFLLFFBQVEsaUJBQWlCO0FBQ3ZDO0FBRUE7Ozs7O0NBS0MsR0FDRCxPQUFPLFNBQVMsWUFBWSxNQUFjO0VBQ3hDLE9BQU8sT0FDSixPQUFPLENBQUMsNEJBQTRCLE1BQ3BDLE9BQU8sQ0FBQyw0QkFBNEIsQ0FBQyxPQUFTLE9BQU8sWUFBWSxDQUFDLEtBQUssV0FBVyxDQUFDLEtBQU0sVUFBVSxLQUNuRyxPQUFPLENBQUMsNkZBQTZGO0FBQzFHIn0=
package/identicon.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A deterministic identicon as an `svg+xml` data URL.
3
+ *
4
+ * A mirror-symmetric pixel grid with a seeded hue to generate a simple recognisable default avatar.
5
+ */ export declare function identicon(seed: string, {}?: {
6
+ }): string;
package/identicon.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A deterministic identicon as an `svg+xml` data URL.
3
+ *
4
+ * A mirror-symmetric pixel grid with a seeded hue to generate a simple recognisable default avatar.
5
+ */ export function identicon(seed, { size = 5 } = {}) {
6
+ if (!Number.isInteger(size) || size <= 0) throw new RangeError(`Invalid identicon size: ${size}`);
7
+ // FNV-1a 32-bit hash of the seed
8
+ let h = 0x811c9dc5;
9
+ for(let i = 0; i < seed.length; i++){
10
+ h ^= seed.charCodeAt(i);
11
+ h = Math.imul(h, 0x01000193);
12
+ }
13
+ h >>>= 0;
14
+ const hue = h % 360;
15
+ const fg = `hsl(${hue} 58% 62%)`;
16
+ const bg = `hsl(${hue} 26% 18%)`;
17
+ // Seed an LCG from the hash
18
+ let r = h || 1;
19
+ const next = ()=>r = Math.imul(r, 1103515245) + 12345 >>> 0;
20
+ const cells = [];
21
+ for(let y = 0; y < size; y++){
22
+ for(let x = 0; x < Math.ceil(size / 2); x++){
23
+ if (next() & 0x10000) {
24
+ cells.push(`<rect x="${x}" y="${y}" width="1" height="1"/>`);
25
+ if (x < Math.floor(size / 2)) cells.push(`<rect x="${size - 1 - x}" y="${y}" width="1" height="1"/>`);
26
+ }
27
+ }
28
+ }
29
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${size} ${size}" ` + `shape-rendering="crispEdges"><rect width="${size}" height="${size}" fill="${bg}"/>` + `<g fill="${fg}">${cells.join("")}</g></svg>`;
30
+ return `data:image/svg+xml;base64,${btoa(svg)}`;
31
+ }
32
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9pZGVudGljb24udHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBIGRldGVybWluaXN0aWMgaWRlbnRpY29uIGFzIGFuIGBzdmcreG1sYCBkYXRhIFVSTC5cbiAqXG4gKiBBIG1pcnJvci1zeW1tZXRyaWMgcGl4ZWwgZ3JpZCB3aXRoIGEgc2VlZGVkIGh1ZSB0byBnZW5lcmF0ZSAgYSBzaW1wbGUgcmVjb2duaXNhYmxlIGRlZmF1bHQgYXZhdGFyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaWRlbnRpY29uKHNlZWQ6IHN0cmluZywgeyBzaXplID0gNSB9ID0ge30pOiBzdHJpbmcge1xuICBpZiAoKCFOdW1iZXIuaXNJbnRlZ2VyKHNpemUpKSB8fCAoc2l6ZSA8PSAwKSlcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcihgSW52YWxpZCBpZGVudGljb24gc2l6ZTogJHtzaXplfWApXG4gIC8vIEZOVi0xYSAzMi1iaXQgaGFzaCBvZiB0aGUgc2VlZFxuICBsZXQgaCA9IDB4ODExYzlkYzVcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWVkLmxlbmd0aDsgaSsrKSB7XG4gICAgaCBePSBzZWVkLmNoYXJDb2RlQXQoaSlcbiAgICBoID0gTWF0aC5pbXVsKGgsIDB4MDEwMDAxOTMpXG4gIH1cbiAgaCA+Pj49IDBcbiAgY29uc3QgaHVlID0gaCAlIDM2MFxuICBjb25zdCBmZyA9IGBoc2woJHtodWV9IDU4JSA2MiUpYFxuICBjb25zdCBiZyA9IGBoc2woJHtodWV9IDI2JSAxOCUpYFxuICAvLyBTZWVkIGFuIExDRyBmcm9tIHRoZSBoYXNoXG4gIGxldCByID0gaCB8fCAxXG4gIGNvbnN0IG5leHQgPSAoKSA9PiAociA9IChNYXRoLmltdWwociwgMTEwMzUxNTI0NSkgKyAxMjM0NSkgPj4+IDApXG4gIGNvbnN0IGNlbGxzOiBzdHJpbmdbXSA9IFtdXG4gIGZvciAobGV0IHkgPSAwOyB5IDwgc2l6ZTsgeSsrKSB7XG4gICAgZm9yIChsZXQgeCA9IDA7IHggPCBNYXRoLmNlaWwoc2l6ZSAvIDIpOyB4KyspIHtcbiAgICAgIGlmIChuZXh0KCkgJiAweDEwMDAwKSB7XG4gICAgICAgIGNlbGxzLnB1c2goYDxyZWN0IHg9XCIke3h9XCIgeT1cIiR7eX1cIiB3aWR0aD1cIjFcIiBoZWlnaHQ9XCIxXCIvPmApXG4gICAgICAgIGlmICh4IDwgTWF0aC5mbG9vcihzaXplIC8gMikpXG4gICAgICAgICAgY2VsbHMucHVzaChgPHJlY3QgeD1cIiR7c2l6ZSAtIDEgLSB4fVwiIHk9XCIke3l9XCIgd2lkdGg9XCIxXCIgaGVpZ2h0PVwiMVwiLz5gKVxuICAgICAgfVxuICAgIH1cbiAgfVxuICBjb25zdCBzdmcgPSBgPHN2ZyB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgdmlld0JveD1cIjAgMCAke3NpemV9ICR7c2l6ZX1cIiBgICtcbiAgICBgc2hhcGUtcmVuZGVyaW5nPVwiY3Jpc3BFZGdlc1wiPjxyZWN0IHdpZHRoPVwiJHtzaXplfVwiIGhlaWdodD1cIiR7c2l6ZX1cIiBmaWxsPVwiJHtiZ31cIi8+YCArXG4gICAgYDxnIGZpbGw9XCIke2ZnfVwiPiR7Y2VsbHMuam9pbihcIlwiKX08L2c+PC9zdmc+YFxuICByZXR1cm4gYGRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsJHtidG9hKHN2Zyl9YFxufVxuIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0NBSUMsR0FDRCxPQUFPLFNBQVMsVUFBVSxJQUFZLEVBQUUsRUFBRSxPQUFPLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztFQUN2RCxJQUFJLEFBQUMsQ0FBQyxPQUFPLFNBQVMsQ0FBQyxTQUFXLFFBQVEsR0FDeEMsTUFBTSxJQUFJLFdBQVcsQ0FBQyx3QkFBd0IsRUFBRSxNQUFNO0VBQ3hELGlDQUFpQztFQUNqQyxJQUFJLElBQUk7RUFDUixJQUFLLElBQUksSUFBSSxHQUFHLElBQUksS0FBSyxNQUFNLEVBQUUsSUFBSztJQUNwQyxLQUFLLEtBQUssVUFBVSxDQUFDO0lBQ3JCLElBQUksS0FBSyxJQUFJLENBQUMsR0FBRztFQUNuQjtFQUNBLE9BQU87RUFDUCxNQUFNLE1BQU0sSUFBSTtFQUNoQixNQUFNLEtBQUssQ0FBQyxJQUFJLEVBQUUsSUFBSSxTQUFTLENBQUM7RUFDaEMsTUFBTSxLQUFLLENBQUMsSUFBSSxFQUFFLElBQUksU0FBUyxDQUFDO0VBQ2hDLDRCQUE0QjtFQUM1QixJQUFJLElBQUksS0FBSztFQUNiLE1BQU0sT0FBTyxJQUFPLElBQUksQUFBQyxLQUFLLElBQUksQ0FBQyxHQUFHLGNBQWMsVUFBVztFQUMvRCxNQUFNLFFBQWtCLEVBQUU7RUFDMUIsSUFBSyxJQUFJLElBQUksR0FBRyxJQUFJLE1BQU0sSUFBSztJQUM3QixJQUFLLElBQUksSUFBSSxHQUFHLElBQUksS0FBSyxJQUFJLENBQUMsT0FBTyxJQUFJLElBQUs7TUFDNUMsSUFBSSxTQUFTLFNBQVM7UUFDcEIsTUFBTSxJQUFJLENBQUMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSx3QkFBd0IsQ0FBQztRQUMzRCxJQUFJLElBQUksS0FBSyxLQUFLLENBQUMsT0FBTyxJQUN4QixNQUFNLElBQUksQ0FBQyxDQUFDLFNBQVMsRUFBRSxPQUFPLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSx3QkFBd0IsQ0FBQztNQUMxRTtJQUNGO0VBQ0Y7RUFDQSxNQUFNLE1BQU0sQ0FBQyxxREFBcUQsRUFBRSxLQUFLLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxHQUNsRixDQUFDLDBDQUEwQyxFQUFFLEtBQUssVUFBVSxFQUFFLEtBQUssUUFBUSxFQUFFLEdBQUcsR0FBRyxDQUFDLEdBQ3BGLENBQUMsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFLE1BQU0sSUFBSSxDQUFDLElBQUksVUFBVSxDQUFDO0VBQy9DLE9BQU8sQ0FBQywwQkFBMEIsRUFBRSxLQUFLLE1BQU07QUFDakQifQ==
package/imgb64.d.ts ADDED
@@ -0,0 +1 @@
1
+ /** Download a remote PNG and return it as a base64 data URL. */ export declare function imgb64(url: string): Promise<string>;
package/imgb64.js ADDED
@@ -0,0 +1,15 @@
1
+ import { encodeBase64 } from "@std/encoding/base64";
2
+ /** Transparent 1x1 PNG data URL. */ const fallback = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==";
3
+ /** Download a remote PNG and return it as a base64 data URL. */ export async function imgb64(url) {
4
+ try {
5
+ const response = await fetch(url);
6
+ if (!response.ok) {
7
+ await response.body?.cancel();
8
+ return fallback;
9
+ }
10
+ return `data:image/png;base64,${encodeBase64(await response.arrayBuffer())}`;
11
+ } catch {
12
+ return fallback;
13
+ }
14
+ }
15
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9pbWdiNjQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgZW5jb2RlQmFzZTY0IH0gZnJvbSBcIkBzdGQvZW5jb2RpbmcvYmFzZTY0XCJcblxuLyoqIFRyYW5zcGFyZW50IDF4MSBQTkcgZGF0YSBVUkwuICovXG5jb25zdCBmYWxsYmFjayA9IFwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFBRUFBQUFCQ0FBQUFBQTZmcHRWQUFBQUNrbEVRVlFJMTJOZ0FBQUFBZ0FCNGlHOE13QUFBQUJKUlU1RXJrSmdnZz09XCJcblxuLyoqIERvd25sb2FkIGEgcmVtb3RlIFBORyBhbmQgcmV0dXJuIGl0IGFzIGEgYmFzZTY0IGRhdGEgVVJMLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGltZ2I2NCh1cmw6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nPiB7XG4gIHRyeSB7XG4gICAgY29uc3QgcmVzcG9uc2UgPSBhd2FpdCBmZXRjaCh1cmwpXG4gICAgaWYgKCFyZXNwb25zZS5vaykge1xuICAgICAgYXdhaXQgcmVzcG9uc2UuYm9keT8uY2FuY2VsKClcbiAgICAgIHJldHVybiBmYWxsYmFja1xuICAgIH1cbiAgICByZXR1cm4gYGRhdGE6aW1hZ2UvcG5nO2Jhc2U2NCwke2VuY29kZUJhc2U2NChhd2FpdCByZXNwb25zZS5hcnJheUJ1ZmZlcigpKX1gXG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxsYmFja1xuICB9XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsU0FBUyxZQUFZLFFBQVEsdUJBQXNCO0FBRW5ELGtDQUFrQyxHQUNsQyxNQUFNLFdBQVc7QUFFakIsOERBQThELEdBQzlELE9BQU8sZUFBZSxPQUFPLEdBQVc7RUFDdEMsSUFBSTtJQUNGLE1BQU0sV0FBVyxNQUFNLE1BQU07SUFDN0IsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFO01BQ2hCLE1BQU0sU0FBUyxJQUFJLEVBQUU7TUFDckIsT0FBTztJQUNUO0lBQ0EsT0FBTyxDQUFDLHNCQUFzQixFQUFFLGFBQWEsTUFBTSxTQUFTLFdBQVcsS0FBSztFQUM5RSxFQUFFLE9BQU07SUFDTixPQUFPO0VBQ1Q7QUFDRiJ9
package/mod.ts ADDED
@@ -0,0 +1 @@
1
+ // No default exports
package/noop.d.ts ADDED
@@ -0,0 +1 @@
1
+ /** No operation. */ export declare function noop(): void;
package/noop.js ADDED
@@ -0,0 +1,2 @@
1
+ /** No operation. */ export function noop() {}
2
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9saWJzL2xpYnMvQGxpYnMvdG9vbGJveC9ub29wLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKiBObyBvcGVyYXRpb24uICovXG5leHBvcnQgZnVuY3Rpb24gbm9vcCgpOiB2b2lkIHt9XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsa0JBQWtCLEdBQ2xCLE9BQU8sU0FBUyxRQUFjIn0=