| @@ -315,7 +315,7 @@ class Tokenizer(object): | |||
| def _parse_bracketed_uri_scheme(self): | |||
| """Parse the URI scheme of a bracket-enclosed external link.""" | |||
| self._push(contexts.EXT_LINK_URI) | |||
| self._push(self._context | contexts.EXT_LINK_URI) | |||
| if self._read() == self._read(1) == "/": | |||
| self._emit_text("//") | |||
| self._head += 2 | |||
| @@ -358,7 +358,7 @@ class Tokenizer(object): | |||
| slashes = self._read() == self._read(1) == "/" | |||
| if not is_scheme(scheme, slashes): | |||
| raise BadRoute() | |||
| self._push(contexts.EXT_LINK_URI) | |||
| self._push(self._context | contexts.EXT_LINK_URI) | |||
| self._emit_text(scheme) | |||
| self._emit_text(":") | |||
| if slashes: | |||
| @@ -385,6 +385,21 @@ class Tokenizer(object): | |||
| self._emit_text(this) | |||
| return punct, tail | |||
| def _is_free_link_end(self, this, next): | |||
| """Return whether the current head is the end of a free link.""" | |||
| # Built from _parse()'s end sentinels: | |||
| after, ctx = self._read(2), self._context | |||
| return (this is self.END or this in ("\n", "[", "]") or | |||
| this == "|" and ctx & contexts.TEMPLATE or | |||
| this == "=" and ctx & contexts.TEMPLATE_PARAM_KEY or | |||
| this == next == "}" and ctx & contexts.TEMPLATE or | |||
| this == next == after == "}" and ctx & contexts.ARGUMENT or | |||
| this == "=" and ctx & contexts.HEADING or | |||
| this == "<" and next == "/" and after is not self.END or | |||
| this == "<" and next != "!" and not ctx & contexts.TAG_CLOSE or | |||
| this == ">" and ctx & contexts.TAG_CLOSE or | |||
| this == next == "'") | |||
| def _really_parse_external_link(self, brackets): | |||
| """Really parse an external link.""" | |||
| if brackets: | |||
| @@ -399,27 +414,28 @@ class Tokenizer(object): | |||
| tail = "" | |||
| while True: | |||
| this, next = self._read(), self._read(1) | |||
| if this is self.END or this == "\n": | |||
| if brackets: | |||
| self._fail_route() | |||
| if not brackets and self._is_free_link_end(this, next): | |||
| return self._pop(), tail, -1 | |||
| elif this is self.END or this == "\n": | |||
| self._fail_route() | |||
| elif this == next == "{" and self._can_recurse(): | |||
| if tail: | |||
| self._emit_text(tail) | |||
| tail = "" | |||
| self._parse_template_or_argument() | |||
| elif this == "[": | |||
| if brackets: | |||
| self._emit_text("[") | |||
| else: | |||
| return self._pop(), tail, -1 | |||
| elif this == "]": | |||
| return self._pop(), tail, 0 if brackets else -1 | |||
| return self._pop(), tail, 0 | |||
| elif this == "&": | |||
| if tail: | |||
| self._emit_text(tail) | |||
| tail = "" | |||
| self._parse_entity() | |||
| elif (this == "<" and next == "!" and self._read(2) == | |||
| self._read(3) == "-"): | |||
| if tail: | |||
| self._emit_text(tail) | |||
| tail = "" | |||
| self._parse_comment() | |||
| elif " " in this: | |||
| before, after = this.split(" ", 1) | |||
| if brackets: | |||