Repository: alecthomas/chroma
Pull request #478 (2021-04-27 18:30:30)

Svelte Lexer Improvements
An Improved version of #458

CIAvash: Why did the tests fail this time? I ran the linter as well.

While testing style's lang tag, I realized SCSS is [broken](https://github.com/pygments/pygments/blob/3f6244bc1d63674c4290d570ab3676040f2189ee/pygments/lexers/css.py#L647-L649), and SASS doesn't capture whitespace and they are shown as errors :disappointed: 
alecthomas: I think you're going to need to log into Circle, I'm not going to keep copying and pasting error messages 😀
alecthomas: I've merged #458, I missed it somehow. Sorry about the conflicts.
alecthomas: Nice! LGTM

Patch:
diff --git a/README.md b/README.md
index 8da1ee3..3aeb887 100644
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@ O | Objective-C, OCaml, Octave, OpenSCAD, Org Mode
 P | PacmanConf, Perl, PHP, PHTML, Pig, PkgConfig, PL/pgSQL, plaintext, Pony, PostgreSQL SQL dialect, PostScript, POVRay, PowerShell, Prolog, PromQL, Protocol Buffer, Puppet, Python, Python 3
 Q | QBasic
 R | R, Racket, Ragel, Raku, react, ReasonML, reg, reStructuredText, Rexx, Ruby, Rust
-S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, Stylus, Swift, SYSTEMD, systemverilog
+S | SAS, Sass, Scala, Scheme, Scilab, SCSS, Smalltalk, Smarty, Snobol, Solidity, SPARQL, SQL, SquidConf, Standard ML, Stylus, Svelte, Swift, SYSTEMD, systemverilog
 T | TableGen, TASM, Tcl, Tcsh, Termcap, Terminfo, Terraform, TeX, Thrift, TOML, TradingView, Transact-SQL, Turing, Turtle, Twig, TypeScript, TypoScript, TypoScriptCssData, TypoScriptHtmlData
 V | VB.net, verilog, VHDL, VimL, vue
 W | WDTE
