@arcjet/sprintf
Advanced tools
+18
| /** | ||
| * Format a string with placeholders using the provided arguments. | ||
| * | ||
| * @param template | ||
| * Template. | ||
| * @param values | ||
| * Values to interpolate. | ||
| * @returns | ||
| * Formatted string. | ||
| */ | ||
| export declare function sprintf(template: string, ...values: unknown[]): string; | ||
| /** | ||
| * Format a string. | ||
| * | ||
| * @deprecated | ||
| * Use `sprintf` instead. | ||
| */ | ||
| export default sprintf; |
+181
| function bigintReplacer(key, value) { | ||
| if (typeof value === "bigint") { | ||
| return "[BigInt]"; | ||
| } | ||
| return value; | ||
| } | ||
| // TODO: Deduplicate this and logger implementation | ||
| function tryStringify(o) { | ||
| try { | ||
| return JSON.stringify(o, bigintReplacer); | ||
| } | ||
| catch { | ||
| return `"[Circular]"`; | ||
| } | ||
| } | ||
| const PERCENT_CODE = 37; /* % */ | ||
| const LOWERCASE_D_CODE = 100; /* d */ | ||
| const LOWERCASE_F_CODE = 102; /* f */ | ||
| const LOWERCASE_I_CODE = 105; /* i */ | ||
| const UPPERCASE_O_CODE = 79; /* O */ | ||
| const LOWERCASE_O_CODE = 111; /* o */ | ||
| const LOWERCASE_J_CODE = 106; /* j */ | ||
| const LOWERCASE_S_CODE = 115; /* s */ | ||
| // Heavily based on https://github.com/pinojs/quick-format-unescaped | ||
| // | ||
| // The MIT License (MIT) | ||
| // | ||
| // Copyright (c) 2016-2019 David Mark Clements | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to deal | ||
| // in the Software without restriction, including without limitation the rights | ||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| // copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in | ||
| // all copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| // SOFTWARE. | ||
| /** | ||
| * Format a string with placeholders using the provided arguments. | ||
| * | ||
| * @param template | ||
| * Template. | ||
| * @param values | ||
| * Values to interpolate. | ||
| * @returns | ||
| * Formatted string. | ||
| */ | ||
| function sprintf(template, ...values) { | ||
| if (typeof template !== "string") { | ||
| throw new TypeError("First argument must be a string"); | ||
| } | ||
| if (values.length === 0) { | ||
| return template; | ||
| } | ||
| let output = ""; | ||
| let valueIndex = 0; | ||
| let lastPosition = -1; | ||
| for (let index = 0; index < template.length;) { | ||
| if (template.charCodeAt(index) === PERCENT_CODE && | ||
| index + 1 < template.length) { | ||
| lastPosition = lastPosition > -1 ? lastPosition : 0; | ||
| switch (template.charCodeAt(index + 1)) { | ||
| case LOWERCASE_D_CODE: | ||
| case LOWERCASE_F_CODE: { | ||
| if (valueIndex >= values.length) { | ||
| break; | ||
| } | ||
| const value = values[valueIndex]; | ||
| if (typeof value !== "number") { | ||
| break; | ||
| } | ||
| if (lastPosition < index) { | ||
| output += template.slice(lastPosition, index); | ||
| } | ||
| output += value; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case LOWERCASE_I_CODE: { | ||
| if (valueIndex >= values.length) { | ||
| break; | ||
| } | ||
| const value = values[valueIndex]; | ||
| if (typeof value !== "number") { | ||
| break; | ||
| } | ||
| if (lastPosition < index) { | ||
| output += template.slice(lastPosition, index); | ||
| } | ||
| output += Math.floor(value); | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case UPPERCASE_O_CODE: | ||
| case LOWERCASE_O_CODE: | ||
| case LOWERCASE_J_CODE: { | ||
| if (valueIndex >= values.length) { | ||
| break; | ||
| } | ||
| const value = values[valueIndex]; | ||
| if (value === undefined) { | ||
| break; | ||
| } | ||
| if (lastPosition < index) { | ||
| output += template.slice(lastPosition, index); | ||
| } | ||
| if (typeof value === "string") { | ||
| output += `'${value}'`; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| if (typeof value === "bigint") { | ||
| output += `"[BigInt]"`; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| if (typeof value === "function") { | ||
| output += value.name || "<anonymous>"; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| output += tryStringify(value); | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case LOWERCASE_S_CODE: { | ||
| if (valueIndex >= values.length) { | ||
| break; | ||
| } | ||
| const value = values[valueIndex]; | ||
| if (typeof value !== "string") { | ||
| break; | ||
| } | ||
| if (lastPosition < index) { | ||
| output += template.slice(lastPosition, index); | ||
| } | ||
| output += value; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case PERCENT_CODE: { | ||
| if (lastPosition < index) { | ||
| output += template.slice(lastPosition, index); | ||
| } | ||
| output += "%"; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| valueIndex--; | ||
| break; | ||
| } | ||
| } | ||
| ++valueIndex; | ||
| } | ||
| ++index; | ||
| } | ||
| if (lastPosition === -1) { | ||
| return template; | ||
| } | ||
| if (lastPosition < template.length) { | ||
| output += template.slice(lastPosition); | ||
| } | ||
| return output; | ||
| } | ||
| export { sprintf as default, sprintf }; |
+29
-32
| { | ||
| "name": "@arcjet/sprintf", | ||
| "version": "1.7.0-rc.1", | ||
| "version": "1.7.0", | ||
| "description": "Arcjet platform-independent replacement for util.format", | ||
@@ -9,6 +9,12 @@ "keywords": [ | ||
| "sprintf", | ||
| "util", | ||
| "utility" | ||
| "utility", | ||
| "util" | ||
| ], | ||
| "license": "Apache-2.0", | ||
| "homepage": "https://arcjet.com", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/arcjet/arcjet-js.git", | ||
| "directory": "sprintf" | ||
| }, | ||
| "bugs": { | ||
@@ -18,3 +24,2 @@ "url": "https://github.com/arcjet/arcjet-js/issues", | ||
| }, | ||
| "license": "Apache-2.0", | ||
| "author": { | ||
@@ -25,40 +30,32 @@ "name": "Arcjet", | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "git+https://github.com/arcjet/arcjet-js.git", | ||
| "directory": "sprintf" | ||
| "engines": { | ||
| "node": ">=22.21.0 <23 || >=24.5.0" | ||
| }, | ||
| "type": "module", | ||
| "main": "./index.js", | ||
| "types": "./index.d.ts", | ||
| "files": [ | ||
| "dist" | ||
| "index.d.ts", | ||
| "index.js" | ||
| ], | ||
| "type": "module", | ||
| "main": "./dist/index.js", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "default": "./dist/index.js" | ||
| }, | ||
| "./package.json": "./package.json" | ||
| }, | ||
| "publishConfig": { | ||
| "access": "public", | ||
| "tag": "latest" | ||
| }, | ||
| "scripts": { | ||
| "build": "tsdown", | ||
| "typecheck": "tsgo --noEmit", | ||
| "test-api": "node --test -- test/*.test.ts", | ||
| "test-coverage": "node --experimental-test-coverage --test -- test/*.test.ts", | ||
| "test": "npm run build && npm run test-coverage" | ||
| "build": "rollup --config rollup.config.js", | ||
| "lint": "eslint .", | ||
| "test-api": "node --test -- test/*.test.js", | ||
| "test-coverage": "node --experimental-test-coverage --test -- test/*.test.js", | ||
| "test": "npm run build && npm run lint && npm run test-coverage" | ||
| }, | ||
| "dependencies": {}, | ||
| "devDependencies": { | ||
| "@arcjet/eslint-config": "1.7.0", | ||
| "@arcjet/rollup-config": "1.7.0", | ||
| "@rollup/wasm-node": "4.62.2", | ||
| "@types/node": "22.19.21", | ||
| "tsdown": "0.22.3", | ||
| "typescript": "6.0.3" | ||
| "eslint": "9.39.4", | ||
| "typescript": "5.9.3" | ||
| }, | ||
| "engines": { | ||
| "node": ">=22.21.0 <23 || >=24.5.0" | ||
| "publishConfig": { | ||
| "access": "public", | ||
| "tag": "latest" | ||
| } | ||
| } |
| //#region src/index.d.ts | ||
| /** | ||
| * Format a string with placeholders using the provided arguments. | ||
| * | ||
| * @param template | ||
| * Template. | ||
| * @param values | ||
| * Values to interpolate. | ||
| * @returns | ||
| * Formatted string. | ||
| */ | ||
| declare function sprintf(template: string, ...values: unknown[]): string; | ||
| //#endregion | ||
| export { sprintf as default, sprintf }; |
-119
| //#region src/index.ts | ||
| function bigintReplacer(key, value) { | ||
| if (typeof value === "bigint") return "[BigInt]"; | ||
| return value; | ||
| } | ||
| function tryStringify(o) { | ||
| try { | ||
| return JSON.stringify(o, bigintReplacer); | ||
| } catch { | ||
| return `"[Circular]"`; | ||
| } | ||
| } | ||
| const PERCENT_CODE = 37; | ||
| const LOWERCASE_D_CODE = 100; | ||
| const LOWERCASE_F_CODE = 102; | ||
| const LOWERCASE_I_CODE = 105; | ||
| const UPPERCASE_O_CODE = 79; | ||
| const LOWERCASE_O_CODE = 111; | ||
| const LOWERCASE_J_CODE = 106; | ||
| const LOWERCASE_S_CODE = 115; | ||
| /** | ||
| * Format a string with placeholders using the provided arguments. | ||
| * | ||
| * @param template | ||
| * Template. | ||
| * @param values | ||
| * Values to interpolate. | ||
| * @returns | ||
| * Formatted string. | ||
| */ | ||
| function sprintf(template, ...values) { | ||
| if (typeof template !== "string") throw new TypeError("First argument must be a string"); | ||
| if (values.length === 0) return template; | ||
| let output = ""; | ||
| let valueIndex = 0; | ||
| let lastPosition = -1; | ||
| for (let index = 0; index < template.length;) { | ||
| if (template.charCodeAt(index) === PERCENT_CODE && index + 1 < template.length) { | ||
| lastPosition = lastPosition > -1 ? lastPosition : 0; | ||
| switch (template.charCodeAt(index + 1)) { | ||
| case LOWERCASE_D_CODE: | ||
| case LOWERCASE_F_CODE: { | ||
| if (valueIndex >= values.length) break; | ||
| const value = values[valueIndex]; | ||
| if (typeof value !== "number") break; | ||
| if (lastPosition < index) output += template.slice(lastPosition, index); | ||
| output += value; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case LOWERCASE_I_CODE: { | ||
| if (valueIndex >= values.length) break; | ||
| const value = values[valueIndex]; | ||
| if (typeof value !== "number") break; | ||
| if (lastPosition < index) output += template.slice(lastPosition, index); | ||
| output += Math.floor(value); | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case UPPERCASE_O_CODE: | ||
| case LOWERCASE_O_CODE: | ||
| case LOWERCASE_J_CODE: { | ||
| if (valueIndex >= values.length) break; | ||
| const value = values[valueIndex]; | ||
| if (value === void 0) break; | ||
| if (lastPosition < index) output += template.slice(lastPosition, index); | ||
| if (typeof value === "string") { | ||
| output += `'${value}'`; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| if (typeof value === "bigint") { | ||
| output += `"[BigInt]"`; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| if (typeof value === "function") { | ||
| output += value.name || "<anonymous>"; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| output += tryStringify(value); | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case LOWERCASE_S_CODE: { | ||
| if (valueIndex >= values.length) break; | ||
| const value = values[valueIndex]; | ||
| if (typeof value !== "string") break; | ||
| if (lastPosition < index) output += template.slice(lastPosition, index); | ||
| output += value; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| break; | ||
| } | ||
| case PERCENT_CODE: | ||
| if (lastPosition < index) output += template.slice(lastPosition, index); | ||
| output += "%"; | ||
| lastPosition = index + 2; | ||
| index++; | ||
| valueIndex--; | ||
| break; | ||
| } | ||
| ++valueIndex; | ||
| } | ||
| ++index; | ||
| } | ||
| if (lastPosition === -1) return template; | ||
| if (lastPosition < template.length) output += template.slice(lastPosition); | ||
| return output; | ||
| } | ||
| //#endregion | ||
| export { sprintf as default, sprintf }; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
23857
15.63%198
50%0
-100%6
100%1
Infinity%