feat: Add string insertion operators Append, Prepend, and Insert At
- Added Append operator to insert text at the end of the input - Added Prepend operator to insert text at the start of the input - Added Insert At operator to insert text at a given index within the input - Added tests for all new operations.
This commit is contained in:
parent
ec4f1f5605
commit
861313e493
@ -349,7 +349,10 @@
|
||||
"Sleep",
|
||||
"File Tree",
|
||||
"Take nth bytes",
|
||||
"Drop nth bytes"
|
||||
"Drop nth bytes",
|
||||
"Append",
|
||||
"Prepend",
|
||||
"Insert At"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
64
src/core/operations/Append.mjs
Normal file
64
src/core/operations/Append.mjs
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @author oliver-mitchell [oliver@polymerlabs.dev]
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { DELIM_OPTIONS } from "../lib/Delim.mjs";
|
||||
|
||||
/**
|
||||
* Append operation.
|
||||
*/
|
||||
class Append extends Operation {
|
||||
/**
|
||||
* Append constructor.
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Append";
|
||||
this.module = "Default";
|
||||
this.description = "Add characters to the end of the input string, optionally with respect to a delimeter.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Text",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": ["None", ...DELIM_OPTIONS]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [text, delim] = args;
|
||||
|
||||
if (delim === "None") {
|
||||
return input + text;
|
||||
}
|
||||
|
||||
const output = [],
|
||||
delimChar = Utils.charRep(delim),
|
||||
subs = input.split(Utils.charRep(delim));
|
||||
|
||||
for (let i = 0; i < subs.length; i++) {
|
||||
output.push(subs[i] + text);
|
||||
}
|
||||
|
||||
return output.join(delimChar);
|
||||
}
|
||||
}
|
||||
|
||||
export default Append;
|
||||
88
src/core/operations/InsertAt.mjs
Normal file
88
src/core/operations/InsertAt.mjs
Normal file
@ -0,0 +1,88 @@
|
||||
/**
|
||||
* @author oliver-mitchell [oliver@polymerlabs.dev]
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { DELIM_OPTIONS } from "../lib/Delim.mjs";
|
||||
|
||||
/**
|
||||
* Insert At operation.
|
||||
*/
|
||||
class InsertAt extends Operation {
|
||||
/**
|
||||
* InsertAt constructor.
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Insert At";
|
||||
this.module = "Default";
|
||||
this.description = "Add characters to input string at a given index, optionally with respect to a delimeter.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Text",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Index",
|
||||
"type": "number",
|
||||
"value": 0,
|
||||
"min": 0
|
||||
},
|
||||
{
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": ["None", ...DELIM_OPTIONS]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [text, index, delim] = args;
|
||||
|
||||
if (delim === "None") {
|
||||
return InsertAt.performInsert(input, text, index);
|
||||
}
|
||||
|
||||
const output = [],
|
||||
delimChar = Utils.charRep(delim),
|
||||
subs = input.split(Utils.charRep(delim));
|
||||
|
||||
for (let i = 0; i < subs.length; i++) {
|
||||
output.push(InsertAt.performInsert(subs[i], text, index));
|
||||
}
|
||||
|
||||
return output.join(delimChar);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {string} text
|
||||
* @param {number} index
|
||||
* @returns {string}
|
||||
*/
|
||||
static performInsert(input, text, index) {
|
||||
if (index >= input.length) {
|
||||
return input + text;
|
||||
}
|
||||
|
||||
if (index <= 0) {
|
||||
return text + input;
|
||||
}
|
||||
|
||||
return input.slice(0, index) + text + input.slice(index);
|
||||
}
|
||||
}
|
||||
|
||||
export default InsertAt;
|
||||
64
src/core/operations/Prepend.mjs
Normal file
64
src/core/operations/Prepend.mjs
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @author oliver-mitchell [oliver@polymerlabs.dev]
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import Utils from "../Utils.mjs";
|
||||
import { DELIM_OPTIONS } from "../lib/Delim.mjs";
|
||||
|
||||
/**
|
||||
* Prepend operation.
|
||||
*/
|
||||
class Prepend extends Operation {
|
||||
/**
|
||||
* Prepend constructor.
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Prepend";
|
||||
this.module = "Default";
|
||||
this.description = "Add characters to the start of the input string, optionally with respect to a delimeter.";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
"name": "Text",
|
||||
"type": "binaryString",
|
||||
"value": ""
|
||||
},
|
||||
{
|
||||
"name": "Delimiter",
|
||||
"type": "option",
|
||||
"value": ["None", ...DELIM_OPTIONS]
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [text, delim] = args;
|
||||
|
||||
if (delim === "None") {
|
||||
return input + text;
|
||||
}
|
||||
|
||||
const output = [],
|
||||
delimChar = Utils.charRep(delim),
|
||||
subs = input.split(Utils.charRep(delim));
|
||||
|
||||
for (let i = 0; i < subs.length; i++) {
|
||||
output.push(text + subs[i]);
|
||||
}
|
||||
|
||||
return output.join(delimChar);
|
||||
}
|
||||
}
|
||||
|
||||
export default Prepend;
|
||||
42
tests/operations/tests/Append.mjs
Normal file
42
tests/operations/tests/Append.mjs
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Media operation tests.
|
||||
* @author oliver-mitchell [oliver@polymerlabs.dev]
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Append empty",
|
||||
input: "test",
|
||||
expectedOutput: "test",
|
||||
recipeConfig: [
|
||||
{ op: "Append", args: ["", "None"] } // [text, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Append empty input",
|
||||
input: "",
|
||||
expectedOutput: "test",
|
||||
recipeConfig: [
|
||||
{ op: "Append", args: ["test", "None"] } // [text, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Append with input and text",
|
||||
input: "hello ",
|
||||
expectedOutput: "hello world",
|
||||
recipeConfig: [
|
||||
{ op: "Append", args: ["world", "None"] } // [text, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Append with space delim",
|
||||
input: "hello world",
|
||||
expectedOutput: "hello: world:",
|
||||
recipeConfig: [
|
||||
{ op: "Append", args: [":", "Space"] } // [text, delimiter]
|
||||
]
|
||||
}
|
||||
]);
|
||||
66
tests/operations/tests/InsertAt.mjs
Normal file
66
tests/operations/tests/InsertAt.mjs
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Media operation tests.
|
||||
* @author oliver-mitchell [oliver@polymerlabs.dev]
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Insert At empty",
|
||||
input: "test",
|
||||
expectedOutput: "test",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: ["", 0, "None"] } // [text, index, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Insert At empty input",
|
||||
input: "",
|
||||
expectedOutput: "test",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: ["test", 0, "None"] } // [text, index, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Insert At with input and text",
|
||||
input: "hello ",
|
||||
expectedOutput: "hello world",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: ["world", 6, "None"] } // [text, index, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Insert At negative",
|
||||
input: " world",
|
||||
expectedOutput: "hello world",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: ["hello", -5, "None"] } // [text, index, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Insert At beyond string length",
|
||||
input: "hello ",
|
||||
expectedOutput: "hello world",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: ["world", 100, "None"] } // [text, index, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Insert At inside",
|
||||
input: "heo",
|
||||
expectedOutput: "hello",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: ["ll", 2, "None"] } // [text, index, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Insert At with space delim",
|
||||
input: "hello world",
|
||||
expectedOutput: "he:llo wo:rld",
|
||||
recipeConfig: [
|
||||
{ op: "Insert At", args: [":", 2, "Space"] } // [text, index, delimiter]
|
||||
]
|
||||
}
|
||||
]);
|
||||
42
tests/operations/tests/Prepend.mjs
Normal file
42
tests/operations/tests/Prepend.mjs
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Media operation tests.
|
||||
* @author oliver-mitchell [oliver@polymerlabs.dev]
|
||||
* @copyright Crown Copyright 2026
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
import TestRegister from "../../lib/TestRegister.mjs";
|
||||
|
||||
TestRegister.addTests([
|
||||
{
|
||||
name: "Prepend empty",
|
||||
input: "test",
|
||||
expectedOutput: "test",
|
||||
recipeConfig: [
|
||||
{ op: "Prepend", args: ["", "None"] } // [text, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Prepend empty input",
|
||||
input: "",
|
||||
expectedOutput: "test",
|
||||
recipeConfig: [
|
||||
{ op: "Prepend", args: ["test", "None"] } // [text, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Prepend with input and text",
|
||||
input: " world",
|
||||
expectedOutput: "hello world",
|
||||
recipeConfig: [
|
||||
{ op: "Prepend", args: ["hello", "None"] } // [text, delimiter]
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Prepend with space delim",
|
||||
input: "hello world",
|
||||
expectedOutput: ":hello :world",
|
||||
recipeConfig: [
|
||||
{ op: "Prepend", args: [":", "Space"] } // [text, delimiter]
|
||||
]
|
||||
}
|
||||
]);
|
||||
Loading…
x
Reference in New Issue
Block a user