Browse Source

Fix parsing of section headings inside templates

see #198
pull/233/head
Jakub Klinkovský 4 years ago
parent
commit
b3aac9545e
3 changed files with 39 additions and 4 deletions
  1. +6
    -2
      mwparserfromhell/parser/ctokenizer/tok_parse.c
  2. +5
    -2
      mwparserfromhell/parser/tokenizer.py
  3. +28
    -0
      tests/tokenizer/templates.mwtest

+ 6
- 2
mwparserfromhell/parser/ctokenizer/tok_parse.c View File

@@ -2632,7 +2632,11 @@ PyObject* Tokenizer_parse(Tokenizer* self, uint64_t context, int push)
return NULL;
}
else if (this == '=' && this_context & LC_TEMPLATE_PARAM_KEY) {
if (Tokenizer_handle_template_param_value(self))
if (!(self->global & GL_HEADING) && (!last || last == '\n') && next == '=') {
if (Tokenizer_parse_heading(self))
return NULL;
}
else if (Tokenizer_handle_template_param_value(self))
return NULL;
}
else if (this == next && next == '}' && this_context & LC_TEMPLATE)
@@ -2672,7 +2676,7 @@ PyObject* Tokenizer_parse(Tokenizer* self, uint64_t context, int push)
}
else if (this == ']' && this_context & LC_EXT_LINK_TITLE)
return Tokenizer_pop(self);
else if (this == '=' && !(self->global & GL_HEADING)) {
else if (this == '=' && !(self->global & GL_HEADING) && !(this_context & LC_TEMPLATE)) {
if (!last || last == '\n') {
if (Tokenizer_parse_heading(self))
return NULL;


+ 5
- 2
mwparserfromhell/parser/tokenizer.py View File

@@ -1326,7 +1326,10 @@ class Tokenizer(object):
elif this == "|" and self._context & contexts.TEMPLATE:
self._handle_template_param()
elif this == "=" and self._context & contexts.TEMPLATE_PARAM_KEY:
self._handle_template_param_value()
if not self._global & contexts.GL_HEADING and self._read(-1) in ("\n", self.START) and next == "=":
self._parse_heading()
else:
self._handle_template_param_value()
elif this == next == "}" and self._context & contexts.TEMPLATE:
return self._handle_template_end()
elif this == "|" and self._context & contexts.ARGUMENT_NAME:
@@ -1351,7 +1354,7 @@ class Tokenizer(object):
self._parse_external_link(False)
elif this == "]" and self._context & contexts.EXT_LINK_TITLE:
return self._pop()
elif this == "=" and not self._global & contexts.GL_HEADING:
elif this == "=" and not self._global & contexts.GL_HEADING and not self._context & contexts.TEMPLATE:
if self._read(-1) in ("\n", self.START):
self._parse_heading()
else:


+ 28
- 0
tests/tokenizer/templates.mwtest View File

@@ -695,3 +695,31 @@ name: recursion_opens_and_closes
label: test potentially dangerous recursion: template openings and closings
input: "{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}{{x|{{x}}"
output: [Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose(), Text(text="{{x|"), TemplateOpen(), Text(text="x"), TemplateClose()]

---

name: invalid_section_level_1
label: level 1 headings inside a template are always invalid
input: "{{foo|bar\n=baz=\n}}"
output: [TemplateOpen(), Text(text="foo"), TemplateParamSeparator(), Text(text="bar\n"), TemplateParamEquals(), Text(text="baz=\n"), TemplateClose()]

---

name: section_level_2
label: valid level 2 heading inside a template
input: "{{foo|bar\n==baz==\n}}"
output: [TemplateOpen(), Text(text="foo"), TemplateParamSeparator(), Text(text="bar\n"), HeadingStart(level=2), Text(text="baz"), HeadingEnd(), Text(text="\n"), TemplateClose()]

---

name: invalid_section_level_2
label: invalid level 2 heading inside a template
input: "{{foo|bar==baz==\n}}"
output: [TemplateOpen(), Text(text="foo"), TemplateParamSeparator(), Text(text="bar"), TemplateParamEquals(), Text(text="=baz==\n"), TemplateClose()]

---

name: section_level_2_after_template_parameter
label: level 2 heading inside a template after a parameter
input: "{{foo|bar=\n==baz==\n}}"
output: [TemplateOpen(), Text(text="foo"), TemplateParamSeparator(), Text(text="bar"), TemplateParamEquals(), Text(text="\n==baz==\n"), TemplateClose()]

Loading…
Cancel
Save