From e69ecf31a0755158701a4285bdd1b187e719ea79 Mon Sep 17 00:00:00 2001 From: Rex Morgan Date: Fri, 19 Jun 2026 20:54:48 -0400 Subject: [PATCH] fix: allow Unicode letters as first character in identifiers (issue #416) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WordParser's IsWord check previously only recognized ASCII letters and a fixed set of special characters as valid identifier start characters. Any Unicode letter (e.g. Japanese kanji like 姓) at the start of a Handlebars expression would fail with "Reached unparseable token in expression". The fix adds char.IsLetter(c) to the start-character check so any Unicode letter is accepted, matching the behaviour of Handlebars.js. Fixes #416 Co-Authored-By: Claude Sonnet 4.6 --- source/Handlebars.Test/IssueTests.cs | 14 ++++++++++++++ .../Compiler/Lexer/Parsers/WordParser.cs | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/source/Handlebars.Test/IssueTests.cs b/source/Handlebars.Test/IssueTests.cs index 31136117..0dd52e99 100644 --- a/source/Handlebars.Test/IssueTests.cs +++ b/source/Handlebars.Test/IssueTests.cs @@ -733,5 +733,19 @@ public void UnrecognisedExpressionThrowsOutOfMemoryException() Assert.Throws(()=> Handlebars.Compile(source)); } + + // Issue: https://github.com/Handlebars-Net/Handlebars.Net/issues/416 + // Non-ASCII characters not supported as the first character of a placeholder identifier + [Fact] + public void Issue416_UnicodeFirstCharacterInIdentifier() + { + var config = new HandlebarsConfiguration { TextEncoder = new HtmlEncoder() }; + var handlebars = Handlebars.Create(config); + // Japanese characters as identifiers — first char is non-ASCII + var template = handlebars.Compile("Hello {{姓}} {{名}},"); + var data = new Dictionary { { "姓", "山田" }, { "名", "太郎" } }; + var result = template(data); + Assert.Equal("Hello 山田 太郎,", result); + } } } \ No newline at end of file diff --git a/source/Handlebars/Compiler/Lexer/Parsers/WordParser.cs b/source/Handlebars/Compiler/Lexer/Parsers/WordParser.cs index 64974024..f4bb1d8f 100644 --- a/source/Handlebars/Compiler/Lexer/Parsers/WordParser.cs +++ b/source/Handlebars/Compiler/Lexer/Parsers/WordParser.cs @@ -31,7 +31,9 @@ public override Token Parse(ExtendedStringReader reader) private static bool IsWord(ExtendedStringReader reader) { var peek = reader.Peek(); - return ValidWordStartCharacters.Contains((char) peek); + if (peek == -1) return false; + var c = (char) peek; + return ValidWordStartCharacters.Contains(c) || char.IsLetter(c); } private static string AccumulateWord(ExtendedStringReader reader)