diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-12-04 12:07:54 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-04 12:07:54 +0100 |
commit | 9f978d387f8b7cb6bc03fe6b4dd52bb16862a784 (patch) | |
tree | dc53e021fbf8a89e7ff0d3e86bbe9416ce5d7ecb /tpl | |
parent | 14d85ec136413dcfc96ad8e4d31633f8f9cbf410 (diff) |
Pull in the latest code from Go's template packages (#11771)
Fixes #10707
Fixes #11507
Diffstat (limited to 'tpl')
21 files changed, 413 insertions, 160 deletions
diff --git a/tpl/internal/go_templates/fmtsort/sort_test.go b/tpl/internal/go_templates/fmtsort/sort_test.go index 064b09107..fef952fa6 100644 --- a/tpl/internal/go_templates/fmtsort/sort_test.go +++ b/tpl/internal/go_templates/fmtsort/sort_test.go @@ -6,13 +6,14 @@ package fmtsort_test import ( "fmt" - "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort" "math" "reflect" "sort" "strings" "testing" "unsafe" + + "github.com/gohugoio/hugo/tpl/internal/go_templates/fmtsort" ) var compareTests = [][]reflect.Value{ @@ -38,7 +39,7 @@ var compareTests = [][]reflect.Value{ ct(reflect.TypeOf(chans[0]), chans[0], chans[1], chans[2]), ct(reflect.TypeOf(toy{}), toy{0, 1}, toy{0, 2}, toy{1, -1}, toy{1, 1}), ct(reflect.TypeOf([2]int{}), [2]int{1, 1}, [2]int{1, 2}, [2]int{2, 0}), - ct(reflect.TypeOf(any(any(0))), iFace, 1, 2, 3), + ct(reflect.TypeOf(any(0)), iFace, 1, 2, 3), } var iFace any @@ -190,12 +191,15 @@ func sprintKey(key reflect.Value) string { var ( ints [3]int chans = makeChans() + // pin runtime.Pinner ) func makeChans() []chan int { cs := []chan int{make(chan int), make(chan int), make(chan int)} // Order channels by address. See issue #49431. - // TODO: pin these pointers once pinning is available (#46787). + for i := range cs { + reflect.ValueOf(cs[i]).UnsafePointer() + } sort.Slice(cs, func(i, j int) bool { return uintptr(reflect.ValueOf(cs[i]).UnsafePointer()) < uintptr(reflect.ValueOf(cs[j]).UnsafePointer()) }) diff --git a/tpl/internal/go_templates/htmltemplate/context.go b/tpl/internal/go_templates/htmltemplate/context.go index 061f17ddb..3acb9bdf0 100644 --- a/tpl/internal/go_templates/htmltemplate/context.go +++ b/tpl/internal/go_templates/htmltemplate/context.go @@ -22,10 +22,15 @@ type context struct { delim delim urlPart urlPart jsCtx jsCtx - attr attr - element element - n parse.Node // for range break/continue - err *Error + // jsBraceDepth contains the current depth, for each JS template literal + // string interpolation expression, of braces we've seen. This is used to + // determine if the next } will close a JS template literal string + // interpolation expression or not. + jsBraceDepth []int + attr attr + element element + n parse.Node // for range break/continue + err *Error } func (c context) String() string { @@ -121,8 +126,8 @@ const ( stateJSDqStr // stateJSSqStr occurs inside a JavaScript single quoted string. stateJSSqStr - // stateJSBqStr occurs inside a JavaScript back quoted string. - stateJSBqStr + // stateJSTmplLit occurs inside a JavaScript back quoted string. + stateJSTmplLit // stateJSRegexp occurs inside a JavaScript regexp literal. stateJSRegexp // stateJSBlockCmt occurs inside a JavaScript /* block comment */. @@ -176,14 +181,14 @@ func isInTag(s state) bool { } // isInScriptLiteral returns true if s is one of the literal states within a -// <script> tag, and as such occurances of "<!--", "<script", and "</script" +// <script> tag, and as such occurrences of "<!--", "<script", and "</script" // need to be treated specially. func isInScriptLiteral(s state) bool { // Ignore the comment states (stateJSBlockCmt, stateJSLineCmt, // stateJSHTMLOpenCmt, stateJSHTMLCloseCmt) because their content is already // omitted from the output. switch s { - case stateJSDqStr, stateJSSqStr, stateJSBqStr, stateJSRegexp: + case stateJSDqStr, stateJSSqStr, stateJSTmplLit, stateJSRegexp: return true } return false diff --git a/tpl/internal/go_templates/htmltemplate/error.go b/tpl/internal/go_templates/htmltemplate/error.go index a4450a4a9..de4b4de1e 100644 --- a/tpl/internal/go_templates/htmltemplate/error.go +++ b/tpl/internal/go_templates/htmltemplate/error.go @@ -222,6 +222,10 @@ const ( // Discussion: // Package html/template does not support actions inside of JS template // literals. + // + // Deprecated: ErrJSTemplate is no longer returned when an action is present + // in a JS template literal. Actions inside of JS template literals are now + // escaped as expected. ErrJSTemplate ) diff --git a/tpl/internal/go_templates/htmltemplate/escape.go b/tpl/internal/go_templates/htmltemplate/escape.go index 5d47a83d3..334bbce0f 100644 --- a/tpl/internal/go_templates/htmltemplate/escape.go +++ b/tpl/internal/go_templates/htmltemplate/escape.go @@ -8,8 +8,6 @@ import ( "bytes" "fmt" "html" - - //"internal/godebug" "io" "regexp" @@ -64,22 +62,23 @@ func evalArgs(args ...any) string { // funcMap maps command names to functions that render their inputs safe. var funcMap = template.FuncMap{ - "_html_template_attrescaper": attrEscaper, - "_html_template_commentescaper": commentEscaper, - "_html_template_cssescaper": cssEscaper, - "_html_template_cssvaluefilter": cssValueFilter, - "_html_template_htmlnamefilter": htmlNameFilter, - "_html_template_htmlescaper": htmlEscaper, - "_html_template_jsregexpescaper": jsRegexpEscaper, - "_html_template_jsstrescaper": jsStrEscaper, - "_html_template_jsvalescaper": jsValEscaper, - "_html_template_nospaceescaper": htmlNospaceEscaper, - "_html_template_rcdataescaper": rcdataEscaper, - "_html_template_srcsetescaper": srcsetFilterAndEscaper, - "_html_template_urlescaper": urlEscaper, - "_html_template_urlfilter": urlFilter, - "_html_template_urlnormalizer": urlNormalizer, - "_eval_args_": evalArgs, + "_html_template_attrescaper": attrEscaper, + "_html_template_commentescaper": commentEscaper, + "_html_template_cssescaper": cssEscaper, + "_html_template_cssvaluefilter": cssValueFilter, + "_html_template_htmlnamefilter": htmlNameFilter, + "_html_template_htmlescaper": htmlEscaper, + "_html_template_jsregexpescaper": jsRegexpEscaper, + "_html_template_jsstrescaper": jsStrEscaper, + "_html_template_jstmpllitescaper": jsTmplLitEscaper, + "_html_template_jsvalescaper": jsValEscaper, + "_html_template_nospaceescaper": htmlNospaceEscaper, + "_html_template_rcdataescaper": rcdataEscaper, + "_html_template_srcsetescaper": srcsetFilterAndEscaper, + "_html_template_urlescaper": urlEscaper, + "_html_template_urlfilter": urlFilter, + "_html_template_urlnormalizer": urlNormalizer, + "_eval_args_": evalArgs, } // escaper collects type inferences about templates and changes needed to make @@ -164,7 +163,6 @@ func (e *escaper) escape(c context, n parse.Node) context { panic("escaping " + n.String() + " is unimplemented") } -// Modified by Hugo. // var debugAllowActionJSTmpl = godebug.New("jstmpllitinterp") // escapeAction escapes an action template node. @@ -230,16 +228,8 @@ func (e *escaper) escapeAction(c context, n *parse.ActionNode) context { c.jsCtx = jsCtxDivOp case stateJSDqStr, stateJSSqStr: s = append(s, "_html_template_jsstrescaper") - case stateJSBqStr: - if SecurityAllowActionJSTmpl.Load() { - // debugAllowActionJSTmpl.IncNonDefault() - s = append(s, "_html_template_jsstrescaper") - } else { - return context{ - state: stateError, - err: errorf(ErrJSTemplate, n, n.Line, "%s appears in a JS template literal", n), - } - } + case stateJSTmplLit: + s = append(s, "_html_template_jstmpllitescaper") case stateJSRegexp: s = append(s, "_html_template_jsregexpescaper") case stateCSS: @@ -398,6 +388,9 @@ var redundantFuncs = map[string]map[string]bool{ "_html_template_jsstrescaper": { "_html_template_attrescaper": true, }, + "_html_template_jstmpllitescaper": { + "_html_template_attrescaper": true, + }, "_html_template_urlescaper": { "_html_template_urlnormalizer": true, }, diff --git a/tpl/internal/go_templates/htmltemplate/escape_test.go b/tpl/internal/go_templates/htmltemplate/escape_test.go index 4ad5316fb..b202afde0 100644 --- a/tpl/internal/go_templates/htmltemplate/escape_test.go +++ b/tpl/internal/go_templates/htmltemplate/escape_test.go @@ -35,14 +35,14 @@ func (x *goodMarshaler) MarshalJSON() ([]byte, error) { func TestEscape(t *testing.T) { data := struct { - F, T bool - C, G, H string - A, E []string - B, M json.Marshaler - N int - U any // untyped nil - Z *int // typed nil - W htmltemplate.HTML + F, T bool + C, G, H, I string + A, E []string + B, M json.Marshaler + N int + U any // untyped nil + Z *int // typed nil + W htmltemplate.HTML }{ F: false, T: true, @@ -57,6 +57,7 @@ func TestEscape(t *testing.T) { U: nil, Z: nil, W: htmltemplate.HTML(`¡<b class="foo">Hello</b>, <textarea>O'World</textarea>!`), + I: "${ asd `` }", } pdata := &data @@ -723,6 +724,21 @@ func TestEscape(t *testing.T) { "<p name=\"{{.U}}\">", "<p name=\"\">", }, + { + "JS template lit special characters", + "<script>var a = `{{.I}}`</script>", + "<script>var a = `\\u0024\\u007b asd \\u0060\\u0060 \\u007d`</script>", + }, + { + "JS template lit special characters, nested lit", + "<script>var a = `${ `{{.I}}` }`</script>", + "<script>var a = `${ `\\u0024\\u007b asd \\u0060\\u0060 \\u007d` }`</script>", + }, + { + "JS template lit, nested JS", + "<script>var a = `${ var a = \"{{\"a \\\" d\"}}\" }`</script>", + "<script>var a = `${ var a = \"a \\u0022 d\" }`</script>", + }, } for _, test := range tests { @@ -981,6 +997,31 @@ func TestErrors(t *testing.T) { "<script>var a = `${a+b}`</script>`", "", }, + { + "<script>var tmpl = `asd`;</script>", + ``, + }, + { + "<script>var tmpl = `${1}`;</script>", + ``, + }, + { + "<script>var tmpl = `${return ``}`;</script>", + ``, + }, + { + "<script>var tmpl = `${return {{.}} }`;</script>", + ``, + }, + { + "<script>var tmpl = `${ let a = {1:1} {{.}} }`;</script>", + ``, + }, + { + "<script>var tmpl = `asd ${return \"{\"}`;</script>", + ``, + }, + // Error cases. { "{{if .Cond}}<a{{end}}", @@ -1127,10 +1168,6 @@ func TestErrors(t *testing.T) { // html is allowed since it is the last command in the pipeline, but urlquery is not. `predefined escaper "urlquery" disallowed in template`, }, - { - "<script>var tmpl = `asd {{.}}`;</script>", - `{{.}} appears in a JS template literal`, - }, } for _, test := range tests { buf := new(bytes.Buffer) @@ -1354,7 +1391,7 @@ func TestEscapeText(t *testing.T) { }, { "<a onclick=\"`foo", - context{state: stateJSBqStr, delim: delimDoubleQuote, attr: attrScript}, + context{state: stateJSTmplLit, delim: delimDoubleQuote, attr: attrScript}, }, { `<A ONCLICK="'`, @@ -1696,6 +1733,94 @@ func TestEscapeText(t *testing.T) { `<svg:a svg:onclick="x()">`, context{}, }, + { + "<script>var a = `", + context{state: stateJSTmplLit, element: elementScript}, + }, + { + "<script>var a = `${", + context{state: stateJS, element: elementScript}, + }, + { + "<script>var a = `${}", + context{state: stateJSTmplLit, element: elementScript}, + }, + { + "<script>var a = `${`", + context{state: stateJSTmplLit, element: elementScript}, + }, + { + "<script>var a = `${var a = \"", + context{state: stateJSDqStr, element: elementScript}, + }, + { + "<script>var a = `${var a = \"`", + context{state: stateJSDqStr, element: elementScript}, + }, + { + "<script>var a = `${var a = \"}", + context{state: stateJSDqStr, element: elementScript}, + }, + { + "<script>var a = `${``", + context{state: stateJS, element: elementScript}, + }, + { + "<script>var a = `${`}", + context{state: stateJSTmplLit, element: elementScript}, + }, + { + "<script>`${ {} } asd`</script><script>`${ {} }", + context{state: stateJSTmplLit, element: elementScript}, + }, + { + "<script>var foo = `${ (_ => { return \"x\" })() + \"${", + context{state: stateJSDqStr, element: elementScript}, + }, + { + "<script>var a = `${ {</script><script>var b = `${ x }", + context{state: stateJSTmplLit, element: elementScript, jsCtx: jsCtxDivOp}, + }, + { + "<script>var foo = `x` + \"${", + context{state: stateJSDqStr, element: elementScript}, + }, + { + "<script>function f() { var a = `${}`; }", + context{state: stateJS, element: elementScript}, + }, + { + "<script>{`${}`}", + context{state: stateJS, element: elementScript}, + }, + { + "<script>`${ function f() { return `${1}` }() }`", + context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp}, + }, + { + "<script>function f() {`${ function f() { `${1}` } }`}", + context{state: stateJS, element: elementScript, jsCtx: jsCtxDivOp}, + }, + { + "<script>`${ { `` }", + context{state: stateJS, element: elementScript}, + }, + { + "<script>`${ { }`", + context{state: stateJSTmplLit, element: elementScript}, + }, + { + "<script>var foo = `${ foo({ a: { c: `${", + context{state: stateJS, element: elementScript}, + }, + { + "<script>var foo = `${ foo({ a: { c: `${ {{.}} }` }, b: ", + context{state: stateJS, element: elementScript}, + }, + { + "<script>`${ `}", + context{state: stateJSTmplLit, element: elementScript}, + }, } for _, test := range tests { diff --git a/tpl/internal/go_templates/htmltemplate/exec_test.go b/tpl/internal/go_templates/htmltemplate/exec_test.go index 8f9b893b4..e91aeafa1 100644 --- a/tpl/internal/go_templates/htmltemplate/exec_test.go +++ b/tpl/internal/go_templates/htmltemplate/exec_test.go @@ -325,12 +325,16 @@ var execTests = []execTest{ {"$.U.V", "{{$.U.V}}", "v", tVal, true}, {"declare in action", "{{$x := $.U.V}}{{$x}}", "v", tVal, true}, {"simple assignment", "{{$x := 2}}{{$x = 3}}{{$x}}", "3", tVal, true}, - {"nested assignment", + { + "nested assignment", "{{$x := 2}}{{if true}}{{$x = 3}}{{end}}{{$x}}", - "3", tVal, true}, - {"nested assignment changes the last declaration", + "3", tVal, true, + }, + { + "nested assignment changes the last declaration", "{{$x := 1}}{{if true}}{{$x := 2}}{{if true}}{{$x = 3}}{{end}}{{end}}{{$x}}", - "1", tVal, true}, + "1", tVal, true, + }, // Type with String method. {"V{6666}.String()", "-{{.V0}}-", "-{6666}-", tVal, true}, // NOTE: -<6666>- in text/template @@ -377,15 +381,21 @@ var execTests = []execTest{ {".Method3(nil constant)", "-{{.Method3 nil}}-", "-Method3: <nil>-", tVal, true}, {".Method3(nil value)", "-{{.Method3 .MXI.unset}}-", "-Method3: <nil>-", tVal, true}, {"method on var", "{{if $x := .}}-{{$x.Method2 .U16 $x.X}}{{end}}-", "-Method2: 16 x-", tVal, true}, - {"method on chained var", + { + "method on chained var", "{{range .MSIone}}{{if $.U.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}", - "true", tVal, true}, - {"chained method", + "true", tVal, true, + }, + { + "chained method", "{{range .MSIone}}{{if $.GetU.TrueFalse $.True}}{{$.U.TrueFalse $.True}}{{else}}WRONG{{end}}{{end}}", - "true", tVal, true}, - {"chained method on variable", + "true", tVal, true, + }, + { + "chained method on variable", "{{with $x := .}}{{with .SI}}{{$.GetU.TrueFalse $.True}}{{end}}{{end}}", - "true", tVal, true}, + "true", tVal, true, + }, {".NilOKFunc not nil", "{{call .NilOKFunc .PI}}", "false", tVal, true}, {".NilOKFunc nil", "{{call .NilOKFunc nil}}", "true", tVal, true}, {"method on nil value from slice", "-{{range .}}{{.Method1 1234}}{{end}}-", "-1234-", tSliceOfNil, true}, @@ -471,10 +481,14 @@ var execTests = []execTest{ {"printf lots", `{{printf "%d %s %g %s" 127 "hello" 7-3i .Method0}}`, "127 hello (7-3i) M0", tVal, true}, // HTML. - {"html", `{{html "<script>alert(\"XSS\");</script>"}}`, - "<script>alert("XSS");</script>", nil, true}, - {"html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`, - "<script>alert("XSS");</script>", nil, true}, + { + "html", `{{html "<script>alert(\"XSS\");</script>"}}`, + "<script>alert("XSS");</script>", nil, true, + }, + { + "html pipeline", `{{printf "<script>alert(\"XSS\");</script>" | html}}`, + "<script>alert("XSS");</script>", nil, true, + }, {"html", `{{html .PS}}`, "a string", tVal, true}, {"html typed nil", `{{html .NIL}}`, "<nil>", tVal, true}, {"html untyped nil", `{{html .Empty0}}`, "<nil>", tVal, true}, // NOTE: "<no value>" in text/template @@ -838,7 +852,7 @@ var delimPairs = []string{ func TestDelims(t *testing.T) { const hello = "Hello, world" - var value = struct{ Str string }{hello} + value := struct{ Str string }{hello} for i := 0; i < len(delimPairs); i += 2 { text := ".Str" left := delimPairs[i+0] @@ -861,7 +875,7 @@ func TestDelims(t *testing.T) { if err != nil { t.Fatalf("delim %q text %q parse err %s", left, text, err) } - var b = new(strings.Builder) + b := new(strings.Builder) err = tmpl.Execute(b, value) if err != nil { t.Fatalf("delim %q exec err %s", left, err) @@ -962,7 +976,7 @@ const treeTemplate = ` ` func TestTree(t *testing.T) { - var tree = &Tree{ + tree := &Tree{ 1, &Tree{ 2, &Tree{ @@ -1213,7 +1227,7 @@ var cmpTests = []cmpTest{ func TestComparison(t *testing.T) { b := new(strings.Builder) - var cmpStruct = struct { + cmpStruct := struct { Uthree, Ufour uint NegOne, Three int Ptr, NilPtr *int diff --git a/tpl/internal/go_templates/htmltemplate/hugo_template.go b/tpl/internal/go_templates/htmltemplate/hugo_template.go index 98e03ad3c..99edf8f68 100644 --- a/tpl/internal/go_templates/htmltemplate/hugo_template.go +++ b/tpl/internal/go_templates/htmltemplate/hugo_template.go @@ -14,15 +14,9 @@ package template import ( - "sync/atomic" - template "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate" ) -// See https://github.com/golang/go/issues/59234 -// Moved here to avoid dependency on Go's internal/debug package. -var SecurityAllowActionJSTmpl atomic.Bool - /* This files contains the Hugo related addons. All the other files in this diff --git a/tpl/internal/go_templates/htmltemplate/js.go b/tpl/internal/go_templates/htmltemplate/js.go index 3b5178eb1..79d9102e5 100644 --- a/tpl/internal/go_templates/htmltemplate/js.go +++ b/tpl/internal/go_templates/htmltemplate/js.go @@ -239,6 +239,11 @@ func jsStrEscaper(args ...any) string { return replace(s, jsStrReplacementTable) } +func jsTmplLitEscaper(args ...any) string { + s, _ := stringify(args...) + return replace(s, jsBqStrReplacementTable) +} + // jsRegexpEscaper behaves like jsStrEscaper but escapes regular expression // specials so the result is treated literally when included in a regular // expression literal. /foo{{.X}}bar/ matches the string "foo" followed by @@ -325,6 +330,31 @@ var jsStrReplacementTable = []string{ '\\': `\\`, } +// jsBqStrReplacementTable is like jsStrReplacementTable except it also contains +// the special characters for JS template literals: $, {, and }. +var jsBqStrReplacementTable = []string{ + 0: `\u0000`, + '\t': `\t`, + '\n': `\n`, + '\v': `\u000b`, // "\v" == "v" on IE 6. + '\f': `\f`, + '\r': `\r`, + // Encode HTML specials as hex so the output can be embedded + // in HTML attributes without further encoding. + '"': `\u0022`, + '`': `\u0060`, + '&': `\u0026`, + '\'': `\u0027`, + '+': `\u002b`, + '/': `\/`, + '<': `\u003c`, + '>': `\u003e`, + '\\': `\\`, + '$': `\u0024`, + '{': `\u007b`, + '}': `\u007d`, +} + // jsStrNormReplacementTable is like jsStrReplacementTable but does not // overencode existing escapes since this table has no entry for `\`. var jsStrNormReplacementTable = []string{ @@ -345,6 +375,7 @@ var jsStrNormReplacementTable = []string{ '<': `\u003c`, '>': `\u003e`, } + var jsRegexpReplacementTable = []string{ 0: `\u0000`, '\t': `\t`, diff --git a/tpl/internal/go_templates/htmltemplate/state_string.go b/tpl/internal/go_templates/htmltemplate/state_string.go index be7a92051..eed1e8bcc 100644 --- a/tpl/internal/go_templates/htmltemplate/state_string.go +++ b/tpl/internal/go_templates/htmltemplate/state_string.go @@ -21,7 +21,7 @@ func _() { _ = x[stateJS-10] _ = x[stateJSDqStr-11] _ = x[stateJSSqStr-12] - _ = x[stateJSBqStr-13] + _ = x[stateJSTmplLit-13] _ = x[stateJSRegexp-14] _ = x[stateJSBlockCmt-15] _ = x[stateJSLineCmt-16] @@ -39,9 +39,9 @@ func _() { _ = x[stateDead-28] } -const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSBqStrstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" +const _state_name = "stateTextstateTagstateAttrNamestateAfterNamestateBeforeValuestateHTMLCmtstateRCDATAstateAttrstateURLstateSrcsetstateJSstateJSDqStrstateJSSqStrstateJSTmplLitstateJSRegexpstateJSBlockCmtstateJSLineCmtstateJSHTMLOpenCmtstateJSHTMLCloseCmtstateCSSstateCSSDqStrstateCSSSqStrstateCSSDqURLstateCSSSqURLstateCSSURLstateCSSBlockCmtstateCSSLineCmtstateErrorstateDead" -var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 154, 167, 182, 196, 214, 233, 241, 254, 267, 280, 293, 304, 320, 335, 345, 354} +var _state_index = [...]uint16{0, 9, 17, 30, 44, 60, 72, 83, 92, 100, 111, 118, 130, 142, 156, 169, 184, 198, 216, 235, 243, 256, 269, 282, 295, 306, 322, 337, 347, 356} func (i state) String() string { if i >= state(len(_state_index)-1) { diff --git a/tpl/internal/go_templates/htmltemplate/transition.go b/tpl/internal/go_templates/htmltemplate/transition.go index 432c365d3..d5a05f66d 100644 --- a/tpl/internal/go_templates/htmltemplate/transition.go +++ b/tpl/internal/go_templates/htmltemplate/transition.go @@ -27,8 +27,8 @@ var transitionFunc = [...]func(context, []byte) (context, int){ stateJS: tJS, stateJSDqStr: tJSDelimited, stateJSSqStr: tJSDelimited, - stateJSBqStr: tJSDelimited, stateJSRegexp: tJSDelimited, + stateJSTmplLit: tJSTmpl, stateJSBlockCmt: tBlockCmt, stateJSLineCmt: tLineCmt, stateJSHTMLOpenCmt: tLineCmt, @@ -270,7 +270,7 @@ func tURL(c context, s []byte) (context, int) { // tJS is the context transition function for the JS state. func tJS(c context, s []byte) (context, int) { - i := bytes.IndexAny(s, "\"`'/<-#") + i := bytes.IndexAny(s, " |