diff options
| author | Ruben Beltran del Rio <jj@r.bdr.sh> | 2025-12-12 15:33:04 +0100 |
|---|---|---|
| committer | Ruben Beltran del Rio <jj@r.bdr.sh> | 2025-12-12 18:01:10 +0100 |
| commit | 80aefd27ffc19a948c74f2418a2a5bf5f95a6868 (patch) | |
| tree | 87467674eadfacae3c4d3fecbbcb95a9c28519c7 | |
| parent | aee5dffd8013f6f6a6b77e5d00edd981bcfcad48 (diff) | |
Use stage instead of number, and use an actual signed value
| -rw-r--r-- | src/index.js | 10 | ||||
| -rw-r--r-- | test/parser.test.js | 240 |
2 files changed, 123 insertions, 127 deletions
diff --git a/src/index.js b/src/index.js index 24a2c2e..f705f5a 100644 --- a/src/index.js +++ b/src/index.js @@ -44,7 +44,7 @@ * An override for the width of an evolution stage. * @typedef {Object} Stage * @property {'stage'} type - Entity type - * @property {string} number - Stage number (i, ii, iii, iv) + * @property {string} stage - Stage number (i, ii, iii, iv) * @property {number} value - Stage value */ @@ -67,7 +67,6 @@ * @typedef {Object} Evolution * @property {'evolution'} type - Entity type * @property {string} component - Component label - * @property {boolean} isPositive - Whether evolution is positive (+) or negative (-) * @property {number} value - Evolution value */ @@ -142,7 +141,7 @@ function parseKeywordEntity(line, start, length) { // Skip whitespace after ']' while (i < length && isWhitespace(line[i])) i++; - // Stage: [I|II|III|IV] number + // Stage: [I|II|III|IV] stage if ( keyword === "i" || keyword === "ii" || @@ -154,7 +153,7 @@ function parseKeywordEntity(line, start, length) { if (i > numStart) { return { type: "stage", - number: keyword, + stage: keyword, value: parseFloat(line.substring(numStart, i)), }; } @@ -250,8 +249,7 @@ function parseKeywordEntity(line, start, length) { return { type: "evolution", component, - isPositive: signCharacter === "+", - value: parseFloat(line.substring(numStart, indexOfNumber)), + value: (signCharacter === "+" ? 1 : -1) * parseFloat(line.substring(numStart, indexOfNumber)), }; } diff --git a/test/parser.test.js b/test/parser.test.js index 975c6f0..13ddd72 100644 --- a/test/parser.test.js +++ b/test/parser.test.js @@ -5,51 +5,51 @@ import { parse } from "../src/index.js"; describe("wmap parser", () => { describe("components", () => { it("should parse a basic component", async () => { - const source = "Tea (0.9, 0.5)"; - const result = await parse(source); + const source = "Dominoes (0.9, 0.5)"; + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "component"); - assert.strictEqual(result.entities[0].label, "Tea"); + assert.strictEqual(result.entities[0].label, "Dominoes"); assert.deepStrictEqual(result.entities[0].coordinates, [0.9, 0.5]); assert.strictEqual(result.entities[0].shape, "circle"); }); it("should parse a component with shape", async () => { - const source = "Database (0.3, 0.8) [Square]"; - const result = await parse(source); + const source = "Database (0.33, 0.81) [Square]"; + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "component"); assert.strictEqual(result.entities[0].label, "Database"); - assert.deepStrictEqual(result.entities[0].coordinates, [0.3, 0.8]); + assert.deepStrictEqual(result.entities[0].coordinates, [0.33, 0.81]); assert.strictEqual(result.entities[0].shape, "square"); }); it("should parse component with x shape", async () => { const source = "API (0.5, 0.6) [x]"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities[0].shape, "x"); }); it("should parse component with triangle shape", async () => { const source = "Service (0.4, 0.7) [Triangle]"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities[0].shape, "triangle"); }); it("should parse component with circle shape", async () => { const source = "Process (0.2, 0.9) [CIRCLE]"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities[0].shape, "circle"); }); it("should handle decimal numbers", async () => { const source = "Item (.5, .123)"; - const result = await parse(source); + const result = parse(source); assert.deepStrictEqual( result.entities[0].coordinates, @@ -59,30 +59,30 @@ describe("wmap parser", () => { it("should handle integers as coordinates", async () => { const source = "Item (1, 0)"; - const result = await parse(source); + const result = parse(source); assert.deepStrictEqual(result.entities[0].coordinates, [1, 0]); }); it("should preserve case in component labels", async () => { - const source = "MySpecialTea (0.5, 0.5)"; - const result = await parse(source); + const source = "RubberGaskets (0.5, 0.5)"; + const result = parse(source); - assert.strictEqual(result.entities[0].label, "MySpecialTea"); + assert.strictEqual(result.entities[0].label, "RubberGaskets"); }); it("should handle component labels with spaces", async () => { - const source = "Cup of Tea (0.5, 0.5)"; - const result = await parse(source); + const source = "Big Lawnmowers (0.5, 0.5)"; + const result = parse(source); - assert.strictEqual(result.entities[0].label, "Cup of Tea"); + assert.strictEqual(result.entities[0].label, "Big Lawnmowers"); }); it("should handle whitespace around tokens", async () => { - const source = " Tea ( 0.9 , 0.5 ) [ Square ] "; - const result = await parse(source); + const source = " Outer Space ( 0.9 , 0.5 ) [ Square ] "; + const result = parse(source); - assert.strictEqual(result.entities[0].label, "Tea"); + assert.strictEqual(result.entities[0].label, "Outer Space"); assert.deepStrictEqual(result.entities[0].coordinates, [0.9, 0.5]); assert.strictEqual(result.entities[0].shape, "square"); }); @@ -90,47 +90,47 @@ describe("wmap parser", () => { describe("dependencies (edges)", () => { it("should parse undirected dependency", async () => { - const source = "Tea -- Cup"; - const result = await parse(source); + const source = "Smoke -- Fire"; + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "dependency"); - assert.strictEqual(result.entities[0].from, "Tea"); - assert.strictEqual(result.entities[0].to, "Cup"); + assert.strictEqual(result.entities[0].from, "Smoke"); + assert.strictEqual(result.entities[0].to, "Fire"); assert.strictEqual(result.entities[0].isDirected, false); }); it("should parse directed dependency", async () => { - const source = "Tea -> Cup"; - const result = await parse(source); + const source = "Cool Thing -> Different Cool Thing"; + const result = parse(source); assert.strictEqual(result.entities[0].type, "dependency"); - assert.strictEqual(result.entities[0].from, "Tea"); - assert.strictEqual(result.entities[0].to, "Cup"); + assert.strictEqual(result.entities[0].from, "Cool Thing"); + assert.strictEqual(result.entities[0].to, "Different Cool Thing"); assert.strictEqual(result.entities[0].isDirected, true); }); it("should preserve case in dependency labels", async () => { - const source = "MyTea -> YourCup"; - const result = await parse(source); + const source = "SaRcAsM -> Seriousness."; + const result = parse(source); - assert.strictEqual(result.entities[0].from, "MyTea"); - assert.strictEqual(result.entities[0].to, "YourCup"); + assert.strictEqual(result.entities[0].from, "SaRcAsM"); + assert.strictEqual(result.entities[0].to, "Seriousness."); }); it("should ignore whitespace in dependencies", async () => { - const source = " Tea -- Cup "; - const result = await parse(source); + const source = " loose --TIGHT"; + const result = parse(source); - assert.strictEqual(result.entities[0].from, "Tea"); - assert.strictEqual(result.entities[0].to, "Cup"); + assert.strictEqual(result.entities[0].from, "loose"); + assert.strictEqual(result.entities[0].to, "TIGHT"); }); }); describe("notes", () => { it("should parse a note", async () => { const source = "[Note] (0.5, 0.5) This is a note"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "note"); @@ -139,22 +139,22 @@ describe("wmap parser", () => { }); it("should handle case insensitive note keyword", async () => { - const source = "[note] (0.5, 0.5) Text"; - const result = await parse(source); + const source = "[note] (0.1, 0.2) Text"; + const result = parse(source); assert.strictEqual(result.entities[0].type, "note"); }); it("should preserve case in note text", async () => { - const source = "[NOTE] (0.5, 0.5) Important NOTE"; - const result = await parse(source); + const source = "[NOTE] (0.77, 0.19) Important NOTE"; + const result = parse(source); assert.strictEqual(result.entities[0].text, "Important NOTE"); }); it("should handle empty note text", async () => { const source = "[Note] (0.5, 0.5) "; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities[0].text, ""); }); @@ -163,41 +163,41 @@ describe("wmap parser", () => { describe("stages", () => { it("should parse stage I", async () => { const source = "[I] 0.25"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "stage"); - assert.strictEqual(result.entities[0].number, "i"); + assert.strictEqual(result.entities[0].stage, "i"); assert.strictEqual(result.entities[0].value, 0.25); }); it("should parse stage II", async () => { const source = "[ii] 0.5"; - const result = await parse(source); + const result = parse(source); - assert.strictEqual(result.entities[0].number, "ii"); + assert.strictEqual(result.entities[0].stage, "ii"); assert.strictEqual(result.entities[0].value, 0.5); }); it("should parse stage III", async () => { const source = "[III] 0.75"; - const result = await parse(source); + const result = parse(source); - assert.strictEqual(result.entities[0].number, "iii"); + assert.strictEqual(result.entities[0].stage, "iii"); assert.strictEqual(result.entities[0].value, 0.75); }); it("should parse stage IV", async () => { const source = "[Iv] 1.0"; - const result = await parse(source); + const result = parse(source); - assert.strictEqual(result.entities[0].number, "iv"); + assert.strictEqual(result.entities[0].stage, "iv"); assert.strictEqual(result.entities[0].value, 1.0); }); it("should handle decimal stage values", async () => { const source = "[I] .333"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities[0].value, 0.333); }); @@ -205,116 +205,114 @@ describe("wmap parser", () => { describe("groups", () => { it("should parse a group with single component", async () => { - const source = "[Group] Tea"; - const result = await parse(source); + const source = "[Group] Lonely"; + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "group"); - assert.deepStrictEqual(result.entities[0].components, ["Tea"]); + assert.deepStrictEqual(result.entities[0].components, ["Lonely"]); }); it("should parse a group with multiple components", async () => { - const source = "[Group] Tea, Cup, Kettle"; - const result = await parse(source); + const source = "[Group] Huey, Dewey, Louie"; + const result = parse(source); assert.deepStrictEqual(result.entities[0].components, [ - "Tea", - "Cup", - "Kettle", + "Huey", + "Dewey", + "Louie", ]); }); it("should handle case insensitive group keyword", async () => { - const source = "[group] Tea, Cup"; - const result = await parse(source); + const source = "[group] Salt, Pepper"; + const result = parse(source); assert.strictEqual(result.entities[0].type, "group"); }); it("should preserve case in group component labels", async () => { - const source = "[GROUP] MyTea, YourCup"; - const result = await parse(source); + const source = "[GROUP] XML, LaTeX"; + const result = parse(source); assert.deepStrictEqual(result.entities[0].components, [ - "MyTea", - "YourCup", + "XML", + "LaTeX", ]); }); it("should handle whitespace around commas", async () => { - const source = "[Group] Tea , Cup , Kettle"; - const result = await parse(source); + const source = "[Group] sky, is large, emperor"; + const result = parse(source); assert.deepStrictEqual(result.entities[0].components, [ - "Tea", - "Cup", - "Kettle", + "sky", + "is large", + "emperor", ]); }); }); describe("inertia", () => { it("should parse inertia", async () => { - const source = "[Inertia] Tea"; - const result = await parse(source); + const source = "[Inertia] Print Media"; + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "inertia"); - assert.strictEqual(result.entities[0].component, "Tea"); + assert.strictEqual(result.entities[0].component, "Print Media"); }); it("should handle case insensitive inertia keyword", async () => { - const source = "[inertia] Tea"; - const result = await parse(source); + const source = "[inertia] Yes"; + const result = parse(source); assert.strictEqual(result.entities[0].type, "inertia"); }); it("should preserve case in inertia component label", async () => { - const source = "[INERTIA] MyTea"; - const result = await parse(source); + const source = "[INERTIA] SpOnGeBoB"; + const result = parse(source); - assert.strictEqual(result.entities[0].component, "MyTea"); + assert.strictEqual(result.entities[0].component, "SpOnGeBoB"); }); }); describe("evolution", () => { it("should parse evolution with positive sign", async () => { - const source = "[Evolution] Tea + 0.5"; - const result = await parse(source); + const source = "[Evolution] Nanomachines + 0.5"; + const result = parse(source); assert.strictEqual(result.entities.length, 1); assert.strictEqual(result.entities[0].type, "evolution"); - assert.strictEqual(result.entities[0].component, "Tea"); - assert.strictEqual(result.entities[0].isPositive, true); + assert.strictEqual(result.entities[0].component, "Nanomachines"); assert.strictEqual(result.entities[0].value, 0.5); }); it("should parse evolution with negative sign", async () => { - const source = "[Evolution] Tea - 0.3"; - const result = await parse(source); + const source = "[Evolution] FOXDIE - 0.3"; + const result = parse(source); - assert.strictEqual(result.entities[0].isPositive, false); - assert.strictEqual(result.entities[0].value, 0.3); + assert.strictEqual(result.entities[0].value, -0.3); }); it("should handle case insensitive evolution keyword", async () => { - const source = "[evolution] Tea + 0.5"; - const result = await parse(source); + const source = "[evolution] tamales + 0.73"; + const result = parse(source); assert.strictEqual(result.entities[0].type, "evolution"); }); it("should preserve case in evolution component label", async () => { - const source = "[EVOLUTION] MyTea - 0.2"; - const result = await parse(source); + const source = "[EVOLUTION] iMac - 0.2"; + const result = parse(source); - assert.strictEqual(result.entities[0].component, "MyTea"); + assert.strictEqual(result.entities[0].component, "iMac"); }); it("should handle decimal evolution values", async () => { - const source = "[Evolution] Tea + .75"; - const result = await parse(source); + const source = "[Evolution] Numerals + .75"; + const result = parse(source); assert.strictEqual(result.entities[0].value, 0.75); }); @@ -322,10 +320,10 @@ describe("wmap parser", () => { describe("multiple entities", () => { it("should parse multiple entities", async () => { - const source = `Tea (0.9, 0.5) -Cup (0.8, 0.4) -Tea -> Cup`; - const result = await parse(source); + const source = `Water (0.9, 0.5) +Bucket (0.8, 0.4) [x] +Water -> Bucket`; + const result = parse(source); assert.strictEqual(result.entities.length, 3); assert.strictEqual(result.entities[0].type, "component"); @@ -334,46 +332,46 @@ Tea -> Cup`; }); it("should handle different line endings (LF)", async () => { - const source = "Tea (0.9, 0.5)\nCup (0.8, 0.4)"; - const result = await parse(source); + const source = "Penguins (0.9, 0.5)\nI Use Arch BTW (0.8, 0.4)"; + const result = parse(source); assert.strictEqual(result.entities.length, 2); }); it("should handle different line endings (CRLF)", async () => { - const source = "Tea (0.9, 0.5)\r\nCup (0.8, 0.4)"; - const result = await parse(source); + const source = "Clippy (0.9, 0.5)\r\nSpace Cadet (0.8, 0.4)"; + const result = parse(source); assert.strictEqual(result.entities.length, 2); }); it("should handle different line endings (CR)", async () => { - const source = "Tea (0.9, 0.5)\rCup (0.8, 0.4)"; - const result = await parse(source); + const source = "SE/30 (0.9, 0.5)\rPerforma (0.8, 0.4)"; + const result = parse(source); assert.strictEqual(result.entities.length, 2); }); it("should handle empty lines", async () => { - const source = `Tea (0.9, 0.5) + const source = `The Void (0.9, 0.5) -Cup (0.8, 0.4)`; - const result = await parse(source); +The Abyss (0.8, 0.4)`; + const result = parse(source); assert.strictEqual(result.entities.length, 2); }); it("should ignore invalid lines", async () => { - const source = `Tea (0.9, 0.5) -This is invalid -Cup (0.8, 0.4) -Another invalid line -Tea -> Cup`; - const result = await parse(source); + const source = `Hello (0.9, 0.5) +Oh No +It's OK (0.8, 0.4) +NO IT ISN'T +Hello -> It's OK`; + const result = parse(source); assert.strictEqual(result.entities.length, 3); - assert.strictEqual(result.entities[0].label, "Tea"); - assert.strictEqual(result.entities[1].label, "Cup"); + assert.strictEqual(result.entities[0].label, "Hello"); + assert.strictEqual(result.entities[1].label, "It's OK"); assert.strictEqual(result.entities[2].type, "dependency"); }); }); @@ -381,32 +379,32 @@ Tea -> Cup`; describe("edge cases", () => { it("should handle empty input", async () => { const source = ""; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities.length, 0); }); it("should handle only whitespace", async () => { const source = " \n \n "; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities.length, 0); }); it("should handle only invalid lines", async () => { const source = "invalid\nstill invalid"; - const result = await parse(source); + const result = parse(source); assert.strictEqual(result.entities.length, 0); }); it("should handle complex component labels", async () => { - const source = "My Super Complex Label 123 (0.5, 0.5)"; - const result = await parse(source); + const source = "My Sü'per Complex Label 123 (0.5, 0.5)"; + const result = parse(source); assert.strictEqual( result.entities[0].label, - "My Super Complex Label 123", + "My Sü'per Complex Label 123", ); }); }); @@ -433,7 +431,7 @@ Kettle -> Hot Water [Inertia] Kettle [Evolution] Tea + 0.1`; - const result = await parse(source); + const result = parse(source); // 4 stages + 4 components + 3 dependencies + 1 note + 1 group + 1 inertia + 1 evolution = 15 assert.strictEqual(result.entities.length, 15); |