| @@ -1,10 +1,6 @@ | |||||
| mwparserfromhell | mwparserfromhell | ||||
| ================ | ================ | ||||
| .. image:: https://api.travis-ci.com/earwig/mwparserfromhell.svg | |||||
| :alt: Build Status | |||||
| :target: https://travis-ci.org/earwig/mwparserfromhell | |||||
| .. image:: https://img.shields.io/coveralls/earwig/mwparserfromhell/main.svg | .. image:: https://img.shields.io/coveralls/earwig/mwparserfromhell/main.svg | ||||
| :alt: Coverage Status | :alt: Coverage Status | ||||
| :target: https://coveralls.io/r/earwig/mwparserfromhell | :target: https://coveralls.io/r/earwig/mwparserfromhell | ||||
| @@ -23,7 +19,9 @@ The easiest way to install the parser is through the `Python Package Index`_; | |||||
| you can install the latest release with ``pip install mwparserfromhell`` | you can install the latest release with ``pip install mwparserfromhell`` | ||||
| (`get pip`_). Make sure your pip is up-to-date first, especially on Windows. | (`get pip`_). Make sure your pip is up-to-date first, especially on Windows. | ||||
| Alternatively, get the latest development version:: | |||||
| Alternatively, get the latest development version: | |||||
| .. code-block:: sh | |||||
| git clone https://github.com/earwig/mwparserfromhell.git | git clone https://github.com/earwig/mwparserfromhell.git | ||||
| cd mwparserfromhell | cd mwparserfromhell | ||||
| @@ -37,49 +35,57 @@ Usage | |||||
| Normal usage is rather straightforward (where ``text`` is page text): | Normal usage is rather straightforward (where ``text`` is page text): | ||||
| >>> import mwparserfromhell | |||||
| >>> wikicode = mwparserfromhell.parse(text) | |||||
| .. code-block:: python | |||||
| >>> import mwparserfromhell | |||||
| >>> wikicode = mwparserfromhell.parse(text) | |||||
| ``wikicode`` is a ``mwparserfromhell.Wikicode`` object, which acts like an | ``wikicode`` is a ``mwparserfromhell.Wikicode`` object, which acts like an | ||||
| ordinary ``str`` object with some extra methods. For example: | ordinary ``str`` object with some extra methods. For example: | ||||
| >>> text = "I has a template! {{foo|bar|baz|eggs=spam}} See it?" | |||||
| >>> wikicode = mwparserfromhell.parse(text) | |||||
| >>> print(wikicode) | |||||
| I has a template! {{foo|bar|baz|eggs=spam}} See it? | |||||
| >>> templates = wikicode.filter_templates() | |||||
| >>> print(templates) | |||||
| ['{{foo|bar|baz|eggs=spam}}'] | |||||
| >>> template = templates[0] | |||||
| >>> print(template.name) | |||||
| foo | |||||
| >>> print(template.params) | |||||
| ['bar', 'baz', 'eggs=spam'] | |||||
| >>> print(template.get(1).value) | |||||
| bar | |||||
| >>> print(template.get("eggs").value) | |||||
| spam | |||||
| .. code-block:: python | |||||
| >>> text = "I has a template! {{foo|bar|baz|eggs=spam}} See it?" | |||||
| >>> wikicode = mwparserfromhell.parse(text) | |||||
| >>> print(wikicode) | |||||
| I has a template! {{foo|bar|baz|eggs=spam}} See it? | |||||
| >>> templates = wikicode.filter_templates() | |||||
| >>> print(templates) | |||||
| ['{{foo|bar|baz|eggs=spam}}'] | |||||
| >>> template = templates[0] | |||||
| >>> print(template.name) | |||||
| foo | |||||
| >>> print(template.params) | |||||
| ['bar', 'baz', 'eggs=spam'] | |||||
| >>> print(template.get(1).value) | |||||
| bar | |||||
| >>> print(template.get("eggs").value) | |||||
| spam | |||||
| Since nodes can contain other nodes, getting nested templates is trivial: | Since nodes can contain other nodes, getting nested templates is trivial: | ||||
| >>> text = "{{foo|{{bar}}={{baz|{{spam}}}}}}" | |||||
| >>> mwparserfromhell.parse(text).filter_templates() | |||||
| ['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}'] | |||||
| .. code-block:: python | |||||
| >>> text = "{{foo|{{bar}}={{baz|{{spam}}}}}}" | |||||
| >>> mwparserfromhell.parse(text).filter_templates() | |||||
| ['{{foo|{{bar}}={{baz|{{spam}}}}}}', '{{bar}}', '{{baz|{{spam}}}}', '{{spam}}'] | |||||
| You can also pass ``recursive=False`` to ``filter_templates()`` and explore | You can also pass ``recursive=False`` to ``filter_templates()`` and explore | ||||
| templates manually. This is possible because nodes can contain additional | templates manually. This is possible because nodes can contain additional | ||||
| ``Wikicode`` objects: | ``Wikicode`` objects: | ||||
| >>> code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}") | |||||
| >>> print(code.filter_templates(recursive=False)) | |||||
| ['{{foo|this {{includes a|template}}}}'] | |||||
| >>> foo = code.filter_templates(recursive=False)[0] | |||||
| >>> print(foo.get(1).value) | |||||
| this {{includes a|template}} | |||||
| >>> print(foo.get(1).value.filter_templates()[0]) | |||||
| {{includes a|template}} | |||||
| >>> print(foo.get(1).value.filter_templates()[0].get(1).value) | |||||
| template | |||||
| .. code-block:: python | |||||
| >>> code = mwparserfromhell.parse("{{foo|this {{includes a|template}}}}") | |||||
| >>> print(code.filter_templates(recursive=False)) | |||||
| ['{{foo|this {{includes a|template}}}}'] | |||||
| >>> foo = code.filter_templates(recursive=False)[0] | |||||
| >>> print(foo.get(1).value) | |||||
| this {{includes a|template}} | |||||
| >>> print(foo.get(1).value.filter_templates()[0]) | |||||
| {{includes a|template}} | |||||
| >>> print(foo.get(1).value.filter_templates()[0].get(1).value) | |||||
| template | |||||
| Templates can be easily modified to add, remove, or alter params. ``Wikicode`` | Templates can be easily modified to add, remove, or alter params. ``Wikicode`` | ||||
| objects can be treated like lists, with ``append()``, ``insert()``, | objects can be treated like lists, with ``append()``, ``insert()``, | ||||
| @@ -87,28 +93,32 @@ objects can be treated like lists, with ``append()``, ``insert()``, | |||||
| for comparing page or template names, which takes care of capitalization and | for comparing page or template names, which takes care of capitalization and | ||||
| whitespace: | whitespace: | ||||
| >>> text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}" | |||||
| >>> code = mwparserfromhell.parse(text) | |||||
| >>> for template in code.filter_templates(): | |||||
| ... if template.name.matches("Cleanup") and not template.has("date"): | |||||
| ... template.add("date", "July 2012") | |||||
| ... | |||||
| >>> print(code) | |||||
| {{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{uncategorized}} | |||||
| >>> code.replace("{{uncategorized}}", "{{bar-stub}}") | |||||
| >>> print(code) | |||||
| {{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}} | |||||
| >>> print(code.filter_templates()) | |||||
| ['{{cleanup|date=July 2012}}', '{{bar-stub}}'] | |||||
| .. code-block:: python | |||||
| >>> text = "{{cleanup}} '''Foo''' is a [[bar]]. {{uncategorized}}" | |||||
| >>> code = mwparserfromhell.parse(text) | |||||
| >>> for template in code.filter_templates(): | |||||
| ... if template.name.matches("Cleanup") and not template.has("date"): | |||||
| ... template.add("date", "July 2012") | |||||
| ... | |||||
| >>> print(code) | |||||
| {{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{uncategorized}} | |||||
| >>> code.replace("{{uncategorized}}", "{{bar-stub}}") | |||||
| >>> print(code) | |||||
| {{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}} | |||||
| >>> print(code.filter_templates()) | |||||
| ['{{cleanup|date=July 2012}}', '{{bar-stub}}'] | |||||
| You can then convert ``code`` back into a regular ``str`` object (for | You can then convert ``code`` back into a regular ``str`` object (for | ||||
| saving the page!) by calling ``str()`` on it: | saving the page!) by calling ``str()`` on it: | ||||
| >>> text = str(code) | |||||
| >>> print(text) | |||||
| {{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}} | |||||
| >>> text == code | |||||
| True | |||||
| .. code-block:: python | |||||
| >>> text = str(code) | |||||
| >>> print(text) | |||||
| {{cleanup|date=July 2012}} '''Foo''' is a [[bar]]. {{bar-stub}} | |||||
| >>> text == code | |||||
| True | |||||
| Limitations | Limitations | ||||
| ----------- | ----------- | ||||