diff options
Diffstat (limited to 'vendor/github.com/tdewolff/parse')
56 files changed, 0 insertions, 9755 deletions
diff --git a/vendor/github.com/tdewolff/parse/.travis.yml b/vendor/github.com/tdewolff/parse/.travis.yml deleted file mode 100644 index a24cef7..0000000 --- a/vendor/github.com/tdewolff/parse/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go -before_install: - - go get github.com/mattn/goveralls -script: - - goveralls -v -service travis-ci -repotoken $COVERALLS_TOKEN || go test -v ./...
\ No newline at end of file diff --git a/vendor/github.com/tdewolff/parse/LICENSE.md b/vendor/github.com/tdewolff/parse/LICENSE.md deleted file mode 100644 index 41677de..0000000 --- a/vendor/github.com/tdewolff/parse/LICENSE.md +++ /dev/null @@ -1,22 +0,0 @@ -Copyright (c) 2015 Taco de Wolff - - Permission is hereby granted, free of charge, to any person - obtaining a copy of this software and associated documentation - files (the "Software"), to deal in the Software without - restriction, including without limitation the rights to use, - copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following - conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file diff --git a/vendor/github.com/tdewolff/parse/README.md b/vendor/github.com/tdewolff/parse/README.md deleted file mode 100644 index f6452a7..0000000 --- a/vendor/github.com/tdewolff/parse/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# Parse [![Build Status](https://travis-ci.org/tdewolff/parse.svg?branch=master)](https://travis-ci.org/tdewolff/parse) [![GoDoc](http://godoc.org/github.com/tdewolff/parse?status.svg)](http://godoc.org/github.com/tdewolff/parse) [![Coverage Status](https://coveralls.io/repos/github/tdewolff/parse/badge.svg?branch=master)](https://coveralls.io/github/tdewolff/parse?branch=master) - -This package contains several lexers and parsers written in [Go][1]. All subpackages are built to be streaming, high performance and to be in accordance with the official (latest) specifications. - -The lexers are implemented using `buffer.Lexer` in https://github.com/tdewolff/parse/buffer and the parsers work on top of the lexers. Some subpackages have hashes defined (using [Hasher](https://github.com/tdewolff/hasher)) that speed up common byte-slice comparisons. - -## Buffer -### Reader -Reader is a wrapper around a `[]byte` that implements the `io.Reader` interface. It is a much thinner layer than `bytes.Buffer` provides and is therefore faster. - -### Writer -Writer is a buffer that implements the `io.Writer` interface. It is a much thinner layer than `bytes.Buffer` provides and is therefore faster. It will expand the buffer when needed. - -The reset functionality allows for better memory reuse. After calling `Reset`, it will overwrite the current buffer and thus reduce allocations. - -### Lexer -Lexer is a read buffer specifically designed for building lexers. It keeps track of two positions: a start and end position. The start position is the beginning of the current token being parsed, the end position is being moved forward until a valid token is found. Calling `Shift` will collapse the positions to the end and return the parsed `[]byte`. - -Moving the end position can go through `Move(int)` which also accepts negative integers. One can also use `Pos() int` to try and parse a token, and if it fails rewind with `Rewind(int)`, passing the previously saved position. - -`Peek(int) byte` will peek forward (relative to the end position) and return the byte at that location. `PeekRune(int) (rune, int)` returns UTF-8 runes and its length at the given **byte** position. Upon an error `Peek` will return `0`, the **user must peek at every character** and not skip any, otherwise it may skip a `0` and panic on out-of-bounds indexing. - -`Lexeme() []byte` will return the currently selected bytes, `Skip()` will collapse the selection. `Shift() []byte` is a combination of `Lexeme() []byte` and `Skip()`. - -When the passed `io.Reader` returned an error, `Err() error` will return that error even if not at the end of the buffer. - -### StreamLexer -StreamLexer behaves like Lexer but uses a buffer pool to read in chunks from `io.Reader`, retaining old buffers in memory that are still in use, and re-using old buffers otherwise. Calling `Free(n int)` frees up `n` bytes from the internal buffer(s). It holds an array of buffers to accommodate for keeping everything in-memory. Calling `ShiftLen() int` returns the number of bytes that have been shifted since the previous call to `ShiftLen`, which can be used to specify how many bytes need to be freed up from the buffer. If you don't need to keep returned byte slices around, call `Free(ShiftLen())` after every `Shift` call. - -## Strconv -This package contains string conversion function much like the standard library's `strconv` package, but it is specifically tailored for the performance needs within the `minify` package. - -For example, the floating-point to string conversion function is approximately twice as fast as the standard library, but it is not as precise. - -## CSS -This package is a CSS3 lexer and parser. Both follow the specification at [CSS Syntax Module Level 3](http://www.w3.org/TR/css-syntax-3/). The lexer takes an io.Reader and converts it into tokens until the EOF. The parser returns a parse tree of the full io.Reader input stream, but the low-level `Next` function can be used for stream parsing to returns grammar units until the EOF. - -[See README here](https://github.com/tdewolff/parse/tree/master/css). - -## HTML -This package is an HTML5 lexer. It follows the specification at [The HTML syntax](http://www.w3.org/TR/html5/syntax.html). The lexer takes an io.Reader and converts it into tokens until the EOF. - -[See README here](https://github.com/tdewolff/parse/tree/master/html). - -## JS -This package is a JS lexer (ECMA-262, edition 6.0). It follows the specification at [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/6.0/). The lexer takes an io.Reader and converts it into tokens until the EOF. - -[See README here](https://github.com/tdewolff/parse/tree/master/js). - -## JSON -This package is a JSON parser (ECMA-404). It follows the specification at [JSON](http://json.org/). The parser takes an io.Reader and converts it into tokens until the EOF. - -[See README here](https://github.com/tdewolff/parse/tree/master/json). - -## SVG -This package contains common hashes for SVG1.1 tags and attributes. - -## XML -This package is an XML1.0 lexer. It follows the specification at [Extensible Markup Language (XML) 1.0 (Fifth Edition)](http://www.w3.org/TR/xml/). The lexer takes an io.Reader and converts it into tokens until the EOF. - -[See README here](https://github.com/tdewolff/parse/tree/master/xml). - -## License -Released under the [MIT license](LICENSE.md). - -[1]: http://golang.org/ "Go Language" diff --git a/vendor/github.com/tdewolff/parse/buffer/buffer.go b/vendor/github.com/tdewolff/parse/buffer/buffer.go deleted file mode 100644 index 3094aa9..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/buffer.go +++ /dev/null @@ -1,15 +0,0 @@ -/* -Package buffer contains buffer and wrapper types for byte slices. It is useful for writing lexers or other high-performance byte slice handling. - -The `Reader` and `Writer` types implement the `io.Reader` and `io.Writer` respectively and provide a thinner and faster interface than `bytes.Buffer`. -The `Lexer` type is useful for building lexers because it keeps track of the start and end position of a byte selection, and shifts the bytes whenever a valid token is found. -The `StreamLexer` does the same, but keeps a buffer pool so that it reads a limited amount at a time, allowing to parse from streaming sources. -*/ -package buffer // import "github.com/tdewolff/parse/buffer" - -// defaultBufSize specifies the default initial length of internal buffers. -var defaultBufSize = 4096 - -// MinBuf specifies the default initial length of internal buffers. -// Solely here to support old versions of parse. -var MinBuf = defaultBufSize diff --git a/vendor/github.com/tdewolff/parse/buffer/lexer.go b/vendor/github.com/tdewolff/parse/buffer/lexer.go deleted file mode 100644 index 45c1844..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/lexer.go +++ /dev/null @@ -1,158 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import ( - "io" - "io/ioutil" -) - -var nullBuffer = []byte{0} - -// Lexer is a buffered reader that allows peeking forward and shifting, taking an io.Reader. -// It keeps data in-memory until Free, taking a byte length, is called to move beyond the data. -type Lexer struct { - buf []byte - pos int // index in buf - start int // index in buf - err error - - restore func() -} - -// NewLexerBytes returns a new Lexer for a given io.Reader, and uses ioutil.ReadAll to read it into a byte slice. -// If the io.Reader implements Bytes, that is used instead. -// It will append a NULL at the end of the buffer. -func NewLexer(r io.Reader) *Lexer { - var b []byte - if r != nil { - if buffer, ok := r.(interface { - Bytes() []byte - }); ok { - b = buffer.Bytes() - } else { - var err error - b, err = ioutil.ReadAll(r) - if err != nil { - return &Lexer{ - buf: []byte{0}, - err: err, - } - } - } - } - return NewLexerBytes(b) -} - -// NewLexerBytes returns a new Lexer for a given byte slice, and appends NULL at the end. -// To avoid reallocation, make sure the capacity has room for one more byte. -func NewLexerBytes(b []byte) *Lexer { - z := &Lexer{ - buf: b, - } - - n := len(b) - if n == 0 { - z.buf = nullBuffer - } else if b[n-1] != 0 { - // Append NULL to buffer, but try to avoid reallocation - if cap(b) > n { - // Overwrite next byte but restore when done - b = b[:n+1] - c := b[n] - b[n] = 0 - - z.buf = b - z.restore = func() { - b[n] = c - } - } else { - z.buf = append(b, 0) - } - } - return z -} - -// Restore restores the replaced byte past the end of the buffer by NULL. -func (z *Lexer) Restore() { - if z.restore != nil { - z.restore() - z.restore = nil - } -} - -// Err returns the error returned from io.Reader or io.EOF when the end has been reached. -func (z *Lexer) Err() error { - return z.PeekErr(0) -} - -// PeekErr returns the error at position pos. When pos is zero, this is the same as calling Err(). -func (z *Lexer) PeekErr(pos int) error { - if z.err != nil { - return z.err - } else if z.pos+pos >= len(z.buf)-1 { - return io.EOF - } - return nil -} - -// Peek returns the ith byte relative to the end position. -// Peek returns 0 when an error has occurred, Err returns the error. -func (z *Lexer) Peek(pos int) byte { - pos += z.pos - return z.buf[pos] -} - -// PeekRune returns the rune and rune length of the ith byte relative to the end position. -func (z *Lexer) PeekRune(pos int) (rune, int) { - // from unicode/utf8 - c := z.Peek(pos) - if c < 0xC0 || z.Peek(pos+1) == 0 { - return rune(c), 1 - } else if c < 0xE0 || z.Peek(pos+2) == 0 { - return rune(c&0x1F)<<6 | rune(z.Peek(pos+1)&0x3F), 2 - } else if c < 0xF0 || z.Peek(pos+3) == 0 { - return rune(c&0x0F)<<12 | rune(z.Peek(pos+1)&0x3F)<<6 | rune(z.Peek(pos+2)&0x3F), 3 - } - return rune(c&0x07)<<18 | rune(z.Peek(pos+1)&0x3F)<<12 | rune(z.Peek(pos+2)&0x3F)<<6 | rune(z.Peek(pos+3)&0x3F), 4 -} - -// Move advances the position. -func (z *Lexer) Move(n int) { - z.pos += n -} - -// Pos returns a mark to which can be rewinded. -func (z *Lexer) Pos() int { - return z.pos - z.start -} - -// Rewind rewinds the position to the given position. -func (z *Lexer) Rewind(pos int) { - z.pos = z.start + pos -} - -// Lexeme returns the bytes of the current selection. -func (z *Lexer) Lexeme() []byte { - return z.buf[z.start:z.pos] -} - -// Skip collapses the position to the end of the selection. -func (z *Lexer) Skip() { - z.start = z.pos -} - -// Shift returns the bytes of the current selection and collapses the position to the end of the selection. -func (z *Lexer) Shift() []byte { - b := z.buf[z.start:z.pos] - z.start = z.pos - return b -} - -// Offset returns the character position in the buffer. -func (z *Lexer) Offset() int { - return z.pos -} - -// Bytes returns the underlying buffer. -func (z *Lexer) Bytes() []byte { - return z.buf -} diff --git a/vendor/github.com/tdewolff/parse/buffer/lexer_test.go b/vendor/github.com/tdewolff/parse/buffer/lexer_test.go deleted file mode 100644 index 1317dd0..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/lexer_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import ( - "bytes" - "io" - "testing" - - "github.com/tdewolff/test" -) - -func TestLexer(t *testing.T) { - s := `Lorem ipsum dolor sit amet, consectetur adipiscing elit.` - z := NewLexer(bytes.NewBufferString(s)) - - test.T(t, z.err, nil, "buffer has no error") - test.T(t, z.Err(), nil, "buffer is at EOF but must not return EOF until we reach that") - test.That(t, z.Pos() == 0, "buffer must start at position 0") - test.That(t, z.Peek(0) == 'L', "first character must be 'L'") - test.That(t, z.Peek(1) == 'o', "second character must be 'o'") - - z.Move(1) - test.That(t, z.Peek(0) == 'o', "must be 'o' at position 1") - test.That(t, z.Peek(1) == 'r', "must be 'r' at position 1") - z.Rewind(6) - test.That(t, z.Peek(0) == 'i', "must be 'i' at position 6") - test.That(t, z.Peek(1) == 'p', "must be 'p' at position 7") - - test.Bytes(t, z.Lexeme(), []byte("Lorem "), "buffered string must now read 'Lorem ' when at position 6") - test.Bytes(t, z.Shift(), []byte("Lorem "), "shift must return the buffered string") - test.That(t, z.Pos() == 0, "after shifting position must be 0") - test.That(t, z.Peek(0) == 'i', "must be 'i' at position 0 after shifting") - test.That(t, z.Peek(1) == 'p', "must be 'p' at position 1 after shifting") - test.T(t, z.Err(), nil, "error must be nil at this point") - - z.Move(len(s) - len("Lorem ") - 1) - test.T(t, z.Err(), nil, "error must be nil just before the end of the buffer") - z.Skip() - test.That(t, z.Pos() == 0, "after skipping position must be 0") - z.Move(1) - test.T(t, z.Err(), io.EOF, "error must be EOF when past the buffer") - z.Move(-1) - test.T(t, z.Err(), nil, "error must be nil just before the end of the buffer, even when it has been past the buffer") -} - -func TestLexerRunes(t *testing.T) { - z := NewLexer(bytes.NewBufferString("aæ†\U00100000")) - r, n := z.PeekRune(0) - test.That(t, n == 1, "first character must be length 1") - test.That(t, r == 'a', "first character must be rune 'a'") - r, n = z.PeekRune(1) - test.That(t, n == 2, "second character must be length 2") - test.That(t, r == 'æ', "second character must be rune 'æ'") - r, n = z.PeekRune(3) - test.That(t, n == 3, "fourth character must be length 3") - test.That(t, r == '†', "fourth character must be rune '†'") - r, n = z.PeekRune(6) - test.That(t, n == 4, "seventh character must be length 4") - test.That(t, r == '\U00100000', "seventh character must be rune '\U00100000'") -} - -func TestLexerBadRune(t *testing.T) { - z := NewLexer(bytes.NewBufferString("\xF0")) // expect four byte rune - r, n := z.PeekRune(0) - test.T(t, n, 1, "length") - test.T(t, r, rune(0xF0), "rune") -} - -func TestLexerZeroLen(t *testing.T) { - z := NewLexer(test.NewPlainReader(bytes.NewBufferString(""))) - test.That(t, z.Peek(0) == 0, "first character must yield error") -} - -func TestLexerEmptyReader(t *testing.T) { - z := NewLexer(test.NewEmptyReader()) - test.That(t, z.Peek(0) == 0, "first character must yield error") - test.T(t, z.Err(), io.EOF, "error must be EOF") - test.That(t, z.Peek(0) == 0, "second peek must also yield error") -} - -func TestLexerErrorReader(t *testing.T) { - z := NewLexer(test.NewErrorReader(0)) - test.That(t, z.Peek(0) == 0, "first character must yield error") - test.T(t, z.Err(), test.ErrPlain, "error must be ErrPlain") - test.That(t, z.Peek(0) == 0, "second peek must also yield error") -} - -func TestLexerBytes(t *testing.T) { - b := []byte{'t', 'e', 's', 't'} - z := NewLexerBytes(b) - test.That(t, z.Peek(4) == 0, "fifth character must yield NULL") -} diff --git a/vendor/github.com/tdewolff/parse/buffer/reader.go b/vendor/github.com/tdewolff/parse/buffer/reader.go deleted file mode 100644 index f1a0925..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/reader.go +++ /dev/null @@ -1,44 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import "io" - -// Reader implements an io.Reader over a byte slice. -type Reader struct { - buf []byte - pos int -} - -// NewReader returns a new Reader for a given byte slice. -func NewReader(buf []byte) *Reader { - return &Reader{ - buf: buf, - } -} - -// Read reads bytes into the given byte slice and returns the number of bytes read and an error if occurred. -func (r *Reader) Read(b []byte) (n int, err error) { - if len(b) == 0 { - return 0, nil - } - if r.pos >= len(r.buf) { - return 0, io.EOF - } - n = copy(b, r.buf[r.pos:]) - r.pos += n - return -} - -// Bytes returns the underlying byte slice. -func (r *Reader) Bytes() []byte { - return r.buf -} - -// Reset resets the position of the read pointer to the beginning of the underlying byte slice. -func (r *Reader) Reset() { - r.pos = 0 -} - -// Len returns the length of the buffer. -func (r *Reader) Len() int { - return len(r.buf) -} diff --git a/vendor/github.com/tdewolff/parse/buffer/reader_test.go b/vendor/github.com/tdewolff/parse/buffer/reader_test.go deleted file mode 100644 index 73600ec..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/reader_test.go +++ /dev/null @@ -1,49 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/test" -) - -func TestReader(t *testing.T) { - s := []byte("abcde") - r := NewReader(s) - test.Bytes(t, r.Bytes(), s, "reader must return bytes stored") - - buf := make([]byte, 3) - n, err := r.Read(buf) - test.T(t, err, nil, "error") - test.That(t, n == 3, "first read must read 3 characters") - test.Bytes(t, buf, []byte("abc"), "first read must match 'abc'") - - n, err = r.Read(buf) - test.T(t, err, nil, "error") - test.That(t, n == 2, "second read must read 2 characters") - test.Bytes(t, buf[:n], []byte("de"), "second read must match 'de'") - - n, err = r.Read(buf) - test.T(t, err, io.EOF, "error") - test.That(t, n == 0, "third read must read 0 characters") - - n, err = r.Read(nil) - test.T(t, err, nil, "error") - test.That(t, n == 0, "read to nil buffer must return 0 characters read") - - r.Reset() - n, err = r.Read(buf) - test.T(t, err, nil, "error") - test.That(t, n == 3, "read after reset must read 3 characters") - test.Bytes(t, buf, []byte("abc"), "read after reset must match 'abc'") -} - -func ExampleNewReader() { - r := NewReader([]byte("Lorem ipsum")) - w := &bytes.Buffer{} - io.Copy(w, r) - fmt.Println(w.String()) - // Output: Lorem ipsum -} diff --git a/vendor/github.com/tdewolff/parse/buffer/streamlexer.go b/vendor/github.com/tdewolff/parse/buffer/streamlexer.go deleted file mode 100644 index 3ed3282..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/streamlexer.go +++ /dev/null @@ -1,223 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import ( - "io" -) - -type block struct { - buf []byte - next int // index in pool plus one - active bool -} - -type bufferPool struct { - pool []block - head int // index in pool plus one - tail int // index in pool plus one - - pos int // byte pos in tail -} - -func (z *bufferPool) swap(oldBuf []byte, size int) []byte { - // find new buffer that can be reused - swap := -1 - for i := 0; i < len(z.pool); i++ { - if !z.pool[i].active && size <= cap(z.pool[i].buf) { - swap = i - break - } - } - if swap == -1 { // no free buffer found for reuse - if z.tail == 0 && z.pos >= len(oldBuf) && size <= cap(oldBuf) { // but we can reuse the current buffer! - z.pos -= len(oldBuf) - return oldBuf[:0] - } - // allocate new - z.pool = append(z.pool, block{make([]byte, 0, size), 0, true}) - swap = len(z.pool) - 1 - } - - newBuf := z.pool[swap].buf - - // put current buffer into pool - z.pool[swap] = block{oldBuf, 0, true} - if z.head != 0 { - z.pool[z.head-1].next = swap + 1 - } - z.head = swap + 1 - if z.tail == 0 { - z.tail = swap + 1 - } - - return newBuf[:0] -} - -func (z *bufferPool) free(n int) { - z.pos += n - // move the tail over to next buffers - for z.tail != 0 && z.pos >= len(z.pool[z.tail-1].buf) { - z.pos -= len(z.pool[z.tail-1].buf) - newTail := z.pool[z.tail-1].next - z.pool[z.tail-1].active = false // after this, any thread may pick up the inactive buffer, so it can't be used anymore - z.tail = newTail - } - if z.tail == 0 { - z.head = 0 - } -} - -// StreamLexer is a buffered reader that allows peeking forward and shifting, taking an io.Reader. -// It keeps data in-memory until Free, taking a byte length, is called to move beyond the data. -type StreamLexer struct { - r io.Reader - err error - - pool bufferPool - - buf []byte - start int // index in buf - pos int // index in buf - prevStart int - - free int -} - -// NewStreamLexer returns a new StreamLexer for a given io.Reader with a 4kB estimated buffer size. -// If the io.Reader implements Bytes, that buffer is used instead. -func NewStreamLexer(r io.Reader) *StreamLexer { - return NewStreamLexerSize(r, defaultBufSize) -} - -// NewStreamLexerSize returns a new StreamLexer for a given io.Reader and estimated required buffer size. -// If the io.Reader implements Bytes, that buffer is used instead. -func NewStreamLexerSize(r io.Reader, size int) *StreamLexer { - // if reader has the bytes in memory already, use that instead - if buffer, ok := r.(interface { - Bytes() []byte - }); ok { - return &StreamLexer{ - err: io.EOF, - buf: buffer.Bytes(), - } - } - return &StreamLexer{ - r: r, - buf: make([]byte, 0, size), - } -} - -func (z *StreamLexer) read(pos int) byte { - if z.err != nil { - return 0 - } - - // free unused bytes - z.pool.free(z.free) - z.free = 0 - - // get new buffer - c := cap(z.buf) - p := pos - z.start + 1 - if 2*p > c { // if the token is larger than half the buffer, increase buffer size - c = 2*c + p - } - d := len(z.buf) - z.start - buf := z.pool.swap(z.buf[:z.start], c) - copy(buf[:d], z.buf[z.start:]) // copy the left-overs (unfinished token) from the old buffer - - // read in new data for the rest of the buffer - var n int - for pos-z.start >= d && z.err == nil { - n, z.err = z.r.Read(buf[d:cap(buf)]) - d += n - } - pos -= z.start - z.pos -= z.start - z.start, z.buf = 0, buf[:d] - if pos >= d { - return 0 - } - return z.buf[pos] -} - -// Err returns the error returned from io.Reader. It may still return valid bytes for a while though. -func (z *StreamLexer) Err() error { - if z.err == io.EOF && z.pos < len(z.buf) { - return nil - } - return z.err -} - -// Free frees up bytes of length n from previously shifted tokens. -// Each call to Shift should at one point be followed by a call to Free with a length returned by ShiftLen. -func (z *StreamLexer) Free(n int) { - z.free += n -} - -// Peek returns the ith byte relative to the end position and possibly does an allocation. -// Peek returns zero when an error has occurred, Err returns the error. -// TODO: inline function -func (z *StreamLexer) Peek(pos int) byte { - pos += z.pos - if uint(pos) < uint(len(z.buf)) { // uint for BCE - return z.buf[pos] - } - return z.read(pos) -} - -// PeekRune returns the rune and rune length of the ith byte relative to the end position. -func (z *StreamLexer) PeekRune(pos int) (rune, int) { - // from unicode/utf8 - c := z.Peek(pos) - if c < 0xC0 { - return rune(c), 1 - } else if c < 0xE0 { - return rune(c&0x1F)<<6 | rune(z.Peek(pos+1)&0x3F), 2 - } else if c < 0xF0 { - return rune(c&0x0F)<<12 | rune(z.Peek(pos+1)&0x3F)<<6 | rune(z.Peek(pos+2)&0x3F), 3 - } - return rune(c&0x07)<<18 | rune(z.Peek(pos+1)&0x3F)<<12 | rune(z.Peek(pos+2)&0x3F)<<6 | rune(z.Peek(pos+3)&0x3F), 4 -} - -// Move advances the position. -func (z *StreamLexer) Move(n int) { - z.pos += n -} - -// Pos returns a mark to which can be rewinded. -func (z *StreamLexer) Pos() int { - return z.pos - z.start -} - -// Rewind rewinds the position to the given position. -func (z *StreamLexer) Rewind(pos int) { - z.pos = z.start + pos -} - -// Lexeme returns the bytes of the current selection. -func (z *StreamLexer) Lexeme() []byte { - return z.buf[z.start:z.pos] -} - -// Skip collapses the position to the end of the selection. -func (z *StreamLexer) Skip() { - z.start = z.pos -} - -// Shift returns the bytes of the current selection and collapses the position to the end of the selection. -// It also returns the number of bytes we moved since the last call to Shift. This can be used in calls to Free. -func (z *StreamLexer) Shift() []byte { - if z.pos > len(z.buf) { // make sure we peeked at least as much as we shift - z.read(z.pos - 1) - } - b := z.buf[z.start:z.pos] - z.start = z.pos - return b -} - -// ShiftLen returns the number of bytes moved since the last call to ShiftLen. This can be used in calls to Free because it takes into account multiple Shifts or Skips. -func (z *StreamLexer) ShiftLen() int { - n := z.start - z.prevStart - z.prevStart = z.start - return n -} diff --git a/vendor/github.com/tdewolff/parse/buffer/streamlexer_test.go b/vendor/github.com/tdewolff/parse/buffer/streamlexer_test.go deleted file mode 100644 index d37b0c1..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/streamlexer_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import ( - "bytes" - "io" - "testing" - - "github.com/tdewolff/test" -) - -func TestBufferPool(t *testing.T) { - z := &bufferPool{} - - lorem := []byte("Lorem ipsum") - dolor := []byte("dolor sit amet") - consectetur := []byte("consectetur adipiscing elit") - - // set lorem as first buffer and get new dolor buffer - b := z.swap(lorem, len(dolor)) - test.That(t, len(b) == 0) - test.That(t, cap(b) == len(dolor)) - b = append(b, dolor...) - - // free first buffer so it will be reused - z.free(len(lorem)) - b = z.swap(b, len(lorem)) - b = b[:len(lorem)] - test.Bytes(t, b, lorem) - - b = z.swap(b, len(consectetur)) - b = append(b, consectetur...) - - // free in advance to reuse the same buffer - z.free(len(dolor) + len(lorem) + len(consectetur)) - test.That(t, z.head == 0) - b = z.swap(b, len(consectetur)) - b = b[:len(consectetur)] - test.Bytes(t, b, consectetur) - - // free in advance but request larger buffer - z.free(len(consectetur)) - b = z.swap(b, len(consectetur)+1) - b = append(b, consectetur...) - b = append(b, '.') - test.That(t, cap(b) == len(consectetur)+1) -} - -func TestStreamLexer(t *testing.T) { - s := `Lorem ipsum dolor sit amet, consectetur adipiscing elit.` - z := NewStreamLexer(bytes.NewBufferString(s)) - - test.T(t, z.err, io.EOF, "buffer must be fully in memory") - test.T(t, z.Err(), nil, "buffer is at EOF but must not return EOF until we reach that") - test.That(t, z.Pos() == 0, "buffer must start at position 0") - test.That(t, z.Peek(0) == 'L', "first character must be 'L'") - test.That(t, z.Peek(1) == 'o', "second character must be 'o'") - - z.Move(1) - test.That(t, z.Peek(0) == 'o', "must be 'o' at position 1") - test.That(t, z.Peek(1) == 'r', "must be 'r' at position 1") - z.Rewind(6) - test.That(t, z.Peek(0) == 'i', "must be 'i' at position 6") - test.That(t, z.Peek(1) == 'p', "must be 'p' at position 7") - - test.Bytes(t, z.Lexeme(), []byte("Lorem "), "buffered string must now read 'Lorem ' when at position 6") - test.Bytes(t, z.Shift(), []byte("Lorem "), "shift must return the buffered string") - test.That(t, z.ShiftLen() == len("Lorem "), "shifted length must equal last shift") - test.That(t, z.Pos() == 0, "after shifting position must be 0") - test.That(t, z.Peek(0) == 'i', "must be 'i' at position 0 after shifting") - test.That(t, z.Peek(1) == 'p', "must be 'p' at position 1 after shifting") - test.T(t, z.Err(), nil, "error must be nil at this point") - - z.Move(len(s) - len("Lorem ") - 1) - test.T(t, z.Err(), nil, "error must be nil just before the end of the buffer") - z.Skip() - test.That(t, z.Pos() == 0, "after skipping position must be 0") - z.Move(1) - test.T(t, z.Err(), io.EOF, "error must be EOF when past the buffer") - z.Move(-1) - test.T(t, z.Err(), nil, "error must be nil just before the end of the buffer, even when it has been past the buffer") - z.Free(0) // has already been tested -} - -func TestStreamLexerShift(t *testing.T) { - s := `Lorem ipsum dolor sit amet, consectetur adipiscing elit.` - z := NewStreamLexerSize(test.NewPlainReader(bytes.NewBufferString(s)), 5) - - z.Move(len("Lorem ")) - test.Bytes(t, z.Shift(), []byte("Lorem "), "shift must return the buffered string") - test.That(t, z.ShiftLen() == len("Lorem "), "shifted length must equal last shift") -} - -func TestStreamLexerSmall(t *testing.T) { - s := `abcdefghijklm` - z := NewStreamLexerSize(test.NewPlainReader(bytes.NewBufferString(s)), 4) - test.That(t, z.Peek(8) == 'i', "first character must be 'i' at position 8") - - z = NewStreamLexerSize(test.NewPlainReader(bytes.NewBufferString(s)), 4) - test.That(t, z.Peek(12) == 'm', "first character must be 'm' at position 12") - - z = NewStreamLexerSize(test.NewPlainReader(bytes.NewBufferString(s)), 0) - test.That(t, z.Peek(4) == 'e', "first character must be 'e' at position 4") - - z = NewStreamLexerSize(test.NewPlainReader(bytes.NewBufferString(s)), 13) - test.That(t, z.Peek(13) == 0, "must yield error at position 13") -} - -func TestStreamLexerSingle(t *testing.T) { - z := NewStreamLexer(test.NewInfiniteReader()) - test.That(t, z.Peek(0) == '.') - test.That(t, z.Peek(1) == '.') - test.That(t, z.Peek(3) == '.', "required two successful reads") -} - -func TestStreamLexerRunes(t *testing.T) { - z := NewStreamLexer(bytes.NewBufferString("aæ†\U00100000")) - r, n := z.PeekRune(0) - test.That(t, n == 1, "first character must be length 1") - test.That(t, r == 'a', "first character must be rune 'a'") - r, n = z.PeekRune(1) - test.That(t, n == 2, "second character must be length 2") - test.That(t, r == 'æ', "second character must be rune 'æ'") - r, n = z.PeekRune(3) - test.That(t, n == 3, "fourth character must be length 3") - test.That(t, r == '†', "fourth character must be rune '†'") - r, n = z.PeekRune(6) - test.That(t, n == 4, "seventh character must be length 4") - test.That(t, r == '\U00100000', "seventh character must be rune '\U00100000'") -} - -func TestStreamLexerBadRune(t *testing.T) { - z := NewStreamLexer(bytes.NewBufferString("\xF0")) // expect four byte rune - r, n := z.PeekRune(0) - test.T(t, n, 4, "length") - test.T(t, r, rune(0), "rune") -} - -func TestStreamLexerZeroLen(t *testing.T) { - z := NewStreamLexer(test.NewPlainReader(bytes.NewBufferString(""))) - test.That(t, z.Peek(0) == 0, "first character must yield error") -} - -func TestStreamLexerEmptyReader(t *testing.T) { - z := NewStreamLexer(test.NewEmptyReader()) - test.That(t, z.Peek(0) == 0, "first character must yield error") - test.T(t, z.Err(), io.EOF, "error must be EOF") - test.That(t, z.Peek(0) == 0, "second peek must also yield error") -} diff --git a/vendor/github.com/tdewolff/parse/buffer/writer.go b/vendor/github.com/tdewolff/parse/buffer/writer.go deleted file mode 100644 index ded2f36..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/writer.go +++ /dev/null @@ -1,41 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -// Writer implements an io.Writer over a byte slice. -type Writer struct { - buf []byte -} - -// NewWriter returns a new Writer for a given byte slice. -func NewWriter(buf []byte) *Writer { - return &Writer{ - buf: buf, - } -} - -// Write writes bytes from the given byte slice and returns the number of bytes written and an error if occurred. When err != nil, n == 0. -func (w *Writer) Write(b []byte) (int, error) { - n := len(b) - end := len(w.buf) - if end+n > cap(w.buf) { - buf := make([]byte, end, 2*cap(w.buf)+n) - copy(buf, w.buf) - w.buf = buf - } - w.buf = w.buf[:end+n] - return copy(w.buf[end:], b), nil -} - -// Len returns the length of the underlying byte slice. -func (w *Writer) Len() int { - return len(w.buf) -} - -// Bytes returns the underlying byte slice. -func (w *Writer) Bytes() []byte { - return w.buf -} - -// Reset empties and reuses the current buffer. Subsequent writes will overwrite the buffer, so any reference to the underlying slice is invalidated after this call. -func (w *Writer) Reset() { - w.buf = w.buf[:0] -} diff --git a/vendor/github.com/tdewolff/parse/buffer/writer_test.go b/vendor/github.com/tdewolff/parse/buffer/writer_test.go deleted file mode 100644 index f56f5f7..0000000 --- a/vendor/github.com/tdewolff/parse/buffer/writer_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package buffer // import "github.com/tdewolff/parse/buffer" - -import ( - "fmt" - "testing" - - "github.com/tdewolff/test" -) - -func TestWriter(t *testing.T) { - w := NewWriter(make([]byte, 0, 3)) - - test.That(t, w.Len() == 0, "buffer must initially have zero length") - - n, _ := w.Write([]byte("abc")) - test.That(t, n == 3, "first write must write 3 characters") - test.Bytes(t, w.Bytes(), []byte("abc"), "first write must match 'abc'") - test.That(t, w.Len() == 3, "buffer must have length 3 after first write") - - n, _ = w.Write([]byte("def")) - test.That(t, n == 3, "second write must write 3 characters") - test.Bytes(t, w.Bytes(), []byte("abcdef"), "second write must match 'abcdef'") - - w.Reset() - test.Bytes(t, w.Bytes(), []byte(""), "reset must match ''") - - n, _ = w.Write([]byte("ghijkl")) - test.That(t, n == 6, "third write must write 6 characters") - test.Bytes(t, w.Bytes(), []byte("ghijkl"), "third write must match 'ghijkl'") -} - -func ExampleNewWriter() { - w := NewWriter(make([]byte, 0, 11)) // initial buffer length is 11 - w.Write([]byte("Lorem ipsum")) - fmt.Println(string(w.Bytes())) - // Output: Lorem ipsum -} - -func ExampleWriter_Reset() { - w := NewWriter(make([]byte, 0, 11)) // initial buffer length is 10 - w.Write([]byte("garbage that will be overwritten")) // does reallocation - w.Reset() - w.Write([]byte("Lorem ipsum")) - fmt.Println(string(w.Bytes())) - // Output: Lorem ipsum -} diff --git a/vendor/github.com/tdewolff/parse/common.go b/vendor/github.com/tdewolff/parse/common.go deleted file mode 100644 index 3b7158e..0000000 --- a/vendor/github.com/tdewolff/parse/common.go +++ /dev/null @@ -1,231 +0,0 @@ -// Package parse contains a collection of parsers for various formats in its subpackages. -package parse // import "github.com/tdewolff/parse" - -import ( - "bytes" - "encoding/base64" - "errors" - "net/url" -) - -// ErrBadDataURI is returned by DataURI when the byte slice does not start with 'data:' or is too short. -var ErrBadDataURI = errors.New("not a data URI") - -// Number returns the number of bytes that parse as a number of the regex format (+|-)?([0-9]+(\.[0-9]+)?|\.[0-9]+)((e|E)(+|-)?[0-9]+)?. -func Number(b []byte) int { - if len(b) == 0 { - return 0 - } - i := 0 - if b[i] == '+' || b[i] == '-' { - i++ - if i >= len(b) { - return 0 - } - } - firstDigit := (b[i] >= '0' && b[i] <= '9') - if firstDigit { - i++ - for i < len(b) && b[i] >= '0' && b[i] <= '9' { - i++ - } - } - if i < len(b) && b[i] == '.' { - i++ - if i < len(b) && b[i] >= '0' && b[i] <= '9' { - i++ - for i < len(b) && b[i] >= '0' && b[i] <= '9' { - i++ - } - } else if firstDigit { - // . could belong to the next token - i-- - return i - } else { - return 0 - } - } else if !firstDigit { - return 0 - } - iOld := i - if i < len(b) && (b[i] == 'e' || b[i] == 'E') { - i++ - if i < len(b) && (b[i] == '+' || b[i] == '-') { - i++ - } - if i >= len(b) || b[i] < '0' || b[i] > '9' { - // e could belong to next token - return iOld - } - for i < len(b) && b[i] >= '0' && b[i] <= '9' { - i++ - } - } - return i -} - -// Dimension parses a byte-slice and returns the length of the number and its unit. -func Dimension(b []byte) (int, int) { - num := Number(b) - if num == 0 || num == len(b) { - return num, 0 - } else if b[num] == '%' { - return num, 1 - } else if b[num] >= 'a' && b[num] <= 'z' || b[num] >= 'A' && b[num] <= 'Z' { - i := num + 1 - for i < len(b) && (b[i] >= 'a' && b[i] <= 'z' || b[i] >= 'A' && b[i] <= 'Z') { - i++ - } - return num, i - num - } - return num, 0 -} - -// Mediatype parses a given mediatype and splits the mimetype from the parameters. -// It works similar to mime.ParseMediaType but is faster. -func Mediatype(b []byte) ([]byte, map[string]string) { - i := 0 - for i < len(b) && b[i] == ' ' { - i++ - } - b = b[i:] - n := len(b) - mimetype := b - var params map[string]string - for i := 3; i < n; i++ { // mimetype is at least three characters long - if b[i] == ';' || b[i] == ' ' { - mimetype = b[:i] - if b[i] == ' ' { - i++ - for i < n && b[i] == ' ' { - i++ - } - if i < n && b[i] != ';' { - break - } - } - params = map[string]string{} - s := string(b) - PARAM: - i++ - for i < n && s[i] == ' ' { - i++ - } - start := i - for i < n && s[i] != '=' && s[i] != ';' && s[i] != ' ' { - i++ - } - key := s[start:i] - for i < n && s[i] == ' ' { - i++ - } - if i < n && s[i] == '=' { - i++ - for i < n && s[i] == ' ' { - i++ - } - start = i - for i < n && s[i] != ';' && s[i] != ' ' { - i++ - } - } else { - start = i - } - params[key] = s[start:i] - for i < n && s[i] == ' ' { - i++ - } - if i < n && s[i] == ';' { - goto PARAM - } - break - } - } - return mimetype, params -} - -// DataURI parses the given data URI and returns the mediatype, data and ok. -func DataURI(dataURI []byte) ([]byte, []byte, error) { - if len(dataURI) > 5 && bytes.Equal(dataURI[:5], []byte("data:")) { - dataURI = dataURI[5:] - inBase64 := false - var mediatype []byte - i := 0 - for j := 0; j < len(dataURI); j++ { - c := dataURI[j] - if c == '=' || c == ';' || c == ',' { - if c != '=' && bytes.Equal(TrimWhitespace(dataURI[i:j]), []byte("base64")) { - if len(mediatype) > 0 { - mediatype = mediatype[:len(mediatype)-1] - } - inBase64 = true - i = j - } else if c != ',' { - mediatype = append(append(mediatype, TrimWhitespace(dataURI[i:j])...), c) - i = j + 1 - } else { - mediatype = append(mediatype, TrimWhitespace(dataURI[i:j])...) - } - if c == ',' { - if len(mediatype) == 0 || mediatype[0] == ';' { - mediatype = []byte("text/plain") - } - data := dataURI[j+1:] - if inBase64 { - decoded := make([]byte, base64.StdEncoding.DecodedLen(len(data))) - n, err := base64.StdEncoding.Decode(decoded, data) - if err != nil { - return nil, nil, err - } - data = decoded[:n] - } else if unescaped, err := url.QueryUnescape(string(data)); err == nil { - data = []byte(unescaped) - } - return mediatype, data, nil - } - } - } - } - return nil, nil, ErrBadDataURI -} - -// QuoteEntity parses the given byte slice and returns the quote that got matched (' or ") and its entity length. -func QuoteEntity(b []byte) (quote byte, n int) { - if len(b) < 5 || b[0] != '&' { - return 0, 0 - } - if b[1] == '#' { - if b[2] == 'x' { - i := 3 - for i < len(b) && b[i] == '0' { - i++ - } - if i+2 < len(b) && b[i] == '2' && b[i+2] == ';' { - if b[i+1] == '2' { - return '"', i + 3 // " - } else if b[i+1] == '7' { - return '\'', i + 3 // ' - } - } - } else { - i := 2 - for i < len(b) && b[i] == '0' { - i++ - } - if i+2 < len(b) && b[i] == '3' && b[i+2] == ';' { - if b[i+1] == '4' { - return '"', i + 3 // " - } else if b[i+1] == '9' { - return '\'', i + 3 // ' - } - } - } - } else if len(b) >= 6 && b[5] == ';' { - if EqualFold(b[1:5], []byte{'q', 'u', 'o', 't'}) { - return '"', 6 // " - } else if EqualFold(b[1:5], []byte{'a', 'p', 'o', 's'}) { - return '\'', 6 // ' - } - } - return 0, 0 -} diff --git a/vendor/github.com/tdewolff/parse/common_test.go b/vendor/github.com/tdewolff/parse/common_test.go deleted file mode 100644 index a3dbcf4..0000000 --- a/vendor/github.com/tdewolff/parse/common_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package parse // import "github.com/tdewolff/parse" - -import ( - "encoding/base64" - "mime" - "testing" - - "github.com/tdewolff/test" -) - -func TestParseNumber(t *testing.T) { - var numberTests = []struct { - number string - expected int - }{ - {"5", 1}, - {"0.51", 4}, - {"0.5e-99", 7}, - {"0.5e-", 3}, - {"+50.0", 5}, - {".0", 2}, - {"0.", 1}, - {"", 0}, - {"+", 0}, - {".", 0}, - {"a", 0}, - } - for _, tt := range numberTests { - t.Run(tt.number, func(t *testing.T) { - n := Number([]byte(tt.number)) - test.T(t, n, tt.expected) - }) - } -} - -func TestParseDimension(t *testing.T) { - var dimensionTests = []struct { - dimension string - expectedNum int - expectedUnit int - }{ - {"5px", 1, 2}, - {"5px ", 1, 2}, - {"5%", 1, 1}, - {"5em", 1, 2}, - {"px", 0, 0}, - {"1", 1, 0}, - {"1~", 1, 0}, - } - for _, tt := range dimensionTests { - t.Run(tt.dimension, func(t *testing.T) { - num, unit := Dimension([]byte(tt.dimension)) - test.T(t, num, tt.expectedNum, "number") - test.T(t, unit, tt.expectedUnit, "unit") - }) - } -} - -func TestMediatype(t *testing.T) { - var mediatypeTests = []struct { - mediatype string - expectedMimetype string - expectedParams map[string]string - }{ - {"text/plain", "text/plain", nil}, - {"text/plain;charset=US-ASCII", "text/plain", map[string]string{"charset": "US-ASCII"}}, - {" text/plain ; charset = US-ASCII ", "text/plain", map[string]string{"charset": "US-ASCII"}}, - {" text/plain a", "text/plain", nil}, - {"text/plain;base64", "text/plain", map[string]string{"base64": ""}}, - {"text/plain;inline=;base64", "text/plain", map[string]string{"inline": "", "base64": ""}}, - } - for _, tt := range mediatypeTests { - t.Run(tt.mediatype, func(t *testing.T) { - mimetype, _ := Mediatype([]byte(tt.mediatype)) - test.String(t, string(mimetype), tt.expectedMimetype, "mimetype") - //test.T(t, params, tt.expectedParams, "parameters") // TODO - }) - } -} - -func TestParseDataURI(t *testing.T) { - var dataURITests = []struct { - dataURI string - expectedMimetype string - expectedData string - expectedErr error - }{ - {"www.domain.com", "", "", ErrBadDataURI}, - {"data:,", "text/plain", "", nil}, - {"data:text/xml,", "text/xml", "", nil}, - {"data:,text", "text/plain", "text", nil}, - {"data:;base64,dGV4dA==", "text/plain", "text", nil}, - {"data:image/svg+xml,", "image/svg+xml", "", nil}, - {"data:;base64,()", "", "", base64.CorruptInputError(0)}, - } - for _, tt := range dataURITests { - t.Run(tt.dataURI, func(t *testing.T) { - mimetype, data, err := DataURI([]byte(tt.dataURI)) - test.T(t, err, tt.expectedErr) - test.String(t, string(mimetype), tt.expectedMimetype, "mimetype") - test.String(t, string(data), tt.expectedData, "data") - }) - } -} - -func TestParseQuoteEntity(t *testing.T) { - var quoteEntityTests = []struct { - quoteEntity string - expectedQuote byte - expectedN int - }{ - {""", '"', 5}, - {"'", '\'', 6}, - {""", '"', 8}, - {"'", '\'', 6}, - {""", '"', 6}, - {"'", '\'', 6}, - {">", 0x00, 0}, - {"&", 0x00, 0}, - } - for _, tt := range quoteEntityTests { - t.Run(tt.quoteEntity, func(t *testing.T) { - quote, n := QuoteEntity([]byte(tt.quoteEntity)) - test.T(t, quote, tt.expectedQuote, "quote") - test.T(t, n, tt.expectedN, "quote length") - }) - } -} - -//////////////////////////////////////////////////////////////// - -func BenchmarkParseMediatypeStd(b *testing.B) { - mediatype := "text/plain" - for i := 0; i < b.N; i++ { - mime.ParseMediaType(mediatype) - } -} - -func BenchmarkParseMediatypeParamStd(b *testing.B) { - mediatype := "text/plain;inline=1" - for i := 0; i < b.N; i++ { - mime.ParseMediaType(mediatype) - } -} - -func BenchmarkParseMediatypeParamsStd(b *testing.B) { - mediatype := "text/plain;charset=US-ASCII;language=US-EN;compression=gzip;base64" - for i := 0; i < b.N; i++ { - mime.ParseMediaType(mediatype) - } -} - -func BenchmarkParseMediatypeParse(b *testing.B) { - mediatype := []byte("text/plain") - for i := 0; i < b.N; i++ { - Mediatype(mediatype) - } -} - -func BenchmarkParseMediatypeParamParse(b *testing.B) { - mediatype := []byte("text/plain;inline=1") - for i := 0; i < b.N; i++ { - Mediatype(mediatype) - } -} - -func BenchmarkParseMediatypeParamsParse(b *testing.B) { - mediatype := []byte("text/plain;charset=US-ASCII;language=US-EN;compression=gzip;base64") - for i := 0; i < b.N; i++ { - Mediatype(mediatype) - } -} diff --git a/vendor/github.com/tdewolff/parse/css/README.md b/vendor/github.com/tdewolff/parse/css/README.md deleted file mode 100644 index 2013248..0000000 --- a/vendor/github.com/tdewolff/parse/css/README.md +++ /dev/null @@ -1,171 +0,0 @@ -# CSS [![GoDoc](http://godoc.org/github.com/tdewolff/parse/css?status.svg)](http://godoc.org/github.com/tdewolff/parse/css) [![GoCover](http://gocover.io/_badge/github.com/tdewolff/parse/css)](http://gocover.io/github.com/tdewolff/parse/css) - -This package is a CSS3 lexer and parser written in [Go][1]. Both follow the specification at [CSS Syntax Module Level 3](http://www.w3.org/TR/css-syntax-3/). The lexer takes an io.Reader and converts it into tokens until the EOF. The parser returns a parse tree of the full io.Reader input stream, but the low-level `Next` function can be used for stream parsing to returns grammar units until the EOF. - -## Installation -Run the following command - - go get github.com/tdewolff/parse/css - -or add the following import and run project with `go get` - - import "github.com/tdewolff/parse/css" - -## Lexer -### Usage -The following initializes a new Lexer with io.Reader `r`: -``` go -l := css.NewLexer(r) -``` - -To tokenize until EOF an error, use: -``` go -for { - tt, text := l.Next() - switch tt { - case css.ErrorToken: - // error or EOF set in l.Err() - return - // ... - } -} -``` - -All tokens (see [CSS Syntax Module Level 3](http://www.w3.org/TR/css3-syntax/)): -``` go -ErrorToken // non-official token, returned when errors occur -IdentToken -FunctionToken // rgb( rgba( ... -AtKeywordToken // @abc -HashToken // #abc -StringToken -BadStringToken -UrlToken // url( -BadUrlToken -DelimToken // any unmatched character -NumberToken // 5 -PercentageToken // 5% -DimensionToken // 5em -UnicodeRangeToken -IncludeMatchToken // ~= -DashMatchToken // |= -PrefixMatchToken // ^= -SuffixMatchToken // $= -SubstringMatchToken // *= -ColumnToken // || -WhitespaceToken -CDOToken // <!-- -CDCToken // --> -ColonToken -SemicolonToken -CommaToken -BracketToken // ( ) [ ] { }, all bracket tokens use this, Data() can distinguish between the brackets -CommentToken // non-official token -``` - -### Examples -``` go -package main - -import ( - "os" - - "github.com/tdewolff/parse/css" -) - -// Tokenize CSS3 from stdin. -func main() { - l := css.NewLexer(os.Stdin) - for { - tt, text := l.Next() - switch tt { - case css.ErrorToken: - if l.Err() != io.EOF { - fmt.Println("Error on line", l.Line(), ":", l.Err()) - } - return - case css.IdentToken: - fmt.Println("Identifier", string(text)) - case css.NumberToken: - fmt.Println("Number", string(text)) - // ... - } - } -} -``` - -## Parser -### Usage -The following creates a new Parser. -``` go -// true because this is the content of an inline style attribute -p := css.NewParser(bytes.NewBufferString("color: red;"), true) -``` - -To iterate over the stylesheet, use: -``` go -for { - gt, _, data := p.Next() - if gt == css.ErrorGrammar { - break - } - // ... -} -``` - -All grammar units returned by `Next`: -``` go -ErrorGrammar -AtRuleGrammar -EndAtRuleGrammar -RulesetGrammar -EndRulesetGrammar -DeclarationGrammar -TokenGrammar -``` - -### Examples -``` go -package main - -import ( - "bytes" - "fmt" - - "github.com/tdewolff/parse/css" -) - -func main() { - // true because this is the content of an inline style attribute - p := css.NewParser(bytes.NewBufferString("color: red;"), true) - out := "" - for { - gt, _, data := p.Next() - if gt == css.ErrorGrammar { - break - } else if gt == css.AtRuleGrammar || gt == css.BeginAtRuleGrammar || gt == css.BeginRulesetGrammar || gt == css.DeclarationGrammar { - out += string(data) - if gt == css.DeclarationGrammar { - out += ":" - } - for _, val := range p.Values() { - out += string(val.Data) - } - if gt == css.BeginAtRuleGrammar || gt == css.BeginRulesetGrammar { - out += "{" - } else if gt == css.AtRuleGrammar || gt == css.DeclarationGrammar { - out += ";" - } - } else { - out += string(data) - } - } - fmt.Println(out) -} - -``` - -## License -Released under the [MIT license](https://github.com/tdewolff/parse/blob/master/LICENSE.md). - -[1]: http://golang.org/ "Go Language" diff --git a/vendor/github.com/tdewolff/parse/css/hash.go b/vendor/github.com/tdewolff/parse/css/hash.go deleted file mode 100644 index 77f383f..0000000 --- a/vendor/github.com/tdewolff/parse/css/hash.go +++ /dev/null @@ -1,689 +0,0 @@ -package css - -// generated by hasher -type=Hash -file=hash.go; DO NOT EDIT, except for adding more constants to the list and rerun go generate - -// uses github.com/tdewolff/hasher -//go:generate hasher -type=Hash -file=hash.go - -// Hash defines perfect hashes for a predefined list of strings -type Hash uint32 - -// Unique hash definitions to be used instead of strings -const ( - Accelerator Hash = 0x4b30b // accelerator - Aliceblue Hash = 0x56109 // aliceblue - Alpha Hash = 0x5eb05 // alpha - Antiquewhite Hash = 0x4900c // antiquewhite - Aquamarine Hash = 0x73a0a // aquamarine - Azimuth Hash = 0x5ef07 // azimuth - Background Hash = 0xa // background - Background_Attachment Hash = 0x9115 // background-attachment - Background_Color Hash = 0x11210 // background-color - Background_Image Hash = 0x9ca10 // background-image - Background_Position Hash = 0x13 // background-position - Background_Position_X Hash = 0x84015 // background-position-x - Background_Position_Y Hash = 0x15 // background-position-y - Background_Repeat Hash = 0x1511 // background-repeat - Behavior Hash = 0x3108 // behavior - Black Hash = 0x5805 // black - Blanchedalmond Hash = 0x5d0e // blanchedalmond - Blueviolet Hash = 0x5660a // blueviolet - Bold Hash = 0x7204 // bold - Border Hash = 0x7d06 // border - Border_Bottom Hash = 0x7d0d // border-bottom - Border_Bottom_Color Hash = 0x7d13 // border-bottom-color - Border_Bottom_Style Hash = 0xb413 // border-bottom-style - Border_Bottom_Width Hash = 0xd713 // border-bottom-width - Border_Collapse Hash = 0xf80f // border-collapse - Border_Color Hash = 0x1480c // border-color - Border_Left Hash = 0x15d0b // border-left - Border_Left_Color Hash = 0x15d11 // border-left-color - Border_Left_Style Hash = 0x18911 // border-left-style - Border_Left_Width Hash = 0x19a11 // border-left-width - Border_Right Hash = 0x1ab0c // border-right - Border_Right_Color Hash = 0x1ab12 // border-right-color - Border_Right_Style Hash = 0x1c912 // border-right-style - Border_Right_Width Hash = 0x1db12 // border-right-width - Border_Spacing Hash = 0x1ed0e // border-spacing - Border_Style Hash = 0x2100c // border-style - Border_Top Hash = 0x21c0a // border-top - Border_Top_Color Hash = 0x21c10 // border-top-color - Border_Top_Style Hash = 0x22c10 // border-top-style - Border_Top_Width Hash = 0x23c10 // border-top-width - Border_Width Hash = 0x24c0c // border-width - Bottom Hash = 0x8406 // bottom - Box_Shadow Hash = 0x2580a // box-shadow - Burlywood Hash = 0x26b09 // burlywood - Cadetblue Hash = 0x28a09 // cadetblue - Calc Hash = 0x28704 // calc - Caption_Side Hash = 0x2930c // caption-side - Charset Hash = 0x47607 // charset - Chartreuse Hash = 0x2a50a // chartreuse - Chocolate Hash = 0x2af09 // chocolate - Clear Hash = 0x2dd05 // clear - Clip Hash = 0x2e204 // clip - Color Hash = 0x8b05 // color - Content Hash = 0x31e07 // content - Cornflowerblue Hash = 0x3530e // cornflowerblue - Cornsilk Hash = 0x36108 // cornsilk - Counter_Increment Hash = 0x36911 // counter-increment - Counter_Reset Hash = 0x3840d // counter-reset - Cue Hash = 0x39103 // cue - Cue_After Hash = 0x39109 // cue-after - Cue_Before Hash = 0x39a0a // cue-before - Cursive Hash = 0x3ab07 // cursive - Cursor Hash = 0x3be06 // cursor - Darkblue Hash = 0x6a08 // darkblue - Darkcyan Hash = 0x7508 // darkcyan - Darkgoldenrod Hash = 0x2730d // darkgoldenrod - Darkgray Hash = 0x27f08 // darkgray - Darkgreen Hash = 0x7ca09 // darkgreen - Darkkhaki Hash = 0x8bd09 // darkkhaki - Darkmagenta Hash = 0x5280b // darkmagenta - Darkolivegreen Hash = 0x7590e // darkolivegreen - Darkorange Hash = 0x7be0a // darkorange - Darkorchid Hash = 0x8b40a // darkorchid - Darksalmon Hash = 0x8f80a // darksalmon - Darkseagreen Hash = 0x95c0c // darkseagreen - Darkslateblue Hash = 0x3c40d // darkslateblue - Darkslategray Hash = 0x3d10d // darkslategray - Darkturquoise Hash = 0x3de0d // darkturquoise - Darkviolet Hash = 0x3eb0a // darkviolet - Deeppink Hash = 0x29d08 // deeppink - Deepskyblue Hash = 0x8cb0b // deepskyblue - Default Hash = 0x5b707 // default - Direction Hash = 0xa2909 // direction - Display Hash = 0x3f507 // display - Document Hash = 0x40308 // document - Dodgerblue Hash = 0x40b0a // dodgerblue - Elevation Hash = 0x4d409 // elevation - Empty_Cells Hash = 0x4f60b // empty-cells - Fantasy Hash = 0x60a07 // fantasy - Filter Hash = 0x5d406 // filter - Firebrick Hash = 0x41509 // firebrick - Flex Hash = 0x41e04 // flex - Float Hash = 0x42205 // float - Floralwhite Hash = 0x4270b // floralwhite - Font Hash = 0xce04 // font - Font_Face Hash = 0xce09 // font-face - Font_Family Hash = 0x4510b // font-family - Font_Size Hash = 0x45c09 // font-size - Font_Size_Adjust Hash = 0x45c10 // font-size-adjust - Font_Stretch Hash = 0x46c0c // font-stretch - Font_Style Hash = 0x47d0a // font-style - Font_Variant Hash = 0x4870c // font-variant - Font_Weight Hash = 0x4a20b // font-weight - Forestgreen Hash = 0x3a00b // forestgreen - Fuchsia Hash = 0x4ad07 // fuchsia - Gainsboro Hash = 0x17909 // gainsboro - Ghostwhite Hash = 0x1fa0a // ghostwhite - Goldenrod Hash = 0x27709 // goldenrod - Greenyellow Hash = 0x7ce0b // greenyellow - Height Hash = 0x6ae06 // height - Honeydew Hash = 0x5f508 // honeydew - Hsl Hash = 0xe903 // hsl - Hsla Hash = 0xe904 // hsla - Ime_Mode Hash = 0x8c508 // ime-mode - Import Hash = 0x51706 // import - Important Hash = 0x51709 // important - Include_Source Hash = 0x82a0e // include-source - Indianred Hash = 0x52009 // indianred - Inherit Hash = 0x55507 // inherit - Initial Hash = 0x55c07 // initial - Keyframes Hash = 0x43509 // keyframes - Lavender Hash = 0xeb08 // lavender - Lavenderblush Hash = 0xeb0d // lavenderblush - Lawngreen Hash = 0x50e09 // lawngreen - Layer_Background_Color Hash = 0x10c16 // layer-background-color - Layer_Background_Image Hash = 0x9c416 // layer-background-image - Layout_Flow Hash = 0x5370b // layout-flow - Layout_Grid Hash = 0x57b0b // layout-grid - Layout_Grid_Char Hash = 0x57b10 // layout-grid-char - Layout_Grid_Char_Spacing Hash = 0x57b18 // layout-grid-char-spacing - Layout_Grid_Line Hash = 0x59310 // layout-grid-line - Layout_Grid_Mode Hash = 0x5a910 // layout-grid-mode - Layout_Grid_Type Hash = 0x5be10 // layout-grid-type - Left Hash = 0x16404 // left - Lemonchiffon Hash = 0xc50c // lemonchiffon - Letter_Spacing Hash = 0x56d0e // letter-spacing - Lightblue Hash = 0x5da09 // lightblue - Lightcoral Hash = 0x5e30a // lightcoral - Lightcyan Hash = 0x61109 // lightcyan - Lightgoldenrodyellow Hash = 0x61a14 // lightgoldenrodyellow - Lightgray Hash = 0x63909 // lightgray - Lightgreen Hash = 0x6420a // lightgreen - Lightpink Hash = 0x64c09 // lightpink - Lightsalmon Hash = 0x6550b // lightsalmon - Lightseagreen Hash = 0x6600d // lightseagreen - Lightskyblue Hash = 0x66d0c // lightskyblue - Lightslateblue Hash = 0x6790e // lightslateblue - Lightsteelblue Hash = 0x6870e // lightsteelblue - Lightyellow Hash = 0x6950b // lightyellow - Limegreen Hash = 0x6a009 // limegreen - Line_Break Hash = 0x59f0a // line-break - Line_Height Hash = 0x6a90b // line-height - Linear_Gradient Hash = 0x6b40f // linear-gradient - List_Style Hash = 0x6c30a // list-style - List_Style_Image Hash = 0x6c310 // list-style-image - List_Style_Position Hash = 0x6d313 // list-style-position - List_Style_Type Hash = 0x6e60f // list-style-type - Magenta Hash = 0x52c07 // magenta - Margin Hash = 0x2f206 // margin - Margin_Bottom Hash = 0x2f20d // margin-bottom - Margin_Left Hash = 0x2fe0b // margin-left - Margin_Right Hash = 0x3310c // margin-right - Margin_Top Hash = 0x8050a // margin-top - Marker_Offset Hash = 0x6f50d // marker-offset - Marks Hash = 0x70205 // marks - Max_Height Hash = 0x7210a // max-height - Max_Width Hash = 0x72b09 // max-width - Media Hash = 0xa4c05 // media - Mediumaquamarine Hash = 0x73410 // mediumaquamarine - Mediumblue Hash = 0x7440a // mediumblue - Mediumorchid Hash = 0x74e0c // mediumorchid - Mediumpurple Hash = 0x7670c // mediumpurple - Mediumseagreen Hash = 0x7730e // mediumseagreen - Mediumslateblue Hash = 0x7810f // mediumslateblue - Mediumspringgreen Hash = 0x79011 // mediumspringgreen - Mediumturquoise Hash = 0x7a10f // mediumturquoise - Mediumvioletred Hash = 0x7b00f // mediumvioletred - Midnightblue Hash = 0x7de0c // midnightblue - Min_Height Hash = 0x7ea0a // min-height - Min_Width Hash = 0x7f409 // min-width - Mintcream Hash = 0x7fd09 // mintcream - Mistyrose Hash = 0x81b09 // mistyrose - Moccasin Hash = 0x82408 // moccasin - Monospace Hash = 0x8ff09 // monospace - Namespace Hash = 0x4cc09 // namespace - Navajowhite Hash = 0x4dc0b // navajowhite - None Hash = 0x4f304 // none - Normal Hash = 0x50906 // normal - Olivedrab Hash = 0x83809 // olivedrab - Orangered Hash = 0x7c209 // orangered - Orphans Hash = 0x4bc07 // orphans - Outline Hash = 0x85507 // outline - Outline_Color Hash = 0x8550d // outline-color - Outline_Style Hash = 0x8620d // outline-style - Outline_Width Hash = 0x86f0d // outline-width - Overflow Hash = 0xaa08 // overflow - Overflow_X Hash = 0xaa0a // overflow-x - Overflow_Y Hash = 0x87c0a // overflow-y - Padding Hash = 0x2e507 // padding - Padding_Bottom Hash = 0x2e50e // padding-bottom - Padding_Left Hash = 0x5490c // padding-left - Padding_Right Hash = 0x80e0d // padding-right - Padding_Top Hash = 0x9110b // padding-top - Page Hash = 0x88604 // page - Page_Break_After Hash = 0x91b10 // page-break-after - Page_Break_Before Hash = 0x88611 // page-break-before - Page_Break_Inside Hash = 0x89711 // page-break-inside - Palegoldenrod Hash = 0x8a80d // palegoldenrod - Palegreen Hash = 0x8d609 // palegreen - Paleturquoise Hash = 0x8df0d // paleturquoise - Palevioletred Hash = 0x8ec0d // palevioletred - Papayawhip Hash = 0x9080a // papayawhip - Pause Hash = 0x92b05 // pause - Pause_After Hash = 0x92b0b // pause-after - Pause_Before Hash = 0x9360c // pause-before - Peachpuff Hash = 0x5cc09 // peachpuff - Pitch Hash = 0x94205 // pitch - Pitch_Range Hash = 0x9420b // pitch-range - Play_During Hash = 0x3f80b // play-during - Position Hash = 0xb08 // position - Powderblue Hash = 0x94d0a // powderblue - Progid Hash = 0x95706 // progid - Quotes Hash = 0x96806 // quotes - Radial_Gradient Hash = 0x380f // radial-gradient - Rgb Hash = 0x8f03 // rgb - Rgba Hash = 0x8f04 // rgba - Richness Hash = 0x12108 // richness - Right Hash = 0x1b205 // right - Rosybrown Hash = 0x18009 // rosybrown - Royalblue Hash = 0x13f09 // royalblue - Ruby_Align Hash = 0x1530a // ruby-align - Ruby_Overhang Hash = 0x16d0d // ruby-overhang - Ruby_Position Hash = 0x1bc0d // ruby-position - Saddlebrown Hash = 0x4c20b // saddlebrown - Sandybrown Hash = 0x5000a // sandybrown - Sans_Serif Hash = 0x6010a // sans-serif - Scrollbar_3d_Light_Color Hash = 0x12818 // scrollbar-3d-light-color - Scrollbar_Arrow_Color Hash = 0x2c815 // scrollbar-arrow-color - Scrollbar_Base_Color Hash = 0x43d14 // scrollbar-base-color - Scrollbar_Dark_Shadow_Color Hash = 0x7061b // scrollbar-dark-shadow-color - Scrollbar_Face_Color Hash = 0x96d14 // scrollbar-face-color - Scrollbar_Highlight_Color Hash = 0xa0619 // scrollbar-highlight-color - Scrollbar_Shadow_Color Hash = 0x98116 // scrollbar-shadow-color - Scrollbar_Track_Color Hash = 0x99715 // scrollbar-track-color - Seagreen Hash = 0x66508 // seagreen - Seashell Hash = 0x10508 // seashell - Serif Hash = 0x60605 // serif - Size Hash = 0x46104 // size - Slateblue Hash = 0x3c809 // slateblue - Slategray Hash = 0x3d509 // slategray - Speak Hash = 0x9ac05 // speak - Speak_Header Hash = 0x9ac0c // speak-header - Speak_Numeral Hash = 0x9b80d // speak-numeral - Speak_Punctuation Hash = 0x9da11 // speak-punctuation - Speech_Rate Hash = 0x9eb0b // speech-rate - Springgreen Hash = 0x7960b // springgreen - Steelblue Hash = 0x68c09 // steelblue - Stress Hash = 0x2c306 // stress - Supports Hash = 0x9ff08 // supports - Table_Layout Hash = 0x5310c // table-layout - Text_Align Hash = 0x2b60a // text-align - Text_Align_Last Hash = 0x2b60f // text-align-last - Text_Autospace Hash = 0x2020e // text-autospace - Text_Decoration Hash = 0x4e50f // text-decoration - Text_Indent Hash = 0x9f40b // text-indent - Text_Justify Hash = 0x250c // text-justify - Text_Kashida_Space Hash = 0x4612 // text-kashida-space - Text_Overflow Hash = 0xa50d // text-overflow - Text_Shadow Hash = 0x3080b // text-shadow - Text_Transform Hash = 0x3240e // text-transform - Text_Underline_Position Hash = 0x33c17 // text-underline-position - Top Hash = 0x22303 // top - Transparent Hash = 0x3790b // transparent - Turquoise Hash = 0x3e209 // turquoise - Unicode_Bidi Hash = 0xa1f0c // unicode-bidi - Vertical_Align Hash = 0x3b00e // vertical-align - Visibility Hash = 0xa320a // visibility - Voice_Family Hash = 0xa3c0c // voice-family - Volume Hash = 0xa4806 // volume - White Hash = 0x1ff05 // white - White_Space Hash = 0x4970b // white-space - Whitesmoke Hash = 0x42d0a // whitesmoke - Widows Hash = 0x5fc06 // widows - Width Hash = 0xe505 // width - Word_Break Hash = 0x2610a // word-break - Word_Spacing Hash = 0x3120c // word-spacing - Word_Wrap Hash = 0x54109 // word-wrap - Writing_Mode Hash = 0x62d0c // writing-mode - Yellow Hash = 0x62806 // yellow - Yellowgreen Hash = 0x7d30b // yellowgreen - Z_Index Hash = 0xa5107 // z-index -) - -// String returns the hash' name. -func (i Hash) String() string { - start := uint32(i >> 8) - n := uint32(i & 0xff) - if start+n > uint32(len(_Hash_text)) { - return "" - } - return _Hash_text[start : start+n] -} - -// ToHash returns the hash whose name is s. It returns zero if there is no -// such hash. It is case sensitive. -func ToHash(s []byte) Hash { - if len(s) == 0 || len(s) > _Hash_maxLen { - return 0 - } - h := uint32(_Hash_hash0) - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - goto NEXT - } - } - return i - } -NEXT: - if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - return 0 - } - } - return i - } - return 0 -} - -const _Hash_hash0 = 0x700e0976 -const _Hash_maxLen = 27 -const _Hash_text = "background-position-ybackground-repeatext-justifybehavioradi" + - "al-gradientext-kashida-spaceblackblanchedalmondarkblueboldar" + - "kcyanborder-bottom-colorgbackground-attachmentext-overflow-x" + - "border-bottom-stylemonchiffont-faceborder-bottom-widthslaven" + - "derblushborder-collapseashellayer-background-colorichnesscro" + - "llbar-3d-light-coloroyalblueborder-coloruby-alignborder-left" + - "-coloruby-overhangainsborosybrownborder-left-styleborder-lef" + - "t-widthborder-right-coloruby-positionborder-right-styleborde" + - "r-right-widthborder-spacinghostwhitext-autospaceborder-style" + - "border-top-colorborder-top-styleborder-top-widthborder-width" + - "box-shadoword-breakburlywoodarkgoldenrodarkgraycalcadetbluec" + - "aption-sideeppinkchartreusechocolatext-align-lastresscrollba" + - "r-arrow-colorclearclipadding-bottomargin-bottomargin-leftext" + - "-shadoword-spacingcontentext-transformargin-rightext-underli" + - "ne-positioncornflowerbluecornsilkcounter-incrementransparent" + - "counter-resetcue-aftercue-beforestgreencursivertical-aligncu" + - "rsordarkslatebluedarkslategraydarkturquoisedarkvioletdisplay" + - "-duringdocumentdodgerbluefirebrickflexfloatfloralwhitesmokey" + - "framescrollbar-base-colorfont-familyfont-size-adjustfont-str" + - "etcharsetfont-stylefont-variantiquewhite-spacefont-weightfuc" + - "hsiacceleratorphansaddlebrownamespacelevationavajowhitext-de" + - "corationonempty-cellsandybrownormalawngreenimportantindianre" + - "darkmagentable-layout-floword-wrapadding-leftinheritinitiali" + - "cebluevioletter-spacinglayout-grid-char-spacinglayout-grid-l" + - "ine-breaklayout-grid-modefaultlayout-grid-typeachpuffilterli" + - "ghtbluelightcoralphazimuthoneydewidowsans-serifantasylightcy" + - "anlightgoldenrodyellowriting-modelightgraylightgreenlightpin" + - "klightsalmonlightseagreenlightskybluelightslatebluelightstee" + - "lbluelightyellowlimegreenline-heightlinear-gradientlist-styl" + - "e-imagelist-style-positionlist-style-typemarker-offsetmarksc" + - "rollbar-dark-shadow-colormax-heightmax-widthmediumaquamarine" + - "mediumbluemediumorchidarkolivegreenmediumpurplemediumseagree" + - "nmediumslatebluemediumspringgreenmediumturquoisemediumviolet" + - "redarkorangeredarkgreenyellowgreenmidnightbluemin-heightmin-" + - "widthmintcreamargin-topadding-rightmistyrosemoccasinclude-so" + - "urceolivedrabackground-position-xoutline-coloroutline-styleo" + - "utline-widthoverflow-ypage-break-beforepage-break-insidepale" + - "goldenrodarkorchidarkkhakime-modeepskybluepalegreenpaleturqu" + - "oisepalevioletredarksalmonospacepapayawhipadding-topage-brea" + - "k-afterpause-afterpause-beforepitch-rangepowderblueprogidark" + - "seagreenquotescrollbar-face-colorscrollbar-shadow-colorscrol" + - "lbar-track-colorspeak-headerspeak-numeralayer-background-ima" + - "gespeak-punctuationspeech-ratext-indentsupportscrollbar-high" + - "light-colorunicode-bidirectionvisibilityvoice-familyvolumedi" + - "az-index" - -var _Hash_table = [1 << 9]Hash{ - 0x0: 0x5000a, // sandybrown - 0x1: 0x22303, // top - 0x4: 0x13f09, // royalblue - 0x6: 0x4e50f, // text-decoration - 0xb: 0x5370b, // layout-flow - 0xc: 0x11210, // background-color - 0xd: 0x8406, // bottom - 0x10: 0x6600d, // lightseagreen - 0x11: 0x8cb0b, // deepskyblue - 0x12: 0x3c809, // slateblue - 0x13: 0x4f60b, // empty-cells - 0x14: 0x2e204, // clip - 0x15: 0x7440a, // mediumblue - 0x16: 0x4cc09, // namespace - 0x18: 0x2f20d, // margin-bottom - 0x1a: 0x1480c, // border-color - 0x1b: 0x5f508, // honeydew - 0x1d: 0x24c0c, // border-width - 0x1e: 0x9ac0c, // speak-header - 0x1f: 0x8ec0d, // palevioletred - 0x20: 0x1ed0e, // border-spacing - 0x22: 0x2e507, // padding - 0x23: 0x3310c, // margin-right - 0x27: 0x7f409, // min-width - 0x29: 0x8f03, // rgb - 0x2a: 0x6950b, // lightyellow - 0x2c: 0x91b10, // page-break-after - 0x2d: 0x31e07, // content - 0x30: 0x250c, // text-justify - 0x32: 0x2b60f, // text-align-last - 0x34: 0x96d14, // scrollbar-face-color - 0x35: 0x43509, // keyframes - 0x36: 0x27f08, // darkgray - 0x37: 0x52c07, // magenta - 0x38: 0x3d509, // slategray - 0x3a: 0x9ca10, // background-image - 0x3c: 0x82a0e, // include-source - 0x3d: 0x68c09, // steelblue - 0x3e: 0x8550d, // outline-color - 0x40: 0xf80f, // border-collapse - 0x41: 0xeb08, // lavender - 0x42: 0x9ff08, // supports - 0x44: 0x6a90b, // line-height - 0x45: 0x9da11, // speak-punctuation - 0x46: 0xa320a, // visibility - 0x47: 0x2dd05, // clear - 0x4b: 0x5660a, // blueviolet - 0x4e: 0x5b707, // default - 0x50: 0x6f50d, // marker-offset - 0x52: 0x36911, // counter-increment - 0x53: 0x6790e, // lightslateblue - 0x54: 0x10508, // seashell - 0x56: 0x1bc0d, // ruby-position - 0x57: 0x8620d, // outline-style - 0x58: 0x66508, // seagreen - 0x59: 0x8b05, // color - 0x5c: 0x2930c, // caption-side - 0x5d: 0x6ae06, // height - 0x5e: 0x7810f, // mediumslateblue - 0x5f: 0x9360c, // pause-before - 0x60: 0xc50c, // lemonchiffon - 0x63: 0x3ab07, // cursive - 0x66: 0x4dc0b, // navajowhite - 0x67: 0xa3c0c, // voice-family - 0x68: 0x2730d, // darkgoldenrod - 0x69: 0x41509, // firebrick - 0x6a: 0x47d0a, // font-style - 0x6b: 0xa2909, // direction - 0x6d: 0x7be0a, // darkorange - 0x6f: 0x4870c, // font-variant - 0x70: 0x2f206, // margin - 0x71: 0x88611, // page-break-before - 0x73: 0xa50d, // text-overflow - 0x74: 0x4612, // text-kashida-space - 0x75: 0x36108, // cornsilk - 0x76: 0x4a20b, // font-weight - 0x77: 0x46104, // size - 0x78: 0x57b0b, // layout-grid - 0x79: 0x9110b, // padding-top - 0x7a: 0x47607, // charset - 0x7d: 0x81b09, // mistyrose - 0x7e: 0x5ef07, // azimuth - 0x7f: 0x92b0b, // pause-after - 0x83: 0x28704, // calc - 0x84: 0x3be06, // cursor - 0x85: 0xe903, // hsl - 0x86: 0x56d0e, // letter-spacing - 0x88: 0x7ca09, // darkgreen - 0x8b: 0x40308, // document - 0x8d: 0x39109, // cue-after - 0x8f: 0x39a0a, // cue-before - 0x91: 0x60a07, // fantasy - 0x94: 0x16d0d, // ruby-overhang - 0x95: 0x2e50e, // padding-bottom - 0x9a: 0x5da09, // lightblue - 0x9c: 0x8f80a, // darksalmon - 0x9d: 0x45c10, // font-size-adjust - 0x9e: 0x64c09, // lightpink - 0xa0: 0x95c0c, // darkseagreen - 0xa2: 0x89711, // page-break-inside - 0xa4: 0x27709, // goldenrod - 0xa5: 0x63909, // lightgray - 0xa6: 0xa4c05, // media - 0xa7: 0x57b18, // layout-grid-char-spacing - 0xa9: 0x51709, // important - 0xaa: 0x7ea0a, // min-height - 0xb0: 0x15d11, // border-left-color - 0xb1: 0x88604, // page - 0xb2: 0x9c416, // layer-background-image - 0xb5: 0x59310, // layout-grid-line - 0xb6: 0x1511, // background-repeat - 0xb7: 0x7d13, // border-bottom-color - 0xb9: 0x2580a, // box-shadow - 0xbb: 0x5490c, // padding-left - 0xbc: 0x1b205, // right - 0xc0: 0x43d14, // scrollbar-base-color - 0xc1: 0x41e04, // flex - 0xc2: 0xe505, // width - 0xc5: 0x3e209, // turquoise - 0xc8: 0x42205, // float - 0xca: 0x1530a, // ruby-align - 0xcb: 0xb08, // position - 0xcc: 0x8050a, // margin-top - 0xce: 0x2fe0b, // margin-left - 0xcf: 0x3080b, // text-shadow - 0xd0: 0x2610a, // word-break - 0xd4: 0x42d0a, // whitesmoke - 0xd6: 0x33c17, // text-underline-position - 0xd7: 0x1db12, // border-right-width - 0xd8: 0x83809, // olivedrab - 0xd9: 0x8d609, // palegreen - 0xdb: 0x51706, // import - 0xdc: 0x70205, // marks - 0xdd: 0x3eb0a, // darkviolet - 0xde: 0x13, // background-position - 0xe0: 0x73410, // mediumaquamarine - 0xe1: 0x7204, // bold - 0xe2: 0x7a10f, // mediumturquoise - 0xe4: 0x8a80d, // palegoldenrod - 0xe5: 0x5280b, // darkmagenta - 0xe6: 0x18009, // rosybrown - 0xe7: 0x19a11, // border-left-width - 0xe8: 0x8bd09, // darkkhaki - 0xea: 0x5d0e, // blanchedalmond - 0xeb: 0x55c07, // initial - 0xec: 0x7061b, // scrollbar-dark-shadow-color - 0xee: 0x4c20b, // saddlebrown - 0xef: 0x8df0d, // paleturquoise - 0xf1: 0x1ab12, // border-right-color - 0xf3: 0x1ff05, // white - 0xf7: 0xa0619, // scrollbar-highlight-color - 0xf9: 0x5a910, // layout-grid-mode - 0xfc: 0x2100c, // border-style - 0xfe: 0x6d313, // list-style-position - 0x100: 0x10c16, // layer-background-color - 0x102: 0x5be10, // layout-grid-type - 0x103: 0x15d0b, // border-left - 0x104: 0xaa08, // overflow - 0x105: 0x7de0c, // midnightblue - 0x10b: 0x2b60a, // text-align - 0x10e: 0x22c10, // border-top-style - 0x110: 0x61a14, // lightgoldenrodyellow - 0x114: 0x7d06, // border - 0x119: 0xce04, // font - 0x11c: 0x73a0a, // aquamarine - 0x11d: 0x6420a, // lightgreen - 0x11e: 0x62806, // yellow - 0x120: 0x9ac05, // speak - 0x121: 0x4970b, // white-space - 0x123: 0x3c40d, // darkslateblue - 0x125: 0x2020e, // text-autospace - 0x128: 0xeb0d, // lavenderblush - 0x12c: 0x6550b, // lightsalmon - 0x12d: 0x55507, // inherit - 0x131: 0x8b40a, // darkorchid - 0x132: 0x21c0a, // border-top - 0x133: 0x3f80b, // play-during - 0x137: 0x23c10, // border-top-width - 0x139: 0x4bc07, // orphans - 0x13a: 0x4510b, // font-family - 0x13d: 0x40b0a, // dodgerblue - 0x13f: 0x9080a, // papayawhip - 0x140: 0x92b05, // pause - 0x142: 0x6b40f, // linear-gradient - 0x143: 0x3530e, // cornflowerblue - 0x144: 0x3f507, // display - 0x146: 0x56109, // aliceblue - 0x14a: 0x6a08, // darkblue - 0x14b: 0x3108, // behavior - 0x14c: 0x3840d, // counter-reset - 0x14d: 0x7ce0b, // greenyellow - 0x14e: 0x79011, // mediumspringgreen - 0x14f: 0x94d0a, // powderblue - 0x150: 0x57b10, // layout-grid-char - 0x158: 0x85507, // outline - 0x159: 0x26b09, // burlywood - 0x15b: 0xd713, // border-bottom-width - 0x15c: 0x4f304, // none - 0x15e: 0x39103, // cue - 0x15f: 0x5310c, // table-layout - 0x160: 0x9420b, // pitch-range - 0x161: 0xa5107, // z-index - 0x162: 0x2c306, // stress - 0x163: 0x84015, // background-position-x - 0x165: 0x50906, // normal - 0x167: 0x7670c, // mediumpurple - 0x169: 0x5e30a, // lightcoral - 0x16c: 0x7210a, // max-height - 0x16d: 0x8f04, // rgba - 0x16e: 0x6c310, // list-style-image - 0x170: 0x29d08, // deeppink - 0x173: 0x95706, // progid - 0x175: 0x7960b, // springgreen - 0x176: 0x3a00b, // forestgreen - 0x178: 0x3790b, // transparent - 0x179: 0x82408, // moccasin - 0x17a: 0x7b00f, // mediumvioletred - 0x17e: 0x9f40b, // text-indent - 0x181: 0x6e60f, // list-style-type - 0x182: 0x17909, // gainsboro - 0x183: 0x3de0d, // darkturquoise - 0x184: 0x3d10d, // darkslategray - 0x189: 0xaa0a, // overflow-x - 0x18b: 0x96806, // quotes - 0x18c: 0x9115, // background-attachment - 0x18f: 0x1ab0c, // border-right - 0x191: 0x5805, // black - 0x192: 0x7d30b, // yellowgreen - 0x194: 0x5cc09, // peachpuff - 0x197: 0x4270b, // floralwhite - 0x19c: 0x7590e, // darkolivegreen - 0x19d: 0x54109, // word-wrap - 0x19e: 0x18911, // border-left-style - 0x1a0: 0x9eb0b, // speech-rate - 0x1a1: 0x86f0d, // outline-width - 0x1a2: 0xa1f0c, // unicode-bidi - 0x1a3: 0x6c30a, // list-style - 0x1a4: 0x94205, // pitch - 0x1a5: 0x99715, // scrollbar-track-color - 0x1a6: 0x4ad07, // fuchsia - 0x1a8: 0x3b00e, // vertical-align - 0x1ad: 0x5eb05, // alpha - 0x1ae: 0x72b09, // max-width - 0x1af: 0x12108, // richness - 0x1b0: 0x380f, // radial-gradient - 0x1b1: 0x80e0d, // padding-right - 0x1b2: 0x2c815, // scrollbar-arrow-color - 0x1b3: 0x16404, // left - 0x1b5: 0x4d409, // elevation - 0x1b6: 0x59f0a, // line-break - 0x1ba: 0x2af09, // chocolate - 0x1bb: 0x9b80d, // speak-numeral - 0x1bd: 0x4b30b, // accelerator - 0x1be: 0x6a009, // limegreen - 0x1c1: 0x7508, // darkcyan - 0x1c3: 0x66d0c, // lightskyblue - 0x1c5: 0x6010a, // sans-serif - 0x1c6: 0x7d0d, // border-bottom - 0x1c7: 0xa, // background - 0x1c8: 0xa4806, // volume - 0x1ca: 0x62d0c, // writing-mode - 0x1cb: 0x12818, // scrollbar-3d-light-color - 0x1cc: 0x5fc06, // widows - 0x1cf: 0x45c09, // font-size - 0x1d0: 0x15, // background-position-y - 0x1d1: 0x61109, // lightcyan - 0x1d4: 0x52009, // indianred - 0x1d7: 0x1fa0a, // ghostwhite - 0x1db: 0x7c209, // orangered - 0x1dc: 0x4900c, // antiquewhite - 0x1dd: 0x50e09, // lawngreen - 0x1df: 0x7730e, // mediumseagreen - 0x1e0: 0x21c10, // border-top-color - 0x1e2: 0xe904, // hsla - 0x1e4: 0x3240e, // text-transform - 0x1e6: 0x74e0c, // mediumorchid - 0x1e9: 0x8ff09, // monospace - 0x1ec: 0x98116, // scrollbar-shadow-color - 0x1ed: 0x6870e, // lightsteelblue - 0x1ef: 0x28a09, // cadetblue - 0x1f0: 0x5d406, // filter - 0x1f1: 0x1c912, // border-right-style - 0x1f6: 0x87c0a, // overflow-y - 0x1f7: 0xce09, // font-face - 0x1f8: 0x3120c, // word-spacing - 0x1fa: 0xb413, // border-bottom-style - 0x1fb: 0x46c0c, // font-stretch - 0x1fc: 0x7fd09, // mintcream - 0x1fd: 0x8c508, // ime-mode - 0x1fe: 0x2a50a, // chartreuse - 0x1ff: 0x60605, // serif -} diff --git a/vendor/github.com/tdewolff/parse/css/hash_test.go b/vendor/github.com/tdewolff/parse/css/hash_test.go deleted file mode 100644 index e176cc1..0000000 --- a/vendor/github.com/tdewolff/parse/css/hash_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package css // import "github.com/tdewolff/parse/css" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestHashTable(t *testing.T) { - test.T(t, ToHash([]byte("font")), Font, "'font' must resolve to hash.Font") - test.T(t, Font.String(), "font") - test.T(t, Margin_Left.String(), "margin-left") - test.T(t, ToHash([]byte("")), Hash(0), "empty string must resolve to zero") - test.T(t, Hash(0xffffff).String(), "") - test.T(t, ToHash([]byte("fonts")), Hash(0), "'fonts' must resolve to zero") -} diff --git a/vendor/github.com/tdewolff/parse/css/lex.go b/vendor/github.com/tdewolff/parse/css/lex.go deleted file mode 100644 index 3924bb7..0000000 --- a/vendor/github.com/tdewolff/parse/css/lex.go +++ /dev/null @@ -1,710 +0,0 @@ -// Package css is a CSS3 lexer and parser following the specifications at http://www.w3.org/TR/css-syntax-3/. -package css // import "github.com/tdewolff/parse/css" - -// TODO: \uFFFD replacement character for NULL bytes in strings for example, or atleast don't end the string early - -import ( - "bytes" - "io" - "strconv" - - "github.com/tdewolff/parse" - "github.com/tdewolff/parse/buffer" -) - -// TokenType determines the type of token, eg. a number or a semicolon. -type TokenType uint32 - -// TokenType values. -const ( - ErrorToken TokenType = iota // extra token when errors occur - IdentToken - FunctionToken // rgb( rgba( ... - AtKeywordToken // @abc - HashToken // #abc - StringToken - BadStringToken - URLToken - BadURLToken - DelimToken // any unmatched character - NumberToken // 5 - PercentageToken // 5% - DimensionToken // 5em - UnicodeRangeToken // U+554A - IncludeMatchToken // ~= - DashMatchToken // |= - PrefixMatchToken // ^= - SuffixMatchToken // $= - SubstringMatchToken // *= - ColumnToken // || - WhitespaceToken // space \t \r \n \f - CDOToken // <!-- - CDCToken // --> - ColonToken // : - SemicolonToken // ; - CommaToken // , - LeftBracketToken // [ - RightBracketToken // ] - LeftParenthesisToken // ( - RightParenthesisToken // ) - LeftBraceToken // { - RightBraceToken // } - CommentToken // extra token for comments - EmptyToken - CustomPropertyNameToken - CustomPropertyValueToken -) - -// String returns the string representation of a TokenType. -func (tt TokenType) String() string { - switch tt { - case ErrorToken: - return "Error" - case IdentToken: - return "Ident" - case FunctionToken: - return "Function" - case AtKeywordToken: - return "AtKeyword" - case HashToken: - return "Hash" - case StringToken: - return "String" - case BadStringToken: - return "BadString" - case URLToken: - return "URL" - case BadURLToken: - return "BadURL" - case DelimToken: - return "Delim" - case NumberToken: - return "Number" - case PercentageToken: - return "Percentage" - case DimensionToken: - return "Dimension" - case UnicodeRangeToken: - return "UnicodeRange" - case IncludeMatchToken: - return "IncludeMatch" - case DashMatchToken: - return "DashMatch" - case PrefixMatchToken: - return "PrefixMatch" - case SuffixMatchToken: - return "SuffixMatch" - case SubstringMatchToken: - return "SubstringMatch" - case ColumnToken: - return "Column" - case WhitespaceToken: - return "Whitespace" - case CDOToken: - return "CDO" - case CDCToken: - return "CDC" - case ColonToken: - return "Colon" - case SemicolonToken: - return "Semicolon" - case CommaToken: - return "Comma" - case LeftBracketToken: - return "LeftBracket" - case RightBracketToken: - return "RightBracket" - case LeftParenthesisToken: - return "LeftParenthesis" - case RightParenthesisToken: - return "RightParenthesis" - case LeftBraceToken: - return "LeftBrace" - case RightBraceToken: - return "RightBrace" - case CommentToken: - return "Comment" - case EmptyToken: - return "Empty" - case CustomPropertyNameToken: - return "CustomPropertyName" - case CustomPropertyValueToken: - return "CustomPropertyValue" - } - return "Invalid(" + strconv.Itoa(int(tt)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// Lexer is the state for the lexer. -type Lexer struct { - r *buffer.Lexer -} - -// NewLexer returns a new Lexer for a given io.Reader. -func NewLexer(r io.Reader) *Lexer { - return &Lexer{ - buffer.NewLexer(r), - } -} - -// Err returns the error encountered during lexing, this is often io.EOF but also other errors can be returned. -func (l *Lexer) Err() error { - return l.r.Err() -} - -// Restore restores the NULL byte at the end of the buffer. -func (l *Lexer) Restore() { - l.r.Restore() -} - -// Next returns the next Token. It returns ErrorToken when an error was encountered. Using Err() one can retrieve the error message. -func (l *Lexer) Next() (TokenType, []byte) { - switch l.r.Peek(0) { - case ' ', '\t', '\n', '\r', '\f': - l.r.Move(1) - for l.consumeWhitespace() { - } - return WhitespaceToken, l.r.Shift() - case ':': - l.r.Move(1) - return ColonToken, l.r.Shift() - case ';': - l.r.Move(1) - return SemicolonToken, l.r.Shift() - case ',': - l.r.Move(1) - return CommaToken, l.r.Shift() - case '(', ')', '[', ']', '{', '}': - if t := l.consumeBracket(); t != ErrorToken { - return t, l.r.Shift() - } - case '#': - if l.consumeHashToken() { - return HashToken, l.r.Shift() - } - case '"', '\'': - if t := l.consumeString(); t != ErrorToken { - return t, l.r.Shift() - } - case '.', '+': - if t := l.consumeNumeric(); t != ErrorToken { - return t, l.r.Shift() - } - case '-': - if t := l.consumeNumeric(); t != ErrorToken { - return t, l.r.Shift() - } else if t := l.consumeIdentlike(); t != ErrorToken { - return t, l.r.Shift() - } else if l.consumeCDCToken() { - return CDCToken, l.r.Shift() - } else if l.consumeCustomVariableToken() { - return CustomPropertyNameToken, l.r.Shift() - } - case '@': - if l.consumeAtKeywordToken() { - return AtKeywordToken, l.r.Shift() - } - case '$', '*', '^', '~': - if t := l.consumeMatch(); t != ErrorToken { - return t, l.r.Shift() - } - case '/': - if l.consumeComment() { - return CommentToken, l.r.Shift() - } - case '<': - if l.consumeCDOToken() { - return CDOToken, l.r.Shift() - } - case '\\': - if t := l.consumeIdentlike(); t != ErrorToken { - return t, l.r.Shift() - } - case 'u', 'U': - if l.consumeUnicodeRangeToken() { - return UnicodeRangeToken, l.r.Shift() - } else if t := l.consumeIdentlike(); t != ErrorToken { - return t, l.r.Shift() - } - case '|': - if t := l.consumeMatch(); t != ErrorToken { - return t, l.r.Shift() - } else if l.consumeColumnToken() { - return ColumnToken, l.r.Shift() - } - case 0: - if l.Err() != nil { - return ErrorToken, nil - } - default: - if t := l.consumeNumeric(); t != ErrorToken { - return t, l.r.Shift() - } else if t := l.consumeIdentlike(); t != ErrorToken { - return t, l.r.Shift() - } - } - // can't be rune because consumeIdentlike consumes that as an identifier - l.r.Move(1) - return DelimToken, l.r.Shift() -} - -//////////////////////////////////////////////////////////////// - -/* -The following functions follow the railroad diagrams in http://www.w3.org/TR/css3-syntax/ -*/ - -func (l *Lexer) consumeByte(c byte) bool { - if l.r.Peek(0) == c { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeComment() bool { - if l.r.Peek(0) != '/' || l.r.Peek(1) != '*' { - return false - } - l.r.Move(2) - for { - c := l.r.Peek(0) - if c == 0 && l.Err() != nil { - break - } else if c == '*' && l.r.Peek(1) == '/' { - l.r.Move(2) - return true - } - l.r.Move(1) - } - return true -} - -func (l *Lexer) consumeNewline() bool { - c := l.r.Peek(0) - if c == '\n' || c == '\f' { - l.r.Move(1) - return true - } else if c == '\r' { - if l.r.Peek(1) == '\n' { - l.r.Move(2) - } else { - l.r.Move(1) - } - return true - } - return false -} - -func (l *Lexer) consumeWhitespace() bool { - c := l.r.Peek(0) - if c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeDigit() bool { - c := l.r.Peek(0) - if c >= '0' && c <= '9' { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeHexDigit() bool { - c := l.r.Peek(0) - if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeEscape() bool { - if l.r.Peek(0) != '\\' { - return false - } - mark := l.r.Pos() - l.r.Move(1) - if l.consumeNewline() { - l.r.Rewind(mark) - return false - } else if l.consumeHexDigit() { - for k := 1; k < 6; k++ { - if !l.consumeHexDigit() { - break - } - } - l.consumeWhitespace() - return true - } else { - c := l.r.Peek(0) - if c >= 0xC0 { - _, n := l.r.PeekRune(0) - l.r.Move(n) - return true - } else if c == 0 && l.r.Err() != nil { - return true - } - } - l.r.Move(1) - return true -} - -func (l *Lexer) consumeIdentToken() bool { - mark := l.r.Pos() - if l.r.Peek(0) == '-' { - l.r.Move(1) - } - c := l.r.Peek(0) - if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || c >= 0x80) { - if c != '\\' || !l.consumeEscape() { - l.r.Rewind(mark) - return false - } - } else { - l.r.Move(1) - } - for { - c := l.r.Peek(0) - if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c >= 0x80) { - if c != '\\' || !l.consumeEscape() { - break - } - } else { - l.r.Move(1) - } - } - return true -} - -// support custom variables, https://www.w3.org/TR/css-variables-1/ -func (l *Lexer) consumeCustomVariableToken() bool { - // expect to be on a '-' - l.r.Move(1) - if l.r.Peek(0) != '-' { - l.r.Move(-1) - return false - } - if !l.consumeIdentToken() { - l.r.Move(-1) - return false - } - return true -} - -func (l *Lexer) consumeAtKeywordToken() bool { - // expect to be on an '@' - l.r.Move(1) - if !l.consumeIdentToken() { - l.r.Move(-1) - return false - } - return true -} - -func (l *Lexer) consumeHashToken() bool { - // expect to be on a '#' - mark := l.r.Pos() - l.r.Move(1) - c := l.r.Peek(0) - if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c >= 0x80) { - if c != '\\' || !l.consumeEscape() { - l.r.Rewind(mark) - return false - } - } else { - l.r.Move(1) - } - for { - c := l.r.Peek(0) - if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_' || c == '-' || c >= 0x80) { - if c != '\\' || !l.consumeEscape() { - break - } - } else { - l.r.Move(1) - } - } - return true -} - -func (l *Lexer) consumeNumberToken() bool { - mark := l.r.Pos() - c := l.r.Peek(0) - if c == '+' || c == '-' { - l.r.Move(1) - } - firstDigit := l.consumeDigit() - if firstDigit { - for l.consumeDigit() { - } - } - if l.r.Peek(0) == '.' { - l.r.Move(1) - if l.consumeDigit() { - for l.consumeDigit() { - } - } else if firstDigit { - // . could belong to the next token - l.r.Move(-1) - return true - } else { - l.r.Rewind(mark) - return false - } - } else if !firstDigit { - l.r.Rewind(mark) - return false - } - mark = l.r.Pos() - c = l.r.Peek(0) - if c == 'e' || c == 'E' { - l.r.Move(1) - c = l.r.Peek(0) - if c == '+' || c == '-' { - l.r.Move(1) - } - if !l.consumeDigit() { - // e could belong to next token - l.r.Rewind(mark) - return true - } - for l.consumeDigit() { - } - } - return true -} - -func (l *Lexer) consumeUnicodeRangeToken() bool { - c := l.r.Peek(0) - if (c != 'u' && c != 'U') || l.r.Peek(1) != '+' { - return false - } - mark := l.r.Pos() - l.r.Move(2) - if l.consumeHexDigit() { - // consume up to 6 hexDigits - k := 1 - for ; k < 6; k++ { - if !l.consumeHexDigit() { - break - } - } - - // either a minus or a question mark or the end is expected - if l.consumeByte('-') { - // consume another up to 6 hexDigits - if l.consumeHexDigit() { - for k := 1; k < 6; k++ { - if !l.consumeHexDigit() { - break - } - } - } else { - l.r.Rewind(mark) - return false - } - } else { - // could be filled up to 6 characters with question marks or else regular hexDigits - if l.consumeByte('?') { - k++ - for ; k < 6; k++ { - if !l.consumeByte('?') { - l.r.Rewind(mark) - return false - } - } - } - } - } else { - // consume 6 question marks - for k := 0; k < 6; k++ { - if !l.consumeByte('?') { - l.r.Rewind(mark) - return false - } - } - } - return true -} - -func (l *Lexer) consumeColumnToken() bool { - if l.r.Peek(0) == '|' && l.r.Peek(1) == '|' { - l.r.Move(2) - return true - } - return false -} - -func (l *Lexer) consumeCDOToken() bool { - if l.r.Peek(0) == '<' && l.r.Peek(1) == '!' && l.r.Peek(2) == '-' && l.r.Peek(3) == '-' { - l.r.Move(4) - return true - } - return false -} - -func (l *Lexer) consumeCDCToken() bool { - if l.r.Peek(0) == '-' && l.r.Peek(1) == '-' && l.r.Peek(2) == '>' { - l.r.Move(3) - return true - } - return false -} - -//////////////////////////////////////////////////////////////// - -// consumeMatch consumes any MatchToken. -func (l *Lexer) consumeMatch() TokenType { - if l.r.Peek(1) == '=' { - switch l.r.Peek(0) { - case '~': - l.r.Move(2) - return IncludeMatchToken - case '|': - l.r.Move(2) - return DashMatchToken - case '^': - l.r.Move(2) - return PrefixMatchToken - case '$': - l.r.Move(2) - return SuffixMatchToken - case '*': - l.r.Move(2) - return SubstringMatchToken - } - } - return ErrorToken -} - -// consumeBracket consumes any bracket token. -func (l *Lexer) consumeBracket() TokenType { - switch l.r.Peek(0) { - case '(': - l.r.Move(1) - return LeftParenthesisToken - case ')': - l.r.Move(1) - return RightParenthesisToken - case '[': - l.r.Move(1) - return LeftBracketToken - case ']': - l.r.Move(1) - return RightBracketToken - case '{': - l.r.Move(1) - return LeftBraceToken - case '}': - l.r.Move(1) - return RightBraceToken - } - return ErrorToken -} - -// consumeNumeric consumes NumberToken, PercentageToken or DimensionToken. -func (l *Lexer) consumeNumeric() TokenType { - if l.consumeNumberToken() { - if l.consumeByte('%') { - return PercentageToken - } else if l.consumeIdentToken() { - return DimensionToken - } - return NumberToken - } - return ErrorToken -} - -// consumeString consumes a string and may return BadStringToken when a newline is encountered. -func (l *Lexer) consumeString() TokenType { - // assume to be on " or ' - delim := l.r.Peek(0) - l.r.Move(1) - for { - c := l.r.Peek(0) - if c == 0 && l.Err() != nil { - break - } else if c == '\n' || c == '\r' || c == '\f' { - l.r.Move(1) - return BadStringToken - } else if c == delim { - l.r.Move(1) - break - } else if c == '\\' { - if !l.consumeEscape() { - l.r.Move(1) - l.consumeNewline() - } - } else { - l.r.Move(1) - } - } - return StringToken -} - -func (l *Lexer) consumeUnquotedURL() bool { - for { - c := l.r.Peek(0) - if c == 0 && l.Err() != nil || c == ')' { - break - } else if c == '"' || c == '\'' || c == '(' || c == '\\' || c == ' ' || c <= 0x1F || c == 0x7F { - if c != '\\' || !l.consumeEscape() { - return false - } - } else { - l.r.Move(1) - } - } - return true -} - -// consumeRemnantsBadUrl consumes bytes of a BadUrlToken so that normal tokenization may continue. -func (l *Lexer) consumeRemnantsBadURL() { - for { - if l.consumeByte(')') || l.Err() != nil { - break - } else if !l.consumeEscape() { - l.r.Move(1) - } - } -} - -// consumeIdentlike consumes IdentToken, FunctionToken or UrlToken. -func (l *Lexer) consumeIdentlike() TokenType { - if l.consumeIdentToken() { - if l.r.Peek(0) != '(' { - return IdentToken - } else if !parse.EqualFold(bytes.Replace(l.r.Lexeme(), []byte{'\\'}, nil, -1), []byte{'u', 'r', 'l'}) { - l.r.Move(1) - return FunctionToken - } - l.r.Move(1) - - // consume url - for l.consumeWhitespace() { - } - if c := l.r.Peek(0); c == '"' || c == '\'' { - if l.consumeString() == BadStringToken { - l.consumeRemnantsBadURL() - return BadURLToken - } - } else if !l.consumeUnquotedURL() && !l.consumeWhitespace() { - l.consumeRemnantsBadURL() - return BadURLToken - } - for l.consumeWhitespace() { - } - if !l.consumeByte(')') && l.Err() != io.EOF { - l.consumeRemnantsBadURL() - return BadURLToken - } - return URLToken - } - return ErrorToken -} diff --git a/vendor/github.com/tdewolff/parse/css/lex_test.go b/vendor/github.com/tdewolff/parse/css/lex_test.go deleted file mode 100644 index 0bdc891..0000000 --- a/vendor/github.com/tdewolff/parse/css/lex_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package css // import "github.com/tdewolff/parse/css" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/test" -) - -type TTs []TokenType - -func TestTokens(t *testing.T) { - var tokenTests = []struct { - css string - expected []TokenType - }{ - {" ", TTs{}}, - {"5.2 .4", TTs{NumberToken, NumberToken}}, - {"color: red;", TTs{IdentToken, ColonToken, IdentToken, SemicolonToken}}, - {"background: url(\"http://x\");", TTs{IdentToken, ColonToken, URLToken, SemicolonToken}}, - {"background: URL(x.png);", TTs{IdentToken, ColonToken, URLToken, SemicolonToken}}, - {"color: rgb(4, 0%, 5em);", TTs{IdentToken, ColonToken, FunctionToken, NumberToken, CommaToken, PercentageToken, CommaToken, DimensionToken, RightParenthesisToken, SemicolonToken}}, - {"body { \"string\" }", TTs{IdentToken, LeftBraceToken, StringToken, RightBraceToken}}, - {"body { \"str\\\"ing\" }", TTs{IdentToken, LeftBraceToken, StringToken, RightBraceToken}}, - {".class { }", TTs{DelimToken, IdentToken, LeftBraceToken, RightBraceToken}}, - {"#class { }", TTs{HashToken, LeftBraceToken, RightBraceToken}}, - {"#class\\#withhash { }", TTs{HashToken, LeftBraceToken, RightBraceToken}}, - {"@media print { }", TTs{AtKeywordToken, IdentToken, LeftBraceToken, RightBraceToken}}, - {"/*comment*/", TTs{CommentToken}}, - {"/*com* /ment*/", TTs{CommentToken}}, - {"~= |= ^= $= *=", TTs{IncludeMatchToken, DashMatchToken, PrefixMatchToken, SuffixMatchToken, SubstringMatchToken}}, - {"||", TTs{ColumnToken}}, - {"<!-- -->", TTs{CDOToken, CDCToken}}, - {"U+1234", TTs{UnicodeRangeToken}}, - {"5.2 .4 4e-22", TTs{NumberToken, NumberToken, NumberToken}}, - {"--custom-variable", TTs{CustomPropertyNameToken}}, - - // unexpected ending - {"ident", TTs{IdentToken}}, - {"123.", TTs{NumberToken, DelimToken}}, - {"\"string", TTs{StringToken}}, - {"123/*comment", TTs{NumberToken, CommentToken}}, - {"U+1-", TTs{IdentToken, NumberToken, DelimToken}}, - - // unicode - {"fooδbar", TTs{IdentToken}}, - {"foo\\æ\\†", TTs{IdentToken}}, - // {"foo\x00bar", TTs{IdentToken}}, - {"'foo\u554abar'", TTs{StringToken}}, - {"\\000026B", TTs{IdentToken}}, - {"\\26 B", TTs{IdentToken}}, - - // hacks - {`\-\mo\z\-b\i\nd\in\g:\url(//business\i\nfo.co.uk\/labs\/xbl\/xbl\.xml\#xss);`, TTs{IdentToken, ColonToken, URLToken, SemicolonToken}}, - {"width/**/:/**/ 40em;", TTs{IdentToken, CommentToken, ColonToken, CommentToken, DimensionToken, SemicolonToken}}, - {":root *> #quince", TTs{ColonToken, IdentToken, DelimToken, DelimToken, HashToken}}, - {"html[xmlns*=\"\"]:root", TTs{IdentToken, LeftBracketToken, IdentToken, SubstringMatchToken, StringToken, RightBracketToken, ColonToken, IdentToken}}, - {"body:nth-of-type(1)", TTs{IdentToken, ColonToken, FunctionToken, NumberToken, RightParenthesisToken}}, - {"color/*\\**/: blue\\9;", TTs{IdentToken, CommentToken, ColonToken, IdentToken, SemicolonToken}}, - {"color: blue !ie;", TTs{IdentToken, ColonToken, IdentToken, DelimToken, IdentToken, SemicolonToken}}, - - // escapes, null and replacement character - {"c\\\x00olor: white;", TTs{IdentToken, ColonToken, IdentToken, SemicolonToken}}, - {"null\\0", TTs{IdentToken}}, - {"eof\\", TTs{IdentToken}}, - {"\"a\x00b\"", TTs{StringToken}}, - {"a\\\x00b", TTs{IdentToken}}, - {"url(a\x00b)", TTs{BadURLToken}}, // null character cannot be unquoted - {"/*a\x00b*/", TTs{CommentToken}}, - - // coverage - {" \n\r\n\r\"\\\r\n\\\r\"", TTs{StringToken}}, - {"U+?????? U+ABCD?? U+ABC-DEF", TTs{UnicodeRangeToken, UnicodeRangeToken, UnicodeRangeToken}}, - {"U+? U+A?", TTs{IdentToken, DelimToken, DelimToken, IdentToken, DelimToken, IdentToken, DelimToken}}, - {"-5.23 -moz", TTs{NumberToken, IdentToken}}, - {"()", TTs{LeftParenthesisToken, RightParenthesisToken}}, - {"url( //url )", TTs{URLToken}}, - {"url( ", TTs{URLToken}}, - {"url( //url", TTs{URLToken}}, - {"url(\")a", TTs{URLToken}}, - {"url(a'\\\n)a", TTs{BadURLToken, IdentToken}}, - {"url(\"\n)a", TTs{BadURLToken, IdentToken}}, - {"url(a h)a", TTs{BadURLToken, IdentToken}}, - {"<!- | @4 ## /2", TTs{DelimToken, DelimToken, DelimToken, DelimToken, DelimToken, NumberToken, DelimToken, DelimToken, DelimToken, NumberToken}}, - {"\"s\\\n\"", TTs{StringToken}}, - {"\"a\\\"b\"", TTs{StringToken}}, - {"\"s\n", TTs{BadStringToken}}, - - // small - {"\"abcd", TTs{StringToken}}, - {"/*comment", TTs{CommentToken}}, - {"U+A-B", TTs{UnicodeRangeToken}}, - {"url((", TTs{BadURLToken}}, - {"id\u554a", TTs{IdentToken}}, - } - for _, tt := range tokenTests { - t.Run(tt.css, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.css)) - i := 0 - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } else if token == WhitespaceToken { - continue - } - test.That(t, i < len(tt.expected), "index", i, "must not exceed expected token types size", len(tt.expected)) - if i < len(tt.expected) { - test.T(t, token, tt.expected[i], "token types must match") - } - i++ - } - }) - } - - test.T(t, WhitespaceToken.String(), "Whitespace") - test.T(t, EmptyToken.String(), "Empty") - test.T(t, CustomPropertyValueToken.String(), "CustomPropertyValue") - test.T(t, TokenType(100).String(), "Invalid(100)") - test.T(t, NewLexer(bytes.NewBufferString("x")).consumeBracket(), ErrorToken, "consumeBracket on 'x' must return error") -} - -//////////////////////////////////////////////////////////////// - -func ExampleNewLexer() { - l := NewLexer(bytes.NewBufferString("color: red;")) - out := "" - for { - tt, data := l.Next() - if tt == ErrorToken { - break - } else if tt == WhitespaceToken || tt == CommentToken { - continue - } - out += string(data) - } - fmt.Println(out) - // Output: color:red; -} diff --git a/vendor/github.com/tdewolff/parse/css/parse.go b/vendor/github.com/tdewolff/parse/css/parse.go deleted file mode 100644 index cedd237..0000000 --- a/vendor/github.com/tdewolff/parse/css/parse.go +++ /dev/null @@ -1,402 +0,0 @@ -package css // import "github.com/tdewolff/parse/css" - -import ( - "bytes" - "io" - "strconv" - - "github.com/tdewolff/parse" -) - -var wsBytes = []byte(" ") -var endBytes = []byte("}") -var emptyBytes = []byte("") - -// GrammarType determines the type of grammar. -type GrammarType uint32 - -// GrammarType values. -const ( - ErrorGrammar GrammarType = iota // extra token when errors occur - CommentGrammar - AtRuleGrammar - BeginAtRuleGrammar - EndAtRuleGrammar - QualifiedRuleGrammar - BeginRulesetGrammar - EndRulesetGrammar - DeclarationGrammar - TokenGrammar - CustomPropertyGrammar -) - -// String returns the string representation of a GrammarType. -func (tt GrammarType) String() string { - switch tt { - case ErrorGrammar: - return "Error" - case CommentGrammar: - return "Comment" - case AtRuleGrammar: - return "AtRule" - case BeginAtRuleGrammar: - return "BeginAtRule" - case EndAtRuleGrammar: - return "EndAtRule" - case QualifiedRuleGrammar: - return "QualifiedRule" - case BeginRulesetGrammar: - return "BeginRuleset" - case EndRulesetGrammar: - return "EndRuleset" - case DeclarationGrammar: - return "Declaration" - case TokenGrammar: - return "Token" - case CustomPropertyGrammar: - return "CustomProperty" - } - return "Invalid(" + strconv.Itoa(int(tt)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// State is the state function the parser currently is in. -type State func(*Parser) GrammarType - -// Token is a single TokenType and its associated data. -type Token struct { - TokenType - Data []byte -} - -func (t Token) String() string { - return t.TokenType.String() + "('" + string(t.Data) + "')" -} - -// Parser is the state for the parser. -type Parser struct { - l *Lexer - state []State - err error - - buf []Token - level int - - tt TokenType - data []byte - prevWS bool - prevEnd bool -} - -// NewParser returns a new CSS parser from an io.Reader. isInline specifies whether this is an inline style attribute. -func NewParser(r io.Reader, isInline bool) *Parser { - l := NewLexer(r) - p := &Parser{ - l: l, - state: make([]State, 0, 4), - } - - if isInline { - p.state = append(p.state, (*Parser).parseDeclarationList) - } else { - p.state = append(p.state, (*Parser).parseStylesheet) - } - return p -} - -// Err returns the error encountered during parsing, this is often io.EOF but also other errors can be returned. -func (p *Parser) Err() error { - if p.err != nil { - return p.err - } - return p.l.Err() -} - -// Restore restores the NULL byte at the end of the buffer. -func (p *Parser) Restore() { - p.l.Restore() -} - -// Next returns the next Grammar. It returns ErrorGrammar when an error was encountered. Using Err() one can retrieve the error message. -func (p *Parser) Next() (GrammarType, TokenType, []byte) { - p.err = nil - - if p.prevEnd { - p.tt, p.data = RightBraceToken, endBytes - p.prevEnd = false - } else { - p.tt, p.data = p.popToken(true) - } - gt := p.state[len(p.state)-1](p) - return gt, p.tt, p.data -} - -// Values returns a slice of Tokens for the last Grammar. Only AtRuleGrammar, BeginAtRuleGrammar, BeginRulesetGrammar and Declaration will return the at-rule components, ruleset selector and declaration values respectively. -func (p *Parser) Values() []Token { - return p.buf -} - -func (p *Parser) popToken(allowComment bool) (TokenType, []byte) { - p.prevWS = false - tt, data := p.l.Next() - for tt == WhitespaceToken || tt == CommentToken { - if tt == WhitespaceToken { - p.prevWS = true - } else if allowComment && len(p.state) == 1 { - break - } - tt, data = p.l.Next() - } - return tt, data -} - -func (p *Parser) initBuf() { - p.buf = p.buf[:0] -} - -func (p *Parser) pushBuf(tt TokenType, data []byte) { - p.buf = append(p.buf, Token{tt, data}) -} - -//////////////////////////////////////////////////////////////// - -func (p *Parser) parseStylesheet() GrammarType { - if p.tt == CDOToken || p.tt == CDCToken { - return TokenGrammar - } else if p.tt == AtKeywordToken { - return p.parseAtRule() - } else if p.tt == CommentToken { - return CommentGrammar - } else if p.tt == ErrorToken { - return ErrorGrammar - } - return p.parseQualifiedRule() -} - -func (p *Parser) parseDeclarationList() GrammarType { - if p.tt == CommentToken { - p.tt, p.data = p.popToken(false) - } - for p.tt == SemicolonToken { - p.tt, p.data = p.popToken(false) - } - if p.tt == ErrorToken { - return ErrorGrammar - } else if p.tt == AtKeywordToken { - return p.parseAtRule() - } else if p.tt == IdentToken { - return p.parseDeclaration() - } else if p.tt == CustomPropertyNameToken { - return p.parseCustomProperty() - } - - // parse error - p.initBuf() - p.err = parse.NewErrorLexer("unexpected token in declaration", p.l.r) - for { - tt, data := p.popToken(false) - if (tt == SemicolonToken || tt == RightBraceToken) && p.level == 0 || tt == ErrorToken { - p.prevEnd = (tt == RightBraceToken) - return ErrorGrammar - } - p.pushBuf(tt, data) - } -} - -//////////////////////////////////////////////////////////////// - -func (p *Parser) parseAtRule() GrammarType { - p.initBuf() - parse.ToLower(p.data) - atRuleName := p.data - if len(atRuleName) > 0 && atRuleName[1] == '-' { - if i := bytes.IndexByte(atRuleName[2:], '-'); i != -1 { - atRuleName = atRuleName[i+2:] // skip vendor specific prefix - } - } - atRule := ToHash(atRuleName[1:]) - - first := true - skipWS := false - for { - tt, data := p.popToken(false) - if tt == LeftBraceToken && p.level == 0 { - if atRule == Font_Face || atRule == Page { - p.state = append(p.state, (*Parser).parseAtRuleDeclarationList) - } else if atRule == Document || atRule == Keyframes || atRule == Media || atRule == Supports { - p.state = append(p.state, (*Parser).parseAtRuleRuleList) - } else { - p.state = append(p.state, (*Parser).parseAtRuleUnknown) - } - return BeginAtRuleGrammar - } else if (tt == SemicolonToken || tt == RightBraceToken) && p.level == 0 || tt == ErrorToken { - p.prevEnd = (tt == RightBraceToken) - return AtRuleGrammar - } else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken { - p.level++ - } else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken { - p.level-- - } - if first { - if tt == LeftParenthesisToken || tt == LeftBracketToken { - p.prevWS = false - } - first = false - } - if len(data) == 1 && (data[0] == ',' || data[0] == ':') { - skipWS = true - } else if p.prevWS && !skipWS && tt != RightParenthesisToken { - p.pushBuf(WhitespaceToken, wsBytes) - } else { - skipWS = false - } - if tt == LeftParenthesisToken { - skipWS = true - } - p.pushBuf(tt, data) - } -} - -func (p *Parser) parseAtRuleRuleList() GrammarType { - if p.tt == RightBraceToken || p.tt == ErrorToken { - p.state = p.state[:len(p.state)-1] - return EndAtRuleGrammar - } else if p.tt == AtKeywordToken { - return p.parseAtRule() - } else { - return p.parseQualifiedRule() - } -} - -func (p *Parser) parseAtRuleDeclarationList() GrammarType { - for p.tt == SemicolonToken { - p.tt, p.data = p.popToken(false) - } - if p.tt == RightBraceToken || p.tt == ErrorToken { - p.state = p.state[:len(p.state)-1] - return EndAtRuleGrammar - } - return p.parseDeclarationList() -} - -func (p *Parser) parseAtRuleUnknown() GrammarType { - if p.tt == RightBraceToken && p.level == 0 || p.tt == ErrorToken { - p.state = p.state[:len(p.state)-1] - return EndAtRuleGrammar - } - if p.tt == LeftParenthesisToken || p.tt == LeftBraceToken || p.tt == LeftBracketToken || p.tt == FunctionToken { - p.level++ - } else if p.tt == RightParenthesisToken || p.tt == RightBraceToken || p.tt == RightBracketToken { - p.level-- - } - return TokenGrammar -} - -func (p *Parser) parseQualifiedRule() GrammarType { - p.initBuf() - first := true - inAttrSel := false - skipWS := true - var tt TokenType - var data []byte - for { - if first { - tt, data = p.tt, p.data - p.tt = WhitespaceToken - p.data = emptyBytes - first = false - } else { - tt, data = p.popToken(false) - } - if tt == LeftBraceToken && p.level == 0 { - p.state = append(p.state, (*Parser).parseQualifiedRuleDeclarationList) - return BeginRulesetGrammar - } else if tt == ErrorToken { - p.err = parse.NewErrorLexer("unexpected ending in qualified rule, expected left brace token", p.l.r) - return ErrorGrammar - } else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken { - p.level++ - } else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken { - p.level-- - } - if len(data) == 1 && (data[0] == ',' || data[0] == '>' || data[0] == '+' || data[0] == '~') { - if data[0] == ',' { - return QualifiedRuleGrammar - } - skipWS = true - } else if p.prevWS && !skipWS && !inAttrSel { - p.pushBuf(WhitespaceToken, wsBytes) - } else { - skipWS = false - } - if tt == LeftBracketToken { - inAttrSel = true - } else if tt == RightBracketToken { - inAttrSel = false - } - p.pushBuf(tt, data) - } -} - -func (p *Parser) parseQualifiedRuleDeclarationList() GrammarType { - for p.tt == SemicolonToken { - p.tt, p.data = p.popToken(false) - } - if p.tt == RightBraceToken || p.tt == ErrorToken { - p.state = p.state[:len(p.state)-1] - return EndRulesetGrammar - } - return p.parseDeclarationList() -} - -func (p *Parser) parseDeclaration() GrammarType { - p.initBuf() - parse.ToLower(p.data) - if tt, _ := p.popToken(false); tt != ColonToken { - p.err = parse.NewErrorLexer("unexpected token in declaration", p.l.r) - return ErrorGrammar - } - skipWS := true - for { - tt, data := p.popToken(false) - if (tt == SemicolonToken || tt == RightBraceToken) && p.level == 0 || tt == ErrorToken { - p.prevEnd = (tt == RightBraceToken) - return DeclarationGrammar - } else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken { - p.level++ - } else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken { - p.level-- - } - if len(data) == 1 && (data[0] == ',' || data[0] == '/' || data[0] == ':' || data[0] == '!' || data[0] == '=') { - skipWS = true - } else if p.prevWS && !skipWS { - p.pushBuf(WhitespaceToken, wsBytes) - } else { - skipWS = false - } - p.pushBuf(tt, data) - } -} - -func (p *Parser) parseCustomProperty() GrammarType { - p.initBuf() - if tt, _ := p.popToken(false); tt != ColonToken { - p.err = parse.NewErrorLexer("unexpected token in declaration", p.l.r) - return ErrorGrammar - } - val := []byte{} - for { - tt, data := p.l.Next() - if (tt == SemicolonToken || tt == RightBraceToken) && p.level == 0 || tt == ErrorToken { - p.prevEnd = (tt == RightBraceToken) - p.pushBuf(CustomPropertyValueToken, val) - return CustomPropertyGrammar - } else if tt == LeftParenthesisToken || tt == LeftBraceToken || tt == LeftBracketToken || tt == FunctionToken { - p.level++ - } else if tt == RightParenthesisToken || tt == RightBraceToken || tt == RightBracketToken { - p.level-- - } - val = append(val, data...) - } -} diff --git a/vendor/github.com/tdewolff/parse/css/parse_test.go b/vendor/github.com/tdewolff/parse/css/parse_test.go deleted file mode 100644 index 9871854..0000000 --- a/vendor/github.com/tdewolff/parse/css/parse_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package css // import "github.com/tdewolff/parse/css" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/parse" - "github.com/tdewolff/test" -) - -//////////////////////////////////////////////////////////////// - -func TestParse(t *testing.T) { - var parseTests = []struct { - inline bool - css string - expected string - }{ - {true, " x : y ; ", "x:y;"}, - {true, "color: red;", "color:red;"}, - {true, "color : red;", "color:red;"}, - {true, "color: red; border: 0;", "color:red;border:0;"}, - {true, "color: red !important;", "color:red!important;"}, - {true, "color: red ! important;", "color:red!important;"}, - {true, "white-space: -moz-pre-wrap;", "white-space:-moz-pre-wrap;"}, - {true, "display: -moz-inline-stack;", "display:-moz-inline-stack;"}, - {true, "x: 10px / 1em;", "x:10px/1em;"}, - {true, "x: 1em/1.5em \"Times New Roman\", Times, serif;", "x:1em/1.5em \"Times New Roman\",Times,serif;"}, - {true, "x: hsla(100,50%, 75%, 0.5);", "x:hsla(100,50%,75%,0.5);"}, - {true, "x: hsl(100,50%, 75%);", "x:hsl(100,50%,75%);"}, - {true, "x: rgba(255, 238 , 221, 0.3);", "x:rgba(255,238,221,0.3);"}, - {true, "x: 50vmax;", "x:50vmax;"}, - {true, "color: linear-gradient(to right, black, white);", "color:linear-gradient(to right,black,white);"}, - {true, "color: calc(100%/2 - 1em);", "color:calc(100%/2 - 1em);"}, - {true, "color: calc(100%/2--1em);", "color:calc(100%/2--1em);"}, - {false, "<!-- @charset; -->", "<!--@charset;-->"}, - {false, "@media print, screen { }", "@media print,screen{}"}, - {false, "@media { @viewport ; }", "@media{@viewport;}"}, - {false, "@keyframes 'diagonal-slide' { from { left: 0; top: 0; } to { left: 100px; top: 100px; } }", "@keyframes 'diagonal-slide'{from{left:0;top:0;}to{left:100px;top:100px;}}"}, - {false, "@keyframes movingbox{0%{left:90%;}50%{left:10%;}100%{left:90%;}}", "@keyframes movingbox{0%{left:90%;}50%{left:10%;}100%{left:90%;}}"}, - {false, ".foo { color: #fff;}", ".foo{color:#fff;}"}, - {false, ".foo { ; _color: #fff;}", ".foo{_color:#fff;}"}, - {false, "a { color: red; border: 0; }", "a{color:red;border:0;}"}, - {false, "a { color: red; border: 0; } b { padding: 0; }", "a{color:red;border:0;}b{padding:0;}"}, - {false, "/* comment */", "/* comment */"}, - - // extraordinary - {true, "color: red;;", "color:red;"}, - {true, "color:#c0c0c0", "color:#c0c0c0;"}, - {true, "background:URL(x.png);", "background:URL(x.png);"}, - {true, "filter: progid : DXImageTransform.Microsoft.BasicImage(rotation=1);", "filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);"}, - {true, "/*a*/\n/*c*/\nkey: value;", "key:value;"}, - {true, "@-moz-charset;", "@-moz-charset;"}, - {true, "--custom-variable: (0;) ;", "--custom-variable: (0;) ;"}, - {false, "@import;@import;", "@import;@import;"}, - {false, ".a .b#c, .d<.e { x:y; }", ".a .b#c,.d<.e{x:y;}"}, - {false, ".a[b~=c]d { x:y; }", ".a[b~=c]d{x:y;}"}, - // {false, "{x:y;}", "{x:y;}"}, - {false, "a{}", "a{}"}, - {false, "a,.b/*comment*/ {x:y;}", "a,.b{x:y;}"}, - {false, "a,.b/*comment*/.c {x:y;}", "a,.b.c{x:y;}"}, - {false, "a{x:; z:q;}", "a{x:;z:q;}"}, - {false, "@font-face { x:y; }", "@font-face{x:y;}"}, - {false, "a:not([controls]){x:y;}", "a:not([controls]){x:y;}"}, - {false, "@document regexp('https:.*') { p { color: red; } }", "@document regexp('https:.*'){p{color:red;}}"}, - {false, "@media all and ( max-width:400px ) { }", "@media all and (max-width:400px){}"}, - {false, "@media (max-width:400px) { }", "@media(max-width:400px){}"}, - {false, "@media (max-width:400px)", "@media(max-width:400px);"}, - {false, "@font-face { ; font:x; }", "@font-face{font:x;}"}, - {false, "@-moz-font-face { ; font:x; }", "@-moz-font-face{font:x;}"}, - {false, "@unknown abc { {} lala }", "@unknown abc{{}lala}"}, - {false, "a[x={}]{x:y;}", "a[x={}]{x:y;}"}, - {false, "a[x=,]{x:y;}", "a[x=,]{x:y;}"}, - {false, "a[x=+]{x:y;}", "a[x=+]{x:y;}"}, - {false, ".cla .ss > #id { x:y; }", ".cla .ss>#id{x:y;}"}, - {false, ".cla /*a*/ /*b*/ .ss{}", ".cla .ss{}"}, - {false, "a{x:f(a(),b);}", "a{x:f(a(),b);}"}, - {false, "a{x:y!z;}", "a{x:y!z;}"}, - {false, "[class*=\"column\"]+[class*=\"column\"]:last-child{a:b;}", "[class*=\"column\"]+[class*=\"column\"]:last-child{a:b;}"}, - {false, "@media { @viewport }", "@media{@viewport;}"}, - {false, "table { @unknown }", "table{@unknown;}"}, - - // early endings - {false, "selector{", "selector{"}, - {false, "@media{selector{", "@media{selector{"}, - - // bad grammar - {true, "~color:red", "~color:red;"}, - {false, ".foo { *color: #fff;}", ".foo{*color:#fff;}"}, - {true, "*color: red; font-size: 12pt;", "*color:red;font-size:12pt;"}, - {true, "_color: red; font-size: 12pt;", "_color:red;font-size:12pt;"}, - - // issues - {false, "@media print {.class{width:5px;}}", "@media print{.class{width:5px;}}"}, // #6 - {false, ".class{width:calc((50% + 2em)/2 + 14px);}", ".class{width:calc((50% + 2em)/2 + 14px);}"}, // #7 - {false, ".class [c=y]{}", ".class [c=y]{}"}, // tdewolff/minify#16 - {false, "table{font-family:Verdana}", "table{font-family:Verdana;}"}, // tdewolff/minify#22 - - // go-fuzz - {false, "@-webkit-", "@-webkit-;"}, - } - for _, tt := range parseTests { - t.Run(tt.css, func(t *testing.T) { - output := "" - p := NewParser(bytes.NewBufferString(tt.css), tt.inline) - for { - grammar, _, data := p.Next() - data = parse.Copy(data) - if grammar == ErrorGrammar { - if err := p.Err(); err != io.EOF { - for _, val := range p.Values() { - data = append(data, val.Data...) - } - if perr, ok := err.(*parse.Error); ok && perr.Message == "unexpected token in declaration" { - data = append(data, ";"...) - } - } else { - test.T(t, err, io.EOF) - break - } - } else if grammar == AtRuleGrammar || grammar == BeginAtRuleGrammar || grammar == QualifiedRuleGrammar || grammar == BeginRulesetGrammar || grammar == DeclarationGrammar || grammar == CustomPropertyGrammar { - if grammar == DeclarationGrammar || grammar == CustomPropertyGrammar { - data = append(data, ":"...) - } - for _, val := range p.Values() { - data = append(data, val.Data...) - } - if grammar == BeginAtRuleGrammar || grammar == BeginRulesetGrammar { - data = append(data, "{"...) - } else if grammar == AtRuleGrammar || grammar == DeclarationGrammar || grammar == CustomPropertyGrammar { - data = append(data, ";"...) - } else if grammar == QualifiedRuleGrammar { - data = append(data, ","...) - } - } - output += string(data) - } - test.String(t, output, tt.expected) - }) - } - - test.T(t, ErrorGrammar.String(), "Error") - test.T(t, AtRuleGrammar.String(), "AtRule") - test.T(t, BeginAtRuleGrammar.String(), "BeginAtRule") - test.T(t, EndAtRuleGrammar.String(), "EndAtRule") - test.T(t, BeginRulesetGrammar.String(), "BeginRuleset") - test.T(t, EndRulesetGrammar.String(), "EndRuleset") - test.T(t, DeclarationGrammar.String(), "Declaration") - test.T(t, TokenGrammar.String(), "Token") - test.T(t, CommentGrammar.String(), "Comment") - test.T(t, CustomPropertyGrammar.String(), "CustomProperty") - test.T(t, GrammarType(100).String(), "Invalid(100)") -} - -func TestParseError(t *testing.T) { - var parseErrorTests = []struct { - inline bool - css string - col int - }{ - {false, "selector", 9}, - {true, "color 0", 8}, - {true, "--color 0", 10}, - {true, "--custom-variable:0", 0}, - } - for _, tt := range parseErrorTests { - t.Run(tt.css, func(t *testing.T) { - p := NewParser(bytes.NewBufferString(tt.css), tt.inline) - for { - grammar, _, _ := p.Next() - if grammar == ErrorGrammar { - if tt.col == 0 { - test.T(t, p.Err(), io.EOF) - } else if perr, ok := p.Err().(*parse.Error); ok { - _, col, _ := perr.Position() - test.T(t, col, tt.col) - } else { - test.Fail(t, "bad error:", p.Err()) - } - break - } - } - }) - } -} - -func TestReader(t *testing.T) { - input := "x:a;" - p := NewParser(test.NewPlainReader(bytes.NewBufferString(input)), true) - for { - grammar, _, _ := p.Next() - if grammar == ErrorGrammar { - break - } - } -} - -//////////////////////////////////////////////////////////////// - -type Obj struct{} - -func (*Obj) F() {} - -var f1 func(*Obj) - -func BenchmarkFuncPtr(b *testing.B) { - for i := 0; i < b.N; i++ { - f1 = (*Obj).F - } -} - -var f2 func() - -func BenchmarkMemFuncPtr(b *testing.B) { - obj := &Obj{} - for i := 0; i < b.N; i++ { - f2 = obj.F - } -} - -func ExampleNewParser() { - p := NewParser(bytes.NewBufferString("color: red;"), true) // false because this is the content of an inline style attribute - out := "" - for { - gt, _, data := p.Next() - if gt == ErrorGrammar { - break - } else if gt == AtRuleGrammar || gt == BeginAtRuleGrammar || gt == BeginRulesetGrammar || gt == DeclarationGrammar { - out += string(data) - if gt == DeclarationGrammar { - out += ":" - } - for _, val := range p.Values() { - out += string(val.Data) - } - if gt == BeginAtRuleGrammar || gt == BeginRulesetGrammar { - out += "{" - } else if gt == AtRuleGrammar || gt == DeclarationGrammar { - out += ";" - } - } else { - out += string(data) - } - } - fmt.Println(out) - // Output: color:red; -} diff --git a/vendor/github.com/tdewolff/parse/css/util.go b/vendor/github.com/tdewolff/parse/css/util.go deleted file mode 100644 index 676dee8..0000000 --- a/vendor/github.com/tdewolff/parse/css/util.go +++ /dev/null @@ -1,47 +0,0 @@ -package css // import "github.com/tdewolff/parse/css" - -import "github.com/tdewolff/parse/buffer" - -// IsIdent returns true if the bytes are a valid identifier. -func IsIdent(b []byte) bool { - l := NewLexer(buffer.NewReader(b)) - l.consumeIdentToken() - l.r.Restore() - return l.r.Pos() == len(b) -} - -// IsURLUnquoted returns true if the bytes are a valid unquoted URL. -func IsURLUnquoted(b []byte) bool { - l := NewLexer(buffer.NewReader(b)) - l.consumeUnquotedURL() - l.r.Restore() - return l.r.Pos() == len(b) -} - -// HSL2RGB converts HSL to RGB with all of range [0,1] -// from http://www.w3.org/TR/css3-color/#hsl-color -func HSL2RGB(h, s, l float64) (float64, float64, float64) { - m2 := l * (s + 1) - if l > 0.5 { - m2 = l + s - l*s - } - m1 := l*2 - m2 - return hue2rgb(m1, m2, h+1.0/3.0), hue2rgb(m1, m2, h), hue2rgb(m1, m2, h-1.0/3.0) -} - -func hue2rgb(m1, m2, h float64) float64 { - if h < 0.0 { - h += 1.0 - } - if h > 1.0 { - h -= 1.0 - } - if h*6.0 < 1.0 { - return m1 + (m2-m1)*h*6.0 - } else if h*2.0 < 1.0 { - return m2 - } else if h*3.0 < 2.0 { - return m1 + (m2-m1)*(2.0/3.0-h)*6.0 - } - return m1 -} diff --git a/vendor/github.com/tdewolff/parse/css/util_test.go b/vendor/github.com/tdewolff/parse/css/util_test.go deleted file mode 100644 index 9eb5aa9..0000000 --- a/vendor/github.com/tdewolff/parse/css/util_test.go +++ /dev/null @@ -1,34 +0,0 @@ -package css // import "github.com/tdewolff/parse/css" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestIsIdent(t *testing.T) { - test.That(t, IsIdent([]byte("color"))) - test.That(t, !IsIdent([]byte("4.5"))) -} - -func TestIsURLUnquoted(t *testing.T) { - test.That(t, IsURLUnquoted([]byte("http://x"))) - test.That(t, !IsURLUnquoted([]byte(")"))) -} - -func TestHsl2Rgb(t *testing.T) { - r, g, b := HSL2RGB(0.0, 1.0, 0.5) - test.T(t, r, 1.0) - test.T(t, g, 0.0) - test.T(t, b, 0.0) - - r, g, b = HSL2RGB(1.0, 1.0, 0.5) - test.T(t, r, 1.0) - test.T(t, g, 0.0) - test.T(t, b, 0.0) - - r, g, b = HSL2RGB(0.66, 0.0, 1.0) - test.T(t, r, 1.0) - test.T(t, g, 1.0) - test.T(t, b, 1.0) -} diff --git a/vendor/github.com/tdewolff/parse/error.go b/vendor/github.com/tdewolff/parse/error.go deleted file mode 100644 index e790379..0000000 --- a/vendor/github.com/tdewolff/parse/error.go +++ /dev/null @@ -1,49 +0,0 @@ -package parse - -import ( - "fmt" - "io" - - "github.com/tdewolff/parse/buffer" -) - -// Error is a parsing error returned by parser. It contains a message and an offset at which the error occurred. -type Error struct { - Message string - r io.Reader - Offset int - line int - column int - context string -} - -// NewError creates a new error -func NewError(msg string, r io.Reader, offset int) *Error { - return &Error{ - Message: msg, - r: r, - Offset: offset, - } -} - -// NewErrorLexer creates a new error from a *buffer.Lexer -func NewErrorLexer(msg string, l *buffer.Lexer) *Error { - r := buffer.NewReader(l.Bytes()) - offset := l.Offset() - return NewError(msg, r, offset) -} - -// Positions re-parses the file to determine the line, column, and context of the error. -// Context is the entire line at which the error occurred. -func (e *Error) Position() (int, int, string) { - if e.line == 0 { - e.line, e.column, e.context, _ = Position(e.r, e.Offset) - } - return e.line, e.column, e.context -} - -// Error returns the error string, containing the context and line + column number. -func (e *Error) Error() string { - line, column, context := e.Position() - return fmt.Sprintf("parse error:%d:%d: %s\n%s", line, column, e.Message, context) -} diff --git a/vendor/github.com/tdewolff/parse/html/README.md b/vendor/github.com/tdewolff/parse/html/README.md deleted file mode 100644 index edca629..0000000 --- a/vendor/github.com/tdewolff/parse/html/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# HTML [![GoDoc](http://godoc.org/github.com/tdewolff/parse/html?status.svg)](http://godoc.org/github.com/tdewolff/parse/html) [![GoCover](http://gocover.io/_badge/github.com/tdewolff/parse/html)](http://gocover.io/github.com/tdewolff/parse/html) - -This package is an HTML5 lexer written in [Go][1]. It follows the specification at [The HTML syntax](http://www.w3.org/TR/html5/syntax.html). The lexer takes an io.Reader and converts it into tokens until the EOF. - -## Installation -Run the following command - - go get github.com/tdewolff/parse/html - -or add the following import and run project with `go get` - - import "github.com/tdewolff/parse/html" - -## Lexer -### Usage -The following initializes a new Lexer with io.Reader `r`: -``` go -l := html.NewLexer(r) -``` - -To tokenize until EOF an error, use: -``` go -for { - tt, data := l.Next() - switch tt { - case html.ErrorToken: - // error or EOF set in l.Err() - return - case html.StartTagToken: - // ... - for { - ttAttr, dataAttr := l.Next() - if ttAttr != html.AttributeToken { - break - } - // ... - } - // ... - } -} -``` - -All tokens: -``` go -ErrorToken TokenType = iota // extra token when errors occur -CommentToken -DoctypeToken -StartTagToken -StartTagCloseToken -StartTagVoidToken -EndTagToken -AttributeToken -TextToken -``` - -### Examples -``` go -package main - -import ( - "os" - - "github.com/tdewolff/parse/html" -) - -// Tokenize HTML from stdin. -func main() { - l := html.NewLexer(os.Stdin) - for { - tt, data := l.Next() - switch tt { - case html.ErrorToken: - if l.Err() != io.EOF { - fmt.Println("Error on line", l.Line(), ":", l.Err()) - } - return - case html.StartTagToken: - fmt.Println("Tag", string(data)) - for { - ttAttr, dataAttr := l.Next() - if ttAttr != html.AttributeToken { - break - } - - key := dataAttr - val := l.AttrVal() - fmt.Println("Attribute", string(key), "=", string(val)) - } - // ... - } - } -} -``` - -## License -Released under the [MIT license](https://github.com/tdewolff/parse/blob/master/LICENSE.md). - -[1]: http://golang.org/ "Go Language" diff --git a/vendor/github.com/tdewolff/parse/html/hash.go b/vendor/github.com/tdewolff/parse/html/hash.go deleted file mode 100644 index 382e5c5..0000000 --- a/vendor/github.com/tdewolff/parse/html/hash.go +++ /dev/null @@ -1,831 +0,0 @@ -package html - -// generated by hasher -type=Hash -file=hash.go; DO NOT EDIT, except for adding more constants to the list and rerun go generate - -// uses github.com/tdewolff/hasher -//go:generate hasher -type=Hash -file=hash.go - -// Hash defines perfect hashes for a predefined list of strings -type Hash uint32 - -// Unique hash definitions to be used instead of strings -const ( - A Hash = 0x1 // a - Abbr Hash = 0x4 // abbr - Accept Hash = 0x3206 // accept - Accept_Charset Hash = 0x320e // accept-charset - Accesskey Hash = 0x4409 // accesskey - Acronym Hash = 0xbb07 // acronym - Action Hash = 0x2ba06 // action - Address Hash = 0x67e07 // address - Align Hash = 0x1605 // align - Alink Hash = 0xd205 // alink - Allowfullscreen Hash = 0x23d0f // allowfullscreen - Alt Hash = 0xee03 // alt - Annotation Hash = 0x2070a // annotation - AnnotationXml Hash = 0x2070d // annotationXml - Applet Hash = 0x14506 // applet - Area Hash = 0x38d04 // area - Article Hash = 0x40e07 // article - Aside Hash = 0x8305 // aside - Async Hash = 0xfa05 // async - Audio Hash = 0x11605 // audio - Autocomplete Hash = 0x12e0c // autocomplete - Autofocus Hash = 0x13a09 // autofocus - Autoplay Hash = 0x14f08 // autoplay - Axis Hash = 0x15704 // axis - B Hash = 0x101 // b - Background Hash = 0x1e0a // background - Base Hash = 0x45404 // base - Basefont Hash = 0x45408 // basefont - Bdi Hash = 0xcb03 // bdi - Bdo Hash = 0x18403 // bdo - Bgcolor Hash = 0x19707 // bgcolor - Bgsound Hash = 0x19e07 // bgsound - Big Hash = 0x1a603 // big - Blink Hash = 0x1a905 // blink - Blockquote Hash = 0x1ae0a // blockquote - Body Hash = 0x4004 // body - Border Hash = 0x33806 // border - Br Hash = 0x202 // br - Button Hash = 0x1b806 // button - Canvas Hash = 0x7f06 // canvas - Caption Hash = 0x27f07 // caption - Center Hash = 0x62a06 // center - Challenge Hash = 0x1e509 // challenge - Charset Hash = 0x3907 // charset - Checked Hash = 0x3b407 // checked - Cite Hash = 0xfe04 // cite - Class Hash = 0x1c305 // class - Classid Hash = 0x1c307 // classid - Clear Hash = 0x41205 // clear - Code Hash = 0x1d604 // code - Codebase Hash = 0x45008 // codebase - Codetype Hash = 0x1d608 // codetype - Col Hash = 0x19903 // col - Colgroup Hash = 0x1ee08 // colgroup - Color Hash = 0x19905 // color - Cols Hash = 0x20204 // cols - Colspan Hash = 0x20207 // colspan - Command Hash = 0x21407 // command - Compact Hash = 0x21b07 // compact - Content Hash = 0x4a907 // content - Contenteditable Hash = 0x4a90f // contenteditable - Contextmenu Hash = 0x3bd0b // contextmenu - Controls Hash = 0x22a08 // controls - Coords Hash = 0x23606 // coords - Crossorigin Hash = 0x25b0b // crossorigin - Data Hash = 0x4c004 // data - Datalist Hash = 0x4c008 // datalist - Datetime Hash = 0x2ea08 // datetime - Dd Hash = 0x31602 // dd - Declare Hash = 0x8607 // declare - Default Hash = 0x5407 // default - DefaultChecked Hash = 0x5040e // defaultChecked - DefaultMuted Hash = 0x5650c // defaultMuted - DefaultSelected Hash = 0x540f // defaultSelected - Defer Hash = 0x6205 // defer - Del Hash = 0x7203 // del - Desc Hash = 0x7c04 // desc - Details Hash = 0x9207 // details - Dfn Hash = 0xab03 // dfn - Dialog Hash = 0xcc06 // dialog - Dir Hash = 0xd903 // dir - Dirname Hash = 0xd907 // dirname - Disabled Hash = 0x10408 // disabled - Div Hash = 0x10b03 // div - Dl Hash = 0x1a402 // dl - Download Hash = 0x48608 // download - Draggable Hash = 0x1c909 // draggable - Dropzone Hash = 0x41908 // dropzone - Dt Hash = 0x60602 // dt - Em Hash = 0x6e02 // em - Embed Hash = 0x6e05 // embed - Enabled Hash = 0x4e07 // enabled - Enctype Hash = 0x2cf07 // enctype - Face Hash = 0x62804 // face - Fieldset Hash = 0x26c08 // fieldset - Figcaption Hash = 0x27c0a // figcaption - Figure Hash = 0x29006 // figure - Font Hash = 0x45804 // font - Footer Hash = 0xf106 // footer - For Hash = 0x29c03 // for - ForeignObject Hash = 0x29c0d // foreignObject - Foreignobject Hash = 0x2a90d // foreignobject - Form Hash = 0x2b604 // form - Formaction Hash = 0x2b60a // formaction - Formenctype Hash = 0x2cb0b // formenctype - Formmethod Hash = 0x2d60a // formmethod - Formnovalidate Hash = 0x2e00e // formnovalidate - Formtarget Hash = 0x2f50a // formtarget - Frame Hash = 0xa305 // frame - Frameborder Hash = 0x3330b // frameborder - Frameset Hash = 0xa308 // frameset - H1 Hash = 0x19502 // h1 - H2 Hash = 0x32402 // h2 - H3 Hash = 0x34902 // h3 - H4 Hash = 0x38602 // h4 - H5 Hash = 0x60802 // h5 - H6 Hash = 0x2ff02 // h6 - Head Hash = 0x37204 // head - Header Hash = 0x37206 // header - Headers Hash = 0x37207 // headers - Height Hash = 0x30106 // height - Hgroup Hash = 0x30906 // hgroup - Hidden Hash = 0x31406 // hidden - High Hash = 0x32104 // high - Hr Hash = 0xaf02 // hr - Href Hash = 0xaf04 // href - Hreflang Hash = 0xaf08 // hreflang - Html Hash = 0x30504 // html - Http_Equiv Hash = 0x3260a // http-equiv - I Hash = 0x601 // i - Icon Hash = 0x4a804 // icon - Id Hash = 0x8502 // id - Iframe Hash = 0x33206 // iframe - Image Hash = 0x33e05 // image - Img Hash = 0x34303 // img - Inert Hash = 0x55005 // inert - Input Hash = 0x47305 // input - Ins Hash = 0x26403 // ins - Isindex Hash = 0x15907 // isindex - Ismap Hash = 0x34b05 // ismap - Itemid Hash = 0xff06 // itemid - Itemprop Hash = 0x58808 // itemprop - Itemref Hash = 0x62207 // itemref - Itemscope Hash = 0x35609 // itemscope - Itemtype Hash = 0x36008 // itemtype - Kbd Hash = 0xca03 // kbd - Keygen Hash = 0x4a06 // keygen - Keytype Hash = 0x68807 // keytype - Kind Hash = 0xd604 // kind - Label Hash = 0x7405 // label - Lang Hash = 0xb304 // lang - Language Hash = 0xb308 // language - Legend Hash = 0x1d006 // legend - Li Hash = 0x1702 // li - Link Hash = 0xd304 // link - List Hash = 0x4c404 // list - Listing Hash = 0x4c407 // listing - Longdesc Hash = 0x7808 // longdesc - Loop Hash = 0x12104 // loop - Low Hash = 0x23f03 // low - Main Hash = 0x1004 // main - Malignmark Hash = 0xc10a // malignmark - Manifest Hash = 0x65e08 // manifest - Map Hash = 0x14403 // map - Mark Hash = 0xc704 // mark - Marquee Hash = 0x36807 // marquee - Math Hash = 0x36f04 // math - Max Hash = 0x37e03 // max - Maxlength Hash = 0x37e09 // maxlength - Media Hash = 0xde05 // media - Mediagroup Hash = 0xde0a // mediagroup - Menu Hash = 0x3c404 // menu - Meta Hash = 0x4d304 // meta - Meter Hash = 0x2f005 // meter - Method Hash = 0x2da06 // method - Mglyph Hash = 0x34406 // mglyph - Mi Hash = 0x2c02 // mi - Min Hash = 0x2c03 // min - Mn Hash = 0x2e302 // mn - Mo Hash = 0x4f702 // mo - Ms Hash = 0x35902 // ms - Mtext Hash = 0x38805 // mtext - Multiple Hash = 0x39608 // multiple - Muted Hash = 0x39e05 // muted - Name Hash = 0xdc04 // name - Nav Hash = 0x1303 // nav - Nobr Hash = 0x1a04 // nobr - Noembed Hash = 0x6c07 // noembed - Noframes Hash = 0xa108 // noframes - Nohref Hash = 0xad06 // nohref - Noresize Hash = 0x24b08 // noresize - Noscript Hash = 0x31908 // noscript - Noshade Hash = 0x4ff07 // noshade - Novalidate Hash = 0x2e40a // novalidate - Nowrap Hash = 0x59106 // nowrap - Object Hash = 0x2b006 // object - Ol Hash = 0x17102 // ol - Onabort Hash = 0x1bc07 // onabort - Onafterprint Hash = 0x2840c // onafterprint - Onbeforeprint Hash = 0x2be0d // onbeforeprint - Onbeforeunload Hash = 0x6720e // onbeforeunload - Onblur Hash = 0x17e06 // onblur - Oncancel Hash = 0x11a08 // oncancel - Oncanplay Hash = 0x18609 // oncanplay - Oncanplaythrough Hash = 0x18610 // oncanplaythrough - Onchange Hash = 0x42f08 // onchange - Onclick Hash = 0x6b607 // onclick - Onclose Hash = 0x3a307 // onclose - Oncontextmenu Hash = 0x3bb0d // oncontextmenu - Oncuechange Hash = 0x3c80b // oncuechange - Ondblclick Hash = 0x3d30a // ondblclick - Ondrag Hash = 0x3dd06 // ondrag - Ondragend Hash = 0x3dd09 // ondragend - Ondragenter Hash = 0x3e60b // ondragenter - Ondragleave Hash = 0x3f10b // ondragleave - Ondragover Hash = 0x3fc0a // ondragover - Ondragstart Hash = 0x4060b // ondragstart - Ondrop Hash = 0x41706 // ondrop - Ondurationchange Hash = 0x42710 // ondurationchange - Onemptied Hash = 0x41e09 // onemptied - Onended Hash = 0x43707 // onended - Onerror Hash = 0x43e07 // onerror - Onfocus Hash = 0x44507 // onfocus - Onhashchange Hash = 0x4650c // onhashchange - Oninput Hash = 0x47107 // oninput - Oninvalid Hash = 0x47809 // oninvalid - Onkeydown Hash = 0x48109 // onkeydown - Onkeypress Hash = 0x48e0a // onkeypress - Onkeyup Hash = 0x49e07 // onkeyup - Onload Hash = 0x4b806 // onload - Onloadeddata Hash = 0x4b80c // onloadeddata - Onloadedmetadata Hash = 0x4cb10 // onloadedmetadata - Onloadstart Hash = 0x4e10b // onloadstart - Onmessage Hash = 0x4ec09 // onmessage - Onmousedown Hash = 0x4f50b // onmousedown - Onmousemove Hash = 0x5120b // onmousemove - Onmouseout Hash = 0x51d0a // onmouseout - Onmouseover Hash = 0x52a0b // onmouseover - Onmouseup Hash = 0x53509 // onmouseup - Onmousewheel Hash = 0x53e0c // onmousewheel - Onoffline Hash = 0x54a09 // onoffline - Ononline Hash = 0x55508 // ononline - Onpagehide Hash = 0x55d0a // onpagehide - Onpageshow Hash = 0x5710a // onpageshow - Onpause Hash = 0x57d07 // onpause - Onplay Hash = 0x59c06 // onplay - Onplaying Hash = 0x59c09 // onplaying - Onpopstate Hash = 0x5a50a // onpopstate - Onprogress Hash = 0x5af0a // onprogress - Onratechange Hash = 0x5be0c // onratechange - Onreset Hash = 0x5ca07 // onreset - Onresize Hash = 0x5d108 // onresize - Onscroll Hash = 0x5d908 // onscroll - Onseeked Hash = 0x5e408 // onseeked - Onseeking Hash = 0x5ec09 // onseeking - Onselect Hash = 0x5f508 // onselect - Onshow Hash = 0x5ff06 // onshow - Onstalled Hash = 0x60a09 // onstalled - Onstorage Hash = 0x61309 // onstorage - Onsubmit Hash = 0x61c08 // onsubmit - Onsuspend Hash = 0x63009 // onsuspend - Ontimeupdate Hash = 0x4590c // ontimeupdate - Onunload Hash = 0x63908 // onunload - Onvolumechange Hash = 0x6410e // onvolumechange - Onwaiting Hash = 0x64f09 // onwaiting - Open Hash = 0x58e04 // open - Optgroup Hash = 0x12308 // optgroup - Optimum Hash = 0x65807 // optimum - Option Hash = 0x66e06 // option - Output Hash = 0x52406 // output - P Hash = 0xc01 // p - Param Hash = 0xc05 // param - Pattern Hash = 0x9b07 // pattern - Pauseonexit Hash = 0x57f0b // pauseonexit - Picture Hash = 0xe707 // picture - Ping Hash = 0x12a04 // ping - Placeholder Hash = 0x16b0b // placeholder - Plaintext Hash = 0x1f509 // plaintext - Poster Hash = 0x30e06 // poster - Pre Hash = 0x34f03 // pre - Preload Hash = 0x34f07 // preload - Profile Hash = 0x66707 // profile - Progress Hash = 0x5b108 // progress - Prompt Hash = 0x59606 // prompt - Public Hash = 0x4a406 // public - Q Hash = 0x8d01 // q - Radiogroup Hash = 0x30a // radiogroup - Rb Hash = 0x1d02 // rb - Readonly Hash = 0x38e08 // readonly - Rel Hash = 0x35003 // rel - Required Hash = 0x8b08 // required - Rev Hash = 0x29403 // rev - Reversed Hash = 0x29408 // reversed - Rows Hash = 0x6604 // rows - Rowspan Hash = 0x6607 // rowspan - Rp Hash = 0x28a02 // rp - Rt Hash = 0x1c102 // rt - Rtc Hash = 0x1c103 // rtc - Ruby Hash = 0xf604 // ruby - Rules Hash = 0x17505 // rules - S Hash = 0x3d01 // s - Samp Hash = 0x9804 // samp - Sandbox Hash = 0x16307 // sandbox - Scope Hash = 0x35a05 // scope - Scoped Hash = 0x35a06 // scoped - Script Hash = 0x31b06 // script - Scrolling Hash = 0x5db09 // scrolling - Seamless Hash = 0x3a808 // seamless - Section Hash = 0x17907 // section - Select Hash = 0x5f706 // select - Selected Hash = 0x5f708 // selected - Shape Hash = 0x23105 // shape - Size Hash = 0x24f04 // size - Sizes Hash = 0x24f05 // sizes - Small Hash = 0x23b05 // small - Sortable Hash = 0x25308 // sortable - Source Hash = 0x26606 // source - Spacer Hash = 0x37806 // spacer - Span Hash = 0x6904 // span - Spellcheck Hash = 0x3af0a // spellcheck - Src Hash = 0x44b03 // src - Srcdoc Hash = 0x44b06 // srcdoc - Srclang Hash = 0x49707 // srclang - Srcset Hash = 0x5b806 // srcset - Start Hash = 0x40c05 // start - Step Hash = 0x66404 // step - Strike Hash = 0x68406 // strike - Strong Hash = 0x68f06 // strong - Style Hash = 0x69505 // style - Sub Hash = 0x61e03 // sub - Summary Hash = 0x69a07 // summary - Sup Hash = 0x6a103 // sup - Svg Hash = 0x6a403 // svg - System Hash = 0x6a706 // system - Tabindex Hash = 0x4d908 // tabindex - Table Hash = 0x25605 // table - Target Hash = 0x2f906 // target - Tbody Hash = 0x3f05 // tbody - Td Hash = 0xaa02 // td - Template Hash = 0x6aa08 // template - Text Hash = 0x1fa04 // text - Textarea Hash = 0x38908 // textarea - Tfoot Hash = 0xf005 // tfoot - Th Hash = 0x18f02 // th - Thead Hash = 0x37105 // thead - Time Hash = 0x2ee04 // time - Title Hash = 0x14a05 // title - Tr Hash = 0x1fd02 // tr - Track Hash = 0x1fd05 // track - Translate Hash = 0x22109 // translate - Truespeed Hash = 0x27309 // truespeed - Tt Hash = 0x9d02 // tt - Type Hash = 0x11204 // type - Typemustmatch Hash = 0x1da0d // typemustmatch - U Hash = 0xb01 // u - Ul Hash = 0x5802 // ul - Undeterminate Hash = 0x250d // undeterminate - Usemap Hash = 0x14106 // usemap - Valign Hash = 0x1506 // valign - Value Hash = 0x10d05 // value - Valuetype Hash = 0x10d09 // valuetype - Var Hash = 0x32f03 // var - Video Hash = 0x6b205 // video - Visible Hash = 0x6bd07 // visible - Vlink Hash = 0x6c405 // vlink - Wbr Hash = 0x57a03 // wbr - Width Hash = 0x60405 // width - Wrap Hash = 0x59304 // wrap - Xmlns Hash = 0x15f05 // xmlns - Xmp Hash = 0x16903 // xmp -) - -// String returns the hash' name. -func (i Hash) String() string { - start := uint32(i >> 8) - n := uint32(i & 0xff) - if start+n > uint32(len(_Hash_text)) { - return "" - } - return _Hash_text[start : start+n] -} - -// ToHash returns the hash whose name is s. It returns zero if there is no -// such hash. It is case sensitive. -func ToHash(s []byte) Hash { - if len(s) == 0 || len(s) > _Hash_maxLen { - return 0 - } - h := uint32(_Hash_hash0) - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - goto NEXT - } - } - return i - } -NEXT: - if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - return 0 - } - } - return i - } - return 0 -} - -const _Hash_hash0 = 0x5334b67c -const _Hash_maxLen = 16 -const _Hash_text = "abbradiogrouparamainavalignobrbackgroundeterminateaccept-cha" + - "rsetbodyaccesskeygenabledefaultSelectedeferowspanoembedelabe" + - "longdescanvasideclarequiredetailsampatternoframesetdfnohrefl" + - "anguageacronymalignmarkbdialogalinkindirnamediagroupictureal" + - "tfooterubyasyncitemidisabledivaluetypeaudioncancelooptgroupi" + - "ngautocompleteautofocusemappletitleautoplayaxisindexmlnsandb" + - "oxmplaceholderulesectionblurbdoncanplaythrough1bgcolorbgsoun" + - "dlbigblinkblockquotebuttonabortclassidraggablegendcodetypemu" + - "stmatchallengecolgrouplaintextrackcolspannotationXmlcommandc" + - "ompactranslatecontrolshapecoordsmallowfullscreenoresizesorta" + - "blecrossoriginsourcefieldsetruespeedfigcaptionafterprintfigu" + - "reversedforeignObjectforeignobjectformactionbeforeprintforme" + - "nctypeformmethodformnovalidatetimeterformtargeth6heightmlhgr" + - "ouposterhiddenoscripthigh2http-equivariframeborderimageimgly" + - "ph3ismapreloaditemscopeditemtypemarqueematheaderspacermaxlen" + - "gth4mtextareadonlymultiplemutedoncloseamlesspellcheckedoncon" + - "textmenuoncuechangeondblclickondragendondragenterondragleave" + - "ondragoverondragstarticlearondropzonemptiedondurationchangeo" + - "nendedonerroronfocusrcdocodebasefontimeupdateonhashchangeoni" + - "nputoninvalidonkeydownloadonkeypressrclangonkeyupublicontent" + - "editableonloadeddatalistingonloadedmetadatabindexonloadstart" + - "onmessageonmousedownoshadefaultCheckedonmousemoveonmouseoutp" + - "utonmouseoveronmouseuponmousewheelonofflinertononlineonpageh" + - "idefaultMutedonpageshowbronpauseonexitempropenowrapromptonpl" + - "ayingonpopstateonprogressrcsetonratechangeonresetonresizeons" + - "crollingonseekedonseekingonselectedonshowidth5onstalledonsto" + - "rageonsubmitemrefacenteronsuspendonunloadonvolumechangeonwai" + - "tingoptimumanifesteprofileoptionbeforeunloaddresstrikeytypes" + - "trongstylesummarysupsvgsystemplatevideonclickvisiblevlink" - -var _Hash_table = [1 << 9]Hash{ - 0x0: 0x2cb0b, // formenctype - 0x1: 0x2d60a, // formmethod - 0x2: 0x3c80b, // oncuechange - 0x3: 0x3dd06, // ondrag - 0x6: 0x68406, // strike - 0x7: 0x6b205, // video - 0x9: 0x4a907, // content - 0xa: 0x4e07, // enabled - 0xb: 0x59106, // nowrap - 0xc: 0xd304, // link - 0xe: 0x28a02, // rp - 0xf: 0x2840c, // onafterprint - 0x10: 0x14506, // applet - 0x11: 0xf005, // tfoot - 0x12: 0x5040e, // defaultChecked - 0x13: 0x3330b, // frameborder - 0x14: 0xf106, // footer - 0x15: 0x5f708, // selected - 0x16: 0x49707, // srclang - 0x18: 0x52a0b, // onmouseover - 0x19: 0x1d604, // code - 0x1b: 0x47809, // oninvalid - 0x1c: 0x62804, // face - 0x1e: 0x3bd0b, // contextmenu - 0x1f: 0xa308, // frameset - 0x21: 0x5650c, // defaultMuted - 0x22: 0x19905, // color - 0x23: 0x59c06, // onplay - 0x25: 0x2f005, // meter - 0x26: 0x61309, // onstorage - 0x27: 0x38e08, // readonly - 0x29: 0x66707, // profile - 0x2a: 0x8607, // declare - 0x2b: 0xb01, // u - 0x2c: 0x31908, // noscript - 0x2d: 0x65e08, // manifest - 0x2e: 0x1b806, // button - 0x2f: 0x2ea08, // datetime - 0x30: 0x47305, // input - 0x31: 0x5407, // default - 0x32: 0x1d608, // codetype - 0x33: 0x2a90d, // foreignobject - 0x34: 0x36807, // marquee - 0x36: 0x19707, // bgcolor - 0x37: 0x19502, // h1 - 0x39: 0x1e0a, // background - 0x3b: 0x2f50a, // formtarget - 0x41: 0x2f906, // target - 0x43: 0x23b05, // small - 0x44: 0x45008, // codebase - 0x45: 0x55005, // inert - 0x47: 0x38805, // mtext - 0x48: 0x6607, // rowspan - 0x49: 0x2be0d, // onbeforeprint - 0x4a: 0x55508, // ononline - 0x4c: 0x29006, // figure - 0x4d: 0x4cb10, // onloadedmetadata - 0x4e: 0xbb07, // acronym - 0x50: 0x39608, // multiple - 0x51: 0x320e, // accept-charset - 0x52: 0x24f05, // sizes - 0x53: 0x29c0d, // foreignObject - 0x55: 0x2e40a, // novalidate - 0x56: 0x55d0a, // onpagehide - 0x57: 0x2e302, // mn - 0x58: 0x38602, // h4 - 0x5a: 0x1c102, // rt - 0x5b: 0xd205, // alink - 0x5e: 0x59606, // prompt - 0x5f: 0x17102, // ol - 0x61: 0x5d108, // onresize - 0x64: 0x69a07, // summary - 0x65: 0x5a50a, // onpopstate - 0x66: 0x38d04, // area - 0x68: 0x64f09, // onwaiting - 0x6b: 0xdc04, // name - 0x6c: 0x23606, // coords - 0x6d: 0x34303, // img - 0x6e: 0x66404, // step - 0x6f: 0x5ec09, // onseeking - 0x70: 0x32104, // high - 0x71: 0x49e07, // onkeyup - 0x72: 0x5f706, // select - 0x73: 0x1fd05, // track - 0x74: 0x34b05, // ismap - 0x76: 0x47107, // oninput - 0x77: 0x8d01, // q - 0x78: 0x48109, // onkeydown - 0x79: 0x33e05, // image - 0x7a: 0x2b604, // form - 0x7b: 0x60a09, // onstalled - 0x7c: 0xe707, // picture - 0x7d: 0x42f08, // onchange - 0x7e: 0x1a905, // blink - 0x7f: 0xee03, // alt - 0x80: 0xfa05, // async - 0x82: 0x1702, // li - 0x84: 0x2c02, // mi - 0x85: 0xff06, // itemid - 0x86: 0x11605, // audio - 0x87: 0x31b06, // script - 0x8b: 0x44b06, // srcdoc - 0x8e: 0xc704, // mark - 0x8f: 0x18403, // bdo - 0x91: 0x5120b, // onmousemove - 0x93: 0x3c404, // menu - 0x94: 0x45804, // font - 0x95: 0x14f08, // autoplay - 0x96: 0x6c405, // vlink - 0x98: 0x6e02, // em - 0x9a: 0x5b806, // srcset - 0x9b: 0x1ee08, // colgroup - 0x9c: 0x58e04, // open - 0x9d: 0x1d006, // legend - 0x9e: 0x4e10b, // onloadstart - 0xa2: 0x22109, // translate - 0xa3: 0x6e05, // embed - 0xa4: 0x1c305, // class - 0xa6: 0x6aa08, // template - 0xa7: 0x37206, // header - 0xa9: 0x4b806, // onload - 0xaa: 0x37105, // thead - 0xab: 0x5db09, // scrolling - 0xac: 0xc05, // param - 0xae: 0x9b07, // pattern - 0xaf: 0x9207, // details - 0xb1: 0x4a406, // public - 0xb3: 0x4f50b, // onmousedown - 0xb4: 0x14403, // map - 0xb6: 0x25b0b, // crossorigin - 0xb7: 0x1506, // valign - 0xb9: 0x1bc07, // onabort - 0xba: 0x66e06, // option - 0xbb: 0x26606, // source - 0xbc: 0x6205, // defer - 0xbd: 0x1e509, // challenge - 0xbf: 0x10d05, // value - 0xc0: 0x23d0f, // allowfullscreen - 0xc1: 0xca03, // kbd - 0xc2: 0x2070d, // annotationXml - 0xc3: 0x5be0c, // onratechange - 0xc4: 0x4f702, // mo - 0xc6: 0x3af0a, // spellcheck - 0xc7: 0x2c03, // min - 0xc8: 0x4b80c, // onloadeddata - 0xc9: 0x41205, // clear - 0xca: 0x42710, // ondurationchange - 0xcb: 0x1a04, // nobr - 0xcd: 0x27309, // truespeed - 0xcf: 0x30906, // hgroup - 0xd0: 0x40c05, // start - 0xd3: 0x41908, // dropzone - 0xd5: 0x7405, // label - 0xd8: 0xde0a, // mediagroup - 0xd9: 0x17e06, // onblur - 0xdb: 0x27f07, // caption - 0xdd: 0x7c04, // desc - 0xde: 0x15f05, // xmlns - 0xdf: 0x30106, // height - 0xe0: 0x21407, // command - 0xe2: 0x57f0b, // pauseonexit - 0xe3: 0x68f06, // strong - 0xe4: 0x43e07, // onerror - 0xe5: 0x61c08, // onsubmit - 0xe6: 0xb308, // language - 0xe7: 0x48608, // download - 0xe9: 0x53509, // onmouseup - 0xec: 0x2cf07, // enctype - 0xed: 0x5f508, // onselect - 0xee: 0x2b006, // object - 0xef: 0x1f509, // plaintext - 0xf0: 0x3d30a, // ondblclick - 0xf1: 0x18610, // oncanplaythrough - 0xf2: 0xd903, // dir - 0xf3: 0x38908, // textarea - 0xf4: 0x12a04, // ping - 0xf5: 0x2da06, // method - 0xf6: 0x22a08, // controls - 0xf7: 0x37806, // spacer - 0xf8: 0x6a403, // svg - 0xf9: 0x30504, // html - 0xfa: 0x3d01, // s - 0xfc: 0xcc06, // dialog - 0xfe: 0x1da0d, // typemustmatch - 0xff: 0x3b407, // checked - 0x101: 0x30e06, // poster - 0x102: 0x3260a, // http-equiv - 0x103: 0x44b03, // src - 0x104: 0x10408, // disabled - 0x105: 0x37207, // headers - 0x106: 0x5af0a, // onprogress - 0x107: 0x26c08, // fieldset - 0x108: 0x32f03, // var - 0x10a: 0xa305, // frame - 0x10b: 0x36008, // itemtype - 0x10c: 0x3fc0a, // ondragover - 0x10d: 0x13a09, // autofocus - 0x10f: 0x601, // i - 0x110: 0x35902, // ms - 0x111: 0x45404, // base - 0x113: 0x35a05, // scope - 0x114: 0x3206, // accept - 0x115: 0x58808, // itemprop - 0x117: 0xfe04, // cite - 0x118: 0x3907, // charset - 0x119: 0x14a05, // title - 0x11a: 0x68807, // keytype - 0x11b: 0x1fa04, // text - 0x11c: 0x65807, // optimum - 0x11e: 0x37204, // head - 0x121: 0x21b07, // compact - 0x123: 0x63009, // onsuspend - 0x124: 0x4c404, // list - 0x125: 0x4590c, // ontimeupdate - 0x126: 0x62a06, // center - 0x127: 0x31406, // hidden - 0x129: 0x35609, // itemscope - 0x12c: 0x1a402, // dl - 0x12d: 0x17907, // section - 0x12e: 0x11a08, // oncancel - 0x12f: 0x6b607, // onclick - 0x130: 0xde05, // media - 0x131: 0x52406, // output - 0x132: 0x4c008, // datalist - 0x133: 0x53e0c, // onmousewheel - 0x134: 0x45408, // basefont - 0x135: 0x37e09, // maxlength - 0x136: 0x6bd07, // visible - 0x137: 0x2e00e, // formnovalidate - 0x139: 0x16903, // xmp - 0x13a: 0x101, // b - 0x13b: 0x5710a, // onpageshow - 0x13c: 0xf604, // ruby - 0x13d: 0x16b0b, // placeholder - 0x13e: 0x4c407, // listing - 0x140: 0x26403, // ins - 0x141: 0x62207, // itemref - 0x144: 0x540f, // defaultSelected - 0x146: 0x3f10b, // ondragleave - 0x147: 0x1ae0a, // blockquote - 0x148: 0x59304, // wrap - 0x14a: 0x1a603, // big - 0x14b: 0x35003, // rel - 0x14c: 0x41706, // ondrop - 0x14e: 0x6a706, // system - 0x14f: 0x30a, // radiogroup - 0x150: 0x25605, // table - 0x152: 0x57a03, // wbr - 0x153: 0x3bb0d, // oncontextmenu - 0x155: 0x250d, // undeterminate - 0x157: 0x20204, // cols - 0x158: 0x16307, // sandbox - 0x159: 0x1303, // nav - 0x15a: 0x37e03, // max - 0x15b: 0x7808, // longdesc - 0x15c: 0x60405, // width - 0x15d: 0x34902, // h3 - 0x15e: 0x19e07, // bgsound - 0x161: 0x10d09, // valuetype - 0x162: 0x69505, // style - 0x164: 0x3f05, // tbody - 0x165: 0x40e07, // article - 0x169: 0xcb03, // bdi - 0x16a: 0x67e07, // address - 0x16b: 0x23105, // shape - 0x16c: 0x2ba06, // action - 0x16e: 0x1fd02, // tr - 0x16f: 0xaa02, // td - 0x170: 0x3dd09, // ondragend - 0x171: 0x5802, // ul - 0x172: 0x33806, // border - 0x174: 0x4a06, // keygen - 0x175: 0x4004, // body - 0x177: 0x1c909, // draggable - 0x178: 0x2b60a, // formaction - 0x17b: 0x34406, // mglyph - 0x17d: 0x1d02, // rb - 0x17e: 0x2ff02, // h6 - 0x17f: 0x41e09, // onemptied - 0x180: 0x5ca07, // onreset - 0x181: 0x1004, // main - 0x182: 0x12104, // loop - 0x183: 0x48e0a, // onkeypress - 0x184: 0x9d02, // tt - 0x186: 0x20207, // colspan - 0x188: 0x36f04, // math - 0x189: 0x1605, // align - 0x18a: 0xa108, // noframes - 0x18b: 0xaf02, // hr - 0x18c: 0xc10a, // malignmark - 0x18e: 0x23f03, // low - 0x18f: 0x8502, // id - 0x190: 0x6604, // rows - 0x191: 0x29403, // rev - 0x192: 0x63908, // onunload - 0x193: 0x39e05, // muted - 0x194: 0x35a06, // scoped - 0x195: 0x31602, // dd - 0x196: 0x60602, // dt - 0x197: 0x6720e, // onbeforeunload - 0x199: 0x2070a, // annotation - 0x19a: 0x29408, // reversed - 0x19c: 0x11204, // type - 0x19d: 0x57d07, // onpause - 0x19e: 0xd604, // kind - 0x19f: 0x4c004, // data - 0x1a0: 0x4ff07, // noshade - 0x1a3: 0x17505, // rules - 0x1a4: 0x12308, // optgroup - 0x1a5: 0x202, // br - 0x1a7: 0x1, // a - 0x1a8: 0x51d0a, // onmouseout - 0x1aa: 0x54a09, // onoffline - 0x1ab: 0x6410e, // onvolumechange - 0x1ae: 0x61e03, // sub - 0x1b3: 0x29c03, // for - 0x1b5: 0x8b08, // required - 0x1b6: 0x5b108, // progress - 0x1b7: 0x14106, // usemap - 0x1b8: 0x7f06, // canvas - 0x1b9: 0x4a804, // icon - 0x1bb: 0x1c103, // rtc - 0x1bc: 0x8305, // aside - 0x1bd: 0x2ee04, // time - 0x1be: 0x4060b, // ondragstart - 0x1c0: 0x27c0a, // figcaption - 0x1c1: 0xaf04, // href - 0x1c2: 0x33206, // iframe - 0x1c3: 0x18609, // oncanplay - 0x1c4: 0x6904, // span - 0x1c5: 0x34f03, // pre - 0x1c6: 0x6c07, // noembed - 0x1c8: 0x5e408, // onseeked - 0x1c9: 0x4d304, // meta - 0x1ca: 0x32402, // h2 - 0x1cb: 0x3a808, // seamless - 0x1cc: 0xab03, // dfn - 0x1cd: 0x15704, // axis - 0x1cf: 0x3e60b, // ondragenter - 0x1d0: 0x18f02, // th - 0x1d1: 0x4650c, // onhashchange - 0x1d2: 0xb304, // lang - 0x1d3: 0x44507, // onfocus - 0x1d5: 0x24f04, // size - 0x1d8: 0x12e0c, // autocomplete - 0x1d9: 0xaf08, // hreflang - 0x1da: 0x9804, // samp - 0x1de: 0x19903, // col - 0x1df: 0x10b03, // div - 0x1e0: 0x25308, // sortable - 0x1e1: 0x7203, // del - 0x1e3: 0x3a307, // onclose - 0x1e6: 0xd907, // dirname - 0x1e8: 0x1c307, // classid - 0x1e9: 0x34f07, // preload - 0x1ea: 0x4d908, // tabindex - 0x1eb: 0x60802, // h5 - 0x1ec: 0x5d908, // onscroll - 0x1ed: 0x4a90f, // contenteditable - 0x1ee: 0x4ec09, // onmessage - 0x1ef: 0x4, // abbr - 0x1f0: 0x15907, // isindex - 0x1f1: 0x6a103, // sup - 0x1f3: 0x24b08, // noresize - 0x1f5: 0x59c09, // onplaying - 0x1f6: 0x4409, // accesskey - 0x1fa: 0xc01, // p - 0x1fb: 0x43707, // onended - 0x1fc: 0x5ff06, // onshow - 0x1fe: 0xad06, // nohref -} diff --git a/vendor/github.com/tdewolff/parse/html/hash_test.go b/vendor/github.com/tdewolff/parse/html/hash_test.go deleted file mode 100644 index c905ba3..0000000 --- a/vendor/github.com/tdewolff/parse/html/hash_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package html // import "github.com/tdewolff/parse/html" - -import ( - "bytes" - "testing" - - "github.com/tdewolff/test" -) - -func TestHashTable(t *testing.T) { - test.T(t, ToHash([]byte("address")), Address, "'address' must resolve to Address") - test.T(t, Address.String(), "address") - test.T(t, Accept_Charset.String(), "accept-charset") - test.T(t, ToHash([]byte("")), Hash(0), "empty string must resolve to zero") - test.T(t, Hash(0xffffff).String(), "") - test.T(t, ToHash([]byte("iter")), Hash(0), "'iter' must resolve to zero") - test.T(t, ToHash([]byte("test")), Hash(0), "'test' must resolve to zero") -} - -//////////////////////////////////////////////////////////////// - -var result int - -// naive scenario -func BenchmarkCompareBytes(b *testing.B) { - var r int - val := []byte("span") - for n := 0; n < b.N; n++ { - if bytes.Equal(val, []byte("span")) { - r++ - } - } - result = r -} - -// using-atoms scenario -func BenchmarkFindAndCompareAtom(b *testing.B) { - var r int - val := []byte("span") - for n := 0; n < b.N; n++ { - if ToHash(val) == Span { - r++ - } - } - result = r -} - -// using-atoms worst-case scenario -func BenchmarkFindAtomCompareBytes(b *testing.B) { - var r int - val := []byte("zzzz") - for n := 0; n < b.N; n++ { - if h := ToHash(val); h == 0 && bytes.Equal(val, []byte("zzzz")) { - r++ - } - } - result = r -} diff --git a/vendor/github.com/tdewolff/parse/html/lex.go b/vendor/github.com/tdewolff/parse/html/lex.go deleted file mode 100644 index b191247..0000000 --- a/vendor/github.com/tdewolff/parse/html/lex.go +++ /dev/null @@ -1,498 +0,0 @@ -// Package html is an HTML5 lexer following the specifications at http://www.w3.org/TR/html5/syntax.html. -package html // import "github.com/tdewolff/parse/html" - -import ( - "io" - "strconv" - - "github.com/tdewolff/parse" - "github.com/tdewolff/parse/buffer" -) - -// TokenType determines the type of token, eg. a number or a semicolon. -type TokenType uint32 - -// TokenType values. -const ( - ErrorToken TokenType = iota // extra token when errors occur - CommentToken - DoctypeToken - StartTagToken - StartTagCloseToken - StartTagVoidToken - EndTagToken - AttributeToken - TextToken - SvgToken - MathToken -) - -// String returns the string representation of a TokenType. -func (tt TokenType) String() string { - switch tt { - case ErrorToken: - return "Error" - case CommentToken: - return "Comment" - case DoctypeToken: - return "Doctype" - case StartTagToken: - return "StartTag" - case StartTagCloseToken: - return "StartTagClose" - case StartTagVoidToken: - return "StartTagVoid" - case EndTagToken: - return "EndTag" - case AttributeToken: - return "Attribute" - case TextToken: - return "Text" - case SvgToken: - return "Svg" - case MathToken: - return "Math" - } - return "Invalid(" + strconv.Itoa(int(tt)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// Lexer is the state for the lexer. -type Lexer struct { - r *buffer.Lexer - err error - - rawTag Hash - inTag bool - - text []byte - attrVal []byte -} - -// NewLexer returns a new Lexer for a given io.Reader. -func NewLexer(r io.Reader) *Lexer { - return &Lexer{ - r: buffer.NewLexer(r), - } -} - -// Err returns the error encountered during lexing, this is often io.EOF but also other errors can be returned. -func (l *Lexer) Err() error { - if l.err != nil { - return l.err - } - return l.r.Err() -} - -// Restore restores the NULL byte at the end of the buffer. -func (l *Lexer) Restore() { - l.r.Restore() -} - -// Next returns the next Token. It returns ErrorToken when an error was encountered. Using Err() one can retrieve the error message. -func (l *Lexer) Next() (TokenType, []byte) { - l.text = nil - var c byte - if l.inTag { - l.attrVal = nil - for { // before attribute name state - if c = l.r.Peek(0); c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' { - l.r.Move(1) - continue - } - break - } - if c == 0 && l.r.Err() != nil { - return ErrorToken, nil - } else if c != '>' && (c != '/' || l.r.Peek(1) != '>') { - return AttributeToken, l.shiftAttribute() - } - start := l.r.Pos() - l.inTag = false - if c == '/' { - l.r.Move(2) - l.text = l.r.Lexeme()[start:] - return StartTagVoidToken, l.r.Shift() - } - l.r.Move(1) - l.text = l.r.Lexeme()[start:] - return StartTagCloseToken, l.r.Shift() - } - - if l.rawTag != 0 { - if rawText := l.shiftRawText(); len(rawText) > 0 { - l.rawTag = 0 - return TextToken, rawText - } - l.rawTag = 0 - } - - for { - c = l.r.Peek(0) - if c == '<' { - c = l.r.Peek(1) - isEndTag := c == '/' && l.r.Peek(2) != '>' && (l.r.Peek(2) != 0 || l.r.PeekErr(2) == nil) - if l.r.Pos() > 0 { - if isEndTag || 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '!' || c == '?' { - // return currently buffered texttoken so that we can return tag next iteration - return TextToken, l.r.Shift() - } - } else if isEndTag { - l.r.Move(2) - // only endtags that are not followed by > or EOF arrive here - if c = l.r.Peek(0); !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { - return CommentToken, l.shiftBogusComment() - } - return EndTagToken, l.shiftEndTag() - } else if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' { - l.r.Move(1) - l.inTag = true - return l.shiftStartTag() - } else if c == '!' { - l.r.Move(2) - return l.readMarkup() - } else if c == '?' { - l.r.Move(1) - return CommentToken, l.shiftBogusComment() - } - } else if c == 0 && l.r.Err() != nil { - if l.r.Pos() > 0 { - return TextToken, l.r.Shift() - } - return ErrorToken, nil - } - l.r.Move(1) - } -} - -// Text returns the textual representation of a token. This excludes delimiters and additional leading/trailing characters. -func (l *Lexer) Text() []byte { - return l.text -} - -// AttrVal returns the attribute value when an AttributeToken was returned from Next. -func (l *Lexer) AttrVal() []byte { - return l.attrVal -} - -//////////////////////////////////////////////////////////////// - -// The following functions follow the specifications at http://www.w3.org/html/wg/drafts/html/master/syntax.html - -func (l *Lexer) shiftRawText() []byte { - if l.rawTag == Plaintext { - for { - if l.r.Peek(0) == 0 && l.r.Err() != nil { - return l.r.Shift() - } - l.r.Move(1) - } - } else { // RCDATA, RAWTEXT and SCRIPT - for { - c := l.r.Peek(0) - if c == '<' { - if l.r.Peek(1) == '/' { - mark := l.r.Pos() - l.r.Move(2) - for { - if c = l.r.Peek(0); !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { - break - } - l.r.Move(1) - } - if h := ToHash(parse.ToLower(parse.Copy(l.r.Lexeme()[mark+2:]))); h == l.rawTag { // copy so that ToLower doesn't change the case of the underlying slice - l.r.Rewind(mark) - return l.r.Shift() - } - } else if l.rawTag == Script && l.r.Peek(1) == '!' && l.r.Peek(2) == '-' && l.r.Peek(3) == '-' { - l.r.Move(4) - inScript := false - for { - c := l.r.Peek(0) - if c == '-' && l.r.Peek(1) == '-' && l.r.Peek(2) == '>' { - l.r.Move(3) - break - } else if c == '<' { - isEnd := l.r.Peek(1) == '/' - if isEnd { - l.r.Move(2) - } else { - l.r.Move(1) - } - mark := l.r.Pos() - for { - if c = l.r.Peek(0); !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { - break - } - l.r.Move(1) - } - if h := ToHash(parse.ToLower(parse.Copy(l.r.Lexeme()[mark:]))); h == Script { // copy so that ToLower doesn't change the case of the underlying slice - if !isEnd { - inScript = true - } else { - if !inScript { - l.r.Rewind(mark - 2) - return l.r.Shift() - } - inScript = false - } - } - } else if c == 0 && l.r.Err() != nil { - return l.r.Shift() - } else { - l.r.Move(1) - } - } - } else { - l.r.Move(1) - } - } else if c == 0 && l.r.Err() != nil { - return l.r.Shift() - } else { - l.r.Move(1) - } - } - } -} - -func (l *Lexer) readMarkup() (TokenType, []byte) { - if l.at('-', '-') { - l.r.Move(2) - for { - if l.r.Peek(0) == 0 && l.r.Err() != nil { - return CommentToken, l.r.Shift() - } else if l.at('-', '-', '>') { - l.text = l.r.Lexeme()[4:] - l.r.Move(3) - return CommentToken, l.r.Shift() - } else if l.at('-', '-', '!', '>') { - l.text = l.r.Lexeme()[4:] - l.r.Move(4) - return CommentToken, l.r.Shift() - } - l.r.Move(1) - } - } else if l.at('[', 'C', 'D', 'A', 'T', 'A', '[') { - l.r.Move(7) - for { - if l.r.Peek(0) == 0 && l.r.Err() != nil { - return TextToken, l.r.Shift() - } else if l.at(']', ']', '>') { - l.r.Move(3) - return TextToken, l.r.Shift() - } - l.r.Move(1) - } - } else { - if l.atCaseInsensitive('d', 'o', 'c', 't', 'y', 'p', 'e') { - l.r.Move(7) - if l.r.Peek(0) == ' ' { - l.r.Move(1) - } - for { - if c := l.r.Peek(0); c == '>' || c == 0 && l.r.Err() != nil { - l.text = l.r.Lexeme()[9:] - if c == '>' { - l.r.Move(1) - } - return DoctypeToken, l.r.Shift() - } - l.r.Move(1) - } - } - } - return CommentToken, l.shiftBogusComment() -} - -func (l *Lexer) shiftBogusComment() []byte { - for { - c := l.r.Peek(0) - if c == '>' { - l.text = l.r.Lexeme()[2:] - l.r.Move(1) - return l.r.Shift() - } else if c == 0 && l.r.Err() != nil { - l.text = l.r.Lexeme()[2:] - return l.r.Shift() - } - l.r.Move(1) - } -} - -func (l *Lexer) shiftStartTag() (TokenType, []byte) { - for { - if c := l.r.Peek(0); c == ' ' || c == '>' || c == '/' && l.r.Peek(1) == '>' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 && l.r.Err() != nil { - break - } - l.r.Move(1) - } - l.text = parse.ToLower(l.r.Lexeme()[1:]) - if h := ToHash(l.text); h == Textarea || h == Title || h == Style || h == Xmp || h == Iframe || h == Script || h == Plaintext || h == Svg || h == Math { - if h == Svg || h == Math { - data := l.shiftXml(h) - if l.err != nil { - return ErrorToken, nil - } - - l.inTag = false - if h == Svg { - return SvgToken, data - } else { - return MathToken, data - } - } - l.rawTag = h - } - return StartTagToken, l.r.Shift() -} - -func (l *Lexer) shiftAttribute() []byte { - nameStart := l.r.Pos() - var c byte - for { // attribute name state - if c = l.r.Peek(0); c == ' ' || c == '=' || c == '>' || c == '/' && l.r.Peek(1) == '>' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 && l.r.Err() != nil { - break - } - l.r.Move(1) - } - nameEnd := l.r.Pos() - for { // after attribute name state - if c = l.r.Peek(0); c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' { - l.r.Move(1) - continue - } - break - } - if c == '=' { - l.r.Move(1) - for { // before attribute value state - if c = l.r.Peek(0); c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' { - l.r.Move(1) - continue - } - break - } - attrPos := l.r.Pos() - delim := c - if delim == '"' || delim == '\'' { // attribute value single- and double-quoted state - l.r.Move(1) - for { - c := l.r.Peek(0) - if c == delim { - l.r.Move(1) - break - } else if c == 0 && l.r.Err() != nil { - break - } - l.r.Move(1) - } - } else { // attribute value unquoted state - for { - if c := l.r.Peek(0); c == ' ' || c == '>' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == 0 && l.r.Err() != nil { - break - } - l.r.Move(1) - } - } - l.attrVal = l.r.Lexeme()[attrPos:] - } else { - l.r.Rewind(nameEnd) - l.attrVal = nil - } - l.text = parse.ToLower(l.r.Lexeme()[nameStart:nameEnd]) - return l.r.Shift() -} - -func (l *Lexer) shiftEndTag() []byte { - for { - c := l.r.Peek(0) - if c == '>' { - l.text = l.r.Lexeme()[2:] - l.r.Move(1) - break - } else if c == 0 && l.r.Err() != nil { - l.text = l.r.Lexeme()[2:] - break - } - l.r.Move(1) - } - - end := len(l.text) - for end > 0 { - if c := l.text[end-1]; c == ' ' || c == '\t' || c == '\n' || c == '\r' { - end-- - continue - } - break - } - l.text = l.text[:end] - return parse.ToLower(l.r.Shift()) -} - -// shiftXml parses the content of a svg or math tag according to the XML 1.1 specifications, including the tag itself. -// So far we have already parsed `<svg` or `<math`. -func (l *Lexer) shiftXml(rawTag Hash) []byte { - inQuote := false - for { - c := l.r.Peek(0) - if c == '"' { - inQuote = !inQuote - l.r.Move(1) - } else if c == '<' && !inQuote && l.r.Peek(1) == '/' { - mark := l.r.Pos() - l.r.Move(2) - for { - if c = l.r.Peek(0); !('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') { - break - } - l.r.Move(1) - } - if h := ToHash(parse.ToLower(parse.Copy(l.r.Lexeme()[mark+2:]))); h == rawTag { // copy so that ToLower doesn't change the case of the underlying slice - break - } - } else if c == 0 { - if l.r.Err() == nil { - l.err = parse.NewErrorLexer("unexpected null character", l.r) - } - return l.r.Shift() - } else { - l.r.Move(1) - } - } - - for { - c := l.r.Peek(0) - if c == '>' { - l.r.Move(1) - break - } else if c == 0 { - if l.r.Err() == nil { - l.err = parse.NewErrorLexer("unexpected null character", l.r) - } - return l.r.Shift() - } - l.r.Move(1) - } - return l.r.Shift() -} - -//////////////////////////////////////////////////////////////// - -func (l *Lexer) at(b ...byte) bool { - for i, c := range b { - if l.r.Peek(i) != c { - return false - } - } - return true -} - -func (l *Lexer) atCaseInsensitive(b ...byte) bool { - for i, c := range b { - if l.r.Peek(i) != c && (l.r.Peek(i)+('a'-'A')) != c { - return false - } - } - return true -} diff --git a/vendor/github.com/tdewolff/parse/html/lex_test.go b/vendor/github.com/tdewolff/parse/html/lex_test.go deleted file mode 100644 index 51d9cfa..0000000 --- a/vendor/github.com/tdewolff/parse/html/lex_test.go +++ /dev/null @@ -1,283 +0,0 @@ -package html // import "github.com/tdewolff/parse/html" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/parse" - "github.com/tdewolff/test" -) - -type TTs []TokenType - -func TestTokens(t *testing.T) { - var tokenTests = []struct { - html string - expected []TokenType - }{ - {"<html></html>", TTs{StartTagToken, StartTagCloseToken, EndTagToken}}, - {"<img/>", TTs{StartTagToken, StartTagVoidToken}}, - {"<!-- comment -->", TTs{CommentToken}}, - {"<!-- comment --!>", TTs{CommentToken}}, - {"<p>text</p>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<input type='button'/>", TTs{StartTagToken, AttributeToken, StartTagVoidToken}}, - {"<input type='button' value=''/>", TTs{StartTagToken, AttributeToken, AttributeToken, StartTagVoidToken}}, - {"<input type='=/>' \r\n\t\f value=\"'\" name=x checked />", TTs{StartTagToken, AttributeToken, AttributeToken, AttributeToken, AttributeToken, StartTagVoidToken}}, - {"<!doctype>", TTs{DoctypeToken}}, - {"<!doctype html>", TTs{DoctypeToken}}, - {"<?bogus>", TTs{CommentToken}}, - {"</0bogus>", TTs{CommentToken}}, - {"<!bogus>", TTs{CommentToken}}, - {"< ", TTs{TextToken}}, - {"</", TTs{TextToken}}, - - // raw tags - {"<title><p></p></title>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<TITLE><p></p></TITLE>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<plaintext></plaintext>", TTs{StartTagToken, StartTagCloseToken, TextToken}}, - {"<script></script>", TTs{StartTagToken, StartTagCloseToken, EndTagToken}}, - {"<script>var x='</script>';</script>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken, TextToken, EndTagToken}}, - {"<script><!--var x='</script>';--></script>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken, TextToken, EndTagToken}}, - {"<script><!--var x='<script></script>';--></script>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<script><!--var x='<script>';--></script>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<![CDATA[ test ]]>", TTs{TextToken}}, - {"<svg>text</svg>", TTs{SvgToken}}, - {"<math>text</math>", TTs{MathToken}}, - {`<svg>text<x a="</svg>"></x></svg>`, TTs{SvgToken}}, - {"<a><svg>text</svg></a>", TTs{StartTagToken, StartTagCloseToken, SvgToken, EndTagToken}}, - - // early endings - {"<!-- comment", TTs{CommentToken}}, - {"<? bogus comment", TTs{CommentToken}}, - {"<foo", TTs{StartTagToken}}, - {"</foo", TTs{EndTagToken}}, - {"<foo x", TTs{StartTagToken, AttributeToken}}, - {"<foo x=", TTs{StartTagToken, AttributeToken}}, - {"<foo x='", TTs{StartTagToken, AttributeToken}}, - {"<foo x=''", TTs{StartTagToken, AttributeToken}}, - {"<!DOCTYPE note SYSTEM", TTs{DoctypeToken}}, - {"<![CDATA[ test", TTs{TextToken}}, - {"<script>", TTs{StartTagToken, StartTagCloseToken}}, - {"<script><!--", TTs{StartTagToken, StartTagCloseToken, TextToken}}, - {"<script><!--var x='<script></script>';-->", TTs{StartTagToken, StartTagCloseToken, TextToken}}, - - // NULL - {"foo\x00bar", TTs{TextToken}}, - {"<\x00foo>", TTs{TextToken}}, - {"<foo\x00>", TTs{StartTagToken, StartTagCloseToken}}, - {"</\x00bogus>", TTs{CommentToken}}, - {"</foo\x00>", TTs{EndTagToken}}, - {"<plaintext>\x00</plaintext>", TTs{StartTagToken, StartTagCloseToken, TextToken}}, - {"<script>\x00</script>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<!--\x00-->", TTs{CommentToken}}, - {"<![CDATA[\x00]]>", TTs{TextToken}}, - {"<!doctype\x00>", TTs{DoctypeToken}}, - {"<?bogus\x00>", TTs{CommentToken}}, - {"<?bogus\x00>", TTs{CommentToken}}, - - // go-fuzz - {"</>", TTs{TextToken}}, - } - for _, tt := range tokenTests { - t.Run(tt.html, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.html)) - i := 0 - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } - test.That(t, i < len(tt.expected), "index", i, "must not exceed expected token types size", len(tt.expected)) - if i < len(tt.expected) { - test.T(t, token, tt.expected[i], "token types must match") - } - i++ - } - }) - } - - test.T(t, TokenType(100).String(), "Invalid(100)") -} - -func TestTags(t *testing.T) { - var tagTests = []struct { - html string - expected string - }{ - {"<foo:bar.qux-norf/>", "foo:bar.qux-norf"}, - {"<foo?bar/qux>", "foo?bar/qux"}, - {"<!DOCTYPE note SYSTEM \"Note.dtd\">", " note SYSTEM \"Note.dtd\""}, - {"</foo >", "foo"}, - - // early endings - {"<foo ", "foo"}, - } - for _, tt := range tagTests { - t.Run(tt.html, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.html)) - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.Fail(t, "when error occurred we must be at the end") - break - } else if token == StartTagToken || token == EndTagToken || token == DoctypeToken { - test.String(t, string(l.Text()), tt.expected) - break - } - } - }) - } -} - -func TestAttributes(t *testing.T) { - var attributeTests = []struct { - attr string - expected []string - }{ - {"<foo a=\"b\" />", []string{"a", "\"b\""}}, - {"<foo \nchecked \r\n value\r=\t'=/>\"' />", []string{"checked", "", "value", "'=/>\"'"}}, - {"<foo bar=\" a \n\t\r b \" />", []string{"bar", "\" a \n\t\r b \""}}, - {"<foo a/>", []string{"a", ""}}, - {"<foo /=/>", []string{"/", "/"}}, - - // early endings - {"<foo x", []string{"x", ""}}, - {"<foo x=", []string{"x", ""}}, - {"<foo x='", []string{"x", "'"}}, - - // NULL - {"<foo \x00>", []string{"\x00", ""}}, - {"<foo \x00=\x00>", []string{"\x00", "\x00"}}, - {"<foo \x00='\x00'>", []string{"\x00", "'\x00'"}}, - } - for _, tt := range attributeTests { - t.Run(tt.attr, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.attr)) - i := 0 - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } else if token == AttributeToken { - test.That(t, i+1 < len(tt.expected), "index", i+1, "must not exceed expected attributes size", len(tt.expected)) - if i+1 < len(tt.expected) { - test.String(t, string(l.Text()), tt.expected[i], "attribute keys must match") - test.String(t, string(l.AttrVal()), tt.expected[i+1], "attribute keys must match") - i += 2 - } - } - } - }) - } -} - -func TestErrors(t *testing.T) { - var errorTests = []struct { - html string - col int - }{ - {"<svg>\x00</svg>", 6}, - {"<svg></svg\x00>", 11}, - } - for _, tt := range errorTests { - t.Run(tt.html, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.html)) - for { - token, _ := l.Next() - if token == ErrorToken { - if tt.col == 0 { - test.T(t, l.Err(), io.EOF) - } else if perr, ok := l.Err().(*parse.Error); ok { - _, col, _ := perr.Position() - test.T(t, col, tt.col) - } else { - test.Fail(t, "bad error:", l.Err()) - } - break - } - } - }) - } -} - -//////////////////////////////////////////////////////////////// - -var J int -var ss = [][]byte{ - []byte(" style"), - []byte("style"), - []byte(" \r\n\tstyle"), - []byte(" style"), - []byte(" x"), - []byte("x"), -} - -func BenchmarkWhitespace1(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, s := range ss { - j := 0 - for { - if c := s[j]; c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' { - j++ - } else { - break - } - } - J += j - } - } -} - -func BenchmarkWhitespace2(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, s := range ss { - j := 0 - for { - if c := s[j]; c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' { - j++ - continue - } - break - } - J += j - } - } -} - -func BenchmarkWhitespace3(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, s := range ss { - j := 0 - for { - if c := s[j]; c != ' ' && c != '\t' && c != '\n' && c != '\r' && c != '\f' { - break - } - j++ - } - J += j - } - } -} - -//////////////////////////////////////////////////////////////// - -func ExampleNewLexer() { - l := NewLexer(bytes.NewBufferString("<span class='user'>John Doe</span>")) - out := "" - for { - tt, data := l.Next() - if tt == ErrorToken { - break - } - out += string(data) - } - fmt.Println(out) - // Output: <span class='user'>John Doe</span> -} diff --git a/vendor/github.com/tdewolff/parse/html/util.go b/vendor/github.com/tdewolff/parse/html/util.go deleted file mode 100644 index c8c3aab..0000000 --- a/vendor/github.com/tdewolff/parse/html/util.go +++ /dev/null @@ -1,129 +0,0 @@ -package html // import "github.com/tdewolff/parse/html" - -import "github.com/tdewolff/parse" - -var ( - singleQuoteEntityBytes = []byte("'") - doubleQuoteEntityBytes = []byte(""") -) - -var charTable = [256]bool{ - // ASCII - false, false, false, false, false, false, false, false, - false, true, true, true, true, true, false, false, // tab, new line, vertical tab, form feed, carriage return - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - true, false, true, false, false, false, true, true, // space, ", &, ' - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, true, true, true, false, // <, =, > - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - true, false, false, false, false, false, false, false, // ` - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - // non-ASCII - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, -} - -// EscapeAttrVal returns the escaped attribute value bytes without quotes. -func EscapeAttrVal(buf *[]byte, orig, b []byte) []byte { - singles := 0 - doubles := 0 - unquoted := true - entities := false - for i, c := range b { - if charTable[c] { - if c == '&' { - entities = true - if quote, n := parse.QuoteEntity(b[i:]); n > 0 { - if quote == '"' { - unquoted = false - doubles++ - } else { - unquoted = false - singles++ - } - } - } else { - unquoted = false - if c == '"' { - doubles++ - } else if c == '\'' { - singles++ - } - } - } - } - if unquoted { - return b - } else if !entities && len(orig) == len(b)+2 && (singles == 0 && orig[0] == '\'' || doubles == 0 && orig[0] == '"') { - return orig - } - - n := len(b) + 2 - var quote byte - var escapedQuote []byte - if doubles > singles { - n += singles * 4 - quote = '\'' - escapedQuote = singleQuoteEntityBytes - } else { - n += doubles * 4 - quote = '"' - escapedQuote = doubleQuoteEntityBytes - } - if n > cap(*buf) { - *buf = make([]byte, 0, n) // maximum size, not actual size - } - t := (*buf)[:n] // maximum size, not actual size - t[0] = quote - j := 1 - start := 0 - for i, c := range b { - if c == '&' { - if entityQuote, n := parse.QuoteEntity(b[i:]); n > 0 { - j += copy(t[j:], b[start:i]) - if entityQuote != quote { - t[j] = entityQuote - j++ - } else { - j += copy(t[j:], escapedQuote) - } - start = i + n - } - } else if c == quote { - j += copy(t[j:], b[start:i]) - j += copy(t[j:], escapedQuote) - start = i + 1 - } - } - j += copy(t[j:], b[start:]) - t[j] = quote - return t[:j+1] -} diff --git a/vendor/github.com/tdewolff/parse/html/util_test.go b/vendor/github.com/tdewolff/parse/html/util_test.go deleted file mode 100644 index 3722a08..0000000 --- a/vendor/github.com/tdewolff/parse/html/util_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package html // import "github.com/tdewolff/parse/html" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestEscapeAttrVal(t *testing.T) { - var escapeAttrValTests = []struct { - attrVal string - expected string - }{ - {"xyz", "xyz"}, - {"", ""}, - {"x&z", "x&z"}, - {"x/z", "x/z"}, - {"x'z", "\"x'z\""}, - {"x\"z", "'x\"z'"}, - {"'x\"z'", "'x\"z'"}, - {"'x'\"'z'", "\"x'"'z\""}, - {"\"x"'"z\"", "'x\"'\"z'"}, - {"\"x'z\"", "\"x'z\""}, - {"'x"z'", "'x\"z'"}, - {"'x\">'", "'x\">'"}, - {"You're encouraged to log in; however, it's not mandatory. [o]", "\"You're encouraged to log in; however, it's not mandatory. [o]\""}, - {"a'b=\"\"", "'a'b=\"\"'"}, - {"x<z", "\"x<z\""}, - {"'x\"'\"z'", "'x\"'\"z'"}, - } - var buf []byte - for _, tt := range escapeAttrValTests { - t.Run(tt.attrVal, func(t *testing.T) { - b := []byte(tt.attrVal) - orig := b - if len(b) > 1 && (b[0] == '"' || b[0] == '\'') && b[0] == b[len(b)-1] { - b = b[1 : len(b)-1] - } - val := EscapeAttrVal(&buf, orig, []byte(b)) - test.String(t, string(val), tt.expected) - }) - } -} diff --git a/vendor/github.com/tdewolff/parse/js/README.md b/vendor/github.com/tdewolff/parse/js/README.md deleted file mode 100644 index 7b06d7c..0000000 --- a/vendor/github.com/tdewolff/parse/js/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# JS [![GoDoc](http://godoc.org/github.com/tdewolff/parse/js?status.svg)](http://godoc.org/github.com/tdewolff/parse/js) [![GoCover](http://gocover.io/_badge/github.com/tdewolff/parse/js)](http://gocover.io/github.com/tdewolff/parse/js) - -This package is a JS lexer (ECMA-262, edition 6.0) written in [Go][1]. It follows the specification at [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/6.0/). The lexer takes an io.Reader and converts it into tokens until the EOF. - -## Installation -Run the following command - - go get github.com/tdewolff/parse/js - -or add the following import and run project with `go get` - - import "github.com/tdewolff/parse/js" - -## Lexer -### Usage -The following initializes a new Lexer with io.Reader `r`: -``` go -l := js.NewLexer(r) -``` - -To tokenize until EOF an error, use: -``` go -for { - tt, text := l.Next() - switch tt { - case js.ErrorToken: - // error or EOF set in l.Err() - return - // ... - } -} -``` - -All tokens (see [ECMAScript Language Specification](http://www.ecma-international.org/ecma-262/6.0/)): -``` go -ErrorToken TokenType = iota // extra token when errors occur -UnknownToken // extra token when no token can be matched -WhitespaceToken // space \t \v \f -LineTerminatorToken // \r \n \r\n -CommentToken -IdentifierToken // also: null true false -PunctuatorToken /* { } ( ) [ ] . ; , < > <= >= == != === !== + - * % ++ -- << >> - >>> & | ^ ! ~ && || ? : = += -= *= %= <<= >>= >>>= &= |= ^= / /= => */ -NumericToken -StringToken -RegexpToken -TemplateToken -``` - -### Quirks -Because the ECMAScript specification for `PunctuatorToken` (of which the `/` and `/=` symbols) and `RegexpToken` depends on a parser state to differentiate between the two, the lexer (to remain modular) uses different rules. It aims to correctly disambiguate contexts and returns `RegexpToken` or `PunctuatorToken` where appropriate with only few exceptions which don't make much sense in runtime and so don't happen in a real-world code: function literal division (`x = function y(){} / z`) and object literal division (`x = {y:1} / z`). - -Another interesting case introduced by ES2015 is `yield` operator in function generators vs `yield` as an identifier in regular functions. This was done for backward compatibility, but is very hard to disambiguate correctly on a lexer level without essentially implementing entire parsing spec as a state machine and hurting performance, code readability and maintainability, so, instead, `yield` is just always assumed to be an operator. In combination with above paragraph, this means that, for example, `yield /x/i` will be always parsed as `yield`-ing regular expression and not as `yield` identifier divided by `x` and then `i`. There is no evidence though that this pattern occurs in any popular libraries. - -### Examples -``` go -package main - -import ( - "os" - - "github.com/tdewolff/parse/js" -) - -// Tokenize JS from stdin. -func main() { - l := js.NewLexer(os.Stdin) - for { - tt, text := l.Next() - switch tt { - case js.ErrorToken: - if l.Err() != io.EOF { - fmt.Println("Error on line", l.Line(), ":", l.Err()) - } - return - case js.IdentifierToken: - fmt.Println("Identifier", string(text)) - case js.NumericToken: - fmt.Println("Numeric", string(text)) - // ... - } - } -} -``` - -## License -Released under the [MIT license](https://github.com/tdewolff/parse/blob/master/LICENSE.md). - -[1]: http://golang.org/ "Go Language" diff --git a/vendor/github.com/tdewolff/parse/js/hash.go b/vendor/github.com/tdewolff/parse/js/hash.go deleted file mode 100644 index 3de86b2..0000000 --- a/vendor/github.com/tdewolff/parse/js/hash.go +++ /dev/null @@ -1,156 +0,0 @@ -package js - -// generated by hasher -file hash.go -type Hash; DO NOT EDIT, except for adding more constants to the list and rerun go generate - -// uses github.com/tdewolff/hasher -//go:generate hasher -type=Hash -file=hash.go - -// Hash defines perfect hashes for a predefined list of strings -type Hash uint32 - -// Unique hash definitions to be used instead of strings -const ( - Break Hash = 0x5 // break - Case Hash = 0x3404 // case - Catch Hash = 0xba05 // catch - Class Hash = 0x505 // class - Const Hash = 0x2c05 // const - Continue Hash = 0x3e08 // continue - Debugger Hash = 0x8408 // debugger - Default Hash = 0xab07 // default - Delete Hash = 0xcd06 // delete - Do Hash = 0x4c02 // do - Else Hash = 0x3704 // else - Enum Hash = 0x3a04 // enum - Export Hash = 0x1806 // export - Extends Hash = 0x4507 // extends - False Hash = 0x5a05 // false - Finally Hash = 0x7a07 // finally - For Hash = 0xc403 // for - Function Hash = 0x4e08 // function - If Hash = 0x5902 // if - Implements Hash = 0x5f0a // implements - Import Hash = 0x6906 // import - In Hash = 0x4202 // in - Instanceof Hash = 0x710a // instanceof - Interface Hash = 0x8c09 // interface - Let Hash = 0xcf03 // let - New Hash = 0x1203 // new - Null Hash = 0x5504 // null - Package Hash = 0x9507 // package - Private Hash = 0x9c07 // private - Protected Hash = 0xa309 // protected - Public Hash = 0xb506 // public - Return Hash = 0xd06 // return - Static Hash = 0x2f06 // static - Super Hash = 0x905 // super - Switch Hash = 0x2606 // switch - This Hash = 0x2304 // this - Throw Hash = 0x1d05 // throw - True Hash = 0xb104 // true - Try Hash = 0x6e03 // try - Typeof Hash = 0xbf06 // typeof - Var Hash = 0xc703 // var - Void Hash = 0xca04 // void - While Hash = 0x1405 // while - With Hash = 0x2104 // with - Yield Hash = 0x8005 // yield -) - -// String returns the hash' name. -func (i Hash) String() string { - start := uint32(i >> 8) - n := uint32(i & 0xff) - if start+n > uint32(len(_Hash_text)) { - return "" - } - return _Hash_text[start : start+n] -} - -// ToHash returns the hash whose name is s. It returns zero if there is no -// such hash. It is case sensitive. -func ToHash(s []byte) Hash { - if len(s) == 0 || len(s) > _Hash_maxLen { - return 0 - } - h := uint32(_Hash_hash0) - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - goto NEXT - } - } - return i - } -NEXT: - if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - return 0 - } - } - return i - } - return 0 -} - -const _Hash_hash0 = 0x9acb0442 -const _Hash_maxLen = 10 -const _Hash_text = "breakclassupereturnewhilexporthrowithiswitchconstaticaselsen" + - "umcontinuextendsdofunctionullifalseimplementsimportryinstanc" + - "eofinallyieldebuggerinterfacepackageprivateprotectedefaultru" + - "epublicatchtypeoforvarvoidelete" - -var _Hash_table = [1 << 6]Hash{ - 0x0: 0x2f06, // static - 0x1: 0x9c07, // private - 0x3: 0xb104, // true - 0x6: 0x5a05, // false - 0x7: 0x4c02, // do - 0x9: 0x2c05, // const - 0xa: 0x2606, // switch - 0xb: 0x6e03, // try - 0xc: 0x1203, // new - 0xd: 0x4202, // in - 0xf: 0x8005, // yield - 0x10: 0x5f0a, // implements - 0x11: 0xc403, // for - 0x12: 0x505, // class - 0x13: 0x3a04, // enum - 0x16: 0xc703, // var - 0x17: 0x5902, // if - 0x19: 0xcf03, // let - 0x1a: 0x9507, // package - 0x1b: 0xca04, // void - 0x1c: 0xcd06, // delete - 0x1f: 0x5504, // null - 0x20: 0x1806, // export - 0x21: 0xd06, // return - 0x23: 0x4507, // extends - 0x25: 0x2304, // this - 0x26: 0x905, // super - 0x27: 0x1405, // while - 0x29: 0x5, // break - 0x2b: 0x3e08, // continue - 0x2e: 0x3404, // case - 0x2f: 0xab07, // default - 0x31: 0x8408, // debugger - 0x32: 0x1d05, // throw - 0x33: 0xbf06, // typeof - 0x34: 0x2104, // with - 0x35: 0xba05, // catch - 0x36: 0x4e08, // function - 0x37: 0x710a, // instanceof - 0x38: 0xa309, // protected - 0x39: 0x8c09, // interface - 0x3b: 0xb506, // public - 0x3c: 0x3704, // else - 0x3d: 0x7a07, // finally - 0x3f: 0x6906, // import -} diff --git a/vendor/github.com/tdewolff/parse/js/hash_test.go b/vendor/github.com/tdewolff/parse/js/hash_test.go deleted file mode 100644 index fa6a213..0000000 --- a/vendor/github.com/tdewolff/parse/js/hash_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package js // import "github.com/tdewolff/parse/js" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestHashTable(t *testing.T) { - test.T(t, ToHash([]byte("break")), Break, "'break' must resolve to hash.Break") - test.T(t, ToHash([]byte("var")), Var, "'var' must resolve to hash.Var") - test.T(t, Break.String(), "break") - test.T(t, ToHash([]byte("")), Hash(0), "empty string must resolve to zero") - test.T(t, Hash(0xffffff).String(), "") - test.T(t, ToHash([]byte("breaks")), Hash(0), "'breaks' must resolve to zero") - test.T(t, ToHash([]byte("sdf")), Hash(0), "'sdf' must resolve to zero") - test.T(t, ToHash([]byte("uio")), Hash(0), "'uio' must resolve to zero") -} diff --git a/vendor/github.com/tdewolff/parse/js/lex.go b/vendor/github.com/tdewolff/parse/js/lex.go deleted file mode 100644 index ce4e1d5..0000000 --- a/vendor/github.com/tdewolff/parse/js/lex.go +++ /dev/null @@ -1,669 +0,0 @@ -// Package js is an ECMAScript5.1 lexer following the specifications at http://www.ecma-international.org/ecma-262/5.1/. -package js // import "github.com/tdewolff/parse/js" - -import ( - "io" - "strconv" - "unicode" - - "github.com/tdewolff/parse/buffer" -) - -var identifierStart = []*unicode.RangeTable{unicode.Lu, unicode.Ll, unicode.Lt, unicode.Lm, unicode.Lo, unicode.Nl, unicode.Other_ID_Start} -var identifierContinue = []*unicode.RangeTable{unicode.Lu, unicode.Ll, unicode.Lt, unicode.Lm, unicode.Lo, unicode.Nl, unicode.Mn, unicode.Mc, unicode.Nd, unicode.Pc, unicode.Other_ID_Continue} - -//////////////////////////////////////////////////////////////// - -// TokenType determines the type of token, eg. a number or a semicolon. -type TokenType uint32 - -// TokenType values. -const ( - ErrorToken TokenType = iota // extra token when errors occur - UnknownToken // extra token when no token can be matched - WhitespaceToken // space \t \v \f - LineTerminatorToken // \r \n \r\n - SingleLineCommentToken - MultiLineCommentToken // token for comments with line terminators (not just any /*block*/) - IdentifierToken - PunctuatorToken /* { } ( ) [ ] . ; , < > <= >= == != === !== + - * % ++ -- << >> - >>> & | ^ ! ~ && || ? : = += -= *= %= <<= >>= >>>= &= |= ^= / /= >= */ - NumericToken - StringToken - RegexpToken - TemplateToken -) - -// TokenState determines a state in which next token should be read -type TokenState uint32 - -// TokenState values -const ( - ExprState TokenState = iota - StmtParensState - SubscriptState - PropNameState -) - -// ParsingContext determines the context in which following token should be parsed. -// This affects parsing regular expressions and template literals. -type ParsingContext uint32 - -// ParsingContext values -const ( - GlobalContext ParsingContext = iota - StmtParensContext - ExprParensContext - BracesContext - TemplateContext -) - -// String returns the string representation of a TokenType. -func (tt TokenType) String() string { - switch tt { - case ErrorToken: - return "Error" - case UnknownToken: - return "Unknown" - case WhitespaceToken: - return "Whitespace" - case LineTerminatorToken: - return "LineTerminator" - case SingleLineCommentToken: - return "SingleLineComment" - case MultiLineCommentToken: - return "MultiLineComment" - case IdentifierToken: - return "Identifier" - case PunctuatorToken: - return "Punctuator" - case NumericToken: - return "Numeric" - case StringToken: - return "String" - case RegexpToken: - return "Regexp" - case TemplateToken: - return "Template" - } - return "Invalid(" + strconv.Itoa(int(tt)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// Lexer is the state for the lexer. -type Lexer struct { - r *buffer.Lexer - stack []ParsingContext - state TokenState - emptyLine bool -} - -// NewLexer returns a new Lexer for a given io.Reader. -func NewLexer(r io.Reader) *Lexer { - return &Lexer{ - r: buffer.NewLexer(r), - stack: make([]ParsingContext, 0, 16), - state: ExprState, - emptyLine: true, - } -} - -func (l *Lexer) enterContext(context ParsingContext) { - l.stack = append(l.stack, context) -} - -func (l *Lexer) leaveContext() ParsingContext { - ctx := GlobalContext - if last := len(l.stack) - 1; last >= 0 { - ctx, l.stack = l.stack[last], l.stack[:last] - } - return ctx -} - -// Err returns the error encountered during lexing, this is often io.EOF but also other errors can be returned. -func (l *Lexer) Err() error { - return l.r.Err() -} - -// Restore restores the NULL byte at the end of the buffer. -func (l *Lexer) Restore() { - l.r.Restore() -} - -// Next returns the next Token. It returns ErrorToken when an error was encountered. Using Err() one can retrieve the error message. -func (l *Lexer) Next() (TokenType, []byte) { - tt := UnknownToken - c := l.r.Peek(0) - switch c { - case '(': - if l.state == StmtParensState { - l.enterContext(StmtParensContext) - } else { - l.enterContext(ExprParensContext) - } - l.state = ExprState - l.r.Move(1) - tt = PunctuatorToken - case ')': - if l.leaveContext() == StmtParensContext { - l.state = ExprState - } else { - l.state = SubscriptState - } - l.r.Move(1) - tt = PunctuatorToken - case '{': - l.enterContext(BracesContext) - l.state = ExprState - l.r.Move(1) - tt = PunctuatorToken - case '}': - if l.leaveContext() == TemplateContext && l.consumeTemplateToken() { - tt = TemplateToken - } else { - // will work incorrectly for objects or functions divided by something, - // but that's an extremely rare case - l.state = ExprState - l.r.Move(1) - tt = PunctuatorToken - } - case ']': - l.state = SubscriptState - l.r.Move(1) - tt = PunctuatorToken - case '[', ';', ',', '~', '?', ':': - l.state = ExprState - l.r.Move(1) - tt = PunctuatorToken - case '<', '>', '=', '!', '+', '-', '*', '%', '&', '|', '^': - if l.consumeHTMLLikeCommentToken() { - return SingleLineCommentToken, l.r.Shift() - } else if l.consumeLongPunctuatorToken() { - l.state = ExprState - tt = PunctuatorToken - } - case '/': - if tt = l.consumeCommentToken(); tt != UnknownToken { - return tt, l.r.Shift() - } else if l.state == ExprState && l.consumeRegexpToken() { - l.state = SubscriptState - tt = RegexpToken - } else if l.consumeLongPunctuatorToken() { - l.state = ExprState - tt = PunctuatorToken - } - case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.': - if l.consumeNumericToken() { - tt = NumericToken - l.state = SubscriptState - } else if c == '.' { - l.state = PropNameState - l.r.Move(1) - tt = PunctuatorToken - } - case '\'', '"': - if l.consumeStringToken() { - l.state = SubscriptState - tt = StringToken - } - case ' ', '\t', '\v', '\f': - l.r.Move(1) - for l.consumeWhitespace() { - } - return WhitespaceToken, l.r.Shift() - case '\n', '\r': - l.r.Move(1) - for l.consumeLineTerminator() { - } - tt = LineTerminatorToken - case '`': - if l.consumeTemplateToken() { - tt = TemplateToken - } - default: - if l.consumeIdentifierToken() { - tt = IdentifierToken - if l.state != PropNameState { - switch hash := ToHash(l.r.Lexeme()); hash { - case 0, This, False, True, Null: - l.state = SubscriptState - case If, While, For, With: - l.state = StmtParensState - default: - // This will include keywords that can't be followed by a regexp, but only - // by a specified char (like `switch` or `try`), but we don't check for syntax - // errors as we don't attempt to parse a full JS grammar when streaming - l.state = ExprState - } - } else { - l.state = SubscriptState - } - } else if c >= 0xC0 { - if l.consumeWhitespace() { - for l.consumeWhitespace() { - } - return WhitespaceToken, l.r.Shift() - } else if l.consumeLineTerminator() { - for l.consumeLineTerminator() { - } - tt = LineTerminatorToken - } - } else if l.Err() != nil { - return ErrorToken, nil - } - } - - l.emptyLine = tt == LineTerminatorToken - - if tt == UnknownToken { - _, n := l.r.PeekRune(0) - l.r.Move(n) - } - return tt, l.r.Shift() -} - -//////////////////////////////////////////////////////////////// - -/* -The following functions follow the specifications at http://www.ecma-international.org/ecma-262/5.1/ -*/ - -func (l *Lexer) consumeWhitespace() bool { - c := l.r.Peek(0) - if c == ' ' || c == '\t' || c == '\v' || c == '\f' { - l.r.Move(1) - return true - } else if c >= 0xC0 { - if r, n := l.r.PeekRune(0); r == '\u00A0' || r == '\uFEFF' || unicode.Is(unicode.Zs, r) { - l.r.Move(n) - return true - } - } - return false -} - -func (l *Lexer) consumeLineTerminator() bool { - c := l.r.Peek(0) - if c == '\n' { - l.r.Move(1) - return true - } else if c == '\r' { - if l.r.Peek(1) == '\n' { - l.r.Move(2) - } else { - l.r.Move(1) - } - return true - } else if c >= 0xC0 { - if r, n := l.r.PeekRune(0); r == '\u2028' || r == '\u2029' { - l.r.Move(n) - return true - } - } - return false -} - -func (l *Lexer) consumeDigit() bool { - if c := l.r.Peek(0); c >= '0' && c <= '9' { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeHexDigit() bool { - if c := l.r.Peek(0); (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeBinaryDigit() bool { - if c := l.r.Peek(0); c == '0' || c == '1' { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeOctalDigit() bool { - if c := l.r.Peek(0); c >= '0' && c <= '7' { - l.r.Move(1) - return true - } - return false -} - -func (l *Lexer) consumeUnicodeEscape() bool { - if l.r.Peek(0) != '\\' || l.r.Peek(1) != 'u' { - return false - } - mark := l.r.Pos() - l.r.Move(2) - if c := l.r.Peek(0); c == '{' { - l.r.Move(1) - if l.consumeHexDigit() { - for l.consumeHexDigit() { - } - if c := l.r.Peek(0); c == '}' { - l.r.Move(1) - return true - } - } - l.r.Rewind(mark) - return false - } else if !l.consumeHexDigit() || !l.consumeHexDigit() || !l.consumeHexDigit() || !l.consumeHexDigit() { - l.r.Rewind(mark) - return false - } - return true -} - -func (l *Lexer) consumeSingleLineComment() { - for { - c := l.r.Peek(0) - if c == '\r' || c == '\n' || c == 0 { - break - } else if c >= 0xC0 { - if r, _ := l.r.PeekRune(0); r == '\u2028' || r == '\u2029' { - break - } - } - l.r.Move(1) - } -} - -//////////////////////////////////////////////////////////////// - -func (l *Lexer) consumeHTMLLikeCommentToken() bool { - c := l.r.Peek(0) - if c == '<' && l.r.Peek(1) == '!' && l.r.Peek(2) == '-' && l.r.Peek(3) == '-' { - // opening HTML-style single line comment - l.r.Move(4) - l.consumeSingleLineComment() - return true - } else if l.emptyLine && c == '-' && l.r.Peek(1) == '-' && l.r.Peek(2) == '>' { - // closing HTML-style single line comment - // (only if current line didn't contain any meaningful tokens) - l.r.Move(3) - l.consumeSingleLineComment() - return true - } - return false -} - -func (l *Lexer) consumeCommentToken() TokenType { - c := l.r.Peek(0) - if c == '/' { - c = l.r.Peek(1) - if c == '/' { - // single line comment - l.r.Move(2) - l.consumeSingleLineComment() - return SingleLineCommentToken - } else if c == '*' { - // block comment (potentially multiline) - tt := SingleLineCommentToken - l.r.Move(2) - for { - c := l.r.Peek(0) - if c == '*' && l.r.Peek(1) == '/' { - l.r.Move(2) - break - } else if c == 0 { - break - } else if l.consumeLineTerminator() { - tt = MultiLineCommentToken - l.emptyLine = true - } else { - l.r.Move(1) - } - } - return tt - } - } - return UnknownToken -} - -func (l *Lexer) consumeLongPunctuatorToken() bool { - c := l.r.Peek(0) - if c == '!' || c == '=' || c == '+' || c == '-' || c == '*' || c == '/' || c == '%' || c == '&' || c == '|' || c == '^' { - l.r.Move(1) - if l.r.Peek(0) == '=' { - l.r.Move(1) - if (c == '!' || c == '=') && l.r.Peek(0) == '=' { - l.r.Move(1) - } - } else if (c == '+' || c == '-' || c == '&' || c == '|') && l.r.Peek(0) == c { - l.r.Move(1) - } else if c == '=' && l.r.Peek(0) == '>' { - l.r.Move(1) - } - } else { // c == '<' || c == '>' - l.r.Move(1) - if l.r.Peek(0) == c { - l.r.Move(1) - if c == '>' && l.r.Peek(0) == '>' { - l.r.Move(1) - } - } - if l.r.Peek(0) == '=' { - l.r.Move(1) - } - } - return true -} - -func (l *Lexer) consumeIdentifierToken() bool { - c := l.r.Peek(0) - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '$' || c == '_' { - l.r.Move(1) - } else if c >= 0xC0 { - if r, n := l.r.PeekRune(0); unicode.IsOneOf(identifierStart, r) { - l.r.Move(n) - } else { - return false - } - } else if !l.consumeUnicodeEscape() { - return false - } - for { - c := l.r.Peek(0) - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '$' || c == '_' { - l.r.Move(1) - } else if c >= 0xC0 { - if r, n := l.r.PeekRune(0); r == '\u200C' || r == '\u200D' || unicode.IsOneOf(identifierContinue, r) { - l.r.Move(n) - } else { - break - } - } else { - break - } - } - return true -} - -func (l *Lexer) consumeNumericToken() bool { - // assume to be on 0 1 2 3 4 5 6 7 8 9 . - mark := l.r.Pos() - c := l.r.Peek(0) - if c == '0' { - l.r.Move(1) - if l.r.Peek(0) == 'x' || l.r.Peek(0) == 'X' { - l.r.Move(1) - if l.consumeHexDigit() { - for l.consumeHexDigit() { - } - } else { - l.r.Move(-1) // return just the zero - } - return true - } else if l.r.Peek(0) == 'b' || l.r.Peek(0) == 'B' { - l.r.Move(1) - if l.consumeBinaryDigit() { - for l.consumeBinaryDigit() { - } - } else { - l.r.Move(-1) // return just the zero - } - return true - } else if l.r.Peek(0) == 'o' || l.r.Peek(0) == 'O' { - l.r.Move(1) - if l.consumeOctalDigit() { - for l.consumeOctalDigit() { - } - } else { - l.r.Move(-1) // return just the zero - } - return true - } - } else if c != '.' { - for l.consumeDigit() { - } - } - if l.r.Peek(0) == '.' { - l.r.Move(1) - if l.consumeDigit() { - for l.consumeDigit() { - } - } else if c != '.' { - // . could belong to the next token - l.r.Move(-1) - return true - } else { - l.r.Rewind(mark) - return false - } - } - mark = l.r.Pos() - c = l.r.Peek(0) - if c == 'e' || c == 'E' { - l.r.Move(1) - c = l.r.Peek(0) - if c == '+' || c == '-' { - l.r.Move(1) - } - if !l.consumeDigit() { - // e could belong to the next token - l.r.Rewind(mark) - return true - } - for l.consumeDigit() { - } - } - return true -} - -func (l *Lexer) consumeStringToken() bool { - // assume to be on ' or " - mark := l.r.Pos() - delim := l.r.Peek(0) - l.r.Move(1) - for { - c := l.r.Peek(0) - if c == delim { - l.r.Move(1) - break - } else if c == '\\' { - l.r.Move(1) - if !l.consumeLineTerminator() { - if c := l.r.Peek(0); c == delim || c == '\\' { - l.r.Move(1) - } - } - continue - } else if c == '\n' || c == '\r' { - l.r.Rewind(mark) - return false - } else if c >= 0xC0 { - if r, _ := l.r.PeekRune(0); r == '\u2028' || r == '\u2029' { - l.r.Rewind(mark) - return false - } - } else if c == 0 { - break - } - l.r.Move(1) - } - return true -} - -func (l *Lexer) consumeRegexpToken() bool { - // assume to be on / and not /* - mark := l.r.Pos() - l.r.Move(1) - inClass := false - for { - c := l.r.Peek(0) - if !inClass && c == '/' { - l.r.Move(1) - break - } else if c == '[' { - inClass = true - } else if c == ']' { - inClass = false - } else if c == '\\' { - l.r.Move(1) - if l.consumeLineTerminator() { - l.r.Rewind(mark) - return false - } else if l.r.Peek(0) == 0 { - return true - } - } else if l.consumeLineTerminator() { - l.r.Rewind(mark) - return false - } else if c == 0 { - return true - } - l.r.Move(1) - } - // flags - for { - c := l.r.Peek(0) - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '$' || c == '_' { - l.r.Move(1) - } else if c >= 0xC0 { - if r, n := l.r.PeekRune(0); r == '\u200C' || r == '\u200D' || unicode.IsOneOf(identifierContinue, r) { - l.r.Move(n) - } else { - break - } - } else { - break - } - } - return true -} - -func (l *Lexer) consumeTemplateToken() bool { - // assume to be on ` or } when already within template - mark := l.r.Pos() - l.r.Move(1) - for { - c := l.r.Peek(0) - if c == '`' { - l.state = SubscriptState - l.r.Move(1) - return true - } else if c == '$' && l.r.Peek(1) == '{' { - l.enterContext(TemplateContext) - l.state = ExprState - l.r.Move(2) - return true - } else if c == '\\' { - l.r.Move(1) - if c := l.r.Peek(0); c != 0 { - l.r.Move(1) - } - continue - } else if c == 0 { - l.r.Rewind(mark) - return false - } - l.r.Move(1) - } -} diff --git a/vendor/github.com/tdewolff/parse/js/lex_test.go b/vendor/github.com/tdewolff/parse/js/lex_test.go deleted file mode 100644 index 1866087..0000000 --- a/vendor/github.com/tdewolff/parse/js/lex_test.go +++ /dev/null @@ -1,155 +0,0 @@ -package js // import "github.com/tdewolff/parse/js" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/test" -) - -type TTs []TokenType - -func TestTokens(t *testing.T) { - var tokenTests = []struct { - js string - expected []TokenType - }{ - {" \t\v\f\u00A0\uFEFF\u2000", TTs{}}, // WhitespaceToken - {"\n\r\r\n\u2028\u2029", TTs{LineTerminatorToken}}, - {"5.2 .04 0x0F 5e99", TTs{NumericToken, NumericToken, NumericToken, NumericToken}}, - {"a = 'string'", TTs{IdentifierToken, PunctuatorToken, StringToken}}, - {"/*comment*/ //comment", TTs{SingleLineCommentToken, SingleLineCommentToken}}, - {"{ } ( ) [ ]", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {". ; , < > <=", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {">= == != === !==", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"+ - * % ++ --", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"<< >> >>> & | ^", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"! ~ && || ? :", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"= += -= *= %= <<=", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {">>= >>>= &= |= ^= =>", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"a = /.*/g;", TTs{IdentifierToken, PunctuatorToken, RegexpToken, PunctuatorToken}}, - - {"/*co\nm\u2028m/*ent*/ //co//mment\u2029//comment", TTs{MultiLineCommentToken, SingleLineCommentToken, LineTerminatorToken, SingleLineCommentToken}}, - {"<!-", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"1<!--2\n", TTs{NumericToken, SingleLineCommentToken, LineTerminatorToken}}, - {"x=y-->10\n", TTs{IdentifierToken, PunctuatorToken, IdentifierToken, PunctuatorToken, PunctuatorToken, NumericToken, LineTerminatorToken}}, - {" /*comment*/ -->nothing\n", TTs{SingleLineCommentToken, SingleLineCommentToken, LineTerminatorToken}}, - {"1 /*comment\nmultiline*/ -->nothing\n", TTs{NumericToken, MultiLineCommentToken, SingleLineCommentToken, LineTerminatorToken}}, - {"$ _\u200C \\u2000 \u200C", TTs{IdentifierToken, IdentifierToken, IdentifierToken, UnknownToken}}, - {">>>=>>>>=", TTs{PunctuatorToken, PunctuatorToken, PunctuatorToken}}, - {"1/", TTs{NumericToken, PunctuatorToken}}, - {"1/=", TTs{NumericToken, PunctuatorToken}}, - {"010xF", TTs{NumericToken, NumericToken, IdentifierToken}}, - {"50e+-0", TTs{NumericToken, IdentifierToken, PunctuatorToken, PunctuatorToken, NumericToken}}, - {"'str\\i\\'ng'", TTs{StringToken}}, - {"'str\\\\'abc", TTs{StringToken, IdentifierToken}}, - {"'str\\\ni\\\\u00A0ng'", TTs{StringToken}}, - {"a = /[a-z/]/g", TTs{IdentifierToken, PunctuatorToken, RegexpToken}}, - {"a=/=/g1", TTs{IdentifierToken, PunctuatorToken, RegexpToken}}, - {"a = /'\\\\/\n", TTs{IdentifierToken, PunctuatorToken, RegexpToken, LineTerminatorToken}}, - {"a=/\\//g1", TTs{IdentifierToken, PunctuatorToken, RegexpToken}}, - {"new RegExp(a + /\\d{1,2}/.source)", TTs{IdentifierToken, IdentifierToken, PunctuatorToken, IdentifierToken, PunctuatorToken, RegexpToken, PunctuatorToken, IdentifierToken, PunctuatorToken}}, - - {"0b0101 0o0707 0b17", TTs{NumericToken, NumericToken, NumericToken, NumericToken}}, - {"`template`", TTs{TemplateToken}}, - {"`a${x+y}b`", TTs{TemplateToken, IdentifierToken, PunctuatorToken, IdentifierToken, TemplateToken}}, - {"`temp\nlate`", TTs{TemplateToken}}, - {"`outer${{x: 10}}bar${ raw`nested${2}endnest` }end`", TTs{TemplateToken, PunctuatorToken, IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, TemplateToken, IdentifierToken, TemplateToken, NumericToken, TemplateToken, TemplateToken}}, - - // early endings - {"'string", TTs{StringToken}}, - {"'\n '\u2028", TTs{UnknownToken, LineTerminatorToken, UnknownToken, LineTerminatorToken}}, - {"'str\\\U00100000ing\\0'", TTs{StringToken}}, - {"'strin\\00g'", TTs{StringToken}}, - {"/*comment", TTs{SingleLineCommentToken}}, - {"a=/regexp", TTs{IdentifierToken, PunctuatorToken, RegexpToken}}, - {"\\u002", TTs{UnknownToken, IdentifierToken}}, - - // coverage - {"Ø a〉", TTs{IdentifierToken, IdentifierToken, UnknownToken}}, - {"0xg 0.f", TTs{NumericToken, IdentifierToken, NumericToken, PunctuatorToken, IdentifierToken}}, - {"0bg 0og", TTs{NumericToken, IdentifierToken, NumericToken, IdentifierToken}}, - {"\u00A0\uFEFF\u2000", TTs{}}, - {"\u2028\u2029", TTs{LineTerminatorToken}}, - {"\\u0029ident", TTs{IdentifierToken}}, - {"\\u{0029FEF}ident", TTs{IdentifierToken}}, - {"\\u{}", TTs{UnknownToken, IdentifierToken, PunctuatorToken, PunctuatorToken}}, - {"\\ugident", TTs{UnknownToken, IdentifierToken}}, - {"'str\u2028ing'", TTs{UnknownToken, IdentifierToken, LineTerminatorToken, IdentifierToken, StringToken}}, - {"a=/\\\n", TTs{IdentifierToken, PunctuatorToken, PunctuatorToken, UnknownToken, LineTerminatorToken}}, - {"a=/x/\u200C\u3009", TTs{IdentifierToken, PunctuatorToken, RegexpToken, UnknownToken}}, - {"a=/x\n", TTs{IdentifierToken, PunctuatorToken, PunctuatorToken, IdentifierToken, LineTerminatorToken}}, - - {"return /abc/;", TTs{IdentifierToken, RegexpToken, PunctuatorToken}}, - {"yield /abc/;", TTs{IdentifierToken, RegexpToken, PunctuatorToken}}, - {"a/b/g", TTs{IdentifierToken, PunctuatorToken, IdentifierToken, PunctuatorToken, IdentifierToken}}, - {"{}/1/g", TTs{PunctuatorToken, PunctuatorToken, RegexpToken}}, - {"i(0)/1/g", TTs{IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, PunctuatorToken, NumericToken, PunctuatorToken, IdentifierToken}}, - {"if(0)/1/g", TTs{IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, RegexpToken}}, - {"a.if(0)/1/g", TTs{IdentifierToken, PunctuatorToken, IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, PunctuatorToken, NumericToken, PunctuatorToken, IdentifierToken}}, - {"while(0)/1/g", TTs{IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, RegexpToken}}, - {"for(;;)/1/g", TTs{IdentifierToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, RegexpToken}}, - {"with(0)/1/g", TTs{IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, RegexpToken}}, - {"this/1/g", TTs{IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, IdentifierToken}}, - {"case /1/g:", TTs{IdentifierToken, RegexpToken, PunctuatorToken}}, - {"function f(){}/1/g", TTs{IdentifierToken, IdentifierToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, PunctuatorToken, RegexpToken}}, - {"this.return/1/g", TTs{IdentifierToken, PunctuatorToken, IdentifierToken, PunctuatorToken, NumericToken, PunctuatorToken, IdentifierToken}}, - {"(a+b)/1/g", TTs{PunctuatorToken, IdentifierToken, PunctuatorToken, IdentifierToken, PunctuatorToken, PunctuatorToken, NumericToken, PunctuatorToken, IdentifierToken}}, - {"`\\``", TTs{TemplateToken}}, - {"`\\${ 1 }`", TTs{TemplateToken}}, - {"`\\\r\n`", TTs{TemplateToken}}, - - // go fuzz - {"`", TTs{UnknownToken}}, - } - - for _, tt := range tokenTests { - t.Run(tt.js, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.js)) - i := 0 - j := 0 - for { - token, _ := l.Next() - j++ - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } else if token == WhitespaceToken { - continue - } - if i < len(tt.expected) { - if token != tt.expected[i] { - test.String(t, token.String(), tt.expected[i].String(), "token types must match") - break - } - } else { - test.Fail(t, "index", i, "must not exceed expected token types size", len(tt.expected)) - break - } - i++ - } - }) - } - - test.T(t, WhitespaceToken.String(), "Whitespace") - test.T(t, TokenType(100).String(), "Invalid(100)") -} - -//////////////////////////////////////////////////////////////// - -func ExampleNewLexer() { - l := NewLexer(bytes.NewBufferString("var x = 'lorem ipsum';")) - out := "" - for { - tt, data := l.Next() - if tt == ErrorToken { - break - } - out += string(data) - } - fmt.Println(out) - // Output: var x = 'lorem ipsum'; -} diff --git a/vendor/github.com/tdewolff/parse/json/README.md b/vendor/github.com/tdewolff/parse/json/README.md deleted file mode 100644 index 7621ca9..0000000 --- a/vendor/github.com/tdewolff/parse/json/README.md +++ /dev/null @@ -1,81 +0,0 @@ -# JSON [![GoDoc](http://godoc.org/github.com/tdewolff/parse/json?status.svg)](http://godoc.org/github.com/tdewolff/parse/json) [![GoCover](http://gocover.io/_badge/github.com/tdewolff/parse/json)](http://gocover.io/github.com/tdewolff/parse/json) - -This package is a JSON lexer (ECMA-404) written in [Go][1]. It follows the specification at [JSON](http://json.org/). The lexer takes an io.Reader and converts it into tokens until the EOF. - -## Installation -Run the following command - - go get github.com/tdewolff/parse/json - -or add the following import and run project with `go get` - - import "github.com/tdewolff/parse/json" - -## Parser -### Usage -The following initializes a new Parser with io.Reader `r`: -``` go -p := json.NewParser(r) -``` - -To tokenize until EOF an error, use: -``` go -for { - gt, text := p.Next() - switch gt { - case json.ErrorGrammar: - // error or EOF set in p.Err() - return - // ... - } -} -``` - -All grammars: -``` go -ErrorGrammar GrammarType = iota // extra grammar when errors occur -WhitespaceGrammar // space \t \r \n -LiteralGrammar // null true false -NumberGrammar -StringGrammar -StartObjectGrammar // { -EndObjectGrammar // } -StartArrayGrammar // [ -EndArrayGrammar // ] -``` - -### Examples -``` go -package main - -import ( - "os" - - "github.com/tdewolff/parse/json" -) - -// Tokenize JSON from stdin. -func main() { - p := json.NewParser(os.Stdin) - for { - gt, text := p.Next() - switch gt { - case json.ErrorGrammar: - if p.Err() != io.EOF { - fmt.Println("Error on line", p.Line(), ":", p.Err()) - } - return - case json.LiteralGrammar: - fmt.Println("Literal", string(text)) - case json.NumberGrammar: - fmt.Println("Number", string(text)) - // ... - } - } -} -``` - -## License -Released under the [MIT license](https://github.com/tdewolff/parse/blob/master/LICENSE.md). - -[1]: http://golang.org/ "Go Language" diff --git a/vendor/github.com/tdewolff/parse/json/parse.go b/vendor/github.com/tdewolff/parse/json/parse.go deleted file mode 100644 index 5c78af8..0000000 --- a/vendor/github.com/tdewolff/parse/json/parse.go +++ /dev/null @@ -1,307 +0,0 @@ -// Package json is a JSON parser following the specifications at http://json.org/. -package json // import "github.com/tdewolff/parse/json" - -import ( - "io" - "strconv" - - "github.com/tdewolff/parse" - "github.com/tdewolff/parse/buffer" -) - -// GrammarType determines the type of grammar -type GrammarType uint32 - -// GrammarType values. -const ( - ErrorGrammar GrammarType = iota // extra grammar when errors occur - WhitespaceGrammar - LiteralGrammar - NumberGrammar - StringGrammar - StartObjectGrammar // { - EndObjectGrammar // } - StartArrayGrammar // [ - EndArrayGrammar // ] -) - -// String returns the string representation of a GrammarType. -func (gt GrammarType) String() string { - switch gt { - case ErrorGrammar: - return "Error" - case WhitespaceGrammar: - return "Whitespace" - case LiteralGrammar: - return "Literal" - case NumberGrammar: - return "Number" - case StringGrammar: - return "String" - case StartObjectGrammar: - return "StartObject" - case EndObjectGrammar: - return "EndObject" - case StartArrayGrammar: - return "StartArray" - case EndArrayGrammar: - return "EndArray" - } - return "Invalid(" + strconv.Itoa(int(gt)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// State determines the current state the parser is in. -type State uint32 - -// State values. -const ( - ValueState State = iota // extra token when errors occur - ObjectKeyState - ObjectValueState - ArrayState -) - -// String returns the string representation of a State. -func (state State) String() string { - switch state { - case ValueState: - return "Value" - case ObjectKeyState: - return "ObjectKey" - case ObjectValueState: - return "ObjectValue" - case ArrayState: - return "Array" - } - return "Invalid(" + strconv.Itoa(int(state)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// Parser is the state for the lexer. -type Parser struct { - r *buffer.Lexer - state []State - err error - - needComma bool -} - -// NewParser returns a new Parser for a given io.Reader. -func NewParser(r io.Reader) *Parser { - return &Parser{ - r: buffer.NewLexer(r), - state: []State{ValueState}, - } -} - -// Err returns the error encountered during tokenization, this is often io.EOF but also other errors can be returned. -func (p *Parser) Err() error { - if p.err != nil { - return p.err - } - return p.r.Err() -} - -// Restore restores the NULL byte at the end of the buffer. -func (p *Parser) Restore() { - p.r.Restore() -} - -// Next returns the next Grammar. It returns ErrorGrammar when an error was encountered. Using Err() one can retrieve the error message. -func (p *Parser) Next() (GrammarType, []byte) { - p.moveWhitespace() - c := p.r.Peek(0) - state := p.state[len(p.state)-1] - if c == ',' { - if state != ArrayState && state != ObjectKeyState { - p.err = parse.NewErrorLexer("unexpected comma character outside an array or object", p.r) - return ErrorGrammar, nil - } - p.r.Move(1) - p.moveWhitespace() - p.needComma = false - c = p.r.Peek(0) - } - p.r.Skip() - - if p.needComma && c != '}' && c != ']' && c != 0 { - p.err = parse.NewErrorLexer("expected comma character or an array or object ending", p.r) - return ErrorGrammar, nil - } else if c == '{' { - p.state = append(p.state, ObjectKeyState) - p.r.Move(1) - return StartObjectGrammar, p.r.Shift() - } else if c == '}' { - if state != ObjectKeyState { - p.err = parse.NewErrorLexer("unexpected right brace character", p.r) - return ErrorGrammar, nil - } - p.needComma = true - p.state = p.state[:len(p.state)-1] - if p.state[len(p.state)-1] == ObjectValueState { - p.state[len(p.state)-1] = ObjectKeyState - } - p.r.Move(1) - return EndObjectGrammar, p.r.Shift() - } else if c == '[' { - p.state = append(p.state, ArrayState) - p.r.Move(1) - return StartArrayGrammar, p.r.Shift() - } else if c == ']' { - p.needComma = true - if state != ArrayState { - p.err = parse.NewErrorLexer("unexpected right bracket character", p.r) - return ErrorGrammar, nil - } - p.state = p.state[:len(p.state)-1] - if p.state[len(p.state)-1] == ObjectValueState { - p.state[len(p.state)-1] = ObjectKeyState - } - p.r.Move(1) - return EndArrayGrammar, p.r.Shift() - } else if state == ObjectKeyState { - if c != '"' || !p.consumeStringToken() { - p.err = parse.NewErrorLexer("expected object key to be a quoted string", p.r) - return ErrorGrammar, nil - } - n := p.r.Pos() - p.moveWhitespace() - if c := p.r.Peek(0); c != ':' { - p.err = parse.NewErrorLexer("expected colon character after object key", p.r) - return ErrorGrammar, nil - } - p.r.Move(1) - p.state[len(p.state)-1] = ObjectValueState - return StringGrammar, p.r.Shift()[:n] - } else { - p.needComma = true - if state == ObjectValueState { - p.state[len(p.state)-1] = ObjectKeyState - } - if c == '"' && p.consumeStringToken() { - return StringGrammar, p.r.Shift() - } else if p.consumeNumberToken() { - return NumberGrammar, p.r.Shift() - } else if p.consumeLiteralToken() { - return LiteralGrammar, p.r.Shift() - } - } - return ErrorGrammar, nil -} - -// State returns the state the parser is currently in (ie. which token is expected). -func (p *Parser) State() State { - return p.state[len(p.state)-1] -} - -//////////////////////////////////////////////////////////////// - -/* -The following functions follow the specifications at http://json.org/ -*/ - -func (p *Parser) moveWhitespace() { - for { - if c := p.r.Peek(0); c != ' ' && c != '\n' && c != '\r' && c != '\t' { - break - } - p.r.Move(1) - } -} - -func (p *Parser) consumeLiteralToken() bool { - c := p.r.Peek(0) - if c == 't' && p.r.Peek(1) == 'r' && p.r.Peek(2) == 'u' && p.r.Peek(3) == 'e' { - p.r.Move(4) - return true - } else if c == 'f' && p.r.Peek(1) == 'a' && p.r.Peek(2) == 'l' && p.r.Peek(3) == 's' && p.r.Peek(4) == 'e' { - p.r.Move(5) - return true - } else if c == 'n' && p.r.Peek(1) == 'u' && p.r.Peek(2) == 'l' && p.r.Peek(3) == 'l' { - p.r.Move(4) - return true - } - return false -} - -func (p *Parser) consumeNumberToken() bool { - mark := p.r.Pos() - if p.r.Peek(0) == '-' { - p.r.Move(1) - } - c := p.r.Peek(0) - if c >= '1' && c <= '9' { - p.r.Move(1) - for { - if c := p.r.Peek(0); c < '0' || c > '9' { - break - } - p.r.Move(1) - } - } else if c != '0' { - p.r.Rewind(mark) - return false - } else { - p.r.Move(1) // 0 - } - if c := p.r.Peek(0); c == '.' { - p.r.Move(1) - if c := p.r.Peek(0); c < '0' || c > '9' { - p.r.Move(-1) - return true - } - for { - if c := p.r.Peek(0); c < '0' || c > '9' { - break - } - p.r.Move(1) - } - } - mark = p.r.Pos() - if c := p.r.Peek(0); c == 'e' || c == 'E' { - p.r.Move(1) - if c := p.r.Peek(0); c == '+' || c == '-' { - p.r.Move(1) - } - if c := p.r.Peek(0); c < '0' || c > '9' { - p.r.Rewind(mark) - return true - } - for { - if c := p.r.Peek(0); c < '0' || c > '9' { - break - } - p.r.Move(1) - } - } - return true -} - -func (p *Parser) consumeStringToken() bool { - // assume to be on " - p.r.Move(1) - for { - c := p.r.Peek(0) - if c == '"' { - escaped := false - for i := p.r.Pos() - 1; i >= 0; i-- { - if p.r.Lexeme()[i] == '\\' { - escaped = !escaped - } else { - break - } - } - if !escaped { - p.r.Move(1) - break - } - } else if c == 0 { - return false - } - p.r.Move(1) - } - return true -} diff --git a/vendor/github.com/tdewolff/parse/json/parse_test.go b/vendor/github.com/tdewolff/parse/json/parse_test.go deleted file mode 100644 index 354a93e..0000000 --- a/vendor/github.com/tdewolff/parse/json/parse_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package json // import "github.com/tdewolff/parse/json" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/parse" - "github.com/tdewolff/test" -) - -type GTs []GrammarType - -func TestGrammars(t *testing.T) { - var grammarTests = []struct { - json string - expected []GrammarType - }{ - {" \t\n\r", GTs{}}, // WhitespaceGrammar - {"null", GTs{LiteralGrammar}}, - {"[]", GTs{StartArrayGrammar, EndArrayGrammar}}, - {"15.2", GTs{NumberGrammar}}, - {"0.4", GTs{NumberGrammar}}, - {"5e9", GTs{NumberGrammar}}, - {"-4E-3", GTs{NumberGrammar}}, - {"true", GTs{LiteralGrammar}}, - {"false", GTs{LiteralGrammar}}, - {"null", GTs{LiteralGrammar}}, - {`""`, GTs{StringGrammar}}, - {`"abc"`, GTs{StringGrammar}}, - {`"\""`, GTs{StringGrammar}}, - {`"\\"`, GTs{StringGrammar}}, - {"{}", GTs{StartObjectGrammar, EndObjectGrammar}}, - {`{"a": "b", "c": "d"}`, GTs{StartObjectGrammar, StringGrammar, StringGrammar, StringGrammar, StringGrammar, EndObjectGrammar}}, - {`{"a": [1, 2], "b": {"c": 3}}`, GTs{StartObjectGrammar, StringGrammar, StartArrayGrammar, NumberGrammar, NumberGrammar, EndArrayGrammar, StringGrammar, StartObjectGrammar, StringGrammar, NumberGrammar, EndObjectGrammar, EndObjectGrammar}}, - {"[null,]", GTs{StartArrayGrammar, LiteralGrammar, EndArrayGrammar}}, - // {"[\"x\\\x00y\", 0]", GTs{StartArrayGrammar, StringGrammar, NumberGrammar, EndArrayGrammar}}, - } - for _, tt := range grammarTests { - t.Run(tt.json, func(t *testing.T) { - p := NewParser(bytes.NewBufferString(tt.json)) - i := 0 - for { - grammar, _ := p.Next() - if grammar == ErrorGrammar { - test.T(t, p.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } else if grammar == WhitespaceGrammar { - continue - } - test.That(t, i < len(tt.expected), "index", i, "must not exceed expected grammar types size", len(tt.expected)) - if i < len(tt.expected) { - test.T(t, grammar, tt.expected[i], "grammar types must match") - } - i++ - } - }) - } - - test.T(t, WhitespaceGrammar.String(), "Whitespace") - test.T(t, GrammarType(100).String(), "Invalid(100)") - test.T(t, ValueState.String(), "Value") - test.T(t, ObjectKeyState.String(), "ObjectKey") - test.T(t, ObjectValueState.String(), "ObjectValue") - test.T(t, ArrayState.String(), "Array") - test.T(t, State(100).String(), "Invalid(100)") -} - -func TestGrammarsError(t *testing.T) { - var grammarErrorTests = []struct { - json string - col int - }{ - {"true, false", 5}, - {"[true false]", 7}, - {"]", 1}, - {"}", 1}, - {"{0: 1}", 2}, - {"{\"a\" 1}", 6}, - {"1.", 2}, - {"1e+", 2}, - {`{"":"`, 0}, - {"\"a\\", 0}, - } - for _, tt := range grammarErrorTests { - t.Run(tt.json, func(t *testing.T) { - p := NewParser(bytes.NewBufferString(tt.json)) - for { - grammar, _ := p.Next() - if grammar == ErrorGrammar { - if tt.col == 0 { - test.T(t, p.Err(), io.EOF) - } else if perr, ok := p.Err().(*parse.Error); ok { - _, col, _ := perr.Position() - test.T(t, col, tt.col) - } else { - test.Fail(t, "bad error:", p.Err()) - } - break - } - } - }) - } -} - -func TestStates(t *testing.T) { - var stateTests = []struct { - json string - expected []State - }{ - {"null", []State{ValueState}}, - {"[null]", []State{ArrayState, ArrayState, ValueState}}, - {"{\"\":null}", []State{ObjectKeyState, ObjectValueState, ObjectKeyState, ValueState}}, - } - for _, tt := range stateTests { - t.Run(tt.json, func(t *testing.T) { - p := NewParser(bytes.NewBufferString(tt.json)) - i := 0 - for { - grammar, _ := p.Next() - state := p.State() - if grammar == ErrorGrammar { - test.T(t, p.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } else if grammar == WhitespaceGrammar { - continue - } - test.That(t, i < len(tt.expected), "index", i, "must not exceed expected states size", len(tt.expected)) - if i < len(tt.expected) { - test.T(t, state, tt.expected[i], "states must match") - } - i++ - } - }) - } -} - -//////////////////////////////////////////////////////////////// - -func ExampleNewParser() { - p := NewParser(bytes.NewBufferString(`{"key": 5}`)) - out := "" - for { - state := p.State() - gt, data := p.Next() - if gt == ErrorGrammar { - break - } - out += string(data) - if state == ObjectKeyState && gt != EndObjectGrammar { - out += ":" - } - // not handling comma insertion - } - fmt.Println(out) - // Output: {"key":5} -} diff --git a/vendor/github.com/tdewolff/parse/position.go b/vendor/github.com/tdewolff/parse/position.go deleted file mode 100644 index 690fcfa..0000000 --- a/vendor/github.com/tdewolff/parse/position.go +++ /dev/null @@ -1,79 +0,0 @@ -package parse - -import ( - "fmt" - "io" - "strings" - - "github.com/tdewolff/parse/buffer" -) - -// Position returns the line and column number for a certain position in a file. It is useful for recovering the position in a file that caused an error. -// It only treates \n, \r, and \r\n as newlines, which might be different from some languages also recognizing \f, \u2028, and \u2029 to be newlines. -func Position(r io.Reader, offset int) (line, col int, context string, err error) { - l := buffer.NewLexer(r) - - line = 1 - for { - c := l.Peek(0) - if c == 0 { - col = l.Pos() + 1 - context = positionContext(l, line, col) - err = l.Err() - if err == nil { - err = io.EOF - } - return - } - - if offset == l.Pos() { - col = l.Pos() + 1 - context = positionContext(l, line, col) - return - } - - if c == '\n' { - l.Move(1) - line++ - offset -= l.Pos() - l.Skip() - } else if c == '\r' { - if l.Peek(1) == '\n' { - if offset == l.Pos()+1 { - l.Move(1) - continue - } - l.Move(2) - } else { - l.Move(1) - } - line++ - offset -= l.Pos() - l.Skip() - } else { - l.Move(1) - } - } -} - -func positionContext(l *buffer.Lexer, line, col int) (context string) { - for { - c := l.Peek(0) - if c == 0 && l.Err() != nil || c == '\n' || c == '\r' { - break - } - l.Move(1) - } - - // replace unprintable characters by a space - b := l.Lexeme() - for i, c := range b { - if c < 0x20 || c == 0x7F { - b[i] = ' ' - } - } - - context += fmt.Sprintf("%5d: %s\n", line, string(b)) - context += fmt.Sprintf("%s^", strings.Repeat(" ", col+6)) - return -} diff --git a/vendor/github.com/tdewolff/parse/position_test.go b/vendor/github.com/tdewolff/parse/position_test.go deleted file mode 100644 index eb1e4e5..0000000 --- a/vendor/github.com/tdewolff/parse/position_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package parse - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/test" -) - -func TestPosition(t *testing.T) { - var newlineTests = []struct { - offset int - buf string - line int - col int - err error - }{ - {0, "x", 1, 1, nil}, - {1, "xx", 1, 2, nil}, - {2, "x\nx", 2, 1, nil}, - {2, "\n\nx", 3, 1, nil}, - {3, "\nxxx", 2, 3, nil}, - {2, "\r\nx", 2, 1, nil}, - - // edge cases - {0, "", 1, 1, io.EOF}, - {0, "\n", 1, 1, nil}, - {1, "\r\n", 1, 2, nil}, - {-1, "x", 1, 2, io.EOF}, // continue till the end - } - for _, tt := range newlineTests { - t.Run(fmt.Sprint(tt.buf, " ", tt.offset), func(t *testing.T) { - r := bytes.NewBufferString(tt.buf) - line, col, _, err := Position(r, tt.offset) - test.T(t, err, tt.err) - test.T(t, line, tt.line, "line") - test.T(t, col, tt.col, "column") - }) - } -} diff --git a/vendor/github.com/tdewolff/parse/strconv/float.go b/vendor/github.com/tdewolff/parse/strconv/float.go deleted file mode 100644 index da1a30d..0000000 --- a/vendor/github.com/tdewolff/parse/strconv/float.go +++ /dev/null @@ -1,251 +0,0 @@ -package strconv // import "github.com/tdewolff/parse/strconv" - -import "math" - -var float64pow10 = []float64{ - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22, -} - -// Float parses a byte-slice and returns the float it represents. -// If an invalid character is encountered, it will stop there. -func ParseFloat(b []byte) (float64, int) { - i := 0 - neg := false - if i < len(b) && (b[i] == '+' || b[i] == '-') { - neg = b[i] == '-' - i++ - } - - dot := -1 - trunk := -1 - n := uint64(0) - for ; i < len(b); i++ { - c := b[i] - if c >= '0' && c <= '9' { - if trunk == -1 { - if n > math.MaxUint64/10 { - trunk = i - } else { - n *= 10 - n += uint64(c - '0') - } - } - } else if dot == -1 && c == '.' { - dot = i - } else { - break - } - } - - f := float64(n) - if neg { - f = -f - } - - mantExp := int64(0) - if dot != -1 { - if trunk == -1 { - trunk = i - } - mantExp = int64(trunk - dot - 1) - } else if trunk != -1 { - mantExp = int64(trunk - i) - } - expExp := int64(0) - if i < len(b) && (b[i] == 'e' || b[i] == 'E') { - i++ - if e, expLen := ParseInt(b[i:]); expLen > 0 { - expExp = e - i += expLen - } - } - exp := expExp - mantExp - - // copied from strconv/atof.go - if exp == 0 { - return f, i - } else if exp > 0 && exp <= 15+22 { // int * 10^k - // If exponent is big but number of digits is not, - // can move a few zeros into the integer part. - if exp > 22 { - f *= float64pow10[exp-22] - exp = 22 - } - if f <= 1e15 && f >= -1e15 { - return f * float64pow10[exp], i - } - } else if exp < 0 && exp >= -22 { // int / 10^k - return f / float64pow10[-exp], i - } - f *= math.Pow10(int(-mantExp)) - return f * math.Pow10(int(expExp)), i -} - -const log2 = 0.301029995 -const int64maxlen = 18 - -func float64exp(f float64) int { - exp2 := 0 - if f != 0.0 { - x := math.Float64bits(f) - exp2 = int(x>>(64-11-1))&0x7FF - 1023 + 1 - } - - exp10 := float64(exp2) * log2 - if exp10 < 0 { - exp10 -= 1.0 - } - return int(exp10) -} - -func AppendFloat(b []byte, f float64, prec int) ([]byte, bool) { - if math.IsNaN(f) || math.IsInf(f, 0) { - return b, false - } else if prec >= int64maxlen { - return b, false - } - - neg := false - if f < 0.0 { - f = -f - neg = true - } - if prec == -1 { - prec = int64maxlen - 1 - } - prec -= float64exp(f) // number of digits in front of the dot - f *= math.Pow10(prec) - - // calculate mantissa and exponent - mant := int64(f) - mantLen := LenInt(mant) - mantExp := mantLen - prec - 1 - if mant == 0 { - return append(b, '0'), true - } - - // expLen is zero for positive exponents, because positive exponents are determined later on in the big conversion loop - exp := 0 - expLen := 0 - if mantExp > 0 { - // positive exponent is determined in the loop below - // but if we initially decreased the exponent to fit in an integer, we can't set the new exponent in the loop alone, - // since the number of zeros at the end determines the positive exponent in the loop, and we just artificially lost zeros - if prec < 0 { - exp = mantExp - } - expLen = 1 + LenInt(int64(exp)) // e + digits - } else if mantExp < -3 { - exp = mantExp - expLen = 2 + LenInt(int64(exp)) // e + minus + digits - } else if mantExp < -1 { - mantLen += -mantExp - 1 // extra zero between dot and first digit - } - - // reserve space in b - i := len(b) - maxLen := 1 + mantLen + expLen // dot + mantissa digits + exponent - if neg { - maxLen++ - } - if i+maxLen > cap(b) { - b = append(b, make([]byte, maxLen)...) - } else { - b = b[:i+maxLen] - } - - // write to string representation - if neg { - b[i] = '-' - i++ - } - - // big conversion loop, start at the end and move to the front - // initially print trailing zeros and remove them later on - // for example if the first non-zero digit is three positions in front of the dot, it will overwrite the zeros with a positive exponent - zero := true - last := i + mantLen // right-most position of digit that is non-zero + dot - dot := last - prec - exp // position of dot - j := last - for mant > 0 { - if j == dot { - b[j] = '.' - j-- - } - newMant := mant / 10 - digit := mant - 10*newMant - if zero && digit > 0 { - // first non-zero digit, if we are still behind the dot we can trim the end to this position - // otherwise trim to the dot (including the dot) - if j > dot { - i = j + 1 - // decrease negative exponent further to get rid of dot - if exp < 0 { - newExp := exp - (j - dot) - // getting rid of the dot shouldn't lower the exponent to more digits (e.g. -9 -> -10) - if LenInt(int64(newExp)) == LenInt(int64(exp)) { - exp = newExp - dot = j - j-- - i-- - } - } - } else { - i = dot - } - last = j - zero = false - } - b[j] = '0' + byte(digit) - j-- - mant = newMant - } - - if j > dot { - // extra zeros behind the dot - for j > dot { - b[j] = '0' - j-- - } - b[j] = '.' - } else if last+3 < dot { - // add positive exponent because we have 3 or more zeros in front of the dot - i = last + 1 - exp = dot - last - 1 - } else if j == dot { - // handle 0.1 - b[j] = '.' - } - - // exponent - if exp != 0 { - if exp == 1 { - b[i] = '0' - i++ - } else if exp == 2 { - b[i] = '0' - b[i+1] = '0' - i += 2 - } else { - b[i] = 'e' - i++ - if exp < 0 { - b[i] = '-' - i++ - exp = -exp - } - i += LenInt(int64(exp)) - j := i - for exp > 0 { - newExp := exp / 10 - digit := exp - 10*newExp - j-- - b[j] = '0' + byte(digit) - exp = newExp - } - } - } - return b[:i], true -} diff --git a/vendor/github.com/tdewolff/parse/strconv/float_test.go b/vendor/github.com/tdewolff/parse/strconv/float_test.go deleted file mode 100644 index b1f2cfb..0000000 --- a/vendor/github.com/tdewolff/parse/strconv/float_test.go +++ /dev/null @@ -1,196 +0,0 @@ -package strconv // import "github.com/tdewolff/parse/strconv" - -import ( - "fmt" - "math" - "math/rand" - "strconv" - "testing" - - "github.com/tdewolff/test" -) - -func TestParseFloat(t *testing.T) { - floatTests := []struct { - f string - expected float64 - }{ - {"5", 5}, - {"5.1", 5.1}, - {"-5.1", -5.1}, - {"5.1e-2", 5.1e-2}, - {"5.1e+2", 5.1e+2}, - {"0.0e1", 0.0e1}, - {"18446744073709551620", 18446744073709551620.0}, - {"1e23", 1e23}, - // TODO: hard to test due to float imprecision - // {"1.7976931348623e+308", 1.7976931348623e+308) - // {"4.9406564584124e-308", 4.9406564584124e-308) - } - for _, tt := range floatTests { - f, n := ParseFloat([]byte(tt.f)) - test.That(t, n == len(tt.f), "parsed", n, "characters instead for", tt.f) - test.That(t, f == tt.expected, "return", tt.expected, "for", tt.f) - } -} - -func TestAppendFloat(t *testing.T) { - floatTests := []struct { - f float64 - prec int - expected string - }{ - {0, 6, "0"}, - {1, 6, "1"}, - {9, 6, "9"}, - {9.99999, 6, "9.99999"}, - {123, 6, "123"}, - {0.123456, 6, ".123456"}, - {0.066, 6, ".066"}, - {0.0066, 6, ".0066"}, - {12e2, 6, "1200"}, - {12e3, 6, "12e3"}, - {0.1, 6, ".1"}, - {0.001, 6, ".001"}, - {0.0001, 6, "1e-4"}, - {-1, 6, "-1"}, - {-123, 6, "-123"}, - {-123.456, 6, "-123.456"}, - {-12e3, 6, "-12e3"}, - {-0.1, 6, "-.1"}, - {-0.0001, 6, "-1e-4"}, - {0.000100009, 10, "100009e-9"}, - {0.0001000009, 10, "1.000009e-4"}, - {1e18, 0, "1e18"}, - //{1e19, 0, "1e19"}, - //{1e19, 18, "1e19"}, - {1e1, 0, "10"}, - {1e2, 1, "100"}, - {1e3, 2, "1e3"}, - {1e10, -1, "1e10"}, - {1e15, -1, "1e15"}, - {1e-5, 6, "1e-5"}, - {math.NaN(), 0, ""}, - {math.Inf(1), 0, ""}, - {math.Inf(-1), 0, ""}, - {0, 19, ""}, - {.000923361977200859392, -1, "9.23361977200859392e-4"}, - } - for _, tt := range floatTests { - f, _ := AppendFloat([]byte{}, tt.f, tt.prec) - test.String(t, string(f), tt.expected, "for", tt.f) - } - - b := make([]byte, 0, 22) - AppendFloat(b, 12.34, -1) - test.String(t, string(b[:5]), "12.34", "in buffer") -} - -//////////////////////////////////////////////////////////////// - -func TestAppendFloatRandom(t *testing.T) { - N := int(1e6) - if testing.Short() { - N = 0 - } - r := rand.New(rand.NewSource(99)) - //prec := 10 - for i := 0; i < N; i++ { - f := r.ExpFloat64() - //f = math.Floor(f*float64(prec)) / float64(prec) - - b, _ := AppendFloat([]byte{}, f, -1) - f2, _ := strconv.ParseFloat(string(b), 64) - if math.Abs(f-f2) > 1e-6 { - fmt.Println("Bad:", f, "!=", f2, "in", string(b)) - } - } -} - -func BenchmarkFloatToBytes1(b *testing.B) { - r := []byte{} //make([]byte, 10) - f := 123.456 - for i := 0; i < b.N; i++ { - r = strconv.AppendFloat(r[:0], f, 'g', 6, 64) - } -} - -func BenchmarkFloatToBytes2(b *testing.B) { - r := make([]byte, 10) - f := 123.456 - for i := 0; i < b.N; i++ { - r, _ = AppendFloat(r[:0], f, 6) - } -} - -func BenchmarkModf1(b *testing.B) { - f := 123.456 - x := 0.0 - for i := 0; i < b.N; i++ { - a, b := math.Modf(f) - x += a + b - } -} - -func BenchmarkModf2(b *testing.B) { - f := 123.456 - x := 0.0 - for i := 0; i < b.N; i++ { - a := float64(int64(f)) - b := f - a - x += a + b - } -} - -func BenchmarkPrintInt1(b *testing.B) { - X := int64(123456789) - n := LenInt(X) - r := make([]byte, n) - for i := 0; i < b.N; i++ { - x := X - j := n - for x > 0 { - j-- - r[j] = '0' + byte(x%10) - x /= 10 - } - } -} - -func BenchmarkPrintInt2(b *testing.B) { - X := int64(123456789) - n := LenInt(X) - r := make([]byte, n) - for i := 0; i < b.N; i++ { - x := X - j := n - for x > 0 { - j-- - newX := x / 10 - r[j] = '0' + byte(x-10*newX) - x = newX - } - } -} - -var int64pow10 = []int64{ - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, -} - -func BenchmarkPrintInt3(b *testing.B) { - X := int64(123456789) - n := LenInt(X) - r := make([]byte, n) - for i := 0; i < b.N; i++ { - x := X - j := 0 - for j < n { - pow := int64pow10[n-j-1] - tmp := x / pow - r[j] = '0' + byte(tmp) - j++ - x -= tmp * pow - } - } -} diff --git a/vendor/github.com/tdewolff/parse/strconv/int.go b/vendor/github.com/tdewolff/parse/strconv/int.go deleted file mode 100644 index a84ecf3..0000000 --- a/vendor/github.com/tdewolff/parse/strconv/int.go +++ /dev/null @@ -1,83 +0,0 @@ -package strconv // import "github.com/tdewolff/parse/strconv" - -import ( - "math" -) - -// Int parses a byte-slice and returns the integer it represents. -// If an invalid character is encountered, it will stop there. -func ParseInt(b []byte) (int64, int) { - i := 0 - neg := false - if len(b) > 0 && (b[0] == '+' || b[0] == '-') { - neg = b[0] == '-' - i++ - } - n := uint64(0) - for i < len(b) { - c := b[i] - if n > math.MaxUint64/10 { - return 0, 0 - } else if c >= '0' && c <= '9' { - n *= 10 - n += uint64(c - '0') - } else { - break - } - i++ - } - if !neg && n > uint64(math.MaxInt64) || n > uint64(math.MaxInt64)+1 { - return 0, 0 - } else if neg { - return -int64(n), i - } - return int64(n), i -} - -func LenInt(i int64) int { - if i < 0 { - if i == -9223372036854775808 { - return 19 - } - i = -i - } - switch { - case i < 10: - return 1 - case i < 100: - return 2 - case i < 1000: - return 3 - case i < 10000: - return 4 - case i < 100000: - return 5 - case i < 1000000: - return 6 - case i < 10000000: - return 7 - case i < 100000000: - return 8 - case i < 1000000000: - return 9 - case i < 10000000000: - return 10 - case i < 100000000000: - return 11 - case i < 1000000000000: - return 12 - case i < 10000000000000: - return 13 - case i < 100000000000000: - return 14 - case i < 1000000000000000: - return 15 - case i < 10000000000000000: - return 16 - case i < 100000000000000000: - return 17 - case i < 1000000000000000000: - return 18 - } - return 19 -} diff --git a/vendor/github.com/tdewolff/parse/strconv/int_test.go b/vendor/github.com/tdewolff/parse/strconv/int_test.go deleted file mode 100644 index 2df2cdf..0000000 --- a/vendor/github.com/tdewolff/parse/strconv/int_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package strconv // import "github.com/tdewolff/parse/strconv" - -import ( - "math" - "math/rand" - "testing" - - "github.com/tdewolff/test" -) - -func TestParseInt(t *testing.T) { - intTests := []struct { - i string - expected int64 - }{ - {"5", 5}, - {"99", 99}, - {"999", 999}, - {"-5", -5}, - {"+5", 5}, - {"9223372036854775807", 9223372036854775807}, - {"9223372036854775808", 0}, - {"-9223372036854775807", -9223372036854775807}, - {"-9223372036854775808", -9223372036854775808}, - {"-9223372036854775809", 0}, - {"18446744073709551620", 0}, - {"a", 0}, - } - for _, tt := range intTests { - i, _ := ParseInt([]byte(tt.i)) - test.That(t, i == tt.expected, "return", tt.expected, "for", tt.i) - } -} - -func TestLenInt(t *testing.T) { - lenIntTests := []struct { - number int64 - expected int - }{ - {0, 1}, - {1, 1}, - {10, 2}, - {99, 2}, - {9223372036854775807, 19}, - {-9223372036854775808, 19}, - - // coverage - {100, 3}, - {1000, 4}, - {10000, 5}, - {100000, 6}, - {1000000, 7}, - {10000000, 8}, - {100000000, 9}, - {1000000000, 10}, - {10000000000, 11}, - {100000000000, 12}, - {1000000000000, 13}, - {10000000000000, 14}, - {100000000000000, 15}, - {1000000000000000, 16}, - {10000000000000000, 17}, - {100000000000000000, 18}, - {1000000000000000000, 19}, - } - for _, tt := range lenIntTests { - test.That(t, LenInt(tt.number) == tt.expected, "return", tt.expected, "for", tt.number) - } -} - -//////////////////////////////////////////////////////////////// - -var num []int64 - -func TestMain(t *testing.T) { - for j := 0; j < 1000; j++ { - num = append(num, rand.Int63n(1000)) - } -} - -func BenchmarkLenIntLog(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for j := 0; j < 1000; j++ { - n += int(math.Log10(math.Abs(float64(num[j])))) + 1 - } - } -} - -func BenchmarkLenIntSwitch(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for j := 0; j < 1000; j++ { - n += LenInt(num[j]) - } - } -} diff --git a/vendor/github.com/tdewolff/parse/strconv/price.go b/vendor/github.com/tdewolff/parse/strconv/price.go deleted file mode 100644 index 94b3834..0000000 --- a/vendor/github.com/tdewolff/parse/strconv/price.go +++ /dev/null @@ -1,83 +0,0 @@ -package strconv - -// AppendPrice will append an int64 formatted as a price, where the int64 is the price in cents. -// It does not display whether a price is negative or not. -func AppendPrice(b []byte, price int64, dec bool, milSeparator byte, decSeparator byte) []byte { - if price < 0 { - if price == -9223372036854775808 { - x := []byte("92 233 720 368 547 758 08") - x[2] = milSeparator - x[6] = milSeparator - x[10] = milSeparator - x[14] = milSeparator - x[18] = milSeparator - x[22] = decSeparator - return append(b, x...) - } - price = -price - } - - // rounding - if !dec { - firstDec := (price / 10) % 10 - if firstDec >= 5 { - price += 100 - } - } - - // calculate size - n := LenInt(price) - 2 - if n > 0 { - n += (n - 1) / 3 // mil separator - } else { - n = 1 - } - if dec { - n += 2 + 1 // decimals + dec separator - } - - // resize byte slice - i := len(b) - if i+n > cap(b) { - b = append(b, make([]byte, n)...) - } else { - b = b[:i+n] - } - - // print fractional-part - i += n - 1 - if dec { - for j := 0; j < 2; j++ { - c := byte(price%10) + '0' - price /= 10 - b[i] = c - i-- - } - b[i] = decSeparator - i-- - } else { - price /= 100 - } - - if price == 0 { - b[i] = '0' - return b - } - - // print integer-part - j := 0 - for price > 0 { - if j == 3 { - b[i] = milSeparator - i-- - j = 0 - } - - c := byte(price%10) + '0' - price /= 10 - b[i] = c - i-- - j++ - } - return b -} diff --git a/vendor/github.com/tdewolff/parse/strconv/price_test.go b/vendor/github.com/tdewolff/parse/strconv/price_test.go deleted file mode 100644 index 3b3fccf..0000000 --- a/vendor/github.com/tdewolff/parse/strconv/price_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package strconv // import "github.com/tdewolff/parse/strconv" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestAppendPrice(t *testing.T) { - priceTests := []struct { - price int64 - dec bool - expected string - }{ - {0, false, "0"}, - {0, true, "0.00"}, - {100, true, "1.00"}, - {-100, true, "1.00"}, - {100000, false, "1,000"}, - {100000, true, "1,000.00"}, - {123456789012, true, "1,234,567,890.12"}, - {9223372036854775807, true, "92,233,720,368,547,758.07"}, - {-9223372036854775808, true, "92,233,720,368,547,758.08"}, - } - for _, tt := range priceTests { - price := AppendPrice([]byte{}, tt.price, tt.dec, ',', '.') - test.String(t, string(price), tt.expected, "for", tt.price) - } -} diff --git a/vendor/github.com/tdewolff/parse/svg/hash.go b/vendor/github.com/tdewolff/parse/svg/hash.go deleted file mode 100644 index 58528aa..0000000 --- a/vendor/github.com/tdewolff/parse/svg/hash.go +++ /dev/null @@ -1,295 +0,0 @@ -package svg - -// generated by hasher -type=Hash -file=hash.go; DO NOT EDIT, except for adding more constants to the list and rerun go generate - -// uses github.com/tdewolff/hasher -//go:generate hasher -type=Hash -file=hash.go - -// Hash defines perfect hashes for a predefined list of strings -type Hash uint32 - -// Unique hash definitions to be used instead of strings -const ( - A Hash = 0x101 // a - Alignment_Baseline Hash = 0x2e12 // alignment-baseline - BaseProfile Hash = 0xb // baseProfile - Baseline_Shift Hash = 0x380e // baseline-shift - Buffered_Rendering Hash = 0x5212 // buffered-rendering - Clip Hash = 0x6404 // clip - Clip_Path Hash = 0x6409 // clip-path - Clip_Rule Hash = 0x8009 // clip-rule - Color Hash = 0xd805 // color - Color_Interpolation Hash = 0xd813 // color-interpolation - Color_Interpolation_Filters Hash = 0xd81b // color-interpolation-filters - Color_Profile Hash = 0x1ea0d // color-profile - Color_Rendering Hash = 0x2250f // color-rendering - ContentScriptType Hash = 0xa011 // contentScriptType - ContentStyleType Hash = 0xb110 // contentStyleType - Cursor Hash = 0xc106 // cursor - D Hash = 0x5901 // d - Defs Hash = 0x35c04 // defs - Direction Hash = 0x2ff09 // direction - Display Hash = 0x9807 // display - Dominant_Baseline Hash = 0x18511 // dominant-baseline - Enable_Background Hash = 0x8811 // enable-background - FeImage Hash = 0x14507 // feImage - Fill Hash = 0xc904 // fill - Fill_Opacity Hash = 0x3300c // fill-opacity - Fill_Rule Hash = 0xc909 // fill-rule - Filter Hash = 0xec06 // filter - Flood_Color Hash = 0xd20b // flood-color - Flood_Opacity Hash = 0x1050d // flood-opacity - Font Hash = 0x11404 // font - Font_Family Hash = 0x1140b // font-family - Font_Size Hash = 0x11f09 // font-size - Font_Size_Adjust Hash = 0x11f10 // font-size-adjust - Font_Stretch Hash = 0x1370c // font-stretch - Font_Style Hash = 0x14c0a // font-style - Font_Variant Hash = 0x1560c // font-variant - Font_Weight Hash = 0x1620b // font-weight - G Hash = 0x1601 // g - Glyph_Orientation_Horizontal Hash = 0x1c61c // glyph-orientation-horizontal - Glyph_Orientation_Vertical Hash = 0x161a // glyph-orientation-vertical - Height Hash = 0x6c06 // height - Href Hash = 0x14204 // href - Image Hash = 0x16d05 // image - Image_Rendering Hash = 0x16d0f // image-rendering - Kerning Hash = 0x1af07 // kerning - Letter_Spacing Hash = 0x90e // letter-spacing - Lighting_Color Hash = 0x1e10e // lighting-color - Line Hash = 0x3c04 // line - Marker Hash = 0x17c06 // marker - Marker_End Hash = 0x17c0a // marker-end - Marker_Mid Hash = 0x1960a // marker-mid - Marker_Start Hash = 0x1a00c // marker-start - Mask Hash = 0x1ac04 // mask - Metadata Hash = 0x1b608 // metadata - Missing_Glyph Hash = 0x1be0d // missing-glyph - Opacity Hash = 0x10b07 // opacity - Overflow Hash = 0x25508 // overflow - Paint_Order Hash = 0x2a10b // paint-order - Path Hash = 0x6904 // path - Pattern Hash = 0x1f707 // pattern - Pointer_Events Hash = 0x1fe0e // pointer-events - Points Hash = 0x21a06 // points - Polygon Hash = 0x23407 // polygon - Polyline Hash = 0x23b08 // polyline - PreserveAspectRatio Hash = 0x24313 // preserveAspectRatio - Rect Hash = 0x30104 // rect - Rx Hash = 0x4f02 // rx - Ry Hash = 0xc602 // ry - Script Hash = 0xf206 // script - Shape_Rendering Hash = 0x20b0f // shape-rendering - Solid_Color Hash = 0x21f0b // solid-color - Solid_Opacity Hash = 0x35f0d // solid-opacity - Stop_Color Hash = 0x12d0a // stop-color - Stop_Opacity Hash = 0x2670c // stop-opacity - Stroke Hash = 0x27306 // stroke - Stroke_Dasharray Hash = 0x27310 // stroke-dasharray - Stroke_Dashoffset Hash = 0x28311 // stroke-dashoffset - Stroke_Linecap Hash = 0x2940e // stroke-linecap - Stroke_Linejoin Hash = 0x2ac0f // stroke-linejoin - Stroke_Miterlimit Hash = 0x2bb11 // stroke-miterlimit - Stroke_Opacity Hash = 0x2cc0e // stroke-opacity - Stroke_Width Hash = 0x2da0c // stroke-width - Style Hash = 0x15105 // style - Svg Hash = 0x2e603 // svg - Switch Hash = 0x2e906 // switch - Symbol Hash = 0x2ef06 // symbol - Text_Anchor Hash = 0x450b // text-anchor - Text_Decoration Hash = 0x710f // text-decoration - Text_Rendering Hash = 0xf70e // text-rendering - Type Hash = 0x11004 // type - Unicode_Bidi Hash = 0x2f50c // unicode-bidi - Use Hash = 0x30803 // use - Vector_Effect Hash = 0x30b0d // vector-effect - Version Hash = 0x31807 // version - ViewBox Hash = 0x31f07 // viewBox - Viewport_Fill Hash = 0x3270d // viewport-fill - Viewport_Fill_Opacity Hash = 0x32715 // viewport-fill-opacity - Visibility Hash = 0x33c0a // visibility - White_Space Hash = 0x25c0b // white-space - Width Hash = 0x2e105 // width - Word_Spacing Hash = 0x3460c // word-spacing - Writing_Mode Hash = 0x3520c // writing-mode - X Hash = 0x4701 // x - X1 Hash = 0x5002 // x1 - X2 Hash = 0x32502 // x2 - Xml_Space Hash = 0x36c09 // xml:space - Y Hash = 0x1801 // y - Y1 Hash = 0x9e02 // y1 - Y2 Hash = 0xc702 // y2 -) - -// String returns the hash' name. -func (i Hash) String() string { - start := uint32(i >> 8) - n := uint32(i & 0xff) - if start+n > uint32(len(_Hash_text)) { - return "" - } - return _Hash_text[start : start+n] -} - -// ToHash returns the hash whose name is s. It returns zero if there is no -// such hash. It is case sensitive. -func ToHash(s []byte) Hash { - if len(s) == 0 || len(s) > _Hash_maxLen { - return 0 - } - h := uint32(_Hash_hash0) - for i := 0; i < len(s); i++ { - h ^= uint32(s[i]) - h *= 16777619 - } - if i := _Hash_table[h&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - goto NEXT - } - } - return i - } -NEXT: - if i := _Hash_table[(h>>16)&uint32(len(_Hash_table)-1)]; int(i&0xff) == len(s) { - t := _Hash_text[i>>8 : i>>8+i&0xff] - for i := 0; i < len(s); i++ { - if t[i] != s[i] { - return 0 - } - } - return i - } - return 0 -} - -const _Hash_hash0 = 0x30372d7b -const _Hash_maxLen = 28 -const _Hash_text = "baseProfiletter-spacinglyph-orientation-verticalignment-base" + - "line-shiftext-anchorx1buffered-renderingclip-patheightext-de" + - "corationclip-rulenable-backgroundisplay1contentScriptTypecon" + - "tentStyleTypecursory2fill-ruleflood-color-interpolation-filt" + - "erscriptext-renderingflood-opacitypefont-familyfont-size-adj" + - "ustop-colorfont-stretchrefeImagefont-stylefont-variantfont-w" + - "eightimage-renderingmarker-endominant-baselinemarker-midmark" + - "er-startmaskerningmetadatamissing-glyph-orientation-horizont" + - "alighting-color-profilepatternpointer-eventshape-renderingpo" + - "intsolid-color-renderingpolygonpolylinepreserveAspectRatiove" + - "rflowhite-spacestop-opacitystroke-dasharraystroke-dashoffset" + - "stroke-linecapaint-orderstroke-linejoinstroke-miterlimitstro" + - "ke-opacitystroke-widthsvgswitchsymbolunicode-bidirectionusev" + - "ector-effectversionviewBox2viewport-fill-opacityvisibilitywo" + - "rd-spacingwriting-modefsolid-opacityxml:space" - -var _Hash_table = [1 << 7]Hash{ - 0x0: 0x2940e, // stroke-linecap - 0x1: 0x1140b, // font-family - 0x2: 0x23b08, // polyline - 0x3: 0x1f707, // pattern - 0x4: 0x30104, // rect - 0x5: 0x5212, // buffered-rendering - 0x7: 0x2f50c, // unicode-bidi - 0x8: 0x450b, // text-anchor - 0x9: 0x2bb11, // stroke-miterlimit - 0xa: 0xc909, // fill-rule - 0xb: 0x27310, // stroke-dasharray - 0xc: 0xc904, // fill - 0xd: 0x1af07, // kerning - 0xe: 0x2670c, // stop-opacity - 0x10: 0x1a00c, // marker-start - 0x11: 0x380e, // baseline-shift - 0x14: 0x17c0a, // marker-end - 0x15: 0x18511, // dominant-baseline - 0x16: 0xc602, // ry - 0x17: 0x161a, // glyph-orientation-vertical - 0x18: 0x5002, // x1 - 0x19: 0x20b0f, // shape-rendering - 0x1a: 0x32502, // x2 - 0x1b: 0x11f10, // font-size-adjust - 0x1c: 0x2250f, // color-rendering - 0x1d: 0x28311, // stroke-dashoffset - 0x1f: 0x3520c, // writing-mode - 0x20: 0x2e906, // switch - 0x21: 0xf70e, // text-rendering - 0x22: 0x23407, // polygon - 0x23: 0x3460c, // word-spacing - 0x24: 0x21f0b, // solid-color - 0x25: 0xec06, // filter - 0x26: 0x1801, // y - 0x27: 0x1be0d, // missing-glyph - 0x29: 0x11404, // font - 0x2a: 0x4f02, // rx - 0x2b: 0x9807, // display - 0x2c: 0x2e603, // svg - 0x2d: 0x1050d, // flood-opacity - 0x2f: 0x14204, // href - 0x30: 0x6404, // clip - 0x31: 0x3c04, // line - 0x32: 0x1620b, // font-weight - 0x33: 0x1c61c, // glyph-orientation-horizontal - 0x34: 0x6c06, // height - 0x35: 0x9e02, // y1 - 0x36: 0x6904, // path - 0x37: 0x31807, // version - 0x38: 0x2ac0f, // stroke-linejoin - 0x39: 0x4701, // x - 0x3a: 0x30803, // use - 0x3b: 0x2cc0e, // stroke-opacity - 0x3c: 0x15105, // style - 0x3d: 0x30b0d, // vector-effect - 0x3e: 0x14c0a, // font-style - 0x40: 0x16d05, // image - 0x41: 0x1e10e, // lighting-color - 0x42: 0xd813, // color-interpolation - 0x43: 0x27306, // stroke - 0x44: 0x2ef06, // symbol - 0x47: 0x8811, // enable-background - 0x48: 0x33c0a, // visibility - 0x49: 0x25508, // overflow - 0x4b: 0x31f07, // viewBox - 0x4c: 0x2e12, // alignment-baseline - 0x4d: 0x5901, // d - 0x4e: 0x1560c, // font-variant - 0x4f: 0x1ac04, // mask - 0x50: 0x21a06, // points - 0x51: 0x1b608, // metadata - 0x52: 0x710f, // text-decoration - 0x53: 0xd81b, // color-interpolation-filters - 0x54: 0x2ff09, // direction - 0x55: 0x6409, // clip-path - 0x56: 0x2da0c, // stroke-width - 0x59: 0x35f0d, // solid-opacity - 0x5a: 0xd805, // color - 0x5b: 0xd20b, // flood-color - 0x5c: 0x1601, // g - 0x5d: 0x2e105, // width - 0x5e: 0x1ea0d, // color-profile - 0x61: 0x35c04, // defs - 0x62: 0x1370c, // font-stretch - 0x63: 0x11004, // type - 0x64: 0x8009, // clip-rule - 0x66: 0x24313, // preserveAspectRatio - 0x67: 0x14507, // feImage - 0x68: 0x36c09, // xml:space - 0x69: 0xc106, // cursor - 0x6a: 0x16d0f, // image-rendering - 0x6b: 0x90e, // letter-spacing - 0x6c: 0xf206, // script - 0x6d: 0x12d0a, // stop-color - 0x6e: 0x101, // a - 0x70: 0x10b07, // opacity - 0x71: 0xb110, // contentStyleType - 0x72: 0x1fe0e, // pointer-events - 0x73: 0xb, // baseProfile - 0x74: 0x11f09, // font-size - 0x75: 0x3270d, // viewport-fill - 0x76: 0x3300c, // fill-opacity - 0x77: 0x25c0b, // white-space - 0x79: 0x17c06, // marker - 0x7b: 0x2a10b, // paint-order - 0x7c: 0xc702, // y2 - 0x7d: 0x32715, // viewport-fill-opacity - 0x7e: 0x1960a, // marker-mid - 0x7f: 0xa011, // contentScriptType -} diff --git a/vendor/github.com/tdewolff/parse/svg/hash_test.go b/vendor/github.com/tdewolff/parse/svg/hash_test.go deleted file mode 100644 index 7038a15..0000000 --- a/vendor/github.com/tdewolff/parse/svg/hash_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package svg // import "github.com/tdewolff/parse/svg" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestHashTable(t *testing.T) { - test.T(t, ToHash([]byte("svg")), Svg, "'svg' must resolve to hash.Svg") - test.T(t, ToHash([]byte("width")), Width, "'width' must resolve to hash.Width") - test.T(t, Svg.String(), "svg") - test.T(t, ToHash([]byte("")), Hash(0), "empty string must resolve to zero") - test.T(t, Hash(0xffffff).String(), "") - test.T(t, ToHash([]byte("svgs")), Hash(0), "'svgs' must resolve to zero") - test.T(t, ToHash([]byte("uopi")), Hash(0), "'uopi' must resolve to zero") -} diff --git a/vendor/github.com/tdewolff/parse/util.go b/vendor/github.com/tdewolff/parse/util.go deleted file mode 100644 index 83509a1..0000000 --- a/vendor/github.com/tdewolff/parse/util.go +++ /dev/null @@ -1,196 +0,0 @@ -package parse // import "github.com/tdewolff/parse" - -// Copy returns a copy of the given byte slice. -func Copy(src []byte) (dst []byte) { - dst = make([]byte, len(src)) - copy(dst, src) - return -} - -// ToLower converts all characters in the byte slice from A-Z to a-z. -func ToLower(src []byte) []byte { - for i, c := range src { - if c >= 'A' && c <= 'Z' { - src[i] = c + ('a' - 'A') - } - } - return src -} - -// EqualFold returns true when s matches case-insensitively the targetLower (which must be lowercase). -func EqualFold(s, targetLower []byte) bool { - if len(s) != len(targetLower) { - return false - } - for i, c := range targetLower { - if s[i] != c && (c < 'A' && c > 'Z' || s[i]+('a'-'A') != c) { - return false - } - } - return true -} - -var whitespaceTable = [256]bool{ - // ASCII - false, false, false, false, false, false, false, false, - false, true, true, false, true, true, false, false, // tab, new line, form feed, carriage return - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - true, false, false, false, false, false, false, false, // space - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - // non-ASCII - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, -} - -// IsWhitespace returns true for space, \n, \r, \t, \f. -func IsWhitespace(c byte) bool { - return whitespaceTable[c] -} - -var newlineTable = [256]bool{ - // ASCII - false, false, false, false, false, false, false, false, - false, false, true, false, false, true, false, false, // new line, carriage return - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - // non-ASCII - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, -} - -// IsNewline returns true for \n, \r. -func IsNewline(c byte) bool { - return newlineTable[c] -} - -// IsAllWhitespace returns true when the entire byte slice consists of space, \n, \r, \t, \f. -func IsAllWhitespace(b []byte) bool { - for _, c := range b { - if !IsWhitespace(c) { - return false - } - } - return true -} - -// TrimWhitespace removes any leading and trailing whitespace characters. -func TrimWhitespace(b []byte) []byte { - n := len(b) - start := n - for i := 0; i < n; i++ { - if !IsWhitespace(b[i]) { - start = i - break - } - } - end := n - for i := n - 1; i >= start; i-- { - if !IsWhitespace(b[i]) { - end = i + 1 - break - } - } - return b[start:end] -} - -// ReplaceMultipleWhitespace replaces character series of space, \n, \t, \f, \r into a single space or newline (when the serie contained a \n or \r). -func ReplaceMultipleWhitespace(b []byte) []byte { - j := 0 - prevWS := false - hasNewline := false - for i, c := range b { - if IsWhitespace(c) { - prevWS = true - if IsNewline(c) { - hasNewline = true - } - } else { - if prevWS { - prevWS = false - if hasNewline { - hasNewline = false - b[j] = '\n' - } else { - b[j] = ' ' - } - j++ - } - b[j] = b[i] - j++ - } - } - if prevWS { - if hasNewline { - b[j] = '\n' - } else { - b[j] = ' ' - } - j++ - } - return b[:j] -} diff --git a/vendor/github.com/tdewolff/parse/util_test.go b/vendor/github.com/tdewolff/parse/util_test.go deleted file mode 100644 index c08c124..0000000 --- a/vendor/github.com/tdewolff/parse/util_test.go +++ /dev/null @@ -1,176 +0,0 @@ -package parse // import "github.com/tdewolff/parse" - -import ( - "bytes" - "math/rand" - "regexp" - "testing" - - "github.com/tdewolff/test" -) - -func helperRand(n, m int, chars []byte) [][]byte { - r := make([][]byte, n) - for i := range r { - for j := 0; j < m; j++ { - r[i] = append(r[i], chars[rand.Intn(len(chars))]) - } - } - return r -} - -//////////////////////////////////////////////////////////////// - -var wsSlices [][]byte - -func init() { - wsSlices = helperRand(100, 20, []byte("abcdefg \n\r\f\t")) -} - -func TestCopy(t *testing.T) { - foo := []byte("abc") - bar := Copy(foo) - foo[0] = 'b' - test.String(t, string(foo), "bbc") - test.String(t, string(bar), "abc") -} - -func TestToLower(t *testing.T) { - foo := []byte("Abc") - bar := ToLower(foo) - bar[1] = 'B' - test.String(t, string(foo), "aBc") - test.String(t, string(bar), "aBc") -} - -func TestEqualFold(t *testing.T) { - test.That(t, EqualFold([]byte("Abc"), []byte("abc"))) - test.That(t, !EqualFold([]byte("Abcd"), []byte("abc"))) - test.That(t, !EqualFold([]byte("Bbc"), []byte("abc"))) -} - -func TestWhitespace(t *testing.T) { - test.That(t, IsAllWhitespace([]byte("\t \r\n\f"))) - test.That(t, !IsAllWhitespace([]byte("\t \r\n\fx"))) -} - -func TestReplaceMultipleWhitespace(t *testing.T) { - wsRegexp := regexp.MustCompile("[ \t\f]+") - wsNewlinesRegexp := regexp.MustCompile("[ ]*[\r\n][ \r\n]*") - for _, e := range wsSlices { - reference := wsRegexp.ReplaceAll(e, []byte(" ")) - reference = wsNewlinesRegexp.ReplaceAll(reference, []byte("\n")) - test.Bytes(t, ReplaceMultipleWhitespace(e), reference, "must remove all multiple whitespace but keep newlines") - } -} - -func TestTrim(t *testing.T) { - test.Bytes(t, TrimWhitespace([]byte("a")), []byte("a")) - test.Bytes(t, TrimWhitespace([]byte(" a")), []byte("a")) - test.Bytes(t, TrimWhitespace([]byte("a ")), []byte("a")) - test.Bytes(t, TrimWhitespace([]byte(" ")), []byte("")) -} - -//////////////////////////////////////////////////////////////// - -func BenchmarkBytesTrim(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - bytes.TrimSpace(e) - } - } -} - -func BenchmarkTrim(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - TrimWhitespace(e) - } - } -} - -func BenchmarkReplace(b *testing.B) { - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - ReplaceMultipleWhitespace(e) - } - } -} - -func BenchmarkWhitespaceTable(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - for _, c := range e { - if IsWhitespace(c) { - n++ - } - } - } - } -} - -func BenchmarkWhitespaceIf1(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - for _, c := range e { - if c == ' ' { - n++ - } - } - } - } -} - -func BenchmarkWhitespaceIf2(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - for _, c := range e { - if c == ' ' || c == '\n' { - n++ - } - } - } - } -} - -func BenchmarkWhitespaceIf3(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - for _, c := range e { - if c == ' ' || c == '\n' || c == '\r' { - n++ - } - } - } - } -} - -func BenchmarkWhitespaceIf4(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - for _, c := range e { - if c == ' ' || c == '\n' || c == '\r' || c == '\t' { - n++ - } - } - } - } -} - -func BenchmarkWhitespaceIf5(b *testing.B) { - n := 0 - for i := 0; i < b.N; i++ { - for _, e := range wsSlices { - for _, c := range e { - if c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == '\f' { - n++ - } - } - } - } -} diff --git a/vendor/github.com/tdewolff/parse/xml/README.md b/vendor/github.com/tdewolff/parse/xml/README.md deleted file mode 100644 index 3aaf6f4..0000000 --- a/vendor/github.com/tdewolff/parse/xml/README.md +++ /dev/null @@ -1,101 +0,0 @@ -# XML [![GoDoc](http://godoc.org/github.com/tdewolff/parse/xml?status.svg)](http://godoc.org/github.com/tdewolff/parse/xml) [![GoCover](http://gocover.io/_badge/github.com/tdewolff/parse/xml)](http://gocover.io/github.com/tdewolff/parse/xml) - -This package is an XML lexer written in [Go][1]. It follows the specification at [Extensible Markup Language (XML) 1.0 (Fifth Edition)](http://www.w3.org/TR/REC-xml/). The lexer takes an io.Reader and converts it into tokens until the EOF. - -## Installation -Run the following command - - go get github.com/tdewolff/parse/xml - -or add the following import and run project with `go get` - - import "github.com/tdewolff/parse/xml" - -## Lexer -### Usage -The following initializes a new Lexer with io.Reader `r`: -``` go -l := xml.NewLexer(r) -``` - -To tokenize until EOF an error, use: -``` go -for { - tt, data := l.Next() - switch tt { - case xml.ErrorToken: - // error or EOF set in l.Err() - return - case xml.StartTagToken: - // ... - for { - ttAttr, dataAttr := l.Next() - if ttAttr != xml.AttributeToken { - // handle StartTagCloseToken/StartTagCloseVoidToken/StartTagClosePIToken - break - } - // ... - } - case xml.EndTagToken: - // ... - } -} -``` - -All tokens: -``` go -ErrorToken TokenType = iota // extra token when errors occur -CommentToken -CDATAToken -StartTagToken -StartTagCloseToken -StartTagCloseVoidToken -StartTagClosePIToken -EndTagToken -AttributeToken -TextToken -``` - -### Examples -``` go -package main - -import ( - "os" - - "github.com/tdewolff/parse/xml" -) - -// Tokenize XML from stdin. -func main() { - l := xml.NewLexer(os.Stdin) - for { - tt, data := l.Next() - switch tt { - case xml.ErrorToken: - if l.Err() != io.EOF { - fmt.Println("Error on line", l.Line(), ":", l.Err()) - } - return - case xml.StartTagToken: - fmt.Println("Tag", string(data)) - for { - ttAttr, dataAttr := l.Next() - if ttAttr != xml.AttributeToken { - break - } - - key := dataAttr - val := l.AttrVal() - fmt.Println("Attribute", string(key), "=", string(val)) - } - // ... - } - } -} -``` - -## License -Released under the [MIT license](https://github.com/tdewolff/parse/blob/master/LICENSE.md). - -[1]: http://golang.org/ "Go Language" diff --git a/vendor/github.com/tdewolff/parse/xml/lex.go b/vendor/github.com/tdewolff/parse/xml/lex.go deleted file mode 100644 index c7ea4d1..0000000 --- a/vendor/github.com/tdewolff/parse/xml/lex.go +++ /dev/null @@ -1,348 +0,0 @@ -// Package xml is an XML1.0 lexer following the specifications at http://www.w3.org/TR/xml/. -package xml // import "github.com/tdewolff/parse/xml" - -import ( - "io" - "strconv" - - "github.com/tdewolff/parse" - "github.com/tdewolff/parse/buffer" -) - -// TokenType determines the type of token, eg. a number or a semicolon. -type TokenType uint32 - -// TokenType values. -const ( - ErrorToken TokenType = iota // extra token when errors occur - CommentToken - DOCTYPEToken - CDATAToken - StartTagToken - StartTagPIToken - StartTagCloseToken - StartTagCloseVoidToken - StartTagClosePIToken - EndTagToken - AttributeToken - TextToken -) - -// String returns the string representation of a TokenType. -func (tt TokenType) String() string { - switch tt { - case ErrorToken: - return "Error" - case CommentToken: - return "Comment" - case DOCTYPEToken: - return "DOCTYPE" - case CDATAToken: - return "CDATA" - case StartTagToken: - return "StartTag" - case StartTagPIToken: - return "StartTagPI" - case StartTagCloseToken: - return "StartTagClose" - case StartTagCloseVoidToken: - return "StartTagCloseVoid" - case StartTagClosePIToken: - return "StartTagClosePI" - case EndTagToken: - return "EndTag" - case AttributeToken: - return "Attribute" - case TextToken: - return "Text" - } - return "Invalid(" + strconv.Itoa(int(tt)) + ")" -} - -//////////////////////////////////////////////////////////////// - -// Lexer is the state for the lexer. -type Lexer struct { - r *buffer.Lexer - err error - - inTag bool - - text []byte - attrVal []byte -} - -// NewLexer returns a new Lexer for a given io.Reader. -func NewLexer(r io.Reader) *Lexer { - return &Lexer{ - r: buffer.NewLexer(r), - } -} - -// Err returns the error encountered during lexing, this is often io.EOF but also other errors can be returned. -func (l *Lexer) Err() error { - if l.err != nil { - return l.err - } - return l.r.Err() -} - -// Restore restores the NULL byte at the end of the buffer. -func (l *Lexer) Restore() { - l.r.Restore() -} - -// Next returns the next Token. It returns ErrorToken when an error was encountered. Using Err() one can retrieve the error message. -func (l *Lexer) Next() (TokenType, []byte) { - l.text = nil - var c byte - if l.inTag { - l.attrVal = nil - for { // before attribute name state - if c = l.r.Peek(0); c == ' ' || c == '\t' || c == '\n' || c == '\r' { - l.r.Move(1) - continue - } - break - } - if c == 0 { - if l.r.Err() == nil { - l.err = parse.NewErrorLexer("unexpected null character", l.r) - } - return ErrorToken, nil - } else if c != '>' && (c != '/' && c != '?' || l.r.Peek(1) != '>') { - return AttributeToken, l.shiftAttribute() - } - start := l.r.Pos() - l.inTag = false - if c == '/' { - l.r.Move(2) - l.text = l.r.Lexeme()[start:] - return StartTagCloseVoidToken, l.r.Shift() - } else if c == '?' { - l.r.Move(2) - l.text = l.r.Lexeme()[start:] - return StartTagClosePIToken, l.r.Shift() - } else { - l.r.Move(1) - l.text = l.r.Lexeme()[start:] - return StartTagCloseToken, l.r.Shift() - } - } - - for { - c = l.r.Peek(0) - if c == '<' { - if l.r.Pos() > 0 { - return TextToken, l.r.Shift() - } - c = l.r.Peek(1) - if c == '/' { - l.r.Move(2) - return EndTagToken, l.shiftEndTag() - } else if c == '!' { - l.r.Move(2) - if l.at('-', '-') { - l.r.Move(2) - return CommentToken, l.shiftCommentText() - } else if l.at('[', 'C', 'D', 'A', 'T', 'A', '[') { - l.r.Move(7) - return CDATAToken, l.shiftCDATAText() - } else if l.at('D', 'O', 'C', 'T', 'Y', 'P', 'E') { - l.r.Move(7) - return DOCTYPEToken, l.shiftDOCTYPEText() - } - l.r.Move(-2) - } else if c == '?' { - l.r.Move(2) - l.inTag = true - return StartTagPIToken, l.shiftStartTag() - } - l.r.Move(1) - l.inTag = true - return StartTagToken, l.shiftStartTag() - } else if c == 0 { - if l.r.Pos() > 0 { - return TextToken, l.r.Shift() - } - if l.r.Err() == nil { - l.err = parse.NewErrorLexer("unexpected null character", l.r) - } - return ErrorToken, nil - } - l.r.Move(1) - } -} - -// Text returns the textual representation of a token. This excludes delimiters and additional leading/trailing characters. -func (l *Lexer) Text() []byte { - return l.text -} - -// AttrVal returns the attribute value when an AttributeToken was returned from Next. -func (l *Lexer) AttrVal() []byte { - return l.attrVal -} - -//////////////////////////////////////////////////////////////// - -// The following functions follow the specifications at http://www.w3.org/html/wg/drafts/html/master/syntax.html - -func (l *Lexer) shiftDOCTYPEText() []byte { - inString := false - inBrackets := false - for { - c := l.r.Peek(0) - if c == '"' { - inString = !inString - } else if (c == '[' || c == ']') && !inString { - inBrackets = (c == '[') - } else if c == '>' && !inString && !inBrackets { - l.text = l.r.Lexeme()[9:] - l.r.Move(1) - return l.r.Shift() - } else if c == 0 { - l.text = l.r.Lexeme()[9:] - return l.r.Shift() - } - l.r.Move(1) - } -} - -func (l *Lexer) shiftCDATAText() []byte { - for { - c := l.r.Peek(0) - if c == ']' && l.r.Peek(1) == ']' && l.r.Peek(2) == '>' { - l.text = l.r.Lexeme()[9:] - l.r.Move(3) - return l.r.Shift() - } else if c == 0 { - l.text = l.r.Lexeme()[9:] - return l.r.Shift() - } - l.r.Move(1) - } -} - -func (l *Lexer) shiftCommentText() []byte { - for { - c := l.r.Peek(0) - if c == '-' && l.r.Peek(1) == '-' && l.r.Peek(2) == '>' { - l.text = l.r.Lexeme()[4:] - l.r.Move(3) - return l.r.Shift() - } else if c == 0 { - return l.r.Shift() - } - l.r.Move(1) - } -} - -func (l *Lexer) shiftStartTag() []byte { - nameStart := l.r.Pos() - for { - if c := l.r.Peek(0); c == ' ' || c == '>' || (c == '/' || c == '?') && l.r.Peek(1) == '>' || c == '\t' || c == '\n' || c == '\r' || c == 0 { - break - } - l.r.Move(1) - } - l.text = l.r.Lexeme()[nameStart:] - return l.r.Shift() -} - -func (l *Lexer) shiftAttribute() []byte { - nameStart := l.r.Pos() - var c byte - for { // attribute name state - if c = l.r.Peek(0); c == ' ' || c == '=' || c == '>' || (c == '/' || c == '?') && l.r.Peek(1) == '>' || c == '\t' || c == '\n' || c == '\r' || c == 0 { - break - } - l.r.Move(1) - } - nameEnd := l.r.Pos() - for { // after attribute name state - if c = l.r.Peek(0); c == ' ' || c == '\t' || c == '\n' || c == '\r' { - l.r.Move(1) - continue - } - break - } - if c == '=' { - l.r.Move(1) - for { // before attribute value state - if c = l.r.Peek(0); c == ' ' || c == '\t' || c == '\n' || c == '\r' { - l.r.Move(1) - continue - } - break - } - attrPos := l.r.Pos() - delim := c - if delim == '"' || delim == '\'' { // attribute value single- and double-quoted state - l.r.Move(1) - for { - c = l.r.Peek(0) - if c == delim { - l.r.Move(1) - break - } else if c == 0 { - break - } - l.r.Move(1) - if c == '\t' || c == '\n' || c == '\r' { - l.r.Lexeme()[l.r.Pos()-1] = ' ' - } - } - } else { // attribute value unquoted state - for { - if c = l.r.Peek(0); c == ' ' || c == '>' || (c == '/' || c == '?') && l.r.Peek(1) == '>' || c == '\t' || c == '\n' || c == '\r' || c == 0 { - break - } - l.r.Move(1) - } - } - l.attrVal = l.r.Lexeme()[attrPos:] - } else { - l.r.Rewind(nameEnd) - l.attrVal = nil - } - l.text = l.r.Lexeme()[nameStart:nameEnd] - return l.r.Shift() -} - -func (l *Lexer) shiftEndTag() []byte { - for { - c := l.r.Peek(0) - if c == '>' { - l.text = l.r.Lexeme()[2:] - l.r.Move(1) - break - } else if c == 0 { - l.text = l.r.Lexeme()[2:] - break - } - l.r.Move(1) - } - - end := len(l.text) - for end > 0 { - if c := l.text[end-1]; c == ' ' || c == '\t' || c == '\n' || c == '\r' { - end-- - continue - } - break - } - l.text = l.text[:end] - return l.r.Shift() -} - -//////////////////////////////////////////////////////////////// - -func (l *Lexer) at(b ...byte) bool { - for i, c := range b { - if l.r.Peek(i) != c { - return false - } - } - return true -} diff --git a/vendor/github.com/tdewolff/parse/xml/lex_test.go b/vendor/github.com/tdewolff/parse/xml/lex_test.go deleted file mode 100644 index d7d0e4a..0000000 --- a/vendor/github.com/tdewolff/parse/xml/lex_test.go +++ /dev/null @@ -1,195 +0,0 @@ -package xml // import "github.com/tdewolff/parse/xml" - -import ( - "bytes" - "fmt" - "io" - "testing" - - "github.com/tdewolff/parse" - "github.com/tdewolff/test" -) - -type TTs []TokenType - -func TestTokens(t *testing.T) { - var tokenTests = []struct { - xml string - expected []TokenType - }{ - {"", TTs{}}, - {"<!-- comment -->", TTs{CommentToken}}, - {"<!-- comment \n multi \r line -->", TTs{CommentToken}}, - {"<foo/>", TTs{StartTagToken, StartTagCloseVoidToken}}, - {"<foo \t\r\n/>", TTs{StartTagToken, StartTagCloseVoidToken}}, - {"<foo:bar.qux-norf/>", TTs{StartTagToken, StartTagCloseVoidToken}}, - {"<foo></foo>", TTs{StartTagToken, StartTagCloseToken, EndTagToken}}, - {"<foo>text</foo>", TTs{StartTagToken, StartTagCloseToken, TextToken, EndTagToken}}, - {"<foo/> text", TTs{StartTagToken, StartTagCloseVoidToken, TextToken}}, - {"<a> <b> <c>text</c> </b> </a>", TTs{StartTagToken, StartTagCloseToken, TextToken, StartTagToken, StartTagCloseToken, TextToken, StartTagToken, StartTagCloseToken, TextToken, EndTagToken, TextToken, EndTagToken, TextToken, EndTagToken}}, - {"<foo a='a' b=\"b\" c=c/>", TTs{StartTagToken, AttributeToken, AttributeToken, AttributeToken, StartTagCloseVoidToken}}, - {"<foo a=\"\"/>", TTs{StartTagToken, AttributeToken, StartTagCloseVoidToken}}, - {"<foo a-b=\"\"/>", TTs{StartTagToken, AttributeToken, StartTagCloseVoidToken}}, - {"<foo \nchecked \r\n value\r=\t'=/>\"' />", TTs{StartTagToken, AttributeToken, AttributeToken, StartTagCloseVoidToken}}, - {"<?xml?>", TTs{StartTagPIToken, StartTagClosePIToken}}, - {"<?xml a=\"a\" ?>", TTs{StartTagPIToken, AttributeToken, StartTagClosePIToken}}, - {"<?xml a=a?>", TTs{StartTagPIToken, AttributeToken, StartTagClosePIToken}}, - {"<![CDATA[ test ]]>", TTs{CDATAToken}}, - {"<!DOCTYPE>", TTs{DOCTYPEToken}}, - {"<!DOCTYPE note SYSTEM \"Note.dtd\">", TTs{DOCTYPEToken}}, - {`<!DOCTYPE note [<!ENTITY nbsp " "><!ENTITY writer "Writer: Donald Duck."><!ENTITY copyright "Copyright:]> W3Schools.">]>`, TTs{DOCTYPEToken}}, - {"<!foo>", TTs{StartTagToken, StartTagCloseToken}}, - - // early endings - {"<!-- comment", TTs{CommentToken}}, - {"<foo", TTs{StartTagToken}}, - {"</foo", TTs{EndTagToken}}, - {"<foo x", TTs{StartTagToken, AttributeToken}}, - {"<foo x=", TTs{StartTagToken, AttributeToken}}, - {"<foo x='", TTs{StartTagToken, AttributeToken}}, - {"<foo x=''", TTs{StartTagToken, AttributeToken}}, - {"<?xml", TTs{StartTagPIToken}}, - {"<![CDATA[ test", TTs{CDATAToken}}, - {"<!DOCTYPE note SYSTEM", TTs{DOCTYPEToken}}, - - // go fuzz - {"</", TTs{EndTagToken}}, - {"</\n", TTs{EndTagToken}}, - } - for _, tt := range tokenTests { - t.Run(tt.xml, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.xml)) - i := 0 - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } - test.That(t, i < len(tt.expected), "index", i, "must not exceed expected token types size", len(tt.expected)) - if i < len(tt.expected) { - test.T(t, token, tt.expected[i], "token types must match") - } - i++ - } - }) - } - - test.T(t, TokenType(100).String(), "Invalid(100)") -} - -func TestTags(t *testing.T) { - var tagTests = []struct { - xml string - expected string - }{ - {"<foo:bar.qux-norf/>", "foo:bar.qux-norf"}, - {"<?xml?>", "xml"}, - {"<foo?bar/qux>", "foo?bar/qux"}, - {"<!DOCTYPE note SYSTEM \"Note.dtd\">", " note SYSTEM \"Note.dtd\""}, - - // early endings - {"<foo ", "foo"}, - } - for _, tt := range tagTests { - t.Run(tt.xml, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.xml)) - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.Fail(t, "when error occurred we must be at the end") - break - } else if token == StartTagToken || token == StartTagPIToken || token == EndTagToken || token == DOCTYPEToken { - test.String(t, string(l.Text()), tt.expected, "tags must match") - break - } - } - }) - } -} - -func TestAttributes(t *testing.T) { - var attributeTests = []struct { - attr string - expected []string - }{ - {"<foo a=\"b\" />", []string{"a", "\"b\""}}, - {"<foo \nchecked \r\n value\r=\t'=/>\"' />", []string{"checked", "", "value", "'=/>\"'"}}, - {"<foo bar=\" a \n\t\r b \" />", []string{"bar", "\" a b \""}}, - {"<?xml a=b?>", []string{"a", "b"}}, - {"<foo /=? >", []string{"/", "?"}}, - - // early endings - {"<foo x", []string{"x", ""}}, - {"<foo x=", []string{"x", ""}}, - {"<foo x='", []string{"x", "'"}}, - } - for _, tt := range attributeTests { - t.Run(tt.attr, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.attr)) - i := 0 - for { - token, _ := l.Next() - if token == ErrorToken { - test.T(t, l.Err(), io.EOF) - test.T(t, i, len(tt.expected), "when error occurred we must be at the end") - break - } else if token == AttributeToken { - test.That(t, i+1 < len(tt.expected), "index", i+1, "must not exceed expected attributes size", len(tt.expected)) - if i+1 < len(tt.expected) { - test.String(t, string(l.Text()), tt.expected[i], "attribute keys must match") - test.String(t, string(l.AttrVal()), tt.expected[i+1], "attribute keys must match") - i += 2 - } - } - } - }) - } -} - -func TestErrors(t *testing.T) { - var errorTests = []struct { - xml string - col int - }{ - {"a\x00b", 2}, - {"<a\x00>", 3}, - } - for _, tt := range errorTests { - t.Run(tt.xml, func(t *testing.T) { - l := NewLexer(bytes.NewBufferString(tt.xml)) - for { - token, _ := l.Next() - if token == ErrorToken { - if tt.col == 0 { - test.T(t, l.Err(), io.EOF) - } else if perr, ok := l.Err().(*parse.Error); ok { - _, col, _ := perr.Position() - test.T(t, col, tt.col) - } else { - test.Fail(t, "bad error:", l.Err()) - } - break - } - } - }) - } -} - -//////////////////////////////////////////////////////////////// - -func ExampleNewLexer() { - l := NewLexer(bytes.NewBufferString("<span class='user'>John Doe</span>")) - out := "" - for { - tt, data := l.Next() - if tt == ErrorToken { - break - } - out += string(data) - } - fmt.Println(out) - // Output: <span class='user'>John Doe</span> -} diff --git a/vendor/github.com/tdewolff/parse/xml/util.go b/vendor/github.com/tdewolff/parse/xml/util.go deleted file mode 100644 index 1501b9b..0000000 --- a/vendor/github.com/tdewolff/parse/xml/util.go +++ /dev/null @@ -1,108 +0,0 @@ -package xml // import "github.com/tdewolff/parse/xml" - -import "github.com/tdewolff/parse" - -var ( - ltEntityBytes = []byte("<") - ampEntityBytes = []byte("&") - singleQuoteEntityBytes = []byte("'") - doubleQuoteEntityBytes = []byte(""") -) - -// EscapeAttrVal returns the escape attribute value bytes without quotes. -func EscapeAttrVal(buf *[]byte, b []byte) []byte { - singles := 0 - doubles := 0 - for i, c := range b { - if c == '&' { - if quote, n := parse.QuoteEntity(b[i:]); n > 0 { - if quote == '"' { - doubles++ - } else { - singles++ - } - } - } else if c == '"' { - doubles++ - } else if c == '\'' { - singles++ - } - } - - n := len(b) + 2 - var quote byte - var escapedQuote []byte - if doubles > singles { - n += singles * 4 - quote = '\'' - escapedQuote = singleQuoteEntityBytes - } else { - n += doubles * 4 - quote = '"' - escapedQuote = doubleQuoteEntityBytes - } - if n > cap(*buf) { - *buf = make([]byte, 0, n) // maximum size, not actual size - } - t := (*buf)[:n] // maximum size, not actual size - t[0] = quote - j := 1 - start := 0 - for i, c := range b { - if c == '&' { - if entityQuote, n := parse.QuoteEntity(b[i:]); n > 0 { - j += copy(t[j:], b[start:i]) - if entityQuote != quote { - t[j] = entityQuote - j++ - } else { - j += copy(t[j:], escapedQuote) - } - start = i + n - } - } else if c == quote { - j += copy(t[j:], b[start:i]) - j += copy(t[j:], escapedQuote) - start = i + 1 - } - } - j += copy(t[j:], b[start:]) - t[j] = quote - return t[:j+1] -} - -// EscapeCDATAVal returns the escaped text bytes. -func EscapeCDATAVal(buf *[]byte, b []byte) ([]byte, bool) { - n := 0 - for _, c := range b { - if c == '<' || c == '&' { - if c == '<' { - n += 3 // < - } else { - n += 4 // & - } - if n > len("<![CDATA[]]>") { - return b, false - } - } - } - if len(b)+n > cap(*buf) { - *buf = make([]byte, 0, len(b)+n) - } - t := (*buf)[:len(b)+n] - j := 0 - start := 0 - for i, c := range b { - if c == '<' { - j += copy(t[j:], b[start:i]) - j += copy(t[j:], ltEntityBytes) - start = i + 1 - } else if c == '&' { - j += copy(t[j:], b[start:i]) - j += copy(t[j:], ampEntityBytes) - start = i + 1 - } - } - j += copy(t[j:], b[start:]) - return t[:j], true -} diff --git a/vendor/github.com/tdewolff/parse/xml/util_test.go b/vendor/github.com/tdewolff/parse/xml/util_test.go deleted file mode 100644 index 65be6b8..0000000 --- a/vendor/github.com/tdewolff/parse/xml/util_test.go +++ /dev/null @@ -1,63 +0,0 @@ -package xml // import "github.com/tdewolff/parse/xml" - -import ( - "testing" - - "github.com/tdewolff/test" -) - -func TestEscapeAttrVal(t *testing.T) { - var attrValTests = []struct { - attrVal string - expected string - }{ - {"xyz", "\"xyz\""}, - {"", "\"\""}, - {"x&z", "\"x&z\""}, - {"x'z", "\"x'z\""}, - {"x\"z", "'x\"z'"}, - {"a'b=\"\"", "'a'b=\"\"'"}, - {"'x'\"'z'", "\"x'"'z\""}, - {"\"x"'"z\"", "'x\"'\"z'"}, - {"a'b=\"\"", "'a'b=\"\"'"}, - } - var buf []byte - for _, tt := range attrValTests { - t.Run(tt.attrVal, func(t *testing.T) { - b := []byte(tt.attrVal) - if len(b) > 1 && (b[0] == '"' || b[0] == '\'') && b[0] == b[len(b)-1] { - b = b[1 : len(b)-1] - } - val := EscapeAttrVal(&buf, []byte(b)) - test.String(t, string(val), tt.expected) - }) - } -} - -func TestEscapeCDATAVal(t *testing.T) { - var CDATAValTests = []struct { - CDATAVal string - expected string - }{ - {"<![CDATA[<b>]]>", "<b>"}, - {"<![CDATA[abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz]]>", "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"}, - {"<![CDATA[ <b> ]]>", " <b> "}, - {"<![CDATA[<<<<<]]>", "<![CDATA[<<<<<]]>"}, - {"<![CDATA[&]]>", "&"}, - {"<![CDATA[&&&&]]>", "<![CDATA[&&&&]]>"}, - {"<![CDATA[ a ]]>", " a "}, - {"<![CDATA[]]>", ""}, - } - var buf []byte - for _, tt := range CDATAValTests { - t.Run(tt.CDATAVal, func(t *testing.T) { - b := []byte(tt.CDATAVal[len("<![CDATA[") : len(tt.CDATAVal)-len("]]>")]) - data, useText := EscapeCDATAVal(&buf, b) - text := string(data) - if !useText { - text = "<![CDATA[" + text + "]]>" - } - test.String(t, text, tt.expected) - }) - } -} |