@protobufjs/codegen
Advanced tools
Comparing version 1.0.8 to 2.0.0
export = codegen; | ||
/** | ||
* A codegen instance as returned by {@link codegen}, that also is a sprintf-like appender function. | ||
* @typedef Codegen | ||
* @type {function} | ||
* @param {string} format Format string | ||
* @param {...*} args Replacements | ||
* @returns {Codegen} Itself | ||
* @property {function(string=):string} str Stringifies the so far generated function source. | ||
* @property {function(string=, Object=):function} eof Ends generation and builds the function whilst applying a scope. | ||
* Appends code to the function's body. | ||
* @param [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any | ||
* @param [formatParams] Format parameters | ||
* @returns Itself or the generated function if finished | ||
*/ | ||
type Codegen = (format: string, ...args: any[]) => Codegen; | ||
type Codegen = (formatStringOrScope?: (string|{ [k: string]: any }), ...formatParams: any[]) => (Codegen|Function); | ||
/** | ||
* A closure for generating functions programmatically. | ||
* @memberof util | ||
* @namespace | ||
* @function | ||
* @param {...string} params Function parameter names | ||
* @returns {Codegen} Codegen instance | ||
* @property {boolean} supported Whether code generation is supported by the environment. | ||
* @property {boolean} verbose=false When set to true, codegen will log generated code to console. Useful for debugging. | ||
* @property {function(string, ...*):string} sprintf Underlying sprintf implementation | ||
* Begins generating a function. | ||
* @param [functionParams] Function parameter names | ||
* @param [functionName] Function name if not anonymous | ||
* @returns Appender that appends code to the function's body | ||
*/ | ||
declare function codegen(...params: string[]): Codegen; | ||
declare function codegen(functionParams?: string[], functionName?: string): Codegen; |
174
index.js
"use strict"; | ||
module.exports = codegen; | ||
var blockOpenRe = /[{[]$/, | ||
blockCloseRe = /^[}\]]/, | ||
casingRe = /:$/, | ||
branchRe = /^\s*(?:if|}?else if|while|for)\b|\b(?:else)\s*$/, | ||
breakRe = /\b(?:break|continue)(?: \w+)?;?$|^\s*return\b/; | ||
codegen.verbose = false; | ||
/** | ||
* A closure for generating functions programmatically. | ||
* Begins generating a function. | ||
* @memberof util | ||
* @namespace | ||
* @function | ||
* @param {...string} params Function parameter names | ||
* @returns {Codegen} Codegen instance | ||
* @property {boolean} supported Whether code generation is supported by the environment. | ||
* @property {boolean} verbose=false When set to true, codegen will log generated code to console. Useful for debugging. | ||
* @property {function(string, ...*):string} sprintf Underlying sprintf implementation | ||
* @param {string[]} [functionParams] Function parameter names | ||
* @param {string} [functionName] Function name if not anonymous | ||
* @returns {Codegen} Appender that appends code to the function's body | ||
* @property {boolean} verbose=false When set to `true`, codegen will log generated code to console. Useful for debugging. | ||
*/ | ||
function codegen() { | ||
var params = [], | ||
src = [], | ||
indent = 1, | ||
inCase = false; | ||
for (var i = 0; i < arguments.length;) | ||
params.push(arguments[i++]); | ||
function codegen(functionParams, functionName) { | ||
/* istanbul ignore if */ | ||
if (typeof functionParams === "string") { | ||
functionName = functionParams; | ||
functionParams = undefined; | ||
} | ||
var body = []; | ||
/** | ||
* A codegen instance as returned by {@link codegen}, that also is a sprintf-like appender function. | ||
* Appends code to the function's body or finishes generation. | ||
* @typedef Codegen | ||
* @type {function} | ||
* @param {string} format Format string | ||
* @param {...*} args Replacements | ||
* @returns {Codegen} Itself | ||
* @property {function(string=):string} str Stringifies the so far generated function source. | ||
* @property {function(string=, Object=):function} eof Ends generation and builds the function whilst applying a scope. | ||
* @param {string|Object.<string,*>} [formatStringOrScope] Format string or, to finish the function, an object of additional scope variables, if any | ||
* @param {...*} [formatParams] Format parameters | ||
* @returns {Codegen|Function} Itself or the generated function if finished | ||
*/ | ||
/**/ | ||
function gen() { | ||
var args = [], | ||
i = 0; | ||
for (; i < arguments.length;) | ||
args.push(arguments[i++]); | ||
var line = sprintf.apply(null, args); | ||
var level = indent; | ||
if (src.length) { | ||
var prev = src[src.length - 1]; | ||
// block open or one time branch | ||
if (blockOpenRe.test(prev)) | ||
level = ++indent; // keep | ||
else if (branchRe.test(prev)) | ||
++level; // once | ||
// casing | ||
if (casingRe.test(prev) && !casingRe.test(line)) { | ||
level = ++indent; | ||
inCase = true; | ||
} else if (inCase && breakRe.test(prev)) { | ||
level = --indent; | ||
inCase = false; | ||
} | ||
// block close | ||
if (blockCloseRe.test(line)) | ||
level = --indent; | ||
function codegen(formatStringOrScope) { | ||
if (typeof formatStringOrScope !== "string") { | ||
var scopeParams = [], | ||
scopeValues = []; | ||
if (formatStringOrScope) | ||
for (var i = 0, keys = Object.keys(formatStringOrScope); i < keys.length; ++i) { | ||
scopeParams.push(keys[i]); | ||
scopeValues.push(formatStringOrScope[keys[i]]); | ||
} | ||
var source = codegen.toString(); | ||
if (codegen.verbose) | ||
console.log("codegen: " + source); // eslint-disable-line no-console | ||
return Function.apply(null, scopeParams.concat("return " + source)).apply(null, scopeValues); | ||
} | ||
for (i = 0; i < level; ++i) | ||
line = "\t" + line; | ||
src.push(line); | ||
return gen; | ||
var formatParams = Array.prototype.slice.call(arguments, 1), | ||
formatParamsIndex = 0; | ||
formatStringOrScope = formatStringOrScope.replace(/%([dfjs])/g, function($0, $1) { | ||
var value = formatParams[formatParamsIndex++]; | ||
return $1 === "d" ? Math.floor(value) | ||
: $1 === "f" ? Number(value) | ||
: $1 === "j" ? JSON.stringify(value) | ||
: value; | ||
}); | ||
if (formatParamsIndex !== formatParams.length) | ||
throw Error("parameter count mismatch"); | ||
body.push(formatStringOrScope); | ||
return codegen; | ||
} | ||
/** | ||
* Stringifies the so far generated function source. | ||
* @param {string} [name] Function name, defaults to generate an anonymous function | ||
* @returns {string} Function source using tabs for indentation | ||
* @inner | ||
*/ | ||
function str(name) { | ||
return "function" + (name ? " " + name.replace(/[^\w_$]/g, "_") : "") + "(" + params.join(",") + ") {\n" + src.join("\n") + "\n}"; | ||
} | ||
codegen.toString = function(functionNameOverride) { | ||
return "function " + (functionNameOverride || functionName || "") + "(" + (functionParams && functionParams.join(",") || "") + "){\n " + body.join("\n ") + "\n}"; | ||
}; | ||
gen.str = str; | ||
/** | ||
* Ends generation and builds the function whilst applying a scope. | ||
* @param {string} [name] Function name, defaults to generate an anonymous function | ||
* @param {Object.<string,*>} [scope] Function scope | ||
* @returns {function} The generated function, with scope applied if specified | ||
* @inner | ||
*/ | ||
function eof(name, scope) { | ||
if (typeof name === "object") { | ||
scope = name; | ||
name = undefined; | ||
} | ||
var source = gen.str(name); | ||
if (codegen.verbose) | ||
console.log("--- codegen ---\n" + source.replace(/^/mg, "> ").replace(/\t/g, " ")); // eslint-disable-line no-console | ||
var keys = Object.keys(scope || (scope = {})); | ||
return Function.apply(null, keys.concat("return " + source)).apply(null, keys.map(function(key) { return scope[key]; })); // eslint-disable-line no-new-func | ||
// ^ Creates a wrapper function with the scoped variable names as its parameters, | ||
// calls it with the respective scoped variable values ^ | ||
// and returns our brand-new properly scoped function. | ||
// | ||
// This works because "Invoking the Function constructor as a function (without using the | ||
// new operator) has the same effect as invoking it as a constructor." | ||
// https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Global_Objects/Function | ||
} | ||
gen.eof = eof; | ||
return gen; | ||
return codegen; | ||
} | ||
function sprintf(format) { | ||
var args = [], | ||
i = 1; | ||
for (; i < arguments.length;) | ||
args.push(arguments[i++]); | ||
i = 0; | ||
format = format.replace(/%([dfjs])/g, function($0, $1) { | ||
switch ($1) { | ||
case "d": | ||
return Math.floor(args[i++]); | ||
case "f": | ||
return Number(args[i++]); | ||
case "j": | ||
return JSON.stringify(args[i++]); | ||
default: | ||
return args[i++]; | ||
} | ||
}); | ||
if (i !== args.length) | ||
throw Error("argument count mismatch"); | ||
return format; | ||
} | ||
codegen.sprintf = sprintf; | ||
codegen.supported = false; try { codegen.supported = codegen("a","b")("return a-b").eof()(2,1) === 1; } catch (e) {} // eslint-disable-line no-empty | ||
codegen.verbose = false; |
{ | ||
"name": "@protobufjs/codegen", | ||
"description": "A closure for generating functions programmatically.", | ||
"version": "1.0.8", | ||
"description": "Minimalistic code generation utility.", | ||
"version": "2.0.0", | ||
"author": "Daniel Wirtz <dcode+protobufjs@dcode.io>", | ||
@@ -6,0 +6,0 @@ "repository": { |
@@ -5,3 +5,3 @@ @protobufjs/codegen | ||
A closure for generating functions programmatically. | ||
Minimalistic code generation utility. | ||
@@ -11,11 +11,39 @@ API | ||
* **codegen(...params: `string`): `function(format: string, ...args: string): self`**<br /> | ||
Begins generating a function programmatically. | ||
* **codegen([functionParams: `string[]`], [functionName: string]): `Codegen`**<br /> | ||
Begins generating a function. | ||
* **codegen#str([name: `string`]): `string`**<br /> | ||
Stringifies the so far generated function source. | ||
* **codegen.verbose = `false`**<br /> | ||
When set to true, codegen will log generated code to console. Useful for debugging. | ||
* **codegen#eof([name?: `string`], [scope: `Object`]): `function`**<br /> | ||
Ends generation and builds the function whilst applying a scope. | ||
Invoking **codegen** returns an appender function that appends code to the function's body and returns itself: | ||
* **Codegen(formatString: `string`, [...formatParams: `any`]): Codegen**<br /> | ||
Appends code to the function's body. The format string can contain placeholders specifying the type of inserted format parameters: | ||
* `%d`: Integer | ||
* `%f`: Floating point number | ||
* `%j`: JSON.stringify'ed value | ||
* `%s`: Raw string | ||
* **Codegen([scope: `Object.<string,*>`]): `Function`**<br /> | ||
Finishes the function and returns it. | ||
* **Codegen.toString([functionNameOverride: `string`]): `string`**<br /> | ||
Returns the function as a string. | ||
Example | ||
------- | ||
```js | ||
var codegen = require("@protobufjs/codegen"); | ||
var add = codegen(["a", "b"], "add") // A function with parameters "a" and "b" named "add" | ||
("// awesome comment") // adds the line to the function's body | ||
("return a + b - c + %d", 1) // replaces %d with 1 and adds the line to the body | ||
({ c: 1 }); // adds "c" with a value of 1 to the function's scope | ||
console.log(add.toString()); // function add(a, b) { return a + b + c + 1 } | ||
console.log(add(1, 2)); // calculates 1 + 2 - 1 + 1 = 3 | ||
``` | ||
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
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.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
48
7309
81
1