Rename folders

This commit is contained in:
Christopher Schleiden
2023-02-22 15:52:40 -08:00
parent 16cc4d9bda
commit 2a3d63551f
469 changed files with 0 additions and 0 deletions
+36
View File
@@ -0,0 +1,36 @@
import {Array, BooleanData, ExpressionData, Kind} from "../data";
import {equals} from "../result";
import {FunctionDefinition} from "./info";
export const contains: FunctionDefinition = {
name: "contains",
description:
"`contains( search, item )`\n\nReturns `true` if `search` contains `item`. If `search` is an array, this function returns `true` if the `item` is an element in the array. If `search` is a string, this function returns `true` if the `item` is a substring of `search`. This function is not case sensitive. Casts values to a string.",
minArgs: 2,
maxArgs: 2,
call: (...args: ExpressionData[]): ExpressionData => {
const left = args[0];
const right = args[1];
if (left.primitive) {
const ls = left.coerceString();
if (right.primitive) {
const rs = right.coerceString();
return new BooleanData(ls.toLowerCase().includes(rs.toLowerCase()));
}
} else if (left.kind === Kind.Array) {
const la = left as Array;
if (la.values().length === 0) {
return new BooleanData(false);
}
for (const v of la.values()) {
if (equals(right, v)) {
return new BooleanData(true);
}
}
}
return new BooleanData(false);
}
};
+27
View File
@@ -0,0 +1,27 @@
import {BooleanData, ExpressionData} from "../data";
import {toUpperSpecial} from "../result";
import {FunctionDefinition} from "./info";
export const endswith: FunctionDefinition = {
name: "endsWith",
description:
"`endsWith( searchString, searchValue )`\n\nReturns `true` if `searchString` ends with `searchValue`. This function is not case sensitive. Casts values to a string.",
minArgs: 2,
maxArgs: 2,
call: (...args: ExpressionData[]): ExpressionData => {
const left = args[0];
if (!left.primitive) {
return new BooleanData(false);
}
const right = args[1];
if (!right.primitive) {
return new BooleanData(false);
}
const ls = toUpperSpecial(left.coerceString());
const rs = toUpperSpecial(right.coerceString());
return new BooleanData(ls.endsWith(rs));
}
};
+11
View File
@@ -0,0 +1,11 @@
import {Null, NumberData, StringData} from "../data";
import {format} from "./format";
describe("format", () => {
it("null", () => {
expect(format.call(new StringData("{0}"), new Null())).toEqual(new StringData(""));
});
it("number", () => {
expect(format.call(new StringData("{0}"), new NumberData(42))).toEqual(new StringData("42"));
});
});
+120
View File
@@ -0,0 +1,120 @@
import {ExpressionData, StringData} from "../data";
import {FunctionDefinition} from "./info";
export const format: FunctionDefinition = {
name: "format",
description:
"`format( string, replaceValue0, replaceValue1, ..., replaceValueN)`\n\nReplaces values in the `string`, with the variable `replaceValueN`. Variables in the `string` are specified using the `{N}` syntax, where `N` is an integer. You must specify at least one `replaceValue` and `string`. There is no maximum for the number of variables (`replaceValueN`) you can use. Escape curly braces using double braces.",
minArgs: 1,
maxArgs: 255 /*MAX_ARGUMENTS*/,
call: (...args: ExpressionData[]): ExpressionData => {
const fs = args[0].coerceString();
const result: string[] = [];
let index = 0;
while (index < fs.length) {
const lbrace = fs.indexOf("{", index);
let rbrace = fs.indexOf("}", index);
// Left brace
if (lbrace >= 0 && (rbrace < 0 || rbrace > lbrace)) {
// Escaped left brace
if (safeCharAt(fs, lbrace + 1) === "{") {
result.push(fs.substr(index, lbrace - index + 1));
index = lbrace + 2;
continue;
}
// Left brace, number, optional format specifiers, right brace
if (rbrace > lbrace + 1) {
const argIndex = readArgIndex(fs, lbrace + 1);
if (argIndex.success) {
// Check parameter count
if (1 + argIndex.result > args.length - 1) {
throw new Error(`The following format string references more arguments than were supplied: ${fs}`);
}
// Append the portion before the left brace
if (lbrace > index) {
result.push(fs.substr(index, lbrace - index));
}
// Append the arg
result.push(`${args[1 + argIndex.result].coerceString()}`);
index = rbrace + 1;
continue;
}
}
throw new Error(`The following format string is invalid: ${fs}`);
}
// Right brace
else if (rbrace >= 0) {
// Escaped right brace
if (safeCharAt(fs, rbrace + 1) === "}") {
result.push(fs.substr(index, rbrace - index + 1));
index = rbrace + 2;
} else {
throw new Error(`The following format string is invalid: ${fs}`);
}
}
// Last segment
else {
result.push(fs.substr(index));
break;
}
}
return new StringData(result.join(""));
}
};
function safeCharAt(string: string, index: number): string {
if (string.length > index) {
return string[index];
}
return "\0";
}
function readArgIndex(string: string, startIndex: number): ArgIndex {
// Count the number of digits
let length = 0;
while (true) {
const nextChar = safeCharAt(string, startIndex + length);
if (nextChar >= "0" && nextChar <= "9") {
length++;
} else {
break;
}
}
// Validate at least one digit
if (length < 1) {
return <ArgIndex>{
success: false
};
}
// Parse the number
const endIndex = startIndex + length - 1;
const result = parseInt(string.substr(startIndex, length));
return <ArgIndex>{
success: !isNaN(result),
result: result,
endIndex: endIndex
};
}
interface ArgIndex {
success: boolean;
result: number;
endIndex: number;
}
interface FormatSpecifiers {
success: boolean;
result: string;
rbrace: number;
}
+26
View File
@@ -0,0 +1,26 @@
import {ExpressionData} from "../data";
import {reviver} from "../data/reviver";
import {ExpressionEvaluationError} from "../errors";
import {FunctionDefinition} from "./info";
export const fromjson: FunctionDefinition = {
name: "fromJson",
description:
"`fromJSON(value)`\n\nReturns a JSON object or JSON data type for `value`. You can use this function to provide a JSON object as an evaluated expression or to convert environment variables from a string.",
minArgs: 1,
maxArgs: 1,
call: (...args: ExpressionData[]): ExpressionData => {
const input = args[0];
const is = input.coerceString();
if (is.trim() === "") {
throw new Error("empty input");
}
try {
return JSON.parse(is, reviver);
} catch (e) {
throw new ExpressionEvaluationError("Error parsing JSON when evaluating fromJson", {cause: e});
}
}
};
+14
View File
@@ -0,0 +1,14 @@
import {ExpressionData} from "../data";
export interface FunctionInfo {
name: string;
description?: string;
minArgs: number;
maxArgs: number;
}
export interface FunctionDefinition extends FunctionInfo {
call: (...args: ExpressionData[]) => ExpressionData;
}
+35
View File
@@ -0,0 +1,35 @@
import {Array, ExpressionData, Kind, StringData} from "../data";
import {FunctionDefinition} from "./info";
export const join: FunctionDefinition = {
name: "join",
description:
"`join( array, optionalSeparator )`\n\nThe value for `array` can be an array or a string. All values in `array` are concatenated into a string. If you provide `optionalSeparator`, it is inserted between the concatenated values. Otherwise, the default separator `,` is used. Casts values to a string.",
minArgs: 1,
maxArgs: 2,
call: (...args: ExpressionData[]): ExpressionData => {
// Primitive
if (args[0].primitive) {
return new StringData(args[0].coerceString());
}
// Array
if (args[0].kind === Kind.Array) {
// Separator
let separator = ",";
if (args.length > 1 && args[1].primitive) {
separator = args[1].coerceString();
}
// Convert items to strings
return new StringData(
(args[0] as Array)
.values()
.map(item => item.coerceString())
.join(separator)
);
}
return new StringData("");
}
};
+27
View File
@@ -0,0 +1,27 @@
import {BooleanData, ExpressionData} from "../data";
import {toUpperSpecial} from "../result";
import {FunctionDefinition} from "./info";
export const startswith: FunctionDefinition = {
name: "startsWith",
description:
"`startsWith( searchString, searchValue )`\n\nReturns `true` when `searchString` starts with `searchValue`. This function is not case sensitive. Casts values to a string.",
minArgs: 2,
maxArgs: 2,
call: (...args: ExpressionData[]): ExpressionData => {
const left = args[0];
if (!left.primitive) {
return new BooleanData(false);
}
const right = args[1];
if (!right.primitive) {
return new BooleanData(false);
}
const ls = toUpperSpecial(left.coerceString());
const rs = toUpperSpecial(right.coerceString());
return new BooleanData(ls.startsWith(rs));
}
};
+14
View File
@@ -0,0 +1,14 @@
import {ExpressionData, StringData} from "../data";
import {replacer} from "../data/replacer";
import {FunctionDefinition} from "./info";
export const tojson: FunctionDefinition = {
name: "toJson",
description:
"`toJSON(value)`\n\nReturns a pretty-print JSON representation of `value`. You can use this function to debug the information provided in contexts.",
minArgs: 1,
maxArgs: 1,
call: (...args: ExpressionData[]): ExpressionData => {
return new StringData(JSON.stringify(args[0], replacer, " "));
}
};