@visulima/fmt 1.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,6 @@
1
+ ## @visulima/fmt 1.0.0 (2023-12-13)
2
+
3
+
4
+ ### Features
5
+
6
+ * new fmt package ([#276](https://github.com/visulima/visulima/issues/276)) ([9fb141e](https://github.com/visulima/visulima/commit/9fb141e31236a3ef7b9e8bc5623dc40d8dd194db))
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 visulima
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,150 @@
1
+ <div align="center">
2
+ <h3>Visulima fmt (util.format)</h3>
3
+ <p>
4
+ Util.format-like unescaped string formatting utility based on <a href="https://github.com/pinojs/quick-format-unescaped">quick-format-unescaped</a>.
5
+ </p>
6
+ </div>
7
+
8
+ <br />
9
+
10
+ <div align="center">
11
+
12
+ [![typescript-image]][typescript-url] [![npm-image]][npm-url] [![license-image]][license-url]
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ <div align="center">
19
+ <p>
20
+ <sup>
21
+ Daniel Bannert's open source work is supported by the community on <a href="https://github.com/sponsors/prisis">GitHub Sponsors</a>
22
+ </sup>
23
+ </p>
24
+ </div>
25
+
26
+ ---
27
+
28
+ ## Install
29
+
30
+ ```sh
31
+ npm install @visulima/fmt
32
+ ```
33
+
34
+ ```sh
35
+ yarn add @visulima/fmt
36
+ ```
37
+
38
+ ```sh
39
+ pnpm add @visulima/fmt
40
+ ```
41
+
42
+ ## Usage
43
+
44
+ ```typescript
45
+ import { format } from "@visulima/fmt";
46
+
47
+ const formatted = format("hello %s %j %d", ["world", [{ obj: true }, 4, { another: "obj" }]]);
48
+
49
+ console.log(formatted); // hello world [{"obj":true},4,{"another":"obj"}] NaN
50
+ ```
51
+
52
+ ### format(fmt, parameters, [options])
53
+
54
+ #### fmt
55
+
56
+ A `printf`-like format string. Example: `'hello %s %j %d'`
57
+
58
+ #### parameters
59
+
60
+ Array of values to be inserted into the `format` string. Example: `['world', {obj:true}]`
61
+
62
+ #### options.stringify
63
+
64
+ Passing an options object as the third parameter with a `stringify` will mean
65
+ any objects will be passed to the supplied function instead of an the
66
+ internal `tryStringify` function. This can be useful when using augmented
67
+ capability serializers such as [`fast-safe-stringify`](http://github.com/davidmarkclements/fast-safe-stringify) or [`fast-redact`](http://github.com/davidmarkclements/fast-redact).
68
+
69
+ > uses `JSON.stringify` instead of `util.inspect`, this means functions _will not be serialized_.
70
+
71
+ ### build
72
+
73
+ With the `build` function you can generate a `format` function that is optimized for your use case.
74
+
75
+ ```typescript
76
+ import { build } from "@visulima/fmt";
77
+
78
+ const format = build({
79
+ formatters: {
80
+ // Pass in whatever % interpolator you want, as long as it's a single character;
81
+ // in this case, it's `t`.
82
+ // The formatter should be a function that takes in a value and returns the formatted value.
83
+ t: (time) => new Date(time).toLocaleString(),
84
+ },
85
+ });
86
+
87
+ const formatted = format("hello %s at %t", ["world", Date.now()]);
88
+
89
+ console.log(formatted); // hello world at 1/1/1970, 1:00:00 AM
90
+ ```
91
+
92
+ ## Format Specifiers
93
+
94
+ Format specifiers are dependent on the type of data-elements that are to be added to the string.
95
+ The most commonly used format specifiers supported are:
96
+
97
+ | Specifier | Description |
98
+ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
99
+ | %s | Converts all values except for `BigInt`, `-0` and `Object` to a string. |
100
+ | %d | Used to convert any value to `Number` of any type other than `BigInt` and `Symbol`. |
101
+ | %i | Used for all values except `BigInt` and `Symbol`. |
102
+ | %f | Used to convert a value to type `Float`. It does not support conversion of values of type `Symbol`. |
103
+ | %j | Used to add JSON data. If a circular reference is present, the string ‘[Circular]’ is added instead. |
104
+ | %o | Adds the string representation of an object. Note that it does not contain non-enumerable characteristics of the object. |
105
+ | %O | Adds the string representation of an object. Note that it will contain all characteristics of the object, including non-enumerable ones. |
106
+ | %% | Used to add the % sign. |
107
+
108
+ ## Benchmark
109
+
110
+ ```sh
111
+ ✓ format simple (3) 4209ms
112
+ name hz min max mean p75 p99 p995 p999 rme samples
113
+ · util.format 2,443,716.24 0.0003 0.8279 0.0004 0.0004 0.0007 0.0008 0.0013 ±0.35% 1221859 fastest
114
+ · @visulima/fmt 2,425,903.43 0.0004 0.1525 0.0004 0.0004 0.0005 0.0006 0.0008 ±0.25% 1212952
115
+ · quick-format-unescaped 1,770,792.34 0.0005 0.3075 0.0006 0.0006 0.0006 0.0006 0.0009 ±0.30% 885397 slowest
116
+
117
+ ✓ format tail object (3) 4922ms
118
+ name hz min max mean p75 p99 p995 p999 rme samples
119
+ · util.format 1,005,974.84 0.0009 0.1501 0.0010 0.0010 0.0013 0.0018 0.0022 ±0.28% 502988 slowest
120
+ · @visulima/fmt 3,082,590.54 0.0003 0.1489 0.0003 0.0003 0.0004 0.0005 0.0006 ±0.30% 1541296 fastest
121
+ · quick-format-unescaped 2,164,780.43 0.0004 0.1654 0.0005 0.0005 0.0005 0.0006 0.0008 ±0.25% 1082391
122
+ ```
123
+
124
+ ## Supported Node.js Versions
125
+
126
+ Libraries in this ecosystem make the best effort to track [Node.js’ release schedule](https://github.com/nodejs/release#release-schedule).
127
+ Here’s [a post on why we think this is important](https://medium.com/the-node-js-collection/maintainers-should-consider-following-node-js-release-schedule-ab08ed4de71a).
128
+
129
+ ## Contributing
130
+
131
+ If you would like to help take a look at the [list of issues](https://github.com/visulima/visulima/issues) and check our [Contributing](.github/CONTRIBUTING.md) guild.
132
+
133
+ > **Note:** please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
134
+
135
+ ## Credits
136
+
137
+ - [quick-format-unescaped](https://github.com/pinojs/quick-format-unescaped)
138
+ - [Daniel Bannert](https://github.com/prisis)
139
+ - [All Contributors](https://github.com/visulima/visulima/graphs/contributors)
140
+
141
+ ## License
142
+
143
+ The visulima fmt is open-sourced software licensed under the [MIT][license-url]
144
+
145
+ [typescript-image]: https://img.shields.io/badge/Typescript-294E80.svg?style=for-the-badge&logo=typescript
146
+ [typescript-url]: "typescript"
147
+ [license-image]: https://img.shields.io/npm/l/@visulima/fmt?color=blueviolet&style=for-the-badge
148
+ [license-url]: LICENSE.md "license"
149
+ [npm-image]: https://img.shields.io/npm/v/@visulima/fmt/latest.svg?style=for-the-badge&logo=npm
150
+ [npm-url]: https://www.npmjs.com/package/@visulima/fmt/v/latest "npm"
@@ -0,0 +1,10 @@
1
+ declare const format: (fmt: NonNullable<Record<string, any> | string>, arguments_?: any[], options?: Options) => string;
2
+ declare const build: (options?: Options) => (f: NonNullable<Record<string, any> | string>, arguments_?: any[], formatOptions?: Omit<Options, "formatters">) => string;
3
+ type FormatterFunction = (argument: any) => string;
4
+ type FormatterMap = Record<number, FormatterFunction>;
5
+ interface Options {
6
+ formatters?: Record<string, FormatterFunction>;
7
+ stringify?: (o: any) => string;
8
+ }
9
+
10
+ export { type FormatterFunction, type FormatterMap, type Options, build, format };
@@ -0,0 +1,10 @@
1
+ declare const format: (fmt: NonNullable<Record<string, any> | string>, arguments_?: any[], options?: Options) => string;
2
+ declare const build: (options?: Options) => (f: NonNullable<Record<string, any> | string>, arguments_?: any[], formatOptions?: Omit<Options, "formatters">) => string;
3
+ type FormatterFunction = (argument: any) => string;
4
+ type FormatterMap = Record<number, FormatterFunction>;
5
+ interface Options {
6
+ formatters?: Record<string, FormatterFunction>;
7
+ stringify?: (o: any) => string;
8
+ }
9
+
10
+ export { type FormatterFunction, type FormatterMap, type Options, build, format };
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ 'use strict';
2
+
3
+ var p=e=>{try{return JSON.stringify(e)}catch{return '"[Circular]"'}},u="%".codePointAt(0),g="s".codePointAt(0),d="d".codePointAt(0),h="f".codePointAt(0),b="i".codePointAt(0),A="O".codePointAt(0),k="o".codePointAt(0),F="j".codePointAt(0),P=(e,n=[],s={})=>{if(typeof e!="string"&&typeof e!="object"||e===null)throw new TypeError(`fmt must be a string or object, got ${e===null?"null":typeof e}`);let c=s.stringify??p,f=1;if(typeof e=="object"){let t=n.length+f;if(t===1)return "{}";let l=Array.from({length:t});l[0]=c(e);for(let a=1;a<t;a++)l[a]=c(n[a-f]);return l.join(" ")}if(n.length===0)return e;let i="",r=1-f,o=-1;for(let t=0;t<e.length;){if(e.codePointAt(t)===u&&t+1<e.length){o=o>-1?o:0;let l=e.codePointAt(t+1);if(l===void 0){++r;break}switch(l){case d:case h:{if(r>=n.length||n[r]==null)break;o<t&&(i+=e.slice(o,t)),i+=Number(n[r]).toString(),o=t+2,t++;break}case b:{if(r>=n.length||n[r]==null)break;o<t&&(i+=e.slice(o,t)),i+=Math.floor(Number(n[r])).toString(),o=t+2,t++;break}case A:case k:case F:{if(r>=n.length||n[r]===void 0)break;o<t&&(i+=e.slice(o,t));let a=n[r],y=typeof a;if(y==="string"){i+=`'${a}'`,o=t+2;break}if(y==="function"){i+=a.name?`[Function: ${a.name}]`:"[Function: <anonymous>]",o=t+2;break}i+=c(a),o=t+2,t++;break}case g:{if(r>=n.length)break;o<t&&(i+=e.slice(o,t)),i+=typeof n[r]=="object"?c(n[r]):String(n[r]),o=t+2,t++;break}case u:{o<t&&(i+=e.slice(o,t)),i+="%",o=t+2,t++,r--;break}}typeof s.formatters?.[l]=="function"&&(i+=s.formatters[l](n[r]),o=t+2),++r;}++t;}return o===-1?e:(o<e.length&&(i+=e.slice(o)),i)},O=(e={})=>{let n={};return typeof e.formatters=="object"&&Object.entries(e.formatters).forEach(([s,c])=>{if(s.length===0)throw new Error(`Formatter %${s} has no characters`);if(s.length>1)throw new Error(`Formatter %${s} has more than one character`);if(typeof c!="function")throw new TypeError(`Formatter for %${s} is not a function`);let f=s.codePointAt(0);if(f===void 0)throw new Error(`${s}.codePointAt(0) failed to return a value, please report this issue`);n[f]=c;}),(s,c=[],f={})=>P(s,c,{...f,formatters:n})};
4
+
5
+ exports.build = O;
6
+ exports.format = P;
7
+ //# sourceMappingURL=out.js.map
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["tryStringify","o","CHAR_PERCENT","CHAR_s","CHAR_d","CHAR_f","CHAR_i","CHAR_O","CHAR_o","CHAR_j","format","fmt","arguments_","options","stringify","offset","argumentsLength","objects","index","result","a","lastPosition","c","temporaryArgument","type","build","formatters","key","formatterFunction","f","formatOptions"],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst tryStringify = (o: any): string => {\n try {\n return JSON.stringify(o);\n } catch {\n return '\"[Circular]\"';\n }\n};\n\nconst CHAR_PERCENT = \"%\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_s = \"s\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_d = \"d\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_f = \"f\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention,unicorn/prevent-abbreviations\nconst CHAR_i = \"i\".codePointAt(0);\nconst CHAR_O = \"O\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_o = \"o\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention,unicorn/prevent-abbreviations\nconst CHAR_j = \"j\".codePointAt(0);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any,sonarjs/cognitive-complexity\nexport const format = (fmt: NonNullable<Record<string, any> | string>, arguments_: any[] = [], options: Options = {}): string => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if ((typeof fmt !== \"string\" && typeof fmt !== \"object\") || fmt === null) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n throw new TypeError(`fmt must be a string or object, got ${fmt === null ? \"null\" : typeof fmt}`);\n }\n\n const stringify = options.stringify ?? tryStringify;\n const offset = 1;\n\n if (typeof fmt === \"object\") {\n const argumentsLength = arguments_.length + offset;\n\n if (argumentsLength === 1) {\n return \"{}\";\n }\n\n const objects = Array.from({ length: argumentsLength });\n\n objects[0] = stringify(fmt);\n\n for (let index = 1; index < argumentsLength; index++) {\n // eslint-disable-next-line security/detect-object-injection\n objects[index] = stringify(arguments_[index - offset]);\n }\n\n return objects.join(\" \");\n }\n\n if (arguments_.length === 0) {\n return fmt;\n }\n\n let result = \"\";\n let a = 1 - offset;\n let lastPosition = -1;\n\n for (let index = 0; index < fmt.length; ) {\n if (fmt.codePointAt(index) === CHAR_PERCENT && index + 1 < fmt.length) {\n lastPosition = lastPosition > -1 ? lastPosition : 0;\n\n const c = fmt.codePointAt(index + 1);\n\n if (c === undefined) {\n ++a;\n break;\n }\n\n // eslint-disable-next-line default-case\n switch (c) {\n case CHAR_d:\n case CHAR_f: {\n if (a >= arguments_.length || arguments_[a as keyof typeof arguments_] == null) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result += Number(arguments_[a as keyof typeof arguments_]).toString();\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_i: {\n if (a >= arguments_.length || arguments_[a as keyof typeof arguments_] == null) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result += Math.floor(Number(arguments_[a as keyof typeof arguments_])).toString();\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_O:\n case CHAR_o:\n case CHAR_j: {\n if (a >= arguments_.length || arguments_[a as keyof typeof arguments_] === undefined) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const temporaryArgument = arguments_[a as keyof typeof arguments_];\n const type = typeof temporaryArgument;\n\n if (type === \"string\") {\n result += `'${temporaryArgument}'`;\n lastPosition = index + 2;\n break;\n }\n\n if (type === \"function\") {\n // eslint-disable-next-line @typescript-eslint/ban-types\n result += (temporaryArgument as Function).name ? `[Function: ${(temporaryArgument as Function).name}]` : \"[Function: <anonymous>]\";\n lastPosition = index + 2;\n break;\n }\n\n result += stringify(temporaryArgument);\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_s: {\n if (a >= arguments_.length) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result +=\n typeof arguments_[a as keyof typeof arguments_] === \"object\"\n ? stringify(arguments_[a as keyof typeof arguments_])\n : String(arguments_[a as keyof typeof arguments_]);\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_PERCENT: {\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result += \"%\";\n lastPosition = index + 2;\n\n index++;\n a--;\n break;\n }\n }\n\n // eslint-disable-next-line security/detect-object-injection\n if (typeof options.formatters?.[c] === \"function\") {\n // eslint-disable-next-line security/detect-object-injection\n result += (options.formatters[c] as FormatterFunction)(arguments_[a as keyof typeof arguments_]);\n lastPosition = index + 2;\n }\n\n ++a;\n }\n\n ++index;\n }\n\n if (lastPosition === -1) {\n return fmt;\n }\n\n if (lastPosition < fmt.length) {\n result += fmt.slice(lastPosition);\n }\n\n return result;\n};\n\nexport const build = (\n options: Options = {},\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): ((f: NonNullable<Record<string, any> | string>, arguments_?: any[], formatOptions?: Omit<Options, \"formatters\">) => string) => {\n const formatters: FormatterMap = {};\n\n if (typeof options.formatters === \"object\") {\n Object.entries(options.formatters).forEach(([key, formatterFunction]) => {\n if (key.length === 0) {\n throw new Error(`Formatter %${key} has no characters`);\n }\n\n if (key.length > 1) {\n throw new Error(`Formatter %${key} has more than one character`);\n }\n\n if (typeof formatterFunction !== \"function\") {\n throw new TypeError(`Formatter for %${key} is not a function`);\n }\n\n const c = key.codePointAt(0);\n\n if (c === undefined) {\n throw new Error(`${key}.codePointAt(0) failed to return a value, please report this issue`);\n }\n\n // eslint-disable-next-line security/detect-object-injection\n formatters[c] = formatterFunction;\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (f: NonNullable<Record<string, any> | string>, arguments_: any[] = [], formatOptions: Omit<Options, \"formatters\"> = {}) =>\n format(f, arguments_, { ...formatOptions, formatters });\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FormatterFunction = (argument: any) => string;\nexport type FormatterMap = Record<number, FormatterFunction>;\n\nexport interface Options {\n formatters?: Record<string, FormatterFunction>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stringify?: (o: any) => string;\n}\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,5 @@
1
+ var p=e=>{try{return JSON.stringify(e)}catch{return '"[Circular]"'}},u="%".codePointAt(0),g="s".codePointAt(0),d="d".codePointAt(0),h="f".codePointAt(0),b="i".codePointAt(0),A="O".codePointAt(0),k="o".codePointAt(0),F="j".codePointAt(0),P=(e,n=[],s={})=>{if(typeof e!="string"&&typeof e!="object"||e===null)throw new TypeError(`fmt must be a string or object, got ${e===null?"null":typeof e}`);let c=s.stringify??p,f=1;if(typeof e=="object"){let t=n.length+f;if(t===1)return "{}";let l=Array.from({length:t});l[0]=c(e);for(let a=1;a<t;a++)l[a]=c(n[a-f]);return l.join(" ")}if(n.length===0)return e;let i="",r=1-f,o=-1;for(let t=0;t<e.length;){if(e.codePointAt(t)===u&&t+1<e.length){o=o>-1?o:0;let l=e.codePointAt(t+1);if(l===void 0){++r;break}switch(l){case d:case h:{if(r>=n.length||n[r]==null)break;o<t&&(i+=e.slice(o,t)),i+=Number(n[r]).toString(),o=t+2,t++;break}case b:{if(r>=n.length||n[r]==null)break;o<t&&(i+=e.slice(o,t)),i+=Math.floor(Number(n[r])).toString(),o=t+2,t++;break}case A:case k:case F:{if(r>=n.length||n[r]===void 0)break;o<t&&(i+=e.slice(o,t));let a=n[r],y=typeof a;if(y==="string"){i+=`'${a}'`,o=t+2;break}if(y==="function"){i+=a.name?`[Function: ${a.name}]`:"[Function: <anonymous>]",o=t+2;break}i+=c(a),o=t+2,t++;break}case g:{if(r>=n.length)break;o<t&&(i+=e.slice(o,t)),i+=typeof n[r]=="object"?c(n[r]):String(n[r]),o=t+2,t++;break}case u:{o<t&&(i+=e.slice(o,t)),i+="%",o=t+2,t++,r--;break}}typeof s.formatters?.[l]=="function"&&(i+=s.formatters[l](n[r]),o=t+2),++r;}++t;}return o===-1?e:(o<e.length&&(i+=e.slice(o)),i)},w=(e={})=>{let n={};return typeof e.formatters=="object"&&Object.entries(e.formatters).forEach(([s,c])=>{if(s.length===0)throw new Error(`Formatter %${s} has no characters`);if(s.length>1)throw new Error(`Formatter %${s} has more than one character`);if(typeof c!="function")throw new TypeError(`Formatter for %${s} is not a function`);let f=s.codePointAt(0);if(f===void 0)throw new Error(`${s}.codePointAt(0) failed to return a value, please report this issue`);n[f]=c;}),(s,c=[],f={})=>P(s,c,{...f,formatters:n})};
2
+
3
+ export { w as build, P as format };
4
+ //# sourceMappingURL=out.js.map
5
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["tryStringify","o","CHAR_PERCENT","CHAR_s","CHAR_d","CHAR_f","CHAR_i","CHAR_O","CHAR_o","CHAR_j","format","fmt","arguments_","options","stringify","offset","argumentsLength","objects","index","result","a","lastPosition","c","temporaryArgument","type","build","formatters","key","formatterFunction","f","formatOptions"],"mappings":"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","sourcesContent":["// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst tryStringify = (o: any): string => {\n try {\n return JSON.stringify(o);\n } catch {\n return '\"[Circular]\"';\n }\n};\n\nconst CHAR_PERCENT = \"%\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_s = \"s\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_d = \"d\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_f = \"f\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention,unicorn/prevent-abbreviations\nconst CHAR_i = \"i\".codePointAt(0);\nconst CHAR_O = \"O\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention\nconst CHAR_o = \"o\".codePointAt(0);\n// eslint-disable-next-line @typescript-eslint/naming-convention,unicorn/prevent-abbreviations\nconst CHAR_j = \"j\".codePointAt(0);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any,sonarjs/cognitive-complexity\nexport const format = (fmt: NonNullable<Record<string, any> | string>, arguments_: any[] = [], options: Options = {}): string => {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if ((typeof fmt !== \"string\" && typeof fmt !== \"object\") || fmt === null) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n throw new TypeError(`fmt must be a string or object, got ${fmt === null ? \"null\" : typeof fmt}`);\n }\n\n const stringify = options.stringify ?? tryStringify;\n const offset = 1;\n\n if (typeof fmt === \"object\") {\n const argumentsLength = arguments_.length + offset;\n\n if (argumentsLength === 1) {\n return \"{}\";\n }\n\n const objects = Array.from({ length: argumentsLength });\n\n objects[0] = stringify(fmt);\n\n for (let index = 1; index < argumentsLength; index++) {\n // eslint-disable-next-line security/detect-object-injection\n objects[index] = stringify(arguments_[index - offset]);\n }\n\n return objects.join(\" \");\n }\n\n if (arguments_.length === 0) {\n return fmt;\n }\n\n let result = \"\";\n let a = 1 - offset;\n let lastPosition = -1;\n\n for (let index = 0; index < fmt.length; ) {\n if (fmt.codePointAt(index) === CHAR_PERCENT && index + 1 < fmt.length) {\n lastPosition = lastPosition > -1 ? lastPosition : 0;\n\n const c = fmt.codePointAt(index + 1);\n\n if (c === undefined) {\n ++a;\n break;\n }\n\n // eslint-disable-next-line default-case\n switch (c) {\n case CHAR_d:\n case CHAR_f: {\n if (a >= arguments_.length || arguments_[a as keyof typeof arguments_] == null) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result += Number(arguments_[a as keyof typeof arguments_]).toString();\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_i: {\n if (a >= arguments_.length || arguments_[a as keyof typeof arguments_] == null) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result += Math.floor(Number(arguments_[a as keyof typeof arguments_])).toString();\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_O:\n case CHAR_o:\n case CHAR_j: {\n if (a >= arguments_.length || arguments_[a as keyof typeof arguments_] === undefined) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n const temporaryArgument = arguments_[a as keyof typeof arguments_];\n const type = typeof temporaryArgument;\n\n if (type === \"string\") {\n result += `'${temporaryArgument}'`;\n lastPosition = index + 2;\n break;\n }\n\n if (type === \"function\") {\n // eslint-disable-next-line @typescript-eslint/ban-types\n result += (temporaryArgument as Function).name ? `[Function: ${(temporaryArgument as Function).name}]` : \"[Function: <anonymous>]\";\n lastPosition = index + 2;\n break;\n }\n\n result += stringify(temporaryArgument);\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_s: {\n if (a >= arguments_.length) {\n break;\n }\n\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result +=\n typeof arguments_[a as keyof typeof arguments_] === \"object\"\n ? stringify(arguments_[a as keyof typeof arguments_])\n : String(arguments_[a as keyof typeof arguments_]);\n lastPosition = index + 2;\n\n index++;\n break;\n }\n case CHAR_PERCENT: {\n if (lastPosition < index) {\n result += fmt.slice(lastPosition, index);\n }\n\n result += \"%\";\n lastPosition = index + 2;\n\n index++;\n a--;\n break;\n }\n }\n\n // eslint-disable-next-line security/detect-object-injection\n if (typeof options.formatters?.[c] === \"function\") {\n // eslint-disable-next-line security/detect-object-injection\n result += (options.formatters[c] as FormatterFunction)(arguments_[a as keyof typeof arguments_]);\n lastPosition = index + 2;\n }\n\n ++a;\n }\n\n ++index;\n }\n\n if (lastPosition === -1) {\n return fmt;\n }\n\n if (lastPosition < fmt.length) {\n result += fmt.slice(lastPosition);\n }\n\n return result;\n};\n\nexport const build = (\n options: Options = {},\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n): ((f: NonNullable<Record<string, any> | string>, arguments_?: any[], formatOptions?: Omit<Options, \"formatters\">) => string) => {\n const formatters: FormatterMap = {};\n\n if (typeof options.formatters === \"object\") {\n Object.entries(options.formatters).forEach(([key, formatterFunction]) => {\n if (key.length === 0) {\n throw new Error(`Formatter %${key} has no characters`);\n }\n\n if (key.length > 1) {\n throw new Error(`Formatter %${key} has more than one character`);\n }\n\n if (typeof formatterFunction !== \"function\") {\n throw new TypeError(`Formatter for %${key} is not a function`);\n }\n\n const c = key.codePointAt(0);\n\n if (c === undefined) {\n throw new Error(`${key}.codePointAt(0) failed to return a value, please report this issue`);\n }\n\n // eslint-disable-next-line security/detect-object-injection\n formatters[c] = formatterFunction;\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return (f: NonNullable<Record<string, any> | string>, arguments_: any[] = [], formatOptions: Omit<Options, \"formatters\"> = {}) =>\n format(f, arguments_, { ...formatOptions, formatters });\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type FormatterFunction = (argument: any) => string;\nexport type FormatterMap = Record<number, FormatterFunction>;\n\nexport interface Options {\n formatters?: Record<string, FormatterFunction>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n stringify?: (o: any) => string;\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,124 @@
1
+ {
2
+ "name": "@visulima/fmt",
3
+ "version": "1.0.0",
4
+ "description": "Util.format-like string formatting utility.",
5
+ "keywords": [
6
+ "visulima",
7
+ "anolilab",
8
+ "fmt",
9
+ "util",
10
+ "util.format",
11
+ "format",
12
+ "string",
13
+ "formatting",
14
+ "string-format",
15
+ "quick-format-unescaped"
16
+ ],
17
+ "homepage": "https://www.visulima.com/docs/package/fmt",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/visulima/visulima.git",
21
+ "directory": "packages/fmt"
22
+ },
23
+ "funding": [
24
+ {
25
+ "type": "github",
26
+ "url": "https://github.com/sponsors/prisis"
27
+ },
28
+ {
29
+ "type": "consulting",
30
+ "url": "https://anolilab.com/support"
31
+ }
32
+ ],
33
+ "license": "MIT",
34
+ "author": {
35
+ "name": "Daniel Bannert",
36
+ "email": "d.bannert@anolilab.de"
37
+ },
38
+ "sideEffects": false,
39
+ "exports": {
40
+ ".": {
41
+ "require": {
42
+ "types": "./dist/index.d.ts",
43
+ "default": "./dist/index.js"
44
+ },
45
+ "import": {
46
+ "types": "./dist/index.d.mts",
47
+ "default": "./dist/index.mjs"
48
+ }
49
+ },
50
+ "./package.json": "./package.json"
51
+ },
52
+ "main": "dist/index.js",
53
+ "module": "dist/index.mjs",
54
+ "source": "src/index.ts",
55
+ "types": "dist/index.d.ts",
56
+ "files": [
57
+ "dist/**",
58
+ "README.md",
59
+ "CHANGELOG.md",
60
+ "LICENSE.md"
61
+ ],
62
+ "scripts": {
63
+ "build": "cross-env NODE_ENV=development tsup",
64
+ "build:prod": "cross-env NODE_ENV=production tsup",
65
+ "clean": "rimraf node_modules dist .eslintcache",
66
+ "dev": "pnpm run build --watch",
67
+ "lint:eslint": "eslint . --ext js,cjs,mjs,jsx,ts,tsx,json,yaml,yml,md,mdx --max-warnings=0 --config .eslintrc.js",
68
+ "lint:eslint:fix": "eslint . --ext js,cjs,mjs,jsx,ts,tsx,json,yaml,yml,md,mdx --max-warnings=0 --config .eslintrc.js --fix",
69
+ "lint:packagejson": "publint --strict",
70
+ "lint:prettier": "prettier --config=.prettierrc.js --check .",
71
+ "lint:prettier:fix": "prettier --config=.prettierrc.js --write .",
72
+ "lint:types": "tsc --noEmit",
73
+ "test": "vitest run",
74
+ "test:bench": "vitest bench",
75
+ "test:coverage": "vitest run --coverage",
76
+ "test:ui": "vitest --ui --coverage.enabled=true",
77
+ "test:watch": "vitest"
78
+ },
79
+ "devDependencies": {
80
+ "@anolilab/eslint-config": "^15.0.2",
81
+ "@anolilab/prettier-config": "^5.0.13",
82
+ "@anolilab/semantic-release-preset": "^8.0.2",
83
+ "@babel/core": "^7.23.5",
84
+ "@rushstack/eslint-plugin-security": "^0.7.1",
85
+ "@types/node": "18.18.8",
86
+ "@vitest/coverage-v8": "^1.0.2",
87
+ "@vitest/ui": "^1.0.2",
88
+ "cross-env": "^7.0.3",
89
+ "eslint": "^8.55.0",
90
+ "eslint-plugin-deprecation": "^2.0.0",
91
+ "eslint-plugin-etc": "^2.0.3",
92
+ "eslint-plugin-import": "npm:eslint-plugin-i@^2.29.0",
93
+ "eslint-plugin-mdx": "^2.2.0",
94
+ "eslint-plugin-vitest": "^0.3.10",
95
+ "eslint-plugin-vitest-globals": "^1.4.0",
96
+ "prettier": "^3.1.0",
97
+ "quick-format-unescaped": "^4.0.4",
98
+ "rimraf": "^5.0.5",
99
+ "semantic-release": "^22.0.10",
100
+ "sort-package-json": "^2.6.0",
101
+ "tsup": "^8.0.1",
102
+ "typescript": "^5.3.3",
103
+ "vitest": "^1.0.2"
104
+ },
105
+ "engines": {
106
+ "node": ">=18.* <=21.*"
107
+ },
108
+ "publishConfig": {
109
+ "access": "public",
110
+ "provenance": true
111
+ },
112
+ "anolilab": {
113
+ "eslint-config": {
114
+ "plugin": {
115
+ "tsdoc": false
116
+ },
117
+ "warn_on_unsupported_typescript_version": false,
118
+ "info_on_disabling_jsx_react_rule": false,
119
+ "info_on_disabling_prettier_conflict_rule": false,
120
+ "info_on_disabling_jsonc_sort_keys_rule": false,
121
+ "info_on_disabling_etc_no_deprecated": false
122
+ }
123
+ }
124
+ }