package parser import ( "strings" "github.com/a-h/parse" ) var scriptElement = scriptElementParser{} type jsQuote string const ( jsQuoteNone jsQuote = "" jsQuoteSingle jsQuote = `'` jsQuoteDouble jsQuote = `"` jsQuoteBacktick jsQuote = "`" ) type scriptElementParser struct{} func (p scriptElementParser) Parse(pi *parse.Input) (n Node, ok bool, err error) { start := pi.Index() // < if _, ok, err = lt.Parse(pi); err != nil || !ok { return } // Element name. e := &ScriptElement{} var name string if name, ok, err = elementNameParser.Parse(pi); err != nil || !ok { pi.Seek(start) return n, false, err } if name != "script" { pi.Seek(start) return n, false, nil } if e.Attributes, ok, err = (attributesParser{}).Parse(pi); err != nil || !ok { pi.Seek(start) return n, false, err } // Optional whitespace. if _, _, err = parse.OptionalWhitespace.Parse(pi); err != nil { pi.Seek(start) return n, false, err } // > if _, ok, err = gt.Parse(pi); err != nil || !ok { pi.Seek(start) return n, false, parse.Error(" - End of the script, break out of the loop. // - ' - Start of a single quoted string. // - " - Start of a double quoted string. // - ` - Start of a backtick quoted string. // - // - Start of a single line comment - can read to the end of the line without parsing. // - /* - Start of a multi-line comment - can read to the end of the comment without parsing. // - \ - Start of an escape sequence, we can just take the value. // - Anything else - Add it to the script. _, ok, err = jsEndTag.Parse(pi) if err != nil { return nil, false, err } if ok { // We've reached the end of the script. break loop } _, ok, err = endTagStart.Parse(pi) if err != nil { return nil, false, err } if ok { return nil, false, parse.Error(" not found", pi.Position()) } // Try for a Go code expression, i.e. {{ goCode }}. code, ok, err := goCodeInJavaScript.Parse(pi) if err != nil { return nil, false, err } if ok { e.Contents = append(e.Contents, NewScriptContentsGo(code.(*GoCode), stringLiteralDelimiter != jsQuoteNone)) continue loop } // Try for a comment. comment, ok, err := jsComment.Parse(pi) if err != nil { return nil, false, err } if ok { e.Contents = append(e.Contents, NewScriptContentsScriptCode(comment)) continue loop } // Read JavaScript characters. charLoop: for { before := pi.Index() // If we're outside of a string literal, check for a regexp literal. // Check for a regular expression literal. if stringLiteralDelimiter == jsQuoteNone { r, ok, err := regexpLiteral.Parse(pi) if err != nil { return nil, false, err } if ok { sb.WriteString(r) continue charLoop } } // Check for EOF. if _, ok, _ = parse.EOF[string]().Parse(pi); ok { return nil, false, parse.Error("script: unclosed ") endTagStart = parse.String("