Rip out column counting.
This makes both the lexer and parser quite a bit easier to use. Counting column numbers isn't also really needed when parsing XML/HTML.
This commit is contained in:
parent
70a39042e7
commit
74bc11a239
|
@ -3,7 +3,7 @@ module Oga
|
||||||
##
|
##
|
||||||
#
|
#
|
||||||
class Node < ::AST::Node
|
class Node < ::AST::Node
|
||||||
attr_reader :line, :column
|
attr_reader :line
|
||||||
end # Node
|
end # Node
|
||||||
end # AST
|
end # AST
|
||||||
end # Oga
|
end # Oga
|
||||||
|
|
|
@ -72,7 +72,6 @@ module Oga
|
||||||
#
|
#
|
||||||
def reset
|
def reset
|
||||||
@line = 1
|
@line = 1
|
||||||
@column = 1
|
|
||||||
@data = nil
|
@data = nil
|
||||||
@ts = nil
|
@ts = nil
|
||||||
@te = nil
|
@te = nil
|
||||||
|
@ -124,15 +123,7 @@ module Oga
|
||||||
# @param [Fixnum] amount The amount of lines to advance.
|
# @param [Fixnum] amount The amount of lines to advance.
|
||||||
#
|
#
|
||||||
def advance_line(amount = 1)
|
def advance_line(amount = 1)
|
||||||
@line += amount
|
@line += amount
|
||||||
@column = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
##
|
|
||||||
# @param [Fixnum] length The amount of columns to advance.
|
|
||||||
#
|
|
||||||
def advance_column(length = 1)
|
|
||||||
@column += length
|
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -166,16 +157,13 @@ module Oga
|
||||||
end
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# Adds a token with the given type and value to the list. If a value is
|
# Adds a token with the given type and value to the list.
|
||||||
# given the column number is also advanced based on the value's length.
|
|
||||||
#
|
#
|
||||||
# @param [Symbol] type The token type.
|
# @param [Symbol] type The token type.
|
||||||
# @param [String] value The token value.
|
# @param [String] value The token value.
|
||||||
#
|
#
|
||||||
def add_token(type, value)
|
def add_token(type, value)
|
||||||
token = [type, value, @line, @column]
|
token = [type, value, @line]
|
||||||
|
|
||||||
advance_column(value.length) if value
|
|
||||||
|
|
||||||
@tokens << token
|
@tokens << token
|
||||||
end
|
end
|
||||||
|
@ -214,7 +202,6 @@ module Oga
|
||||||
#
|
#
|
||||||
def emit_string_buffer
|
def emit_string_buffer
|
||||||
add_token(:T_STRING, @string_buffer)
|
add_token(:T_STRING, @string_buffer)
|
||||||
advance_column
|
|
||||||
|
|
||||||
@string_buffer = ''
|
@string_buffer = ''
|
||||||
end
|
end
|
||||||
|
@ -264,7 +251,6 @@ module Oga
|
||||||
^dquote => buffer_string;
|
^dquote => buffer_string;
|
||||||
dquote => {
|
dquote => {
|
||||||
emit_string_buffer
|
emit_string_buffer
|
||||||
advance_column
|
|
||||||
fret;
|
fret;
|
||||||
};
|
};
|
||||||
*|;
|
*|;
|
||||||
|
@ -274,7 +260,6 @@ module Oga
|
||||||
^squote => buffer_string;
|
^squote => buffer_string;
|
||||||
squote => {
|
squote => {
|
||||||
emit_string_buffer
|
emit_string_buffer
|
||||||
advance_column
|
|
||||||
fret;
|
fret;
|
||||||
};
|
};
|
||||||
*|;
|
*|;
|
||||||
|
@ -308,7 +293,7 @@ module Oga
|
||||||
|
|
||||||
# Whitespace inside doctypes is ignored since there's no point in
|
# Whitespace inside doctypes is ignored since there's no point in
|
||||||
# including it.
|
# including it.
|
||||||
whitespace => { advance_column };
|
whitespace;
|
||||||
|
|
||||||
'>' => {
|
'>' => {
|
||||||
t(:T_DOCTYPE_END)
|
t(:T_DOCTYPE_END)
|
||||||
|
@ -389,7 +374,6 @@ module Oga
|
||||||
action start_element {
|
action start_element {
|
||||||
emit_text_buffer
|
emit_text_buffer
|
||||||
add_token(:T_ELEM_OPEN, nil)
|
add_token(:T_ELEM_OPEN, nil)
|
||||||
advance_column
|
|
||||||
|
|
||||||
# Add the element name. If the name includes a namespace we'll break
|
# Add the element name. If the name includes a namespace we'll break
|
||||||
# the name up into two separate tokens.
|
# the name up into two separate tokens.
|
||||||
|
@ -399,10 +383,6 @@ module Oga
|
||||||
ns, name = name.split(':')
|
ns, name = name.split(':')
|
||||||
|
|
||||||
add_token(:T_ELEM_NS, ns)
|
add_token(:T_ELEM_NS, ns)
|
||||||
|
|
||||||
# Advance the column for the colon (:) that separates the namespace
|
|
||||||
# and element name.
|
|
||||||
advance_column
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@elements << name
|
@elements << name
|
||||||
|
@ -422,7 +402,7 @@ module Oga
|
||||||
# For example, in `<p foo="bar">` the element head is ` foo="bar"`.
|
# For example, in `<p foo="bar">` the element head is ` foo="bar"`.
|
||||||
#
|
#
|
||||||
element_head := |*
|
element_head := |*
|
||||||
(whitespace | '=') => { advance_column };
|
whitespace | '=';
|
||||||
|
|
||||||
# Attribute names.
|
# Attribute names.
|
||||||
element_name => { t(:T_ATTR) };
|
element_name => { t(:T_ATTR) };
|
||||||
|
@ -452,8 +432,6 @@ module Oga
|
||||||
add_token(:T_ELEM_CLOSE, nil)
|
add_token(:T_ELEM_CLOSE, nil)
|
||||||
@elements.pop
|
@elements.pop
|
||||||
end
|
end
|
||||||
|
|
||||||
advance_column
|
|
||||||
};
|
};
|
||||||
|
|
||||||
# Regular closing tags.
|
# Regular closing tags.
|
||||||
|
@ -461,14 +439,11 @@ module Oga
|
||||||
emit_text_buffer
|
emit_text_buffer
|
||||||
add_token(:T_ELEM_CLOSE, nil)
|
add_token(:T_ELEM_CLOSE, nil)
|
||||||
|
|
||||||
advance_column(@te - @ts)
|
|
||||||
|
|
||||||
@elements.pop
|
@elements.pop
|
||||||
};
|
};
|
||||||
|
|
||||||
# Self closing elements that are not handled by the HTML mode.
|
# Self closing elements that are not handled by the HTML mode.
|
||||||
'/>' => {
|
'/>' => {
|
||||||
advance_column
|
|
||||||
add_token(:T_ELEM_CLOSE, nil)
|
add_token(:T_ELEM_CLOSE, nil)
|
||||||
|
|
||||||
@elements.pop
|
@elements.pop
|
||||||
|
|
|
@ -124,25 +124,22 @@ end
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset
|
def reset
|
||||||
@lines = []
|
@lines = []
|
||||||
@line = 1
|
@line = 1
|
||||||
@column = 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def s(type, *children)
|
def s(type, *children)
|
||||||
return AST::Node.new(
|
return AST::Node.new(
|
||||||
type,
|
type,
|
||||||
children.flatten,
|
children.flatten,
|
||||||
:line => @line,
|
:line => @line
|
||||||
:column => @column
|
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def next_token
|
def next_token
|
||||||
type, value, line, column = @tokens.shift
|
type, value, line = @tokens.shift
|
||||||
|
|
||||||
@line = line if line
|
@line = line if line
|
||||||
@column = column if column
|
|
||||||
|
|
||||||
return type ? [type, value] : [false, false]
|
return type ? [type, value] : [false, false]
|
||||||
end
|
end
|
||||||
|
@ -150,18 +147,13 @@ end
|
||||||
def on_error(type, value, stack)
|
def on_error(type, value, stack)
|
||||||
name = token_to_str(type)
|
name = token_to_str(type)
|
||||||
line_str = @lines[@line - 1]
|
line_str = @lines[@line - 1]
|
||||||
indicator = '~' * (@column - 1) + '^'
|
|
||||||
|
|
||||||
raise Racc::ParseError, <<-EOF.strip
|
raise Racc::ParseError, <<-EOF.strip
|
||||||
Failed to parse the supplied input.
|
Unexpected #{name} with value #{value.inspect} on line #{@line}
|
||||||
|
|
||||||
Reason: unexpected #{name} with value #{value.inspect}
|
|
||||||
Location: line #{@line}, column #{@column}
|
|
||||||
|
|
||||||
Offending code:
|
Offending code:
|
||||||
|
|
||||||
#{line_str}
|
#{line_str}
|
||||||
#{indicator}
|
|
||||||
|
|
||||||
Current stack:
|
Current stack:
|
||||||
|
|
||||||
|
|
|
@ -4,25 +4,25 @@ describe Oga::Lexer do
|
||||||
context 'cdata tags' do
|
context 'cdata tags' do
|
||||||
example 'lex a cdata tag' do
|
example 'lex a cdata tag' do
|
||||||
lex('<![CDATA[foo]]>').should == [
|
lex('<![CDATA[foo]]>').should == [
|
||||||
[:T_CDATA_START, '<![CDATA[', 1, 1],
|
[:T_CDATA_START, '<![CDATA[', 1],
|
||||||
[:T_TEXT, 'foo', 1, 10],
|
[:T_TEXT, 'foo', 1],
|
||||||
[:T_CDATA_END, ']]>', 1, 13]
|
[:T_CDATA_END, ']]>', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex tags inside CDATA tags as regular text' do
|
example 'lex tags inside CDATA tags as regular text' do
|
||||||
lex('<![CDATA[<p>Foo</p>]]>').should == [
|
lex('<![CDATA[<p>Foo</p>]]>').should == [
|
||||||
[:T_CDATA_START, '<![CDATA[', 1, 1],
|
[:T_CDATA_START, '<![CDATA[', 1],
|
||||||
[:T_TEXT, '<p>Foo</p>', 1, 10],
|
[:T_TEXT, '<p>Foo</p>', 1],
|
||||||
[:T_CDATA_END, ']]>', 1, 20]
|
[:T_CDATA_END, ']]>', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex double brackets inside a CDATA tag' do
|
example 'lex double brackets inside a CDATA tag' do
|
||||||
lex('<![CDATA[]]]]>').should == [
|
lex('<![CDATA[]]]]>').should == [
|
||||||
[:T_CDATA_START, '<![CDATA[', 1, 1],
|
[:T_CDATA_START, '<![CDATA[', 1],
|
||||||
[:T_TEXT, ']]', 1, 10],
|
[:T_TEXT, ']]', 1],
|
||||||
[:T_CDATA_END, ']]>', 1, 12]
|
[:T_CDATA_END, ']]>', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,51 +4,51 @@ describe Oga::Lexer do
|
||||||
context 'comments' do
|
context 'comments' do
|
||||||
example 'lex a comment' do
|
example 'lex a comment' do
|
||||||
lex('<!-- foo -->').should == [
|
lex('<!-- foo -->').should == [
|
||||||
[:T_COMMENT_START, '<!--', 1, 1],
|
[:T_COMMENT_START, '<!--', 1],
|
||||||
[:T_TEXT, ' foo ', 1, 5],
|
[:T_TEXT, ' foo ', 1],
|
||||||
[:T_COMMENT_END, '-->', 1, 10]
|
[:T_COMMENT_END, '-->', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a comment containing --' do
|
example 'lex a comment containing --' do
|
||||||
lex('<!-- -- -->').should == [
|
lex('<!-- -- -->').should == [
|
||||||
[:T_COMMENT_START, '<!--', 1, 1],
|
[:T_COMMENT_START, '<!--', 1],
|
||||||
[:T_TEXT, ' -- ', 1, 5],
|
[:T_TEXT, ' -- ', 1],
|
||||||
[:T_COMMENT_END, '-->', 1, 9]
|
[:T_COMMENT_END, '-->', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a comment containing ->' do
|
example 'lex a comment containing ->' do
|
||||||
lex('<!-- -> -->').should == [
|
lex('<!-- -> -->').should == [
|
||||||
[:T_COMMENT_START, '<!--', 1, 1],
|
[:T_COMMENT_START, '<!--', 1],
|
||||||
[:T_TEXT, ' -> ', 1, 5],
|
[:T_TEXT, ' -> ', 1],
|
||||||
[:T_COMMENT_END, '-->', 1, 9]
|
[:T_COMMENT_END, '-->', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a comment followed by text' do
|
example 'lex a comment followed by text' do
|
||||||
lex('<!---->foo').should == [
|
lex('<!---->foo').should == [
|
||||||
[:T_COMMENT_START, '<!--', 1, 1],
|
[:T_COMMENT_START, '<!--', 1],
|
||||||
[:T_COMMENT_END, '-->', 1, 5],
|
[:T_COMMENT_END, '-->', 1],
|
||||||
[:T_TEXT, 'foo', 1, 8]
|
[:T_TEXT, 'foo', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex text followed by a comment' do
|
example 'lex text followed by a comment' do
|
||||||
lex('foo<!---->').should == [
|
lex('foo<!---->').should == [
|
||||||
[:T_TEXT, 'foo', 1, 1],
|
[:T_TEXT, 'foo', 1],
|
||||||
[:T_COMMENT_START, '<!--', 1, 4],
|
[:T_COMMENT_START, '<!--', 1],
|
||||||
[:T_COMMENT_END, '-->', 1, 8]
|
[:T_COMMENT_END, '-->', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex an element followed by a comment' do
|
example 'lex an element followed by a comment' do
|
||||||
lex('<p></p><!---->').should == [
|
lex('<p></p><!---->').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 4],
|
[:T_ELEM_CLOSE, nil, 1],
|
||||||
[:T_COMMENT_START, '<!--', 1, 8],
|
[:T_COMMENT_START, '<!--', 1],
|
||||||
[:T_COMMENT_END, '-->', 1, 12]
|
[:T_COMMENT_END, '-->', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,28 +4,28 @@ describe Oga::Lexer do
|
||||||
context 'doctypes' do
|
context 'doctypes' do
|
||||||
example 'lex the HTML5 doctype' do
|
example 'lex the HTML5 doctype' do
|
||||||
lex('<!DOCTYPE html>').should == [
|
lex('<!DOCTYPE html>').should == [
|
||||||
[:T_DOCTYPE_START, '<!DOCTYPE html', 1, 1],
|
[:T_DOCTYPE_START, '<!DOCTYPE html', 1],
|
||||||
[:T_DOCTYPE_END, '>', 1, 15]
|
[:T_DOCTYPE_END, '>', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a doctype with a public and system ID' do
|
example 'lex a doctype with a public and system ID' do
|
||||||
lex('<!DOCTYPE HTML PUBLIC "foobar" "baz">').should == [
|
lex('<!DOCTYPE HTML PUBLIC "foobar" "baz">').should == [
|
||||||
[:T_DOCTYPE_START, '<!DOCTYPE HTML', 1, 1],
|
[:T_DOCTYPE_START, '<!DOCTYPE HTML', 1],
|
||||||
[:T_DOCTYPE_TYPE, 'PUBLIC', 1, 16],
|
[:T_DOCTYPE_TYPE, 'PUBLIC', 1],
|
||||||
[:T_STRING, 'foobar', 1, 23],
|
[:T_STRING, 'foobar', 1],
|
||||||
[:T_STRING, 'baz', 1, 32],
|
[:T_STRING, 'baz', 1],
|
||||||
[:T_DOCTYPE_END, '>', 1, 37]
|
[:T_DOCTYPE_END, '>', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a doctype with a public and system ID using single quotes' do
|
example 'lex a doctype with a public and system ID using single quotes' do
|
||||||
lex("<!DOCTYPE HTML PUBLIC 'foobar' 'baz'>").should == [
|
lex("<!DOCTYPE HTML PUBLIC 'foobar' 'baz'>").should == [
|
||||||
[:T_DOCTYPE_START, '<!DOCTYPE HTML', 1, 1],
|
[:T_DOCTYPE_START, '<!DOCTYPE HTML', 1],
|
||||||
[:T_DOCTYPE_TYPE, 'PUBLIC', 1, 16],
|
[:T_DOCTYPE_TYPE, 'PUBLIC', 1],
|
||||||
[:T_STRING, 'foobar', 1, 23],
|
[:T_STRING, 'foobar', 1],
|
||||||
[:T_STRING, 'baz', 1, 32],
|
[:T_STRING, 'baz', 1],
|
||||||
[:T_DOCTYPE_END, '>', 1, 37]
|
[:T_DOCTYPE_END, '>', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -14,40 +14,40 @@ describe Oga::Lexer do
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
lex(html).should == [
|
lex(html).should == [
|
||||||
[:T_DOCTYPE_START, '<!DOCTYPE html', 1, 1],
|
[:T_DOCTYPE_START, '<!DOCTYPE html', 1],
|
||||||
[:T_DOCTYPE_END, '>', 1, 15],
|
[:T_DOCTYPE_END, '>', 1],
|
||||||
[:T_TEXT, "\n", 1, 16],
|
[:T_TEXT, "\n", 1],
|
||||||
|
|
||||||
# <html>
|
# <html>
|
||||||
[:T_ELEM_OPEN, nil, 2, 1],
|
[:T_ELEM_OPEN, nil, 2],
|
||||||
[:T_ELEM_NAME, 'html', 2, 2],
|
[:T_ELEM_NAME, 'html', 2],
|
||||||
[:T_TEXT, "\n", 2, 7],
|
[:T_TEXT, "\n", 2],
|
||||||
|
|
||||||
# <head>
|
# <head>
|
||||||
[:T_ELEM_OPEN, nil, 3, 1],
|
[:T_ELEM_OPEN, nil, 3],
|
||||||
[:T_ELEM_NAME, 'head', 3, 2],
|
[:T_ELEM_NAME, 'head', 3],
|
||||||
[:T_TEXT, "\n", 3, 7],
|
[:T_TEXT, "\n", 3],
|
||||||
|
|
||||||
# <title>Title</title>
|
# <title>Title</title>
|
||||||
[:T_ELEM_OPEN, nil, 4, 1],
|
[:T_ELEM_OPEN, nil, 4],
|
||||||
[:T_ELEM_NAME, 'title', 4, 2],
|
[:T_ELEM_NAME, 'title', 4],
|
||||||
[:T_TEXT, 'Title', 4, 8],
|
[:T_TEXT, 'Title', 4],
|
||||||
[:T_ELEM_CLOSE, nil, 4, 13],
|
[:T_ELEM_CLOSE, nil, 4],
|
||||||
[:T_TEXT, "\n", 4, 21],
|
[:T_TEXT, "\n", 4],
|
||||||
|
|
||||||
# </head>
|
# </head>
|
||||||
[:T_ELEM_CLOSE, nil, 5, 1],
|
[:T_ELEM_CLOSE, nil, 5],
|
||||||
[:T_TEXT, "\n", 5, 8],
|
[:T_TEXT, "\n", 5],
|
||||||
|
|
||||||
# <body></body>
|
# <body></body>
|
||||||
[:T_ELEM_OPEN, nil, 6, 1],
|
[:T_ELEM_OPEN, nil, 6],
|
||||||
[:T_ELEM_NAME, 'body', 6, 2],
|
[:T_ELEM_NAME, 'body', 6],
|
||||||
[:T_ELEM_CLOSE, nil, 6, 7],
|
[:T_ELEM_CLOSE, nil, 6],
|
||||||
[:T_TEXT, "\n", 6, 14],
|
[:T_TEXT, "\n", 6],
|
||||||
|
|
||||||
# </html>
|
# </html>
|
||||||
[:T_ELEM_CLOSE, nil, 7, 1],
|
[:T_ELEM_CLOSE, nil, 7],
|
||||||
[:T_TEXT, "\n", 7, 8]
|
[:T_TEXT, "\n", 7]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,33 +4,33 @@ describe Oga::Lexer do
|
||||||
context 'elements' do
|
context 'elements' do
|
||||||
example 'lex an opening element' do
|
example 'lex an opening element' do
|
||||||
lex('<p>').should == [
|
lex('<p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2]
|
[:T_ELEM_NAME, 'p', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex an opening an closing element' do
|
example 'lex an opening an closing element' do
|
||||||
lex('<p></p>').should == [
|
lex('<p></p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 4]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a paragraph element with text inside it' do
|
example 'lex a paragraph element with text inside it' do
|
||||||
lex('<p>Hello</p>').should == [
|
lex('<p>Hello</p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_TEXT, 'Hello', 1, 4],
|
[:T_TEXT, 'Hello', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 9]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex text followed by a paragraph element' do
|
example 'lex text followed by a paragraph element' do
|
||||||
lex('Foo<p>').should == [
|
lex('Foo<p>').should == [
|
||||||
[:T_TEXT, 'Foo', 1, 1],
|
[:T_TEXT, 'Foo', 1],
|
||||||
[:T_ELEM_OPEN, nil, 1, 4],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 5]
|
[:T_ELEM_NAME, 'p', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -38,21 +38,21 @@ describe Oga::Lexer do
|
||||||
context 'elements with attributes' do
|
context 'elements with attributes' do
|
||||||
example 'lex an element with an attribute without a value' do
|
example 'lex an element with an attribute without a value' do
|
||||||
lex('<p foo></p>').should == [
|
lex('<p foo></p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_ATTR, 'foo', 1, 4],
|
[:T_ATTR, 'foo', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 8]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a paragraph element with attributes' do
|
example 'lex a paragraph element with attributes' do
|
||||||
lex('<p class="foo">Hello</p>').should == [
|
lex('<p class="foo">Hello</p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_ATTR, 'class', 1, 4],
|
[:T_ATTR, 'class', 1],
|
||||||
[:T_STRING, 'foo', 1, 10],
|
[:T_STRING, 'foo', 1],
|
||||||
[:T_TEXT, 'Hello', 1, 16],
|
[:T_TEXT, 'Hello', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 21]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -60,26 +60,26 @@ describe Oga::Lexer do
|
||||||
context 'nested elements' do
|
context 'nested elements' do
|
||||||
example 'lex a nested element' do
|
example 'lex a nested element' do
|
||||||
lex('<p><a></a></p>').should == [
|
lex('<p><a></a></p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_ELEM_OPEN, nil, 1, 4],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'a', 1, 5],
|
[:T_ELEM_NAME, 'a', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 7],
|
[:T_ELEM_CLOSE, nil, 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 11]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex nested elements and text nodes' do
|
example 'lex nested elements and text nodes' do
|
||||||
lex('<p>Foo<a>bar</a>baz</p>').should == [
|
lex('<p>Foo<a>bar</a>baz</p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 2],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_TEXT, 'Foo', 1, 4],
|
[:T_TEXT, 'Foo', 1],
|
||||||
[:T_ELEM_OPEN, nil, 1, 7],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'a', 1, 8],
|
[:T_ELEM_NAME, 'a', 1],
|
||||||
[:T_TEXT, 'bar', 1, 10],
|
[:T_TEXT, 'bar', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 13],
|
[:T_ELEM_CLOSE, nil, 1],
|
||||||
[:T_TEXT, 'baz', 1, 17],
|
[:T_TEXT, 'baz', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 20]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -87,19 +87,19 @@ describe Oga::Lexer do
|
||||||
context 'void elements' do
|
context 'void elements' do
|
||||||
example 'lex a void element' do
|
example 'lex a void element' do
|
||||||
lex('<br />').should == [
|
lex('<br />').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'br', 1, 2],
|
[:T_ELEM_NAME, 'br', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 6]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a void element with an attribute' do
|
example 'lex a void element with an attribute' do
|
||||||
lex('<br class="foo" />').should == [
|
lex('<br class="foo" />').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'br', 1, 2],
|
[:T_ELEM_NAME, 'br', 1],
|
||||||
[:T_ATTR, 'class', 1, 5],
|
[:T_ATTR, 'class', 1],
|
||||||
[:T_STRING, 'foo', 1, 11],
|
[:T_STRING, 'foo', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 18]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -107,10 +107,10 @@ describe Oga::Lexer do
|
||||||
context 'elements with namespaces' do
|
context 'elements with namespaces' do
|
||||||
example 'lex an element with namespaces' do
|
example 'lex an element with namespaces' do
|
||||||
lex('<foo:p></p>').should == [
|
lex('<foo:p></p>').should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NS, 'foo', 1, 2],
|
[:T_ELEM_NS, 'foo', 1],
|
||||||
[:T_ELEM_NAME, 'p', 1, 6],
|
[:T_ELEM_NAME, 'p', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 8]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,20 +3,20 @@ require 'spec_helper'
|
||||||
describe Oga::Lexer do
|
describe Oga::Lexer do
|
||||||
context 'regular text' do
|
context 'regular text' do
|
||||||
example 'lex regular text' do
|
example 'lex regular text' do
|
||||||
lex('hello').should == [[:T_TEXT, 'hello', 1, 1]]
|
lex('hello').should == [[:T_TEXT, 'hello', 1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex regular whitespace' do
|
example 'lex regular whitespace' do
|
||||||
lex(' ').should == [[:T_TEXT, ' ', 1, 1]]
|
lex(' ').should == [[:T_TEXT, ' ', 1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a newline' do
|
example 'lex a newline' do
|
||||||
lex("\n").should == [[:T_TEXT, "\n", 1, 1]]
|
lex("\n").should == [[:T_TEXT, "\n", 1]]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex text followed by a newline' do
|
example 'lex text followed by a newline' do
|
||||||
lex("foo\n").should == [
|
lex("foo\n").should == [
|
||||||
[:T_TEXT, "foo\n", 1, 1]
|
[:T_TEXT, "foo\n", 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,41 +4,41 @@ describe Oga::Lexer do
|
||||||
context 'HTML void elements' do
|
context 'HTML void elements' do
|
||||||
example 'lex a void element that omits the closing /' do
|
example 'lex a void element that omits the closing /' do
|
||||||
lex('<link>', :html => true).should == [
|
lex('<link>', :html => true).should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'link', 1, 2],
|
[:T_ELEM_NAME, 'link', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 6]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex text after a void element' do
|
example 'lex text after a void element' do
|
||||||
lex('<link>foo', :html => true).should == [
|
lex('<link>foo', :html => true).should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'link', 1, 2],
|
[:T_ELEM_NAME, 'link', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 6],
|
[:T_ELEM_CLOSE, nil, 1],
|
||||||
[:T_TEXT, 'foo', 1, 7]
|
[:T_TEXT, 'foo', 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a void element inside another element' do
|
example 'lex a void element inside another element' do
|
||||||
lex('<head><link></head>', :html => true).should == [
|
lex('<head><link></head>', :html => true).should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'head', 1, 2],
|
[:T_ELEM_NAME, 'head', 1],
|
||||||
[:T_ELEM_OPEN, nil, 1, 7],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'link', 1, 8],
|
[:T_ELEM_NAME, 'link', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 12],
|
[:T_ELEM_CLOSE, nil, 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 13]
|
[:T_ELEM_CLOSE, nil, 1]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
example 'lex a void element inside another element with whitespace' do
|
example 'lex a void element inside another element with whitespace' do
|
||||||
lex("<head><link>\n</head>", :html => true).should == [
|
lex("<head><link>\n</head>", :html => true).should == [
|
||||||
[:T_ELEM_OPEN, nil, 1, 1],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'head', 1, 2],
|
[:T_ELEM_NAME, 'head', 1],
|
||||||
[:T_ELEM_OPEN, nil, 1, 7],
|
[:T_ELEM_OPEN, nil, 1],
|
||||||
[:T_ELEM_NAME, 'link', 1, 8],
|
[:T_ELEM_NAME, 'link', 1],
|
||||||
[:T_ELEM_CLOSE, nil, 1, 12],
|
[:T_ELEM_CLOSE, nil, 1],
|
||||||
[:T_TEXT, "\n", 1, 13],
|
[:T_TEXT, "\n", 1],
|
||||||
[:T_ELEM_CLOSE, nil, 2, 1]
|
[:T_ELEM_CLOSE, nil, 2]
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue