diff --git a/.changeset/afraid-radios-begin.md b/.changeset/afraid-radios-begin.md new file mode 100644 index 00000000..1c9fc226 --- /dev/null +++ b/.changeset/afraid-radios-begin.md @@ -0,0 +1,5 @@ +--- +"htmljs-parser": minor +--- + +Add "isValidScriptlet" api. diff --git a/src/__tests__/validate.test.ts b/src/__tests__/validate.test.ts index a3d6ae7a..59f8f1a6 100644 --- a/src/__tests__/validate.test.ts +++ b/src/__tests__/validate.test.ts @@ -1,5 +1,5 @@ import assert from "node:assert/strict"; -import { isValidAttrValue, isValidStatement } from ".."; +import { isValidAttrValue, isValidScriptlet, isValidStatement } from ".."; describe("validation helpers", () => { describe("isValidStatement", () => { @@ -28,6 +28,32 @@ describe("validation helpers", () => { }); }); + describe("isValidScriptlet", () => { + it("accepts single-line expressions", () => { + assert.equal(isValidScriptlet("foo + bar"), 2); + }); + + it("rejects indented continuation lines", () => { + assert.equal(isValidScriptlet("foo\n + bar"), 0); + }); + + it("rejects unindented continuation lines", () => { + assert.equal(isValidScriptlet("foo\nbar"), 0); + }); + + it("accepts indented ternary continuation", () => { + assert.equal(isValidScriptlet("foo ?\n bar : baz"), 2); + }); + + it("rejects unterminated groups", () => { + assert.equal(isValidScriptlet("(foo"), 0); + }); + + it("rejects mismatched closing groups", () => { + assert.equal(isValidScriptlet(")"), 0); + }); + }); + describe("isValidAttrValue", () => { it("accepts html attr values with operators", () => { assert.equal(isValidAttrValue("foo + bar", false), 2); diff --git a/src/index.ts b/src/index.ts index a53be8aa..583e66df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,7 @@ export { export { isValidStatement, + isValidScriptlet, isValidAttrValue, Validity, } from "./util/validators"; diff --git a/src/util/validators.ts b/src/util/validators.ts index bb0e8105..4975a758 100644 --- a/src/util/validators.ts +++ b/src/util/validators.ts @@ -44,6 +44,15 @@ function prepareStatement(expr: STATE.ExpressionMeta) { expr.consumeIndentedContent = true; } +export function isValidScriptlet(code: string): Validity { + return isValid(code, true, prepareScriptlet); +} + +function prepareScriptlet(expr: STATE.ExpressionMeta) { + expr.operators = true; + expr.terminatedByEOL = true; +} + export function isValidAttrValue(code: string, concise: boolean): Validity { return isValid(code, concise, prepareAttrValue); }