diff --git a/lexers/s/svelte.go b/lexers/s/svelte.go
index 2d44167..1f91a21 100644
--- a/lexers/s/svelte.go
+++ b/lexers/s/svelte.go
@@ -22,18 +22,52 @@ var Svelte = internal.Register(DelegatingLexer(h.HTML, MustNewLazyLexer(
 func svelteRules() Rules {
 	return Rules{
 		"root": {
-			{`(<\s*script\s*lang\s*=\s*['"](?:ts|typescript)['"]\s*>)(.+?)(<\s*/\s*script\s*>)`, ByGroups(Other, Using(t.TypeScript), Other), nil},
-			{`\{`, Punctuation, Push("templates")},
-			{`[^{]`, Other, nil},
+			// Let HTML handle the comments, including comments containing script and style tags
+			{`<!--`, Other, Push("comment")},
+			{
+				// Highlight script and style tags based on lang attribute
+				// and allow attributes besides lang
+				`(<\s*(?:script|style).*?lang\s*=\s*['"])` +
+					`(.+?)(['"].*?>)` +
+					`(.+?)` +
+					`(<\s*/\s*(?:script|style)\s*>)`,
+				UsingByGroup(internal.Get, 2, 4, Other, Other, Other, Other, Other),
+				nil,
+			},
+			{
+				// Make sure `{` is not inside script or style tags
+				`(?<!<\s*(?:script|style)(?:(?!(?:script|style)\s*>).)*?)` +
+					`{` +
+					`(?!(?:(?!<\s*(?:script|style)).)*?(?:script|style)\s*>)`,
+				Punctuation,
+				Push("templates"),
+			},
+			// on:submit|preventDefault
+			{`(?<=\s+on:\w+(?:\|\w+)*)\|(?=\w+)`, Operator, nil},
+			{`.+?`, Other, nil},
+		},
+		"comment": {
+			{`-->`, Other, Pop(1)},
+			{`.+?`, Other, nil},
 		},
 		"templates": {
 			{`}`, Punctuation, Pop(1)},
+			// Let TypeScript handle strings and the curly braces inside them
+			{`(?<!(?<!\\)\\)(['"` + "`])" + `.*?(?<!(?<!\\)\\)\1`, Using(t.TypeScript), nil},
+			// If there is another opening curly brace push to templates again
+			{"{", Punctuation, Push("templates")},
 			{`@(debug|html)\b`, Keyword, nil},
-			{`(#|/)(await|each|if)\b`, Keyword, nil},
+			{
+				`(#await)(\s+)(\w+)(\s+)(then|catch)(\s+)(\w+)`,
+				ByGroups(Keyword, Text, Using(t.TypeScript), Text,
+					Keyword, Text, Using(t.TypeScript),
+				),
+				nil,
+			},
+			{`(#|/)(await|each|if|key)\b`, Keyword, nil},
 			{`(:else)(\s+)(if)?\b`, ByGroups(Keyword, Text, Keyword), nil},
 			{`:(catch|then)\b`, Keyword, nil},
-			{`then\b`, Keyword, nil},
-			{`[^}]+`, Using(t.TypeScript), nil},
+			{`[^{}]+`, Using(t.TypeScript), nil},
 		},
 	}
 }


Test patch:
diff --git a/lexers/testdata/svelte.actual b/lexers/testdata/svelte.actual
index 05f8556..5bba9a6 100644
--- a/lexers/testdata/svelte.actual
+++ b/lexers/testdata/svelte.actual
@@ -20,6 +20,14 @@
 	}
 </style>
 
+<style lang="sass">
+$color: red
+h1
+  color: $color
+  font-family: Arial, Helvetica, sans-serif
+  font-size: 2em
+</style>
+
 <h1>Hello {name}!</h1>
 <img {src} alt="Example image">
 
@@ -27,7 +35,52 @@
 <Nested/>
 
 <ul>
-	{#each names as { id, name }}
-		<li>{name} ({id})</li>
+    {#each names as { id, name }, i}
+	<li>{name} ({id})</li>
 	{/each}
 </ul>
+
+<template>
+    <form on:submit|preventDefault="{submitSearch}">
+        <input type="search" bind:value="{name}" required />
+        <button type="submit">Search</button>
+    </form>
+
+    {#if porridge.temperature > 100}
+	<p>too hot!</p>
+    {:else if 80 > porridge.temperature}
+	<p>too cold!</p>
+    {:else}
+	<p>just right!</p>
+    {/if}
+
+    {#await promise}
+	<!-- promise is pending -->
+	<p>waiting for the promise to resolve...</p>
+    {:then value}
+	<!-- promise was fulfilled -->
+	<p>The value is {value}</p>
+    {:catch error}
+	<!-- promise was rejected -->
+	<p>Something went wrong: {error.message}</p>
+    {/await}
+
+    {#await promise then value}
+	<p>The value is {value}</p>
+    {/await}
+
+    {#await promise catch error}
+	<p>The error is {error}</p>
+    {/await}
+
+    {#key value}
+	<div transition:fade>{value}</div>
+    {/key}
+
+    <div class="blog-post">
+	    <h1>{post.title}</h1>
+	    {@html post.content}
+    </div>
+
+    {@debug user}
+</template>
\ No newline at end of file
diff --git a/lexers/testdata/svelte.expected b/lexers/testdata/svelte.expected
index ecb03b1..68358f0 100644
--- a/lexers/testdata/svelte.expected
+++ b/lexers/testdata/svelte.expected
@@ -103,31 +103,29 @@
   {"type":"Text","value":" "},
   {"type":"Punctuation","value":"{"},
   {"type":"Text","value":"\n\t\t"},
-  {"type":"NameOther","value":"color"},
-  {"type":"Text","value":": "},
-  {"type":"KeywordType","value":"red"},
+  {"type":"Keyword","value":"color"},
+  {"type":"Punctuation","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"KeywordConstant","value":"red"},
   {"type":"Punctuation","value":";"},
   {"type":"Text","value":"\n\t\t"},
-  {"type":"NameOther","value":"font"},
-  {"type":"Operator","value":"-"},
-  {"type":"NameOther","value":"family"},
-  {"type":"Text","value":": "},
-  {"type":"KeywordType","value":"Arial"},
+  {"type":"Keyword","value":"font-family"},
+  {"type":"Punctuation","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"Name","value":"Arial"},
   {"type":"Punctuation","value":","},
   {"type":"Text","value":" "},
-  {"type":"NameOther","value":"Helvetica"},
+  {"type":"Name","value":"Helvetica"},
   {"type":"Punctuation","value":","},
   {"type":"Text","value":" "},
-  {"type":"NameOther","value":"sans"},
-  {"type":"Operator","value":"-"},
-  {"type":"NameOther","value":"serif"},
+  {"type":"KeywordConstant","value":"sans-serif"},
   {"type":"Punctuation","value":";"},
   {"type":"Text","value":"\n\t\t"},
-  {"type":"NameOther","value":"font"},
-  {"type":"Operator","value":"-"},
-  {"type":"NameOther","value":"size"},
-  {"type":"Text","value":": "},
-  {"type":"KeywordType","value":"2em"},
+  {"type":"Keyword","value":"font-size"},
+  {"type":"Punctuation","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"LiteralNumberInteger","value":"2"},
+  {"type":"KeywordType","value":"em"},
   {"type":"Punctuation","value":";"},
   {"type":"Text","value":"\n\t"},
   {"type":"Punctuation","value":"}"},
@@ -137,6 +135,50 @@
   {"type":"Punctuation","value":"\u003e"},
   {"type":"Text","value":"\n\n"},
   {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"style"},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"lang"},
+  {"type":"Operator","value":"="},
+  {"type":"LiteralString","value":"\"sass\""},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n"},
+  {"type":"NameVariable","value":"$color"},
+  {"type":"Operator","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"NameEntity","value":"red"},
+  {"type":"Text","value":"\n"},
+  {"type":"NameTag","value":"h1"},
+  {"type":"Text","value":"\n"},
+  {"type":"Error","value":"  "},
+  {"type":"NameAttribute","value":"color"},
+  {"type":"Operator","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"NameVariable","value":"$color"},
+  {"type":"Text","value":"\n"},
+  {"type":"Error","value":"  "},
+  {"type":"NameAttribute","value":"font-family"},
+  {"type":"Operator","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"Name","value":"Arial"},
+  {"type":"Operator","value":","},
+  {"type":"Text","value":" "},
+  {"type":"Name","value":"Helvetica"},
+  {"type":"Operator","value":","},
+  {"type":"Text","value":" "},
+  {"type":"NameConstant","value":"sans-serif"},
+  {"type":"Text","value":"\n"},
+  {"type":"Error","value":"  "},
+  {"type":"NameAttribute","value":"font-size"},
+  {"type":"Operator","value":":"},
+  {"type":"Text","value":" "},
+  {"type":"LiteralNumberInteger","value":"2"},
+  {"type":"KeywordType","value":"em"},
+  {"type":"Text","value":"\n"},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"style"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n\n"},
+  {"type":"Punctuation","value":"\u003c"},
   {"type":"NameTag","value":"h1"},
   {"type":"Punctuation","value":"\u003e"},
   {"type":"Text","value":"Hello "},
@@ -169,7 +211,7 @@
   {"type":"Punctuation","value":"\u003c"},
   {"type":"NameTag","value":"ul"},
   {"type":"Punctuation","value":"\u003e"},
-  {"type":"Text","value":"\n\t"},
+  {"type":"Text","value":"\n    "},
   {"type":"Punctuation","value":"{"},
   {"type":"Keyword","value":"#each"},
   {"type":"Text","value":" "},
@@ -184,8 +226,11 @@
   {"type":"Text","value":" "},
   {"type":"NameOther","value":"name"},
   {"type":"Text","value":" "},
+  {"type":"Punctuation","value":"},"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"i"},
   {"type":"Punctuation","value":"}"},
-  {"type":"Text","value":"}\n\t\t"},
+  {"type":"Text","value":"\n\t"},
   {"type":"Punctuation","value":"\u003c"},
   {"type":"NameTag","value":"li"},
   {"type":"Punctuation","value":"\u003e{"},
@@ -207,5 +252,282 @@
   {"type":"Punctuation","value":"\u003c/"},
   {"type":"NameTag","value":"ul"},
   {"type":"Punctuation","value":"\u003e"},
-  {"type":"Text","value":"\n"}
+  {"type":"Text","value":"\n\n"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"template"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"form"},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"on:submit"},
+  {"type":"Operator","value":"|"},
+  {"type":"NameAttribute","value":"preventDefault"},
+  {"type":"Operator","value":"="},
+  {"type":"LiteralString","value":"\""},
+  {"type":"Punctuation","value":"{"},
+  {"type":"NameOther","value":"submitSearch"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"LiteralString","value":"\""},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n        "},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"input"},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"type"},
+  {"type":"Operator","value":"="},
+  {"type":"LiteralString","value":"\"search\""},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"bind:value"},
+  {"type":"Operator","value":"="},
+  {"type":"LiteralString","value":"\""},
+  {"type":"Punctuation","value":"{"},
+  {"type":"NameOther","value":"name"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"LiteralString","value":"\""},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"required"},
+  {"type":"Text","value":" "},
+  {"type":"Punctuation","value":"/\u003e"},
+  {"type":"Text","value":"\n        "},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"button"},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"type"},
+  {"type":"Operator","value":"="},
+  {"type":"LiteralString","value":"\"submit\""},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"Search"},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"button"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"form"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"#if"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"porridge"},
+  {"type":"Punctuation","value":"."},
+  {"type":"NameOther","value":"temperature"},
+  {"type":"Text","value":" "},
+  {"type":"Operator","value":"\u003e"},
+  {"type":"Text","value":" "},
+  {"type":"LiteralNumberInteger","value":"100"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"too hot!"},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":":else"},
+  {"type":"Text","value":" "},
+  {"type":"Keyword","value":"if"},
+  {"type":"Text","value":" "},
+  {"type":"LiteralNumberInteger","value":"80"},
+  {"type":"Text","value":" "},
+  {"type":"Operator","value":"\u003e"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"porridge"},
+  {"type":"Punctuation","value":"."},
+  {"type":"NameOther","value":"temperature"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"too cold!"},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Operator","value":":"},
+  {"type":"Keyword","value":"else"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"just right!"},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"/if"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"#await"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"promise"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Comment","value":"\u003c!-- promise is pending --\u003e"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"waiting for the promise to resolve..."},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":":then"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"value"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Comment","value":"\u003c!-- promise was fulfilled --\u003e"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"The value is "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"NameOther","value":"value"},
+  {"type":"Punctuation","value":"}\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":":catch"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"error"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Comment","value":"\u003c!-- promise was rejected --\u003e"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"Something went wrong: "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"NameOther","value":"error"},
+  {"type":"Punctuation","value":"."},
+  {"type":"NameOther","value":"message"},
+  {"type":"Punctuation","value":"}\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"/await"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"#await"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"promise"},
+  {"type":"Text","value":" "},
+  {"type":"Keyword","value":"then"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"value"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"The value is "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"NameOther","value":"value"},
+  {"type":"Punctuation","value":"}\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"/await"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"#await"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"promise"},
+  {"type":"Text","value":" "},
+  {"type":"Keyword","value":"catch"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"error"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"The error is "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"NameOther","value":"error"},
+  {"type":"Punctuation","value":"}\u003c/"},
+  {"type":"NameTag","value":"p"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"/await"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"#key"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"value"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\t"},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"div"},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"transition:fade"},
+  {"type":"Punctuation","value":"\u003e{"},
+  {"type":"NameOther","value":"value"},
+  {"type":"Punctuation","value":"}\u003c/"},
+  {"type":"NameTag","value":"div"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"/key"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"div"},
+  {"type":"Text","value":" "},
+  {"type":"NameAttribute","value":"class"},
+  {"type":"Operator","value":"="},
+  {"type":"LiteralString","value":"\"blog-post\""},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n\t    "},
+  {"type":"Punctuation","value":"\u003c"},
+  {"type":"NameTag","value":"h1"},
+  {"type":"Punctuation","value":"\u003e{"},
+  {"type":"NameOther","value":"post"},
+  {"type":"Punctuation","value":"."},
+  {"type":"NameOther","value":"title"},
+  {"type":"Punctuation","value":"}\u003c/"},
+  {"type":"NameTag","value":"h1"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n\t    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"@html"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"post"},
+  {"type":"Punctuation","value":"."},
+  {"type":"NameOther","value":"content"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n    "},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"div"},
+  {"type":"Punctuation","value":"\u003e"},
+  {"type":"Text","value":"\n\n    "},
+  {"type":"Punctuation","value":"{"},
+  {"type":"Keyword","value":"@debug"},
+  {"type":"Text","value":" "},
+  {"type":"NameOther","value":"user"},
+  {"type":"Punctuation","value":"}"},
+  {"type":"Text","value":"\n"},
+  {"type":"Punctuation","value":"\u003c/"},
+  {"type":"NameTag","value":"template"},
+  {"type":"Punctuation","value":"\u003e"}
 ]