| @@ -59,8 +59,8 @@ class Tag(TagDefinitions, Node): | |||
| return open_ + str(self.contents) + close | |||
| result = "<" + str(self.tag) | |||
| if self.attrs: | |||
| result += " " + " ".join([str(attr) for attr in self.attrs]) | |||
| if self.attributes: | |||
| result += " " + " ".join([str(attr) for attr in self.attributes]) | |||
| if self.self_closing: | |||
| result += self.open_padding + "/>" | |||
| else: | |||
| @@ -73,7 +73,7 @@ class Tag(TagDefinitions, Node): | |||
| if self.showtag: | |||
| for child in getter(self.tag): | |||
| yield self.tag, child | |||
| for attr in self.attrs: | |||
| for attr in self.attributes: | |||
| for child in getter(attr.name): | |||
| yield attr.name, child | |||
| if attr.value: | |||
| @@ -89,12 +89,13 @@ class Tag(TagDefinitions, Node): | |||
| def __showtree__(self, write, get, mark): | |||
| tagnodes = self.tag.nodes | |||
| if (not self.attrs and len(tagnodes) == 1 and isinstance(tagnodes[0], Text)): | |||
| if not self.attributes and (len(tagnodes) == 1 and | |||
| isinstance(tagnodes[0], Text)): | |||
| write("<" + str(tagnodes[0]) + ">") | |||
| else: | |||
| write("<") | |||
| get(self.tag) | |||
| for attr in self.attrs: | |||
| for attr in self.attributes: | |||
| get(attr.name) | |||
| if not attr.value: | |||
| continue | |||
| @@ -71,7 +71,8 @@ Local (stack-specific) contexts: | |||
| * :py:const:`TAG_OPEN_ATTR_NAME` | |||
| * :py:const:`TAG_OPEN_ATTR_BODY` | |||
| * :py:const:`TAG_OPEN_ATTR_BODY_QUOTED` | |||
| * :py:const:`TAG_OPEN_ATTR_QUOTED` | |||
| * :py:const:`TAG_OPEN_ATTR_IGNORE` | |||
| * :py:const:`TAG_BODY` | |||
| * :py:const:`TAG_CLOSE` | |||
| @@ -83,38 +84,39 @@ Global contexts: | |||
| # Local contexts: | |||
| TEMPLATE = 0b00000000000000000111 | |||
| TEMPLATE_NAME = 0b00000000000000000001 | |||
| TEMPLATE_PARAM_KEY = 0b00000000000000000010 | |||
| TEMPLATE_PARAM_VALUE = 0b00000000000000000100 | |||
| ARGUMENT = 0b00000000000000011000 | |||
| ARGUMENT_NAME = 0b00000000000000001000 | |||
| ARGUMENT_DEFAULT = 0b00000000000000010000 | |||
| WIKILINK = 0b00000000000001100000 | |||
| WIKILINK_TITLE = 0b00000000000000100000 | |||
| WIKILINK_TEXT = 0b00000000000001000000 | |||
| HEADING = 0b00000001111110000000 | |||
| HEADING_LEVEL_1 = 0b00000000000010000000 | |||
| HEADING_LEVEL_2 = 0b00000000000100000000 | |||
| HEADING_LEVEL_3 = 0b00000000001000000000 | |||
| HEADING_LEVEL_4 = 0b00000000010000000000 | |||
| HEADING_LEVEL_5 = 0b00000000100000000000 | |||
| HEADING_LEVEL_6 = 0b00000001000000000000 | |||
| COMMENT = 0b00000010000000000000 | |||
| TAG = 0b11111100000000000000 | |||
| TAG_OPEN = 0b00111100000000000000 | |||
| TAG_OPEN_NAME = 0b00000100000000000000 | |||
| TAG_OPEN_ATTR = 0b00111000000000000000 | |||
| TAG_OPEN_ATTR_NAME = 0b00001000000000000000 | |||
| TAG_OPEN_ATTR_BODY = 0b00010000000000000000 | |||
| TAG_OPEN_ATTR_BODY_QUOTED = 0b00100000000000000000 | |||
| TAG_BODY = 0b01000000000000000000 | |||
| TAG_CLOSE = 0b10000000000000000000 | |||
| TEMPLATE = 0b000000000000000000111 | |||
| TEMPLATE_NAME = 0b000000000000000000001 | |||
| TEMPLATE_PARAM_KEY = 0b000000000000000000010 | |||
| TEMPLATE_PARAM_VALUE = 0b000000000000000000100 | |||
| ARGUMENT = 0b000000000000000011000 | |||
| ARGUMENT_NAME = 0b000000000000000001000 | |||
| ARGUMENT_DEFAULT = 0b000000000000000010000 | |||
| WIKILINK = 0b000000000000001100000 | |||
| WIKILINK_TITLE = 0b000000000000000100000 | |||
| WIKILINK_TEXT = 0b000000000000001000000 | |||
| HEADING = 0b000000001111110000000 | |||
| HEADING_LEVEL_1 = 0b000000000000010000000 | |||
| HEADING_LEVEL_2 = 0b000000000000100000000 | |||
| HEADING_LEVEL_3 = 0b000000000001000000000 | |||
| HEADING_LEVEL_4 = 0b000000000010000000000 | |||
| HEADING_LEVEL_5 = 0b000000000100000000000 | |||
| HEADING_LEVEL_6 = 0b000000001000000000000 | |||
| COMMENT = 0b000000010000000000000 | |||
| TAG = 0b111111100000000000000 | |||
| TAG_OPEN = 0b001111100000000000000 | |||
| TAG_OPEN_NAME = 0b000000100000000000000 | |||
| TAG_OPEN_ATTR = 0b001111000000000000000 | |||
| TAG_OPEN_ATTR_NAME = 0b000001000000000000000 | |||
| TAG_OPEN_ATTR_BODY = 0b000010000000000000000 | |||
| TAG_OPEN_ATTR_QUOTED = 0b000100000000000000000 | |||
| TAG_OPEN_ATTR_IGNORE = 0b001000000000000000000 | |||
| TAG_BODY = 0b010000000000000000000 | |||
| TAG_CLOSE = 0b100000000000000000000 | |||
| # Global contexts: | |||
| @@ -457,11 +457,13 @@ class Tokenizer(object): | |||
| self._write_first(tokens.TagOpenOpen(type=tag, showtag=True)) | |||
| self._context ^= contexts.TAG_OPEN_NAME | |||
| self._context |= contexts.TAG_BODY | |||
| padding = "" # TODO | |||
| ## If the last element was TagAttrStart, remove it, add " " to its padding, then return that | |||
| padding = "" | |||
| return padding | |||
| def _actually_handle_chunk(self, chunks, is_new): | |||
| if is_new and not self._context & contexts.TAG_OPEN_ATTR_BODY_QUOTED: | |||
| if is_new and not self._context & contexts.TAG_OPEN_ATTR_QUOTED: | |||
| padding = 0 | |||
| while chunks: | |||
| if chunks[0] == "": | |||
| @@ -470,18 +472,24 @@ class Tokenizer(object): | |||
| else: | |||
| break | |||
| self._write(tokens.TagAttrStart(padding=" " * padding)) | |||
| elif self._context & contexts.TAG_OPEN_ATTR_IGNORE: | |||
| self._context ^= contexts.TAG_OPEN_ATTR_IGNORE | |||
| chunks.pop(0) | |||
| return | |||
| elif self._context & contexts.TAG_OPEN_ATTR_QUOTED: | |||
| self._write_text(" ") # Quoted chunks don't lose their spaces | |||
| if chunks: | |||
| chunk = chunks.pop(0) | |||
| if self._context & contexts.TAG_OPEN_ATTR_BODY: | |||
| self._context ^= contexts.TAG_OPEN_ATTR_BODY | |||
| self._context |= contexts.TAG_OPEN_ATTR_NAME | |||
| if self._context & contexts.TAG_OPEN_ATTR_BODY_QUOTED: | |||
| if self._context & contexts.TAG_OPEN_ATTR_QUOTED: | |||
| if re.search(r'[^\\]"', chunk[:-1]): | |||
| self._fail_route() | |||
| if re.search(r'[^\\]"$', chunk): | |||
| self._write_text(chunk[:-1]) | |||
| self._context ^= contexts.TAG_OPEN_ATTR_BODY_QUOTED | |||
| self._context ^= contexts.TAG_OPEN_ATTR_QUOTED | |||
| self._context |= contexts.TAG_OPEN_ATTR_NAME | |||
| return True # Back to _handle_tag_attribute_body() | |||
| self._write_text(chunk) | |||
| @@ -491,6 +499,8 @@ class Tokenizer(object): | |||
| self._write_text(text) | |||
| return | |||
| chunks = text.split(" ") | |||
| is_new = False | |||
| is_quoted = False | |||
| if self._context & contexts.TAG_OPEN_NAME: | |||
| self._write_text(chunks.pop(0)) | |||
| tag = self._get_tag_type_from_stack() | |||
| @@ -500,9 +510,7 @@ class Tokenizer(object): | |||
| self._context ^= contexts.TAG_OPEN_NAME | |||
| self._context |= contexts.TAG_OPEN_ATTR_NAME | |||
| self._actually_handle_chunk(chunks, True) | |||
| is_new = False | |||
| is_quoted = False | |||
| is_new = True | |||
| while chunks: | |||
| result = self._actually_handle_chunk(chunks, is_new) | |||
| is_quoted = result or is_quoted | |||
| @@ -530,7 +538,7 @@ class Tokenizer(object): | |||
| self._head += 1 | |||
| reset = self._head | |||
| try: | |||
| attr = self._parse(contexts.TAG_OPEN_ATTR_BODY_QUOTED) | |||
| attr = self._parse(contexts.TAG_OPEN_ATTR_QUOTED | contexts.TAG_OPEN_ATTR_IGNORE) | |||
| except BadRoute: | |||
| self._head = reset | |||
| self._write_text(next) | |||
| @@ -538,6 +546,7 @@ class Tokenizer(object): | |||
| self._write(tokens.TagAttrQuote()) | |||
| self._write_text(next[1:]) | |||
| self._write_all(attr) | |||
| return | |||
| self._context ^= contexts.TAG_OPEN_ATTR_BODY | |||
| self._context |= contexts.TAG_OPEN_ATTR_NAME | |||
| while chunks: | |||
| @@ -588,7 +597,7 @@ class Tokenizer(object): | |||
| contexts.HEADING | contexts.COMMENT | contexts.TAG) | |||
| double_fail = ( | |||
| contexts.TEMPLATE_PARAM_KEY | contexts.TAG_CLOSE | | |||
| contexts.TAG_OPEN_ATTR_BODY_QUOTED) | |||
| contexts.TAG_OPEN_ATTR_QUOTED) | |||
| if self._context & double_fail: | |||
| self._pop() | |||
| if self._context & fail: | |||
| @@ -645,7 +654,7 @@ class Tokenizer(object): | |||
| elif this == "<" and next != "/" and ( | |||
| not self._context & (contexts.TAG ^ contexts.TAG_BODY)): | |||
| self._parse_tag() | |||
| elif self._context & (contexts.TAG_OPEN ^ contexts.TAG_OPEN_ATTR_BODY_QUOTED): | |||
| elif self._context & (contexts.TAG_OPEN ^ contexts.TAG_OPEN_ATTR_QUOTED): | |||
| if this == "\n": | |||
| if self._context & contexts.TAG_CLOSE: | |||
| self._pop() | |||