Skip to main content

Syntax and Logic

Lis Novel includes a built-in prompt template language. Tags are wrapped in { and } and can be expressions, control blocks, or comments.

Template structure

Tag typeExamplePurpose
Expression{scene.fullTitle}Insert a value or function result.
Control flow{#if ...} / {#endif}Show or hide sections based on logic.
Comment{! ... !}Notes for yourself; removed from output.

Whitespace around tags is preserved unless removed by your own markup.

Comments

Comments are stripped from the output.

Enter the castle.{! Remind the model this is a stealth sequence. !}

Expressions

Expression tags output the value of an expression.

Identifiers

  • Identifiers are case-sensitive and resolve to variables or functions.
  • Use dot notation to reach nested data: {scene.fullTitle}.

String literals

Strings can use single or double quotes. Newlines inside string literals are not supported.

{"Shadow"}
{'Shadow'}

Numeric literals

The prompt template language supports integers only.

{3}

Function calls

Call helpers with name(arg1, arg2, ...).

  • Arguments can be literals, identifiers, member access, or other function calls.
  • Any argument that evaluates to null or undefined is omitted before the function is invoked, which can shift positions.
  • Functions used as a standalone expression are auto-invoked, so {scene.fullText} is equivalent to {scene.fullText()}.
  • Objects and numbers are stringified using standard JavaScript string conversion. Many Lis Novel helpers override this to output XML.
{wordCount(scene.fullText)}
{chapter.title(chapter.next)}

Operators

The prompt template language supports a small set of infix operators inside expressions.

  • is performs strict equality (===).
  • + concatenates values after string conversion. null and undefined become empty strings.
{hero.role is "antagonist"}
{"Agent " + hero.codename + " reporting."}

Truthiness

Conditionals use JavaScript truthiness: empty strings, 0, null, undefined, and false are falsy; everything else is truthy.

Control flow blocks

{#if isGreaterThan(wordCount(scene.fullText), 1000)}
Flag as long-form scene.
{#elseif isGreaterThan(wordCount(scene.fullText), 200)}
Flag as medium scene.
{#else}
Keep as short scene.
{#endif}
  • {#if} requires a condition.
  • {#elseif} can appear zero or more times.
  • {#else} is optional and must be the final branch.
  • Blocks may nest; each {#if} must be closed by {#endif}.

XML and markup

The prompt template language treats XML, HTML, and other markup as plain text. It does not parse or escape markup on its own. This makes it safe to emit <scene>, <novel>, and <lore> XML directly in prompts.

Syntax errors

Unterminated tags, malformed expressions, or unmatched control-flow blocks cause errors. Keep tags balanced and expressions valid.