diff options
author | Jens Diemer <git@jensdiemer.de> | 2022-08-20 21:54:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-20 21:54:38 +0200 |
commit | e5d71d823a4c304ef3c105feb6d08222ae985bf7 (patch) | |
tree | f5c50bf51b23aad90056ae39c52be5e5a49dde10 | |
parent | c61ef1a82414c170e1460f906cf87a2385fc70a6 (diff) | |
parent | b9bcaed20c3dae4034077e9f6217e999c7904072 (diff) | |
download | creole-e5d71d823a4c304ef3c105feb6d08222ae985bf7.tar.gz |
Merge pull request #64 from jedie/html2markdownv1.5.0.rc0
WIP: html2markdown
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | README.creole | 33 | ||||
-rw-r--r-- | README.md | 456 | ||||
-rw-r--r-- | README.rst | 44 | ||||
-rw-r--r-- | creole/__init__.py | 15 | ||||
-rw-r--r-- | creole/emitter/creol2html_emitter.py | 2 | ||||
-rw-r--r-- | creole/emitter/html2markdown_emitter.py | 192 | ||||
-rw-r--r-- | creole/html_tools/strip_html.py | 1 | ||||
-rw-r--r-- | creole/parser/html_parser.py | 38 | ||||
-rw-r--r-- | creole/setup_utils.py | 96 | ||||
-rw-r--r-- | creole/shared/base_emitter.py | 1 | ||||
-rw-r--r-- | creole/tests/test_creole2html.py | 22 | ||||
-rw-r--r-- | creole/tests/test_cross_compare_markdown.py | 154 | ||||
-rw-r--r-- | creole/tests/test_html2markdown.py | 99 | ||||
-rw-r--r-- | creole/tests/test_project_setup.py | 13 | ||||
-rw-r--r-- | creole/tests/utils/base_unittest.py | 54 | ||||
-rw-r--r-- | poetry.lock | 238 | ||||
-rw-r--r-- | pyproject.toml | 6 |
19 files changed, 1237 insertions, 232 deletions
@@ -10,3 +10,5 @@ coverage.xml /dist /build /publish.log + +README.html @@ -44,8 +44,9 @@ tox: check-poetry ## Run pytest via tox with all environments pytest: check-poetry ## Run pytest poetry run pytest -update-rst-readme: ## update README.rst from README.creole +update-readmes: ## update README.rst from README.creole poetry run update_rst_readme + poetry run update_markdown_readme publish: ## Release new version to PyPi poetry run publish diff --git a/README.creole b/README.creole index 43530f4..3c3cf99 100644 --- a/README.creole +++ b/README.creole @@ -51,7 +51,7 @@ Convert creole markup to html code: {{{ >>> from creole import creole2html >>> creole2html("This is **creole //markup//**") -u'<p>This is <strong>creole <i>markup</i></strong></p>\n' +'<p>This is <strong>creole <i>markup</i></strong></p>\n' }}} @@ -59,8 +59,8 @@ u'<p>This is <strong>creole <i>markup</i></strong></p>\n' Convert html code back into creole markup: {{{ >>> from creole import html2creole ->>> html2creole(u'<p>This is <strong>creole <i>markup</i></strong></p>\n') -u'This is **creole //markup//**' +>>> html2creole('<p>This is <strong>creole <i>markup</i></strong></p>\n') +'This is **creole //markup//**' }}} @@ -69,7 +69,7 @@ Convert ReStructuredText into clean html code (needs [[http://pypi.python.org/py {{{ >>> from creole.rest2html.clean_writer import rest2html >>> rest2html(u"A ReSt link to `PyLucid CMS <http://www.pylucid.org>`_ :)") -u'<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' +'<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' }}} (more information: [[https://github.com/jedie/python-creole/wiki/rest2html|rest2html wiki page]]) @@ -78,8 +78,8 @@ u'<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' Convert html code into ReStructuredText markup: {{{ >>> from creole import html2rest ->>> html2rest(u'<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') -u'This is **ReStructuredText** *markup*!' +>>> html2rest('<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') +'This is **ReStructuredText** *markup*!' }}} @@ -87,8 +87,18 @@ u'This is **ReStructuredText** *markup*!' Convert html code into textile markup {{{ >>> from creole import html2textile ->>> html2textile(u'<p>This is <strong>textile <i>markup</i></strong>!</p>') -u'This is *textile __markup__*!' +>>> html2textile('<p>This is <strong>textile <i>markup</i></strong>!</p>') +'This is *textile __markup__*!' +}}} + +See also: [[http://github.com/jedie/python-creole/blob/master/demo.py]] + +== html2markdown == +Convert html code into textile markup +{{{ +>>> from creole import html2markdown +>>> html2markdown('<p>This is <strong>markdown <i>markup</i></strong>!</p>') +'This is **markdown _markup_**!' }}} See also: [[http://github.com/jedie/python-creole/blob/main/demo.py]] @@ -129,6 +139,7 @@ If you have python-creole installed, you will get these simple CLI scripts: * html2creole * html2rest * html2textile +* html2markdown Here the {{{--help}}} output from {{{html2creole}}}: {{{ @@ -228,6 +239,10 @@ Note: In this case you must install **docutils**! See above. = history = * *dev* - [[https://github.com/jedie/python-creole/compare/v1.4.10...master|compare v1.4.10...master]] +** NEW: html2markdown +** creole2html bugfixes: +*** replace wrong {{{<tt>}}} with {{{<code>}}} +*** Add newline after lists ** Remove deprecated "parser_kwargs" and "emitter_kwargs" ** Rename git {{{master}}} branch to {{{main}}}. ** TBC @@ -377,7 +392,7 @@ Note: In this case you must install **docutils**! See above. ** only emit children of empty tags like div and span (contributed by Eric O'Connell) ** remove inter wiki links and doesn't check the protocol * v0.3.3 -** Use <tt> when ~{~{~{ ... ~}~}~} is inline and not <pre>, see: [[http://forum.pylucid.org/viewtopic.php?f=3&t=320|PyLucid Forum Thread]] +** Use {{{<tt>}}} when ~{~{~{ ... ~}~}~} is inline and not {{{<pre>}}}, see: [[http://forum.pylucid.org/viewtopic.php?f=3&t=320|PyLucid Forum Thread]] ** Bugfix in html2creole: insert newline before new list. TODO: apply to all block tags: [[http://code.google.com/p/python-creole/issues/detail?id=16#c5|issues 16]] * v0.3.2 ** Bugfix for spaces after Headline: [[https://code.google.com/p/python-creole/issues/detail?id=15|issues 15]] diff --git a/README.md b/README.md new file mode 100644 index 0000000..ed348a3 --- /dev/null +++ b/README.md @@ -0,0 +1,456 @@ +# about python-creole + +python-creole is a OpenSource (GPL) Python lib for converting markups. +python-creole is pure python. No external libs needed. + +Compatible Python Versions (see [tox.ini](https://github.com/jedie/python-creole/blob/main/tox.ini)): + + +* 3.9, 3.8, 3.7, 3.6 +* PyPy3 + +Existing converters: + + +* creole -> html +* html -> creole markup +* reSt -> html (for clean html code) +* html -> reStructuredText markup (only a subset of reSt supported) +* html -> textile markup (not completed yet) + +The creole2html part based on the creole markup parser and emitter from the MoinMoin project by Radomir Dopieralski and Thomas Waldmann. + +| ![Build Status on github](https://github.com/jedie/python-creole/workflows/test/badge.svg?branch=master "Build Status on github") | +| ![Coverage Status on coveralls.io](https://coveralls.io/repos/jedie/python-creole/badge.svg "Coverage Status on coveralls.io") | +| ![Status on landscape.io](https://landscape.io/github/jedie/python-creole/main/landscape.svg "Status on landscape.io") | +| ![PyPi version](https://badge.fury.io/py/python-creole.svg "PyPi version") | +# install + +Python packages available on: [http://pypi.python.org/pypi/python-creole/](http://pypi.python.org/pypi/python-creole/) + +``` +~$ pip install python-creole +``` +To setup a virtualenv via Poetry, see `unittests` section below. + +## dependencies + +For the most parts (`creole2html` and `html2creole`) no external libraries are needed. + +For all functionality (and running the unittests) these modules are needed: + + +* [docutils](http://pypi.python.org/pypi/docutils/) (for the ReStructuredText stuff) +* [textile](http://pypi.python.org/pypi/textile/) (for html2textile tests) + +# example + +## creole2html + +Convert creole markup to html code: + +``` +>>> from creole import creole2html +>>> creole2html("This is **creole //markup//**") +'<p>This is <strong>creole <i>markup</i></strong></p>\n' +``` +## html2creole + +Convert html code back into creole markup: + +``` +>>> from creole import html2creole +>>> html2creole('<p>This is <strong>creole <i>markup</i></strong></p>\n') +'This is **creole //markup//**' +``` +## rest2html + +Convert ReStructuredText into clean html code (needs [docutils](http://pypi.python.org/pypi/docutils/)): + +``` +>>> from creole.rest2html.clean_writer import rest2html +>>> rest2html(u"A ReSt link to `PyLucid CMS <http://www.pylucid.org>`_ :)") +'<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' +``` +(more information: [rest2html wiki page](https://github.com/jedie/python-creole/wiki/rest2html)) + +## html2rest + +Convert html code into ReStructuredText markup: + +``` +>>> from creole import html2rest +>>> html2rest('<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') +'This is **ReStructuredText** *markup*!' +``` +## html2textile + +Convert html code into textile markup + +``` +>>> from creole import html2textile +>>> html2textile('<p>This is <strong>textile <i>markup</i></strong>!</p>') +'This is *textile __markup__*!' +``` +See also: [http://github.com/jedie/python-creole/blob/master/demo.py](http://github.com/jedie/python-creole/blob/master/demo.py) + +## html2markdown + +Convert html code into textile markup + +``` +>>> from creole import html2markdown +>>> html2markdown('<p>This is <strong>markdown <i>markup</i></strong>!</p>') +'This is **markdown _markup_**!' +``` +See also: [http://github.com/jedie/python-creole/blob/main/demo.py](http://github.com/jedie/python-creole/blob/main/demo.py) + +# Image size additional + +You can pass image width/height in image tags, e.g.: + +``` +>>> from creole import creole2html +>>> creole_markup="""{{foobar.jpg|image title|90x160}}""" +>>> creole2html(creole_markup) +'<p><img src="foobar.jpg" title="image title" alt="image title" width="90" height="160" /></p>' +``` +The third part (`90x160`) is not in creole standard, you can force a _strict_ mode, e.g.: + +``` +>>> creole2html(creole_markup, strict=True) +'<p><img src="foobar.jpg" title="image title|90x160" alt="image title|90x160" /></p>' +``` +# Source code highlighting support + +You can find a example macro which highlight source code thanks to the pygments +library. It is located here: [/creole/shared/example_macros.py](https://github.com/jedie/python-creole/blob/main/creole/shared/example_macros.py). +Here is how to use it: + +``` +>>> from creole import creole2html +>>> from creole.shared.example_macros import code +>>> creole_markup="""<<code ext=".py">>#some code\nprint('coucou')\n<</code>>""" +>>> creole2html(creole_markup, macros={'code': code}) +``` +# commandline interface + +If you have python-creole installed, you will get these simple CLI scripts: + + +* creole2html +* html2creole +* html2rest +* html2textile +* html2markdown + +Here the `--help` output from `html2creole`: + +``` +$ html2creole --help +usage: html2creole [-h] [-v] [--encoding ENCODING] sourcefile destination + +python-creole is an open-source (GPL) markup converter in pure Python for: +creole2html, html2creole, html2ReSt, html2textile + +positional arguments: + sourcefile source file to convert + destination Output filename + +optional arguments: + -h, --help show this help message and exit + -v, --version show program's version number and exit + --encoding ENCODING Codec for read/write file (default encoding: utf-8) +``` +Example to convert a html file into a creole file: + +``` +$ html2creole foobar.html foobar.creole +``` +# documentation + +We store documentation/examples into the project wiki: + + +* [https://github.com/jedie/python-creole/wiki](https://github.com/jedie/python-creole/wiki) + +How to handle unknown html tags in html2creole: + + +* [https://github.com/jedie/python-creole/wiki/Unknown-Html-Tags](https://github.com/jedie/python-creole/wiki/Unknown-Html-Tags) + +Contributers should take a look at this page: + + +* [https://github.com/jedie/python-creole/wiki/Developer-Info](https://github.com/jedie/python-creole/wiki/Developer-Info) + +Creole Markup Cheat Sheet can be found here: [http://www.wikicreole.org/wiki/CheatSheet](http://www.wikicreole.org/wiki/CheatSheet) + +![Creole Markup Cheat Sheet](http://www.wikicreole.org/imageServlet?page=CheatSheet%2Fcreole_cheat_sheet.png&width=340 "Creole Markup Cheat Sheet") + +## unittests + +``` +# clone repository (or use your fork): +~$ git clone https://github.com/jedie/python-creole.git +~$ cd python-creole + +# install or update poetry: +~/python-creole$ make install-poetry + +# install python-creole via poetry: +~/python-creole$ make install + +# Run pytest: +~/python-creole$ make pytest + +# Run pytest via tox with all environments: +~/python-creole$ make tox + +# Run pytest via tox with one Python version: +~/python-creole$ make tox-py38 +~/python-creole$ make tox-py37 +~/python-creole$ make tox-py36 +``` +## make targets + +To see all make targets, just call `make`: + +``` +~/python-creole$ make +help List all commands +install-poetry install or update poetry +install install python-creole via poetry +lint Run code formatters and linter +fix-code-style Fix code formatting +tox-listenvs List all tox test environments +tox Run pytest via tox with all environments +tox-py36 Run pytest via tox with *python v3.6* +tox-py37 Run pytest via tox with *python v3.7* +tox-py38 Run pytest via tox with *python v3.8* +tox-py39 Run pytest via tox with *python v3.9* +pytest Run pytest +update-rst-readme update README.rst from README.creole +publish Release new version to PyPi +``` +## Use creole in README + +With python-creole you can convert a README on-the-fly from creole into ReStructuredText in setup.py +How to do this, read: [https://github.com/jedie/python-creole/wiki/Use-In-Setup](https://github.com/jedie/python-creole/wiki/Use-In-Setup) + +Note: In this case you must install **docutils**! See above. + +# history + + +* *dev* - [compare v1.4.10...master](https://github.com/jedie/python-creole/compare/v1.4.10...master) + * NEW: html2markdown + * creole2html bugfixes: + * replace wrong `<tt>` with `<code>` + * Add newline after lists + * Remove deprecated "parser_kwargs" and "emitter_kwargs" + * Rename git `master` branch to `main`. + * TBC +* v1.4.10 - 2021-05-11 - [compare v1.4.9...v1.4.10](https://github.com/jedie/python-creole/compare/v1.4.9...v1.4.10) + * Update some string formatting to f-strings + * Replace some `join()` list comprehension with generators + * Test on github actions also under MacOS + * Remove Travis CI (All tests already running via github actions) +* v1.4.9 - 2020-11-4 - [compare v1.4.8...v1.4.9](https://github.com/jedie/python-creole/compare/v1.4.8...v1.4.9) + * Add missing classifier for Python 3.9 ([Contributed by jugmac00](https://github.com/jedie/python-creole/pull/55)) + * Update readme test +* v1.4.8 - 2020-10-17 - [compare v1.4.7...v1.4.8](https://github.com/jedie/python-creole/compare/v1.4.7...v1.4.8) + * Validate generated `README.rst` with [readme-renderer](https://pypi.org/project/readme-renderer/) +* v1.4.7 - 2020-10-17 - [compare v1.4.6...v1.4.7](https://github.com/jedie/python-creole/compare/v1.4.6...v1.4.7) + * `update_rst_readme()` will touch `README.rst` if there are not change (timestamp will not changed in file) + * Run tests with Python 3.9, too. + * Some meta updates to project setup +* v1.4.6 - 2020-02-13 - [compare v1.4.5...v1.4.6](https://github.com/jedie/python-creole/compare/v1.4.5...v1.4.6) + * less restricted dependency specification +* v1.4.5 - 2020-02-13 - [compare v1.4.4...v1.4.5](https://github.com/jedie/python-creole/compare/v1.4.4...v1.4.5) + * new: `creole.setup_utils.assert_rst_readme` for project setup tests + * use [https://github.com/ymyzk/tox-gh-actions](https://github.com/ymyzk/tox-gh-actions) on gitlab CI +* v1.4.4 - 2020-02-07 - [compare v1.4.3...v1.4.4](https://github.com/jedie/python-creole/compare/v1.4.3...v1.4.4) + * Fix #44: Move `poetry-publish` to `dev-dependencies` and lower `docutils` requirement to ![^0.15](^0.15 "^0.15") + * some code style updated + * Always update README.rst before publish +* v1.4.3 - 2020-02-01 - [compare v1.4.2...v1.4.3](https://github.com/jedie/python-creole/compare/v1.4.2...v1.4.3) + * Use new [poetry-publish](https://pypi.org/project/poetry-publish/) for `make publish` +* v1.4.2 - 2020-02-01 - [compare v1.4.1...v1.4.2](https://github.com/jedie/python-creole/compare/v1.4.1...v1.4.2) + * Update CI configs on github and travis + * Update `Makefile`: add `make publish` and `make update-rst-readme` + * Add generated `README.rst` in repository to fix install problems about missing readme +* v1.4.1 - 2020-01-19 - [compare v1.4.0...v1.4.1](https://github.com/jedie/python-creole/compare/v1.4.0...v1.4.1) + * Remove Python v2 support code + * [Fix "Undefined substitution referenced" error](https://github.com/jedie/python-creole/issues/26) contributed by dforsi + * [Fix regression in tests for setup_utils](https://github.com/jedie/python-creole/pull/37) contributed by jugmac00 + * Fix code style with: autopep8 + * sort imports with isort + * change old `%-formatted` and `.format(...)` strings into Python 3.6+'s `f-strings` with flynt + * Activate linting in CI pipeline +* v1.4.0 - 2020-01-19 - [compare v1.3.2...v1.4.0](https://github.com/jedie/python-creole/compare/v1.3.2...v1.4.0) + * modernize project: + * use poetry + * Add a `Makefile` + * use pytest and tox + * remove Python v2 support + * Test with Python v3.6, v3.7 and v3.8 +* v1.3.2 - 2018-02-27 - [compare v1.3.1...v1.3.2](https://github.com/jedie/python-creole/compare/v1.3.1...v1.3.2) + * Adding optional img size to creole2html and html2creole contributed by [John Dupuy](https://github.com/JohnAD) + * run tests also with python 3.5 and 3.6 +* v1.3.1 - 2015-08-15 - [compare v1.3.0...v1.3.1](https://github.com/jedie/python-creole/compare/v1.3.0...v1.3.1) + * Bugfix for "Failed building wheel for python-creole" +* v1.3.0 - 2015-06-02 - [compare v1.2.2...v1.3.0](https://github.com/jedie/python-creole/compare/v1.2.2...v1.3.0) + * Refactory internal file structure + * run unittests and doctests with nose + * Refactor CLI tests + * skip official support for Python 2.6 + * small code cleanups and fixes. + * use **json.dumps()** instead of **repr()** in some cases +* v1.2.2 - 2015-04-05 - [compare v1.2.1...v1.2.2](https://github.com/jedie/python-creole/compare/v1.2.1...v1.2.2) + * Bugfix textile unittests if url scheme is unknown + * migrate google-code Wiki to github and remove google-code links +* v1.2.1 - 2014-09-14 - [compare v1.2.0...v1.2.1](https://github.com/jedie/python-creole/compare/v1.2.0...v1.2.1) + * Use origin PyPi code to check generated reStructuredText in setup.py + * Update unitest for textile v2.1.8 +* v1.2.0 - 2014-05-15 - [compare v1.1.1...v1.2.0](https://github.com/jedie/python-creole/compare/v1.1.1...v1.2.0) + * NEW: Add `<<code>>` example macro (Source code highlighting with pygments) - implemented by Julien Enselme + * NEW: Add `<<toc>>` macro to create a table of contents list + * Bugfix for: AttributeError: 'CreoleParser' object has no attribute '_escaped_char_repl' + * Bugfix for: AttributeError: 'CreoleParser' object has no attribute '_escaped_url_repl' + * API Change: Callable macros will raise a TypeError instead of create a DeprecationWarning (Was removed in v0.5) +* v1.1.1 - 2013-11-08 + * Bugfix: Setup script exited with error: can't copy 'README.creole': doesn't exist or not a regular file +* v1.1.0 - 2013-10-28 + * NEW: Simple commandline interface added. +* v1.0.7 - 2013-08-07 + * Bugfix in 'clean reStructuredText html writer' if docutils => v0.11 used. + * Bugfix for PyPy 2.1 usage +* v1.0.6 - 2012-10-15 + * Security fix in rest2html: Disable "file_insertion_enabled" and "raw_enabled" as default. +* v1.0.5 - 2012-09-03 + * made automatic protocol links more strict: Only whitespace before and at the end are allowed. + * Bugfix: Don't allow `ftp:/broken` (Only one slash) to be a link. +* v1.0.4 - 2012-06-11 + * html2rest: Handle double link/image substitution and raise better error messages + * Bugfix in unittests (include test README file in python package). Thanks to Wen Heping for reporting this. +* v1.0.3 - 2012-06-11 + * Bugfix: `AttributeError: 'module' object has no attribute 'interesting_cdata'` from HTMLParser patch. Thanks to Wen Heping for reporting this. + * Fix a bug in get_long_description() ReSt test for Py3k and his unittests. + * Use Travis CI, too. +* v1.0.2 - 2012-04-04 + * Fix "[AttributeError: 'NoneType' object has no attribute 'parent'](https://github.com/jedie/python-creole/issues/6)" in html2creole. +* v1.0.1 - 2011-11-16 + * Fix "[TypeError: expected string or buffer](https://github.com/jedie/python-creole/issues/5)" in rest2html. + * [Bugfix in exception handling.](https://github.com/jedie/python-creole/commit/e8422f944709a5f8c2c6a8c8a58a84a92620f035) +* v1.0.0 - 2011-10-20 + * Change API: Replace 'parser_kwargs' and 'emitter_kwargs' with separate arguments. (More information on [API Wiki Page](https://github.com/jedie/python-creole/wiki/API)) +* v0.9.2 + * Turn zip_safe in setup.py on and change unittests API. +* v0.9.1 + * Many Bugfixes, tested with CPython 2.6, 2.7, 3.2 and PyPy v1.6 +* v0.9.0 + * Add Python v3 support (like [http://python3porting.com/noconv.html](http://python3porting.com/noconv.html) strategy) + * move unittests into creole/tests/ + * Tested with Python 2.7.1, 3.2 and PyPy v1.6.1 15798ab8cf48 jit +* v0.8.5 + * Bugfix in html2creole: ignore links without href +* v0.8.4 + * Bugfix in html parser if list tag has attributes: [https://code.google.com/p/python-creole/issues/detail?id=19#c4](https://code.google.com/p/python-creole/issues/detail?id=19#c4) +* v0.8.3 + * Better error message if given string is not unicode: [https://code.google.com/p/python-creole/issues/detail?id=19](https://code.google.com/p/python-creole/issues/detail?id=19) +* v0.8.2 + * Bugfix in get_long_description() error handling (_local variable 'long_description_origin' referenced before assignment_) +* v0.8.1 + * Bugfix for installation under python 2.5 + * Note: [setup helper](https://github.com/jedie/python-creole/wiki/Use-In-Setup) changed: rename `GetLongDescription(...)` to `get_long_description(...)` +* v0.8 + * New GetLongDescription() helper for setup.py, see: [https://github.com/jedie/python-creole/wiki/Use-In-Setup](https://github.com/jedie/python-creole/wiki/Use-In-Setup) +* v0.7.3 + * Bugfix in html2rest: + * table without `<th>` header + * new line after table + * create reference hyperlinks in table cells intead of embedded urls. + * Don't always use raise_unknown_node() + * Add child content to raise_unknown_node() +* v0.7.2 + * Activate `----` to `<hr>` in html2rest + * Update demo.py +* v0.7.1 + * Bugfix if docutils are not installed + * API change: rest2html is now here: `from creole.rest2html.clean_writer import rest2html` +* v0.7.0 + * **NEW**: Add a html2reStructuredText converter (only a subset of reSt supported) +* v0.6.1 + * Bugfix: separate lines with one space in "wiki style line breaks" mode +* v0.6 + * **NEW**: html2textile converter + * some **API changed**! +* v0.5 + * **API changed**: + * Html2CreoleEmitter optional argument 'unknown_emit' takes now a callable for handle unknown html tags. + * No macros used as default in creole2html converting. + * We remove the support for callable macros. Only dict and modules are allowed. + * remove unknown html tags is default behaviour in html2creole converting. + * restructure and cleanup sourcecode files. +* v0.4 + * only emit children of empty tags like div and span (contributed by Eric O'Connell) + * remove inter wiki links and doesn't check the protocol +* v0.3.3 + * Use `<tt>` when {{{ ... }}} is inline and not `<pre>`, see: [PyLucid Forum Thread](http://forum.pylucid.org/viewtopic.php?f=3&t=320) + * Bugfix in html2creole: insert newline before new list. TODO: apply to all block tags: [issues 16](http://code.google.com/p/python-creole/issues/detail?id=16#c5) +* v0.3.2 + * Bugfix for spaces after Headline: [issues 15](https://code.google.com/p/python-creole/issues/detail?id=15) +* v0.3.1 + * Make argument 'block_rules' in Parser() optional +* v0.3.0 + * creole2html() has the optional parameter 'blog_line_breaks' to switch from default blog to wiki line breaks +* v0.2.8 + * bugfix in setup.py +* v0.2.7 + * handle obsolete non-closed <br> tag +* v0.2.6 + * bugfix in setup.py + * Cleanup DocStrings + * add unittests +* v0.2.5 + * creole2html: Bugfix if "--", "//" etc. stands alone, see also: [issues 12](http://code.google.com/p/python-creole/issues/detail?id=12) + * Note: bold, italic etc. can't cross line any more. +* v0.2.4 + * creole2html: ignore file extensions in image tag + * see also: [issues 7](http://code.google.com/p/python-creole/issues/detail?id=7) +* v0.2.3 + * html2creole bugfix/enhanced: convert image tag without alt attribute: + * see also: [issues 6](http://code.google.com/p/python-creole/issues/detail?id=6) + * Thanks Betz Stefan alias 'encbladexp' +* v0.2.2 + * html2creole bugfix: convert `<a href="/url/">Search & Destroy</a>` +* v0.2.1 + * html2creole bugfixes in: + * converting tables: ignore tbody tag and better handling p and a tags in td + * converting named entity +* v0.2 + * remove all django template tag stuff: [issues 3](http://code.google.com/p/python-creole/issues/detail?id=3) + * html code always escaped +* v0.1.1 + * improve macros stuff, patch by Vitja Makarov: [issues 2](http://code.google.com/p/python-creole/issues/detail?id=2) +* v0.1.0 + * first version cut out from [PyLucid CMS](http://www.pylucid.org) + +first source code was written 27.11.2008: [Forum thread (de)](http://www.python-forum.de/viewtopic.php?f=3&t=16742) + +## Project links + +| GitHub | [https://github.com/jedie/python-creole](https://github.com/jedie/python-creole) | +| Wiki | [https://github.com/jedie/python-creole/wiki](https://github.com/jedie/python-creole/wiki) | +| PyPi | [https://pypi.org/project/python-creole/](https://pypi.org/project/python-creole/) | +## donation + + +* [paypal.me/JensDiemer](https://www.paypal.me/JensDiemer) +* [Flattr This!](https://flattr.com/submit/auto?uid=jedie&url=https%3A%2F%2Fgithub.com%2Fjedie%2Fpython-creole%2F) +* Send [Bitcoins](http://www.bitcoin.org/) to [1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F](https://blockexplorer.com/address/1823RZ5Md1Q2X5aSXRC5LRPcYdveCiVX6F) + +------------ + +``Note: this file is generated from README.creole 2022-08-20 21:51:36 with "python-creole"``
\ No newline at end of file @@ -81,7 +81,7 @@ Convert creole markup to html code: >>> from creole import creole2html >>> creole2html("This is **creole //markup//**") - u'<p>This is <strong>creole <i>markup</i></strong></p>\n' + '<p>This is <strong>creole <i>markup</i></strong></p>\n' ----------- html2creole @@ -92,8 +92,8 @@ Convert html code back into creole markup: :: >>> from creole import html2creole - >>> html2creole(u'<p>This is <strong>creole <i>markup</i></strong></p>\n') - u'This is **creole //markup//**' + >>> html2creole('<p>This is <strong>creole <i>markup</i></strong></p>\n') + 'This is **creole //markup//**' --------- rest2html @@ -105,7 +105,7 @@ Convert ReStructuredText into clean html code (needs `docutils`_): >>> from creole.rest2html.clean_writer import rest2html >>> rest2html(u"A ReSt link to `PyLucid CMS <http://www.pylucid.org>`_ :)") - u'<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' + '<p>A ReSt link to <a href="http://www.pylucid.org">PyLucid CMS</a> :)</p>\\n' (more information: `rest2html wiki page <https://github.com/jedie/python-creole/wiki/rest2html>`_) @@ -118,8 +118,8 @@ Convert html code into ReStructuredText markup: :: >>> from creole import html2rest - >>> html2rest(u'<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') - u'This is **ReStructuredText** *markup*!' + >>> html2rest('<p>This is <strong>ReStructuredText</strong> <em>markup</em>!</p>') + 'This is **ReStructuredText** *markup*!' ------------ html2textile @@ -130,8 +130,22 @@ Convert html code into textile markup :: >>> from creole import html2textile - >>> html2textile(u'<p>This is <strong>textile <i>markup</i></strong>!</p>') - u'This is *textile __markup__*!' + >>> html2textile('<p>This is <strong>textile <i>markup</i></strong>!</p>') + 'This is *textile __markup__*!' + +See also: `http://github.com/jedie/python-creole/blob/master/demo.py <http://github.com/jedie/python-creole/blob/master/demo.py>`_ + +------------- +html2markdown +------------- + +Convert html code into textile markup + +:: + + >>> from creole import html2markdown + >>> html2markdown('<p>This is <strong>markdown <i>markup</i></strong>!</p>') + 'This is **markdown _markup_**!' See also: `http://github.com/jedie/python-creole/blob/main/demo.py <http://github.com/jedie/python-creole/blob/main/demo.py>`_ @@ -184,6 +198,8 @@ If you have python-creole installed, you will get these simple CLI scripts: * html2textile +* html2markdown + Here the ``--help`` output from ``html2creole``: :: @@ -297,6 +313,14 @@ history * *dev* - `compare v1.4.10...master <https://github.com/jedie/python-creole/compare/v1.4.10...master>`_ + * NEW: html2markdown + + * creole2html bugfixes: + + * replace wrong ``<tt>`` with ``<code>`` + + * Add newline after lists + * Remove deprecated "parser_kwargs" and "emitter_kwargs" * Rename git ``master`` branch to ``main``. @@ -595,7 +619,7 @@ history * v0.3.3 - * Use <tt> when {{{ ... }}} is inline and not <pre>, see: `PyLucid Forum Thread <http://forum.pylucid.org/viewtopic.php?f=3&t=320>`_ + * Use ``<tt>`` when {{{ ... }}} is inline and not ``<pre>``, see: `PyLucid Forum Thread <http://forum.pylucid.org/viewtopic.php?f=3&t=320>`_ * Bugfix in html2creole: insert newline before new list. TODO: apply to all block tags: `issues 16 <http://code.google.com/p/python-creole/issues/detail?id=16#c5>`_ @@ -704,4 +728,4 @@ donation ------------ -``Note: this file is generated from README.creole 2022-08-20 09:52:40 with "python-creole"``
\ No newline at end of file +``Note: this file is generated from README.creole 2022-08-20 21:51:36 with "python-creole"``
\ No newline at end of file diff --git a/creole/__init__.py b/creole/__init__.py index daf3bfa..a7e56d1 100644 --- a/creole/__init__.py +++ b/creole/__init__.py @@ -17,6 +17,7 @@ import warnings from creole.emitter.creol2html_emitter import HtmlEmitter from creole.emitter.html2creole_emitter import CreoleEmitter +from creole.emitter.html2markdown_emitter import MarkdownEmitter from creole.emitter.html2rest_emitter import ReStructuredTextEmitter from creole.emitter.html2textile_emitter import TextileEmitter from creole.parser.creol2html_parser import CreoleParser @@ -111,6 +112,20 @@ def html2textile(html_string, debug=False, return emitter.emit() +def html2markdown(html_string, debug=False, unknown_emit=None): + """ + convert html code into markdown markup + + >>> html2markdown('<p>This is <strong>markdown <i>markup</i></strong>!</p>') + 'This is **markdown _markup_**!' + """ + document_tree = parse_html(html_string, debug=debug) + + # create markdown markup from the document tree + emitter = MarkdownEmitter(document_tree, debug=debug, unknown_emit=unknown_emit) + return emitter.emit() + + def html2rest(html_string, debug=False, unknown_emit=None ): diff --git a/creole/emitter/creol2html_emitter.py b/creole/emitter/creol2html_emitter.py index f3bf4d9..f2da5d4 100644 --- a/creole/emitter/creol2html_emitter.py +++ b/creole/emitter/creol2html_emitter.py @@ -382,7 +382,7 @@ class HtmlEmitter: def pre_inline_emit(self, node): """ pre without newline at the end """ - return f"<tt>{self.html_escape(node.content)}</tt>" + return f"<code>{self.html_escape(node.content)}</code>" def default_emit(self, node): """Fallback function for emitting unknown nodes.""" diff --git a/creole/emitter/html2markdown_emitter.py b/creole/emitter/html2markdown_emitter.py new file mode 100644 index 0000000..540d53a --- /dev/null +++ b/creole/emitter/html2markdown_emitter.py @@ -0,0 +1,192 @@ +""" + html -> Markdown Emitter + ~~~~~~~~~~~~~~~~~~~~~~ + + https://ct.de/y5hr + + :copyleft: 2021 by python-creole team, see AUTHORS for more details. + :license: GNU GPL v3 or above, see LICENSE for more details. + +""" + + +import posixpath + +from creole.parser.html_parser import HtmlParser +from creole.parser.html_parser_config import BLOCK_TAGS +from creole.shared.base_emitter import BaseEmitter +from creole.shared.document_tree import DocNode + + +class MarkdownEmitter(BaseEmitter): + """ + Build from a document_tree (html2creole.parser.HtmlParser instance) a + Markdown markup text. + """ + + def __init__(self, document_tree, strict=False, *args, **kwargs): + self.strict = strict + super().__init__(document_tree, *args, **kwargs) + + self.table_head_prefix = '= ' + self.table_auto_width = True + + def emit(self): + """Emit the document represented by self.root DOM tree.""" + return self.emit_node(self.root).strip() # FIXME + + # -------------------------------------------------------------------------- + + def blockdata_pre_emit(self, node: DocNode): + """pre block -> with newline at the end""" + return f'```{self.deentity.replace_all(node.content)}```\n' + + def inlinedata_pre_emit(self, node: DocNode): + """a pre inline block -> no newline at the end""" + pre_content = node.content + + if pre_content.endswith('</code>'): + # TODO: The parser should parse this! + p = HtmlParser(debug=True) + root_node: DocNode = p.feed(pre_content, preprocess=False) + code_node: DocNode = root_node.children[0] + code = self.deentity.replace_all(code_node.children[0].content) + + class_value = code_node.attrs.get('class') + if class_value: + if class_value.startswith('language-'): + language = class_value.partition('-')[2] + return f'```{language}{code}```\n\n' + + return f'```{code}```\n\n' + + return f'```{self.deentity.replace_all(pre_content)}```\n' + + def blockdata_pass_emit(self, node: DocNode): + return f'{node.content}\n\n' + + # -------------------------------------------------------------------------- + + def p_emit(self, node: DocNode): + result = self.emit_children(node) + if self._inner_list == '': + result += '\n\n' + return result + + def br_emit(self, node: DocNode): + return '\n' + + def headline_emit(self, node: DocNode): + prefix = '#' * node.level + return f'{prefix} {self.emit_children(node)}\n\n' + + # -------------------------------------------------------------------------- + + def strong_emit(self, node: DocNode): + return self._typeface(node, key='**') + + b_emit = strong_emit + big_emit = strong_emit + + def i_emit(self, node: DocNode): + return self._typeface(node, key='_') + + def em_emit(self, node: DocNode): + return self._typeface(node, key='*') + + def tt_emit(self, node: DocNode): + return self._typeface(node, key='##') + + def sup_emit(self, node: DocNode): + return self._typeface(node, key='^^') + + def sub_emit(self, node: DocNode): + return self._typeface(node, key=',,') + + def u_emit(self, node: DocNode): + return self._typeface(node, key='__') + + def small_emit(self, node: DocNode): + return self._typeface(node, key='--') + + def del_emit(self, node: DocNode): + return self._typeface(node, key='~~') + + strike_emit = del_emit + + # -------------------------------------------------------------------------- + + def hr_emit(self, node: DocNode): + return '----\n\n' + + def a_emit(self, node: DocNode): + link_text = self.emit_children(node) + url = node.attrs['href'] + title = node.attrs.get('title') + if title: + return f'[{link_text}]({url} "{title}")' + else: + return f'[{link_text}]({url})' + + def img_emit(self, node: DocNode): + src = node.attrs['src'] + + title = node.attrs.get('title') + alt = node.attrs.get('alt', '') + if title and alt: + return f'![{alt}]({src} "{title}")' + + return f'![{alt}]({src})' + + # -------------------------------------------------------------------------- + + def list_emit(self, node: DocNode): + content = self.emit_children(node) + if node.level == 1: + content += '\n\n' + return content + + ul_emit = list_emit + ol_emit = list_emit + + def li_emit(self, node: DocNode): + list_level = node.level + + list_node = node.parent + list_kind = list_node.kind + if list_kind == 'ul': + prefix = '*' + elif list_kind == 'ol': + prefix = '1.' + else: + raise NotImplementedError(f'List type: {list_kind}') + + indent = ' ' * (list_level - 1) + + content = self.emit_children(node) + return f"\n{indent}{prefix} {content}" + + # -------------------------------------------------------------------------- + def data_emit(self, node: DocNode): + content = node.content + if content == ' ': + # FIXME: Because of bug in creole.html_tools.strip_html.strip_html() + return '' + return node.content + + def code_emit(self, node: DocNode): + code_block = self._emit_content(node) + assert '\n' not in code_block + + if '`' in code_block: + return f'``{code_block}``' + else: + return f'`{code_block}`' + + # -------------------------------------------------------------------------- + + def div_emit(self, node: DocNode): + return self._emit_content(node) + + def span_emit(self, node: DocNode): + return self._emit_content(node) diff --git a/creole/html_tools/strip_html.py b/creole/html_tools/strip_html.py index c4b2c71..39613cc 100644 --- a/creole/html_tools/strip_html.py +++ b/creole/html_tools/strip_html.py @@ -41,6 +41,7 @@ def strip_html(html_code): >>> strip_html('<li> Force <br /> \\n linebreak </li>') '<li>Force<br />linebreak</li>' + FIXME: Space between </strong> </i> : >>> strip_html('one <i>two \\n <strong> \\n three \\n </strong></i>') 'one <i>two <strong>three</strong> </i>' diff --git a/creole/parser/html_parser.py b/creole/parser/html_parser.py index a3879a9..0b8e171 100644 --- a/creole/parser/html_parser.py +++ b/creole/parser/html_parser.py @@ -95,6 +95,7 @@ class HtmlParser(HTMLParser): self.__list_level = 0 def _pre_cut(self, data, type, placeholder): + # TODO: Check if we have a code block, e.g.: "<pre><code>...</code></pre>" if self.debugging: print(f"append blockdata: {data!r}") assert isinstance(data, str), "blockdata is not unicode" @@ -125,27 +126,32 @@ class HtmlParser(HTMLParser): # data = match.group("data") - def feed(self, raw_data): + def feed(self, raw_data, preprocess=True) -> DocNode: assert isinstance(raw_data, str), "feed data must be unicode!" data = raw_data.strip() - - # cut out <pre> and <tt> areas block tag areas - data = block_re.sub(self._pre_cut_out, data) - data = inline_re.sub(self._pre_cut_out, data) - - # Delete whitespace from html code - data = strip_html(data) - - if self.debugging: + if preprocess: + # cut out <pre> and <tt> areas block tag areas + data = block_re.sub(self._pre_cut_out, data) + data = inline_re.sub(self._pre_cut_out, data) + + # Delete whitespace from html code + data = strip_html(data) + + if self.debugging: + print("_" * 79) + print("raw data:") + print(repr(raw_data)) + print(" -" * 40) + print("cleaned data:") + print(data) + print("-" * 79) + # print(data.replace(">", ">\n")) + # print("-"*79) + elif self.debugging: print("_" * 79) - print("raw data:") - print(repr(raw_data)) - print(" -" * 40) - print("cleaned data:") + print("data:") print(data) print("-" * 79) -# print(clean_data.replace(">", ">\n")) -# print("-"*79) HTMLParser.feed(self, data) diff --git a/creole/setup_utils.py b/creole/setup_utils.py index b2e4dbb..2b716ea 100644 --- a/creole/setup_utils.py +++ b/creole/setup_utils.py @@ -19,9 +19,10 @@ import sys import warnings from pathlib import Path +import markdown from readme_renderer.rst import render -from creole import creole2html, html2rest +from creole import creole2html, html2markdown, html2rest from creole.shared.diff_utils import unified_diff from creole.shared.unknown_tags import raise_unknown_node, transparent_unknown_nodes @@ -125,6 +126,24 @@ def _generate_rst_readme(*, creole_readme_path): return rest_readme +def _generate_markdown_readme(*, creole_readme_path): + creole_readme = creole_readme_path.read_text(encoding='utf-8').strip() + + # convert creole into html + html_readme = creole2html(creole_readme) + creole_readme_path.with_suffix('.html').write_text(html_readme) + + # convert html to Markdown + markdown_readme = html2markdown( + html_readme, unknown_emit=raise_unknown_node # raise a error if a unknown node found + ) + + # Just try to render: + html = markdown.markdown(markdown_readme) + + return markdown_readme + + def update_rst_readme(package_root, filename='README.creole'): """ Generate README.rst from README.creole @@ -172,6 +191,54 @@ def update_rst_readme(package_root, filename='README.creole'): return rest_readme_path +def update_markdown_readme(package_root, filename='README.creole'): + """ + Generate README.md from README.creole + """ + assert isinstance(package_root, Path) + assert package_root.is_dir(), f'Directory not found: {package_root}' + creole_readme_path = Path(package_root, filename) + assert creole_readme_path.is_file(), f'File not found: {creole_readme_path}' + + markdown_readme_path = creole_readme_path.with_suffix('.md') + print( + f'Generate {markdown_readme_path.name} from {creole_readme_path.name}', + end='...', + flush=True, + ) + + markdown_readme = _generate_markdown_readme(creole_readme_path=creole_readme_path) + + # # Check if content was changed + changed = False + with markdown_readme_path.open('r') as f: + for new_line, old_line in zip(markdown_readme.splitlines(), f): + if new_line.rstrip() != old_line.rstrip(): + changed = True + break + + if not changed: + # The existing README.rst is up-to-date: Don't change the timestamp + print('nothing changed, ok.') + return markdown_readme_path + + with markdown_readme_path.open('w') as f: + f.write(markdown_readme) + + # Add a note about generation with modification time from source: + + f.write('\n\n------------\n\n') + + modification_time = creole_readme_path.stat().st_mtime + dt = datetime.datetime.fromtimestamp(modification_time) + dt = dt.replace(microsecond=0) + dt = dt.isoformat(sep=' ') + f.write(f'``Note: this file is generated from {filename} {dt} with "python-creole"``') + + print('done.') + return markdown_readme_path + + def assert_rst_readme(package_root, filename='README.creole'): """ raise AssertionError if README.rst is not up-to-date. @@ -179,8 +246,7 @@ def assert_rst_readme(package_root, filename='README.creole'): creole_readme_path = Path(package_root, filename) rest_readme = _generate_rst_readme(creole_readme_path=creole_readme_path) rest_readme_path = creole_readme_path.with_suffix('.rst') - with rest_readme_path.open('r') as f: - content = f.read() + content = rest_readme_path.read_text(encoding='UTF-8') assert len(content) > 0, f'Empty content in {rest_readme_path}' content = content.rsplit('\n', 4)[0] # remove note about generation with modification time @@ -190,6 +256,23 @@ def assert_rst_readme(package_root, filename='README.creole'): raise AssertionError(f'{rest_readme_path.name} is not up-to-date:\n{diff}') +def assert_markdown_readme(package_root, filename='README.creole'): + """ + raise AssertionError if README.md is not up-to-date. + """ + creole_readme_path = Path(package_root, filename) + markdown_readme = _generate_markdown_readme(creole_readme_path=creole_readme_path) + markdown_readme_path = creole_readme_path.with_suffix('.md') + content = markdown_readme_path.read_text(encoding='UTF-8') + + assert len(content) > 0, f'Empty content in {markdown_readme_path}' + content = content.rsplit('\n', 4)[0] # remove note about generation with modification time + + if markdown_readme != content: + diff = unified_diff(content, markdown_readme, filename=markdown_readme_path.name) + raise AssertionError(f'{markdown_readme_path.name} is not up-to-date:\n{diff}') + + def update_creole_rst_readme(): return update_rst_readme( package_root=Path(__file__).parent.parent, @@ -197,5 +280,12 @@ def update_creole_rst_readme(): ) +def update_creole_markdown_readme(): + return update_markdown_readme( + package_root=Path(__file__).parent.parent, filename='README.creole' + ) + + if __name__ == '__main__': update_creole_rst_readme() + update_creole_markdown_readme() diff --git a/creole/shared/base_emitter.py b/creole/shared/base_emitter.py index 4f7c5f4..35d7f88 100644 --- a/creole/shared/base_emitter.py +++ b/creole/shared/base_emitter.py @@ -39,7 +39,6 @@ class BaseEmitter: def blockdata_pass_emit(self, node): return f"{node.content}\n\n" - return node.content # -------------------------------------------------------------------------- diff --git a/creole/tests/test_creole2html.py b/creole/tests/test_creole2html.py index 7babe1d..305c69d 100644 --- a/creole/tests/test_creole2html.py +++ b/creole/tests/test_creole2html.py @@ -637,17 +637,20 @@ class TestCreole2htmlMarkup(BaseCreoleTest): """) def test_toc_with_no_toc(self): - self.assert_creole2html(r""" + self.assert_creole2html( + """ <<toc>> = This is the Headline Use {{{<<toc>>}}} to insert a table of contents. - """, """ + """, + """ <ul> <li><a href="#This is the Headline">This is the Headline</a></li> </ul> <a name="This is the Headline"><h1>This is the Headline</h1></a> - <p>Use <tt><<toc>></tt> to insert a table of contents.</p> - """) + <p>Use <code><<toc>></code> to insert a table of contents.</p> + """, + ) def test_toc_more_then_one_toc(self): self.assert_creole2html(r""" @@ -855,13 +858,16 @@ class TestCreole2htmlMarkup(BaseCreoleTest): """)) def test_tt(self): - self.assert_creole2html(r""" + self.assert_creole2html( + """ inline {{{<escaped>}}} and {{{ **not strong** }}}... ...and ##**strong** Teletyper## ;) - """, """ - <p>inline <tt><escaped></tt> and <tt> **not strong** </tt>...<br /> + """, + """ + <p>inline <code><escaped></code> and <code> **not strong** </code>...<br /> ...and <tt><strong>strong</strong> Teletyper</tt> ;)</p> - """) + """, + ) def test_protocol_in_brackets(self): self.assert_creole2html(r""" diff --git a/creole/tests/test_cross_compare_markdown.py b/creole/tests/test_cross_compare_markdown.py new file mode 100644 index 0000000..2e77a81 --- /dev/null +++ b/creole/tests/test_cross_compare_markdown.py @@ -0,0 +1,154 @@ +""" + cross compare markdown unittest + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Compare all similarities between: + * markdown2html (used the python markdown module) + * html2markdown + + Note: This only works fine if there is no problematic whitespace handling. + In this case, we must test in test_creole2html.py or test_html2creole.py + + :copyleft: 2021 by python-creole team, see AUTHORS for more details. + :license: GNU GPL v3 or above, see LICENSE for more details. +""" +from inspect import cleandoc + +from creole.tests.utils.base_unittest import BaseCreoleTest + + +class CrossCompareMarkdownTests(BaseCreoleTest): + def test_headline(self): + self.cross_compare_markdown( + markdown_string=cleandoc( + ''' + # Headline + + Text under Headline + + ## Sub-Headline + + Text under Sub-Headline + ''' + ), + html_string=cleandoc( + ''' + <h1>Headline</h1> + <p>Text under Headline</p> + <h2>Sub-Headline</h2> + <p>Text under Sub-Headline</p> + ''' + ), + debug=True, + ) + + def test_links(self): + self.cross_compare_markdown( + markdown_string='[This is a Link](https//test.internal/foo/bar)', + html_string='<p><a href="https//test.internal/foo/bar">This is a Link</a></p>', + ) + self.cross_compare_markdown( + markdown_string='[A Link](https//test.internal/ "Title")', + html_string='<p><a href="https//test.internal/" title="Title">A Link</a></p>', + ) + + def test_images(self): + self.cross_compare_markdown( + markdown_string='![Alt text](/path/to/img.jpg)', + html_string='<p><img alt="Alt text" src="/path/to/img.jpg" /></p>', + ) + self.cross_compare_markdown( + markdown_string='![Alt text](/path/to/img.jpg "Title")', + html_string='<p><img alt="Alt text" src="/path/to/img.jpg" title="Title" /></p>', + ) + + def test_image_links(self): + self.cross_compare_markdown( + markdown_string='[![image](image.jpg)](/uri)', + html_string='<p><a href="/uri"><img alt="image" src="image.jpg" /></a></p>', + ) + self.cross_compare_markdown( + markdown_string='[![image](image.jpg "Image Title")](/uri "Link Title")', + html_string=( + '<p><a href="/uri" title="Link Title">' + '<img alt="image" src="image.jpg" title="Image Title" />' + '</a></p>' + ), + ) + + def test_hr(self): + self.cross_compare_markdown( + markdown_string='----', + html_string='<hr />', + ) + + def test_typeface_basic(self): + self.cross_compare_markdown( + markdown_string='*single asterisks*', + html_string='<p><em>single asterisks</em></p>', + ) + self.cross_compare_markdown( + markdown_string='**double asterisks**', + html_string='<p><strong>double asterisks</strong></p>', + ) + + def test_inline_code(self): + self.cross_compare_markdown( + markdown_string='Use the `print()` function.', + html_string='<p>Use the <code>print()</code> function.</p>', + debug=True, + ) + self.cross_compare_markdown( + markdown_string='backtick in: ``print("`")`` function.', + html_string='<p>backtick in: <code>print("`")</code> function.</p>', + debug=True, + ) + + # self.cross_compare_markdown( + # markdown_string=cleandoc( + # ''' + # This is: _italic_, **bold**, `monospace`. + # ''' + # ), + # html_string=cleandoc( + # ''' + # <p>This is: <em>italic</em>, <strong>bold</strong>, <code>monospace</code>.</p> + # ''' + # ), + # debug=True, + # ) + + def test_lists(self): + self.cross_compare_markdown( + markdown_string=cleandoc( + ''' + * apple + * banana + ''' + ), + html_string=cleandoc( + ''' + <ul> + <li>apple</li> + <li>banana</li> + </ul> + ''' + ), + ) + self.cross_compare_markdown( + markdown_string=cleandoc( + ''' + 1. apple + 1. banana + ''' + ), + html_string=cleandoc( + ''' + <ol> + <li>apple</li> + <li>banana</li> + </ol> + ''' + ), + debug=True, + ) diff --git a/creole/tests/test_html2markdown.py b/creole/tests/test_html2markdown.py new file mode 100644 index 0000000..975a15d --- /dev/null +++ b/creole/tests/test_html2markdown.py @@ -0,0 +1,99 @@ +from inspect import cleandoc + +from creole.tests.utils.base_unittest import BaseCreoleTest + + +class MarkdownTests(BaseCreoleTest): + def test_code_block(self): + self.assert_html2markdown( + markdown_string=cleandoc( + ''' + Two prints: + + ```python + print(1) + print(2) + ``` + + Below the code block. + ''' + ), + html_string=cleandoc( + ''' + <p>Two prints:</p> + <pre><code class="language-python"> + print(1) + print(2) + </code></pre> + <p>Below the code block.</p> + ''' + ), + # debug=True, + ) + + def test_lists(self): + self.assert_html2markdown( + markdown_string=cleandoc( + ''' + * one + * one-one + * one-two + * two + 1. two-one + 1. two-two + ''' + ), + html_string=cleandoc( + ''' + <ul> + <li>one + <ul> + <li>one-one</li> + <li>one-two</li> + </ul> + </li> + <li>two + <ol> + <li>two-one</li> + <li>two-two</li> + </ol> + </li> + </ul> + ''' + ), + ) + self.assert_html2markdown( + markdown_string=cleandoc( + ''' + * "one" and "two" + * "three" + ''' + ), + html_string=cleandoc( + ''' + <ul> + <li>"one" and "two"</li> + <li>"three"</li> + </ul> + ''' + ), + # debug=True, + ) + self.assert_html2markdown( + markdown_string=cleandoc( + ''' + * html2markdown + + Here the `--help` output + ''' + ), + html_string=cleandoc( + ''' + <ul> + <li>html2markdown</li> + </ul> + <p>Here the <code>--help</code> output</p> + ''' + ), + # debug=True, + ) diff --git a/creole/tests/test_project_setup.py b/creole/tests/test_project_setup.py index cb9aa1e..d05ffed 100644 --- a/creole/tests/test_project_setup.py +++ b/creole/tests/test_project_setup.py @@ -8,7 +8,7 @@ from poetry_publish.tests.test_project_setup import test_poetry_check as assert_ from poetry_publish.tests.test_project_setup import test_version as assert_version from creole import __version__ -from creole.setup_utils import update_rst_readme +from creole.setup_utils import update_markdown_readme, update_rst_readme from creole.tests.constants import CREOLE_PACKAGE_ROOT @@ -31,6 +31,17 @@ def test_update_rst_readme(capsys): assert str(rest_readme_path).endswith('/README.rst') +def test_update_md_readme(capsys): + rest_readme_path = update_markdown_readme( + package_root=CREOLE_PACKAGE_ROOT, filename='README.creole' + ) + captured = capsys.readouterr() + assert captured.out == 'Generate README.md from README.creole...nothing changed, ok.\n' + assert captured.err == '' + assert isinstance(rest_readme_path, Path) + assert str(rest_readme_path).endswith('/README.md') + + def test_poetry_check(): """ Test 'poetry check' output. diff --git a/creole/tests/utils/base_unittest.py b/creole/tests/utils/base_unittest.py index e97fac5..c669553 100644 --- a/creole/tests/utils/base_unittest.py +++ b/creole/tests/utils/base_unittest.py @@ -11,9 +11,10 @@ import re +import markdown import textile -from creole import creole2html, html2creole, html2rest, html2textile +from creole import creole2html, html2creole, html2markdown, html2rest, html2textile from creole.rest_tools.clean_writer import rest2html from creole.tests.utils.utils import MarkupTest @@ -215,6 +216,31 @@ class BaseCreoleTest(MarkupTest): return textile_string, html_string + def assert_html2markdown( + self, markdown_string, html_string, strip_lines=False, debug=False, **kwargs + ): + """ + Check html2markdown + """ + self.assertNotEqual(markdown_string, html_string) + + markdown_string = self._prepare_text(markdown_string) + html_string = self._prepare_text(html_string) + + if strip_lines: + html_string = strip_html_lines(html_string, strip_lines) + + # compare html -> markdown + markdown_string2 = html2markdown(html_string, debug, **kwargs) + if debug: + print("-" * 79) + print(markdown_string2) + print("-" * 79) + + self.assertEqual(markdown_string2, markdown_string, msg="html2markdown") + + return markdown_string, html_string + def cross_compare_textile(self, textile_string, html_string, strip_lines=False, debug=False, **kwargs): """ @@ -241,6 +267,32 @@ class BaseCreoleTest(MarkupTest): self.assertEqual(html_string, html, msg="textile2html") + def cross_compare_markdown( + self, markdown_string, html_string, strip_lines=False, debug=False, **kwargs + ): + """ + Checks: + * html2markdown + * markdown2html + """ + # assert isinstance(markdown_string, str) + # assert isinstance(html_string, str) + self.assertNotEqual(markdown_string, html_string) + + # compare html -> markdown + markdown_string, html_string = self.assert_html2markdown( + markdown_string, html_string, strip_lines, debug, **kwargs + ) + + # compare markdown -> html + html = markdown.markdown(markdown_string) + html = html.replace("<br />", "<br />\n") + html = tabs2spaces(html) + if strip_lines: + html = strip_html_lines(html, strip_lines) + + self.assertEqual(html_string, html, msg="markdown2html") + def assert_html2rest(self, rest_string, html_string, strip_lines=False, debug=False, **kwargs): """ diff --git a/poetry.lock b/poetry.lock index f64a53d..a0ad687 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,18 +1,4 @@ [[package]] -name = "astroid" -version = "2.11.7" -description = "An abstract syntax tree for Python with inference support." -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -lazy-object-proxy = ">=1.4.0" -typed-ast = {version = ">=1.4.0,<2.0", markers = "implementation_name == \"cpython\" and python_version < \"3.8\""} -typing-extensions = {version = ">=3.10", markers = "python_version < \"3.10\""} -wrapt = ">=1.11,<2" - -[[package]] name = "atomicwrites" version = "1.4.1" description = "Atomic file writes." @@ -199,17 +185,6 @@ isort = ["isort (>=5.0.1)"] color = ["Pygments (>=2.4.0)"] [[package]] -name = "dill" -version = "0.3.5.1" -description = "serialize all of python" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*, !=3.6.*" - -[package.extras] -graph = ["objgraph (>=1.7.2)"] - -[[package]] name = "distlib" version = "0.3.5" description = "Distribution utilities" @@ -238,6 +213,19 @@ testing = ["pytest-timeout (>=2.1)", "pytest-cov (>=3)", "pytest (>=7.1.2)", "co docs = ["sphinx-autodoc-typehints (>=1.19.1)", "sphinx (>=5.1.1)", "furo (>=2022.6.21)"] [[package]] +name = "flake8" +version = "2.5.5" +description = "the modular source code checker: pep8, pyflakes and co" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +mccabe = ">=0.2.1,<0.5" +pep8 = ">=1.5.7,<1.6.0 || >1.6.0,<1.6.1 || >1.6.1,<1.6.2 || >1.6.2" +pyflakes = ">=0.8.1,<1.1" + +[[package]] name = "html5lib" version = "1.1" description = "HTML parser based on the WHATWG HTML specification" @@ -333,20 +321,26 @@ testing = ["pytest-mypy (>=0.9.1)", "pytest-black (>=0.3.7)", "pytest-enabler (> docs = ["jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "jaraco.packaging (>=9)", "sphinx"] [[package]] -name = "lazy-object-proxy" -version = "1.7.1" -description = "A fast and thorough lazy object proxy." +name = "markdown" +version = "3.4.1" +description = "Python implementation of Markdown." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" + +[package.dependencies] +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} + +[package.extras] +testing = ["pyyaml", "coverage"] [[package]] name = "mccabe" -version = "0.7.0" +version = "0.4.0" description = "McCabe checker, plugin for flake8" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = "*" [[package]] name = "mypy-extensions" @@ -376,6 +370,14 @@ optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" [[package]] +name = "pep8" +version = "1.7.1" +description = "Python style guide checker" +category = "dev" +optional = false +python-versions = "*" + +[[package]] name = "pkginfo" version = "1.8.3" description = "Query metadatdata from sdists / bdists / installed packages." @@ -450,6 +452,14 @@ optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] +name = "pyflakes" +version = "1.0.0" +description = "passive checker of Python programs" +category = "dev" +optional = false +python-versions = "*" + +[[package]] name = "pygments" version = "2.13.0" description = "Pygments is a syntax highlighting package written in Python." @@ -461,27 +471,6 @@ python-versions = ">=3.6" plugins = ["importlib-metadata"] [[package]] -name = "pylint" -version = "2.13.9" -description = "python code static checker" -category = "dev" -optional = false -python-versions = ">=3.6.2" - -[package.dependencies] -astroid = ">=2.11.5,<=2.12.0-dev0" -colorama = {version = "*", markers = "sys_platform == \"win32\""} -dill = ">=0.2" -isort = ">=4.2.5,<6" -mccabe = ">=0.6,<0.8" -platformdirs = ">=2.2.0" -tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} - -[package.extras] -testutil = ["gitpython (>3)"] - -[[package]] name = "pyparsing" version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" @@ -767,14 +756,6 @@ optional = false python-versions = "*" [[package]] -name = "wrapt" -version = "1.14.1" -description = "Module for decorators, wrappers and monkey patching." -category = "dev" -optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" - -[[package]] name = "zipp" version = "3.8.1" description = "Backport of pathlib-compatible object wrapper for zip files" @@ -789,13 +770,9 @@ docs = ["jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "jaraco.packaging (>=9) [metadata] lock-version = "1.1" python-versions = ">=3.7,<4.0.0" -content-hash = "268407ff217ceb81b5382c05149777f883ff3fe77fcaab3a4f811277248391ea" +content-hash = "dcd97b13cefcc9ceeb61559ca0e2fbdad229536767ac41cb24b7ab3183885488" [metadata.files] -astroid = [ - {file = "astroid-2.11.7-py3-none-any.whl", hash = "sha256:86b0a340a512c65abf4368b80252754cda17c02cdbbd3f587dddf98112233e7b"}, - {file = "astroid-2.11.7.tar.gz", hash = "sha256:bb24615c77f4837c707669d16907331374ae8a964650a66999da3f5ca68dc946"}, -] atomicwrites = [ {file = "atomicwrites-1.4.1.tar.gz", hash = "sha256:81b2c9071a49367a7f770170e5eec8cb66567cfbbc8c73d20ce5ca4a8d71cf11"}, ] @@ -1002,10 +979,6 @@ darker = [ {file = "darker-1.5.0-py3-none-any.whl", hash = "sha256:effd451a364d603578c9df569cc4ab72900b4bb3ffb7b918160ff559ef8af892"}, {file = "darker-1.5.0.tar.gz", hash = "sha256:a23a917b9abee0725ba68da5f564ed25dd4e63eab6dc5a43d9e2f88b7c19899e"}, ] -dill = [ - {file = "dill-0.3.5.1-py2.py3-none-any.whl", hash = "sha256:33501d03270bbe410c72639b350e941882a8b0fd55357580fbc873fba0c59302"}, - {file = "dill-0.3.5.1.tar.gz", hash = "sha256:d75e41f3eff1eee599d738e76ba8f4ad98ea229db8b085318aa2b3333a208c86"}, -] distlib = [ {file = "distlib-0.3.5-py2.py3-none-any.whl", hash = "sha256:b710088c59f06338ca514800ad795a132da19fda270e3ce4affc74abf955a26c"}, {file = "distlib-0.3.5.tar.gz", hash = "sha256:a7f75737c70be3b25e2bee06288cec4e4c221de18455b2dd037fe2a795cab2fe"}, @@ -1018,6 +991,10 @@ filelock = [ {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, ] +flake8 = [ + {file = "flake8-2.5.5-py2.py3-none-any.whl", hash = "sha256:80a66cd9bd66b0679da030fc930c0a4d09237dd72f354d899427b5c6718223b9"}, + {file = "flake8-2.5.5.tar.gz", hash = "sha256:326a54ace7878a5ad1538110f2145bc6a134df43fff290475fd4e7ba38a6deea"}, +] html5lib = [ {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, @@ -1046,48 +1023,13 @@ keyring = [ {file = "keyring-23.8.2-py3-none-any.whl", hash = "sha256:10d2a8639663fe2090705a00b8c47c687cacdf97598ea9c11456679fa974473a"}, {file = "keyring-23.8.2.tar.gz", hash = "sha256:0d9973f8891850f1ade5f26aafd06bb16865fbbae3fc56b0defb6a14a2624003"}, ] -lazy-object-proxy = [ - {file = "lazy-object-proxy-1.7.1.tar.gz", hash = "sha256:d609c75b986def706743cdebe5e47553f4a5a1da9c5ff66d76013ef396b5a8a4"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bb8c5fd1684d60a9902c60ebe276da1f2281a318ca16c1d0a96db28f62e9166b"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a57d51ed2997e97f3b8e3500c984db50a554bb5db56c50b5dab1b41339b37e36"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fd45683c3caddf83abbb1249b653a266e7069a09f486daa8863fb0e7496a9fdb"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8561da8b3dd22d696244d6d0d5330618c993a215070f473b699e00cf1f3f6443"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fccdf7c2c5821a8cbd0a9440a456f5050492f2270bd54e94360cac663398739b"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-win32.whl", hash = "sha256:898322f8d078f2654d275124a8dd19b079080ae977033b713f677afcfc88e2b9"}, - {file = "lazy_object_proxy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:85b232e791f2229a4f55840ed54706110c80c0a210d076eee093f2b2e33e1bfd"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:46ff647e76f106bb444b4533bb4153c7370cdf52efc62ccfc1a28bdb3cc95442"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:12f3bb77efe1367b2515f8cb4790a11cffae889148ad33adad07b9b55e0ab22c"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c19814163728941bb871240d45c4c30d33b8a2e85972c44d4e63dd7107faba44"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:e40f2013d96d30217a51eeb1db28c9ac41e9d0ee915ef9d00da639c5b63f01a1"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:2052837718516a94940867e16b1bb10edb069ab475c3ad84fd1e1a6dd2c0fcfc"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win32.whl", hash = "sha256:6a24357267aa976abab660b1d47a34aaf07259a0c3859a34e536f1ee6e76b5bb"}, - {file = "lazy_object_proxy-1.7.1-cp36-cp36m-win_amd64.whl", hash = "sha256:6aff3fe5de0831867092e017cf67e2750c6a1c7d88d84d2481bd84a2e019ec35"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:6a6e94c7b02641d1311228a102607ecd576f70734dc3d5e22610111aeacba8a0"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4ce15276a1a14549d7e81c243b887293904ad2d94ad767f42df91e75fd7b5b6"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e368b7f7eac182a59ff1f81d5f3802161932a41dc1b1cc45c1f757dc876b5d2c"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:6ecbb350991d6434e1388bee761ece3260e5228952b1f0c46ffc800eb313ff42"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:553b0f0d8dbf21890dd66edd771f9b1b5f51bd912fa5f26de4449bfc5af5e029"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win32.whl", hash = "sha256:c7a683c37a8a24f6428c28c561c80d5f4fd316ddcf0c7cab999b15ab3f5c5c69"}, - {file = "lazy_object_proxy-1.7.1-cp37-cp37m-win_amd64.whl", hash = "sha256:df2631f9d67259dc9620d831384ed7732a198eb434eadf69aea95ad18c587a28"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:07fa44286cda977bd4803b656ffc1c9b7e3bc7dff7d34263446aec8f8c96f88a"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4dca6244e4121c74cc20542c2ca39e5c4a5027c81d112bfb893cf0790f96f57e"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:91ba172fc5b03978764d1df5144b4ba4ab13290d7bab7a50f12d8117f8630c38"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:043651b6cb706eee4f91854da4a089816a6606c1428fd391573ef8cb642ae4f7"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b9e89b87c707dd769c4ea91f7a31538888aad05c116a59820f28d59b3ebfe25a"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-win32.whl", hash = "sha256:9d166602b525bf54ac994cf833c385bfcc341b364e3ee71e3bf5a1336e677b55"}, - {file = "lazy_object_proxy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:8f3953eb575b45480db6568306893f0bd9d8dfeeebd46812aa09ca9579595148"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dd7ed7429dbb6c494aa9bc4e09d94b778a3579be699f9d67da7e6804c422d3de"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:70ed0c2b380eb6248abdef3cd425fc52f0abd92d2b07ce26359fcbc399f636ad"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7096a5e0c1115ec82641afbdd70451a144558ea5cf564a896294e346eb611be1"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f769457a639403073968d118bc70110e7dce294688009f5c24ab78800ae56dc8"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:39b0e26725c5023757fc1ab2a89ef9d7ab23b84f9251e28f9cc114d5b59c1b09"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-win32.whl", hash = "sha256:2130db8ed69a48a3440103d4a520b89d8a9405f1b06e2cc81640509e8bf6548f"}, - {file = "lazy_object_proxy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:677ea950bef409b47e51e733283544ac3d660b709cfce7b187f5ace137960d61"}, - {file = "lazy_object_proxy-1.7.1-pp37.pp38-none-any.whl", hash = "sha256:d66906d5785da8e0be7360912e99c9188b70f52c422f9fc18223347235691a84"}, +markdown = [ + {file = "Markdown-3.4.1-py3-none-any.whl", hash = "sha256:08fb8465cffd03d10b9dd34a5c3fea908e20391a2a90b88d66362cb05beed186"}, + {file = "Markdown-3.4.1.tar.gz", hash = "sha256:3b809086bb6efad416156e00a0da66fe47618a5d6918dd688f53f40c8e4cfeff"}, ] mccabe = [ - {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, - {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, + {file = "mccabe-0.4.0-py2.py3-none-any.whl", hash = "sha256:cbc2938f6c01061bc6d21d0c838c2489664755cb18676f0734d7617f4577d09e"}, + {file = "mccabe-0.4.0.tar.gz", hash = "sha256:9a2b12ebd876e77c72e41ebf401cc2e7c5b566649d50105ca49822688642207b"}, ] mypy-extensions = [ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, @@ -1101,6 +1043,10 @@ pathspec = [ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, ] +pep8 = [ + {file = "pep8-1.7.1-py2.py3-none-any.whl", hash = "sha256:b22cfae5db09833bb9bd7c8463b53e1a9c9b39f12e304a8d0bba729c501827ee"}, + {file = "pep8-1.7.1.tar.gz", hash = "sha256:fe249b52e20498e59e0b5c5256aa52ee99fc295b26ec9eaa85776ffdb9fe6374"}, +] pkginfo = [ {file = "pkginfo-1.8.3-py2.py3-none-any.whl", hash = "sha256:848865108ec99d4901b2f7e84058b6e7660aae8ae10164e015a6dcf5b242a594"}, {file = "pkginfo-1.8.3.tar.gz", hash = "sha256:a84da4318dd86f870a9447a8c98340aa06216bfc6f2b7bdc4b8766984ae1867c"}, @@ -1129,14 +1075,14 @@ pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, ] +pyflakes = [ + {file = "pyflakes-1.0.0-py2.py3-none-any.whl", hash = "sha256:071d121e9e7b33058aa1ba5de7bce9b97bfa3149cfe1acbb6587c21fc1c8eda1"}, + {file = "pyflakes-1.0.0.tar.gz", hash = "sha256:f39e33a4c03beead8774f005bd3ecf0c3f2f264fa0201de965fce0aff1d34263"}, +] pygments = [ {file = "Pygments-2.13.0-py3-none-any.whl", hash = "sha256:f643f331ab57ba3c9d89212ee4a2dabc6e94f117cf4eefde99a0574720d14c42"}, {file = "Pygments-2.13.0.tar.gz", hash = "sha256:56a8508ae95f98e2b9bdf93a6be5ae3f7d8af858b43e02c5a2ff083726be40c1"}, ] -pylint = [ - {file = "pylint-2.13.9-py3-none-any.whl", hash = "sha256:705c620d388035bdd9ff8b44c5bcdd235bfb49d276d488dd2c8ff1736aa42526"}, - {file = "pylint-2.13.9.tar.gz", hash = "sha256:095567c96e19e6f57b5b907e67d265ff535e588fe26b12b5ebe1fc5645b2c731"}, -] pyparsing = [ {file = "pyparsing-3.0.9-py3-none-any.whl", hash = "sha256:5026bae9a10eeaefb61dab2f09052b9f4307d44aee4eda64b309723d8d206bbc"}, {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, @@ -1319,72 +1265,6 @@ webencodings = [ {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, ] -wrapt = [ - {file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"}, - {file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"}, - {file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"}, - {file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"}, - {file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"}, - {file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"}, - {file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"}, - {file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"}, - {file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"}, - {file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"}, - {file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"}, - {file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"}, - {file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"}, - {file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"}, - {file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"}, - {file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"}, - {file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"}, - {file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"}, - {file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"}, - {file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"}, - {file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"}, - {file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"}, - {file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"}, - {file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"}, - {file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"}, - {file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"}, - {file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"}, - {file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"}, - {file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"}, - {file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"}, - {file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"}, - {file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"}, -] zipp = [ {file = "zipp-3.8.1-py3-none-any.whl", hash = "sha256:47c40d7fe183a6f21403a199b3e4192cca5774656965b0a4988ad2f8feb5f009"}, {file = "zipp-3.8.1.tar.gz", hash = "sha256:05b45f1ee8f807d0cc928485ca40a07cb491cf092ff587c0df9cb1fd154848d2"}, diff --git a/pyproject.toml b/pyproject.toml index 1dc3927..efef02c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,9 +48,10 @@ textile = "*" pytest = "*" pytest-cov = "*" isort = "*" -pylint = "*" +flake8 = "*" autopep8 = "*" darker = "*" +markdown = "*" [tool.poetry.scripts] creole2html = "creole.cmdline:cli_creole2html" @@ -58,6 +59,7 @@ html2creole = "creole.cmdline:cli_html2creole" html2rest = "creole.cmdline:cli_html2rest" html2textile = "creole.cmdline:cli_html2textile" update_rst_readme = "creole.setup_utils:update_creole_rst_readme" +update_markdown_readme = "creole.setup_utils:update_creole_markdown_readme" publish = "creole.publish:publish" [build-system] @@ -76,7 +78,7 @@ check = false stdout = false isort = true lint = [ - "pylint", + "flake8", ] log_level = "INFO" |