diff --git a/src/__snapshots__/notcl.test.ts.snap b/src/__snapshots__/notcl.test.ts.snap index d966ca8..9e8fbdd 100644 --- a/src/__snapshots__/notcl.test.ts.snap +++ b/src/__snapshots__/notcl.test.ts.snap @@ -17,13 +17,23 @@ exports[`Parsing Notcl Misc Big mess of markup 1`] = ` "enchanted": "para", }, { - "text": "[2", - }, - { - "enchanted": "+", - }, - { - "text": "2]", + "pieces": [ + { + "script": [ + [ + { + "enchanted": "2", + }, + { + "enchanted": "+", + }, + { + "enchanted": "2", + }, + ], + ], + }, + ], }, ], [ diff --git a/src/notcl.test.ts b/src/notcl.test.ts index 9e631de..3134adf 100644 --- a/src/notcl.test.ts +++ b/src/notcl.test.ts @@ -129,7 +129,118 @@ b`) // variables- bare, brace }); - describe("command interpolation", () => {}); + describe("command interpolation", () => { + it("can parse empty command interpolations", () => + expect(parse("[]")).toEqual([true, [[{ pieces: [{ script: [] }] }]]])); + it("can parse one-word command interpolations", () => + expect(parse("[a]")).toEqual([ + true, + [[{ pieces: [{ script: [[{ enchanted: "a" }]] }] }]], + ])); + it("can parse multi-word command interpolations", () => + expect(parse("[a b c]")).toEqual([ + true, + [ + [ + { + pieces: [ + { + script: [ + [ + { enchanted: "a" }, + { enchanted: "b" }, + { enchanted: "c" }, + ], + ], + }, + ], + }, + ], + ], + ])); + it("can parse multi-command command interpolations", () => + expect(parse("[a; b c]")).toEqual([ + true, + [ + [ + { + pieces: [ + { + script: [ + [{ enchanted: "a" }], + [{ enchanted: "b" }, { enchanted: "c" }], + ], + }, + ], + }, + ], + ], + ])); + it("can parse nested command interpolations", () => + expect(parse("[[a]]")).toEqual([ + true, + [ + [ + { + pieces: [ + { + script: [[{ pieces: [{ script: [[{ enchanted: "a" }]] }] }]], + }, + ], + }, + ], + ], + ])); + + it("can parse pre-word command interpolations", () => + expect(parse("[a]b")).toEqual([ + true, + [[{ pieces: [{ script: [[{ enchanted: "a" }]] }, { text: "b" }] }]], + ])); + it("can parse mid-word command interpolations", () => + expect(parse("a[b]c")).toEqual([ + true, + [ + [ + { + pieces: [ + { text: "a" }, + { script: [[{ enchanted: "b" }]] }, + { text: "c" }, + ], + }, + ], + ], + ])); + it("can parse end-word command interpolations", () => + expect(parse("a[b]")).toEqual([ + true, + [[{ pieces: [{ text: "a" }, { script: [[{ enchanted: "b" }]] }] }]], + ])); + it("can parse multiple command interpolations in a word", () => + expect(parse("[a][b]")).toEqual([ + true, + [ + [ + { + pieces: [ + { script: [[{ enchanted: "a" }]] }, + { script: [[{ enchanted: "b" }]] }, + ], + }, + ], + ], + ])); + + test.each(["[", "a["])( + "does not permit unterminated commands {%s}", + (text) => expect(parse(text)).toMatchObject([false, {}]) + ); + test.each(['["]"', '"["]', "[{]}", "{[}]"])( + "does not permit overlapping commands and quotes {%s}", + (text) => expect(parse(text)).toMatchObject([false, {}]) + ); + }); describe("brace words", () => { it("can parse empty braces", () => diff --git a/src/notcl.ts b/src/notcl.ts index e352627..b4ea579 100644 --- a/src/notcl.ts +++ b/src/notcl.ts @@ -13,6 +13,7 @@ import { EnchantedWord as EnchantedWordType, InterpolatedPiece, Script, + ScriptPiece, SimplifyWord, TextWord, Word as WordType, @@ -24,7 +25,7 @@ const Comment = Regex(/#[^\n]*/y) const PreWordWhitespace = Regex(/[^\S\n;]+/y).expects("whitespace"); -const EnchantedWord = Regex(/[^\]\[\}\{$\\";\s]+(?=[\s;]|$)/y) +const EnchantedWord = Regex(/[^\]\[\}\{$\\";\s]+(?=[\s;\]]|$)/y) .map(([enchanted]) => ({ enchanted } as EnchantedWordType)) .expects("ENCHANTED_WORD"); @@ -32,7 +33,16 @@ const BackslashEscape = Regex(/\\(.)/y) .expects("\\") .map(([, char]) => ({ text: char })); -const BARE_WORD_CHAR = /[^\s\\;]+/y; +const BARE_WORD_CHAR = /[^\s\\;\[]+/y; +const BARE_BRACKET_WORD_CHAR = /[^\s\\;\[\]]+/y; + +let BracketScript: Pattern