pyhtml2md 1.6.6__tar.gz → 1.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyhtml2md might be problematic. Click here for more details.

Files changed (387) hide show
  1. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/workflows/release.yml +1 -1
  2. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.gitignore +1 -0
  3. pyhtml2md-1.7.0/.vscode/settings.json +7 -0
  4. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/CHANGELOG.md +10 -0
  5. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/CMakeLists.txt +2 -2
  6. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/PKG-INFO +1 -1
  7. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/include/html2md.h +41 -4
  8. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/pyproject.toml +2 -2
  9. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/bindings.cpp +11 -1
  10. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/src/html2md.cpp +91 -24
  11. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/CMakeLists.txt +15 -5
  12. pyhtml2md-1.7.0/tests/benchmark.cpp +184 -0
  13. pyhtml2md-1.7.0/tests/main.cpp +521 -0
  14. {pyhtml2md-1.6.6/tests → pyhtml2md-1.7.0/tests/python}/test_advanced.py +5 -1
  15. pyhtml2md-1.7.0/tests/python/test_html_symbol_conversions.py +118 -0
  16. pyhtml2md-1.6.6/tests/main.cpp +0 -240
  17. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.clang-format +0 -0
  18. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/CODEOWNERS +0 -0
  19. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  20. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  21. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/ISSUE_TEMPLATE/question.md +0 -0
  22. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/dependabot.yml +0 -0
  23. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/workflows/build.yml +0 -0
  24. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/workflows/website.yml +0 -0
  25. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.github/workflows/wheels.yml +0 -0
  26. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/.gitmodules +0 -0
  27. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/CONTRIBUTING.md +0 -0
  28. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/COPYING +0 -0
  29. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/MANIFEST.in +0 -0
  30. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/Package.swift +0 -0
  31. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/README.md +0 -0
  32. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/SECURITY.md +0 -0
  33. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/cli/main.cpp +0 -0
  34. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/cmake/Doc.cmake +0 -0
  35. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/cmake/Packaging.cmake +0 -0
  36. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/Doxyfile +0 -0
  37. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/.gitignore +0 -0
  38. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/LICENSE +0 -0
  39. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js +0 -0
  40. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome-fragment-copy-button.js +0 -0
  41. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome-interactive-toc.js +0 -0
  42. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome-paragraph-link.js +0 -0
  43. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css +0 -0
  44. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome-sidebar-only.css +0 -0
  45. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-awesome.css +0 -0
  46. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-custom/custom.css +0 -0
  47. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/doxygen-awesome-css/doxygen-custom/header.html +0 -0
  48. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/docs/index.md +0 -0
  49. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/html2md.pc.in +0 -0
  50. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/html2mdConfig.cmake.in +0 -0
  51. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/include/table.h +0 -0
  52. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/js/bindings.cpp +0 -0
  53. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/objc/html2md_objc.mm +0 -0
  54. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/objc/include/html2md_objc.h +0 -0
  55. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/README.md +0 -0
  56. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.appveyor.yml +0 -0
  57. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.clang-format +0 -0
  58. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.clang-tidy +0 -0
  59. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.cmake-format.yaml +0 -0
  60. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.codespell-ignore-lines +0 -0
  61. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.gitattributes +0 -0
  62. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/CODEOWNERS +0 -0
  63. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/CONTRIBUTING.md +0 -0
  64. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  65. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/ISSUE_TEMPLATE/config.yml +0 -0
  66. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/dependabot.yml +0 -0
  67. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/labeler.yml +0 -0
  68. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/labeler_merged.yml +0 -0
  69. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/matchers/pylint.json +0 -0
  70. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/pull_request_template.md +0 -0
  71. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/workflows/ci.yml +0 -0
  72. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/workflows/configure.yml +0 -0
  73. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/workflows/format.yml +0 -0
  74. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/workflows/labeler.yml +0 -0
  75. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/workflows/pip.yml +0 -0
  76. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.github/workflows/upstream.yml +0 -0
  77. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.gitignore +0 -0
  78. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.pre-commit-config.yaml +0 -0
  79. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/.readthedocs.yml +0 -0
  80. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/CMakeLists.txt +0 -0
  81. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/LICENSE +0 -0
  82. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/MANIFEST.in +0 -0
  83. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/README.rst +0 -0
  84. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/SECURITY.md +0 -0
  85. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/Doxyfile +0 -0
  86. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/_static/css/custom.css +0 -0
  87. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/chrono.rst +0 -0
  88. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/custom.rst +0 -0
  89. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/eigen.rst +0 -0
  90. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/functional.rst +0 -0
  91. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/index.rst +0 -0
  92. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/overview.rst +0 -0
  93. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/stl.rst +0 -0
  94. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/cast/strings.rst +0 -0
  95. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/classes.rst +0 -0
  96. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/embedding.rst +0 -0
  97. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/exceptions.rst +0 -0
  98. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/functions.rst +0 -0
  99. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/misc.rst +0 -0
  100. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/pycpp/index.rst +0 -0
  101. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/pycpp/numpy.rst +0 -0
  102. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/pycpp/object.rst +0 -0
  103. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/pycpp/utilities.rst +0 -0
  104. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/advanced/smart_ptrs.rst +0 -0
  105. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/basics.rst +0 -0
  106. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/benchmark.py +0 -0
  107. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/benchmark.rst +0 -0
  108. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/changelog.rst +0 -0
  109. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/classes.rst +0 -0
  110. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/cmake/index.rst +0 -0
  111. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/compiling.rst +0 -0
  112. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/conf.py +0 -0
  113. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/faq.rst +0 -0
  114. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/index.rst +0 -0
  115. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/installing.rst +0 -0
  116. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/limitations.rst +0 -0
  117. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/pybind11-logo.png +0 -0
  118. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/pybind11_vs_boost_python1.png +0 -0
  119. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/pybind11_vs_boost_python1.svg +0 -0
  120. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/pybind11_vs_boost_python2.png +0 -0
  121. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/pybind11_vs_boost_python2.svg +0 -0
  122. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/reference.rst +0 -0
  123. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/release.rst +0 -0
  124. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/requirements.in +0 -0
  125. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/requirements.txt +0 -0
  126. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/docs/upgrade.rst +0 -0
  127. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/attr.h +0 -0
  128. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/buffer_info.h +0 -0
  129. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/cast.h +0 -0
  130. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/chrono.h +0 -0
  131. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/common.h +0 -0
  132. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/complex.h +0 -0
  133. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/class.h +0 -0
  134. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/common.h +0 -0
  135. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/descr.h +0 -0
  136. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/init.h +0 -0
  137. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/internals.h +0 -0
  138. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/type_caster_base.h +0 -0
  139. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/detail/typeid.h +0 -0
  140. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/eigen/common.h +0 -0
  141. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/eigen/matrix.h +0 -0
  142. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/eigen/tensor.h +0 -0
  143. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/eigen.h +0 -0
  144. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/embed.h +0 -0
  145. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/eval.h +0 -0
  146. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/functional.h +0 -0
  147. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/gil.h +0 -0
  148. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/gil_safe_call_once.h +0 -0
  149. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/iostream.h +0 -0
  150. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/numpy.h +0 -0
  151. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/operators.h +0 -0
  152. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/options.h +0 -0
  153. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/pybind11.h +0 -0
  154. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/pytypes.h +0 -0
  155. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/stl/filesystem.h +0 -0
  156. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/stl.h +0 -0
  157. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/stl_bind.h +0 -0
  158. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/type_caster_pyobject_ptr.h +0 -0
  159. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/include/pybind11/typing.h +0 -0
  160. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/noxfile.py +0 -0
  161. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pybind11/__init__.py +0 -0
  162. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pybind11/__main__.py +0 -0
  163. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pybind11/_version.py +0 -0
  164. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pybind11/commands.py +0 -0
  165. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pybind11/py.typed +0 -0
  166. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pybind11/setup_helpers.py +0 -0
  167. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/pyproject.toml +0 -0
  168. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/setup.cfg +0 -0
  169. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/setup.py +0 -0
  170. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/CMakeLists.txt +0 -0
  171. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/conftest.py +0 -0
  172. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/constructor_stats.h +0 -0
  173. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/cross_module_gil_utils.cpp +0 -0
  174. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/cross_module_interleaved_error_already_set.cpp +0 -0
  175. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/eigen_tensor_avoid_stl_array.cpp +0 -0
  176. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/env.py +0 -0
  177. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/extra_python_package/pytest.ini +0 -0
  178. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/extra_python_package/test_files.py +0 -0
  179. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/extra_setuptools/pytest.ini +0 -0
  180. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/extra_setuptools/test_setuphelper.py +0 -0
  181. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/local_bindings.h +0 -0
  182. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/object.h +0 -0
  183. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/pybind11_cross_module_tests.cpp +0 -0
  184. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/pybind11_tests.cpp +0 -0
  185. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/pybind11_tests.h +0 -0
  186. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/pytest.ini +0 -0
  187. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/requirements.txt +0 -0
  188. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_async.cpp +0 -0
  189. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_async.py +0 -0
  190. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_buffers.cpp +0 -0
  191. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_buffers.py +0 -0
  192. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_builtin_casters.cpp +0 -0
  193. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_builtin_casters.py +0 -0
  194. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_call_policies.cpp +0 -0
  195. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_call_policies.py +0 -0
  196. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_callbacks.cpp +0 -0
  197. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_callbacks.py +0 -0
  198. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_chrono.cpp +0 -0
  199. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_chrono.py +0 -0
  200. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_class.cpp +0 -0
  201. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_class.py +0 -0
  202. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/CMakeLists.txt +0 -0
  203. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/embed.cpp +0 -0
  204. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/installed_embed/CMakeLists.txt +0 -0
  205. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/installed_function/CMakeLists.txt +0 -0
  206. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/installed_target/CMakeLists.txt +0 -0
  207. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/main.cpp +0 -0
  208. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/subdirectory_embed/CMakeLists.txt +0 -0
  209. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/subdirectory_function/CMakeLists.txt +0 -0
  210. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/subdirectory_target/CMakeLists.txt +0 -0
  211. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_cmake_build/test.py +0 -0
  212. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_const_name.cpp +0 -0
  213. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_const_name.py +0 -0
  214. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_constants_and_functions.cpp +0 -0
  215. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_constants_and_functions.py +0 -0
  216. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_copy_move.cpp +0 -0
  217. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_copy_move.py +0 -0
  218. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_custom_type_casters.cpp +0 -0
  219. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_custom_type_casters.py +0 -0
  220. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_custom_type_setup.cpp +0 -0
  221. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_custom_type_setup.py +0 -0
  222. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_docstring_options.cpp +0 -0
  223. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_docstring_options.py +0 -0
  224. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eigen_matrix.cpp +0 -0
  225. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eigen_matrix.py +0 -0
  226. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eigen_tensor.cpp +0 -0
  227. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eigen_tensor.inl +0 -0
  228. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eigen_tensor.py +0 -0
  229. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_embed/CMakeLists.txt +0 -0
  230. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_embed/catch.cpp +0 -0
  231. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_embed/external_module.cpp +0 -0
  232. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_embed/test_interpreter.cpp +0 -0
  233. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_embed/test_interpreter.py +0 -0
  234. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_embed/test_trampoline.py +0 -0
  235. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_enum.cpp +0 -0
  236. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_enum.py +0 -0
  237. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eval.cpp +0 -0
  238. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eval.py +0 -0
  239. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_eval_call.py +0 -0
  240. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_exceptions.cpp +0 -0
  241. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_exceptions.h +0 -0
  242. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_exceptions.py +0 -0
  243. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_factory_constructors.cpp +0 -0
  244. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_factory_constructors.py +0 -0
  245. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_gil_scoped.cpp +0 -0
  246. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_gil_scoped.py +0 -0
  247. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_iostream.cpp +0 -0
  248. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_iostream.py +0 -0
  249. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_kwargs_and_defaults.cpp +0 -0
  250. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_kwargs_and_defaults.py +0 -0
  251. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_local_bindings.cpp +0 -0
  252. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_local_bindings.py +0 -0
  253. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_methods_and_attributes.cpp +0 -0
  254. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_methods_and_attributes.py +0 -0
  255. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_modules.cpp +0 -0
  256. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_modules.py +0 -0
  257. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_multiple_inheritance.cpp +0 -0
  258. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_multiple_inheritance.py +0 -0
  259. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_numpy_array.cpp +0 -0
  260. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_numpy_array.py +0 -0
  261. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_numpy_dtypes.cpp +0 -0
  262. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_numpy_dtypes.py +0 -0
  263. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_numpy_vectorize.cpp +0 -0
  264. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_numpy_vectorize.py +0 -0
  265. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_opaque_types.cpp +0 -0
  266. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_opaque_types.py +0 -0
  267. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_operator_overloading.cpp +0 -0
  268. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_operator_overloading.py +0 -0
  269. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_pickling.cpp +0 -0
  270. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_pickling.py +0 -0
  271. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_python_multiple_inheritance.cpp +0 -0
  272. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_python_multiple_inheritance.py +0 -0
  273. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_pytypes.cpp +0 -0
  274. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_pytypes.py +0 -0
  275. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_sequences_and_iterators.cpp +0 -0
  276. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_sequences_and_iterators.py +0 -0
  277. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_smart_ptr.cpp +0 -0
  278. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_smart_ptr.py +0 -0
  279. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_stl.cpp +0 -0
  280. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_stl.py +0 -0
  281. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_stl_binders.cpp +0 -0
  282. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_stl_binders.py +0 -0
  283. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_tagbased_polymorphic.cpp +0 -0
  284. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_tagbased_polymorphic.py +0 -0
  285. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_thread.cpp +0 -0
  286. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_thread.py +0 -0
  287. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_type_caster_pyobject_ptr.cpp +0 -0
  288. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_type_caster_pyobject_ptr.py +0 -0
  289. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_union.cpp +0 -0
  290. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_union.py +0 -0
  291. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_unnamed_namespace_a.cpp +0 -0
  292. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_unnamed_namespace_a.py +0 -0
  293. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_unnamed_namespace_b.cpp +0 -0
  294. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_unnamed_namespace_b.py +0 -0
  295. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_vector_unique_ptr_member.cpp +0 -0
  296. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_vector_unique_ptr_member.py +0 -0
  297. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_virtual_functions.cpp +0 -0
  298. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/test_virtual_functions.py +0 -0
  299. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/valgrind-numpy-scipy.supp +0 -0
  300. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tests/valgrind-python.supp +0 -0
  301. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/FindCatch.cmake +0 -0
  302. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/FindEigen3.cmake +0 -0
  303. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/FindPythonLibsNew.cmake +0 -0
  304. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/JoinPaths.cmake +0 -0
  305. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/check-style.sh +0 -0
  306. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/cmake_uninstall.cmake.in +0 -0
  307. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/codespell_ignore_lines_from_errors.py +0 -0
  308. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/libsize.py +0 -0
  309. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/make_changelog.py +0 -0
  310. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pybind11.pc.in +0 -0
  311. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pybind11Common.cmake +0 -0
  312. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pybind11Config.cmake.in +0 -0
  313. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pybind11GuessPythonExtSuffix.cmake +0 -0
  314. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pybind11NewTools.cmake +0 -0
  315. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pybind11Tools.cmake +0 -0
  316. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/pyproject.toml +0 -0
  317. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/setup_global.py.in +0 -0
  318. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/setup_main.py.in +0 -0
  319. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/python/pybind11/tools/test-pybind11GuessPythonExtSuffix.cmake +0 -0
  320. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/scripts/clang-format.sh +0 -0
  321. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/src/table.cpp +0 -0
  322. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/README.md +0 -0
  323. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/blockquote.md +0 -0
  324. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/breaks.md +0 -0
  325. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/code.md +0 -0
  326. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/comment.html +0 -0
  327. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/escaping.md +0 -0
  328. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/formating.md +0 -0
  329. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/links.md +0 -0
  330. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/lists.md +0 -0
  331. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/.gitignore +0 -0
  332. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/.travis.yml +0 -0
  333. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/CHANGELOG.md +0 -0
  334. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/CMakeLists.txt +0 -0
  335. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/LICENSE.md +0 -0
  336. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/README.md +0 -0
  337. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/appveyor.yml +0 -0
  338. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/codecov.yml +0 -0
  339. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/md2html/CMakeLists.txt +0 -0
  340. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/md2html/cmdline.c +0 -0
  341. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/md2html/cmdline.h +0 -0
  342. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/md2html/md2html.1 +0 -0
  343. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/md2html/md2html.c +0 -0
  344. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/build_folding_map.py +0 -0
  345. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/build_punct_map.py +0 -0
  346. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/build_symbol_map.py +0 -0
  347. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/build_whitespace_map.py +0 -0
  348. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/coverity.sh +0 -0
  349. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/run-tests.sh +0 -0
  350. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/unicode/CaseFolding.txt +0 -0
  351. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/scripts/unicode/DerivedGeneralCategory.txt +0 -0
  352. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/CMakeLists.txt +0 -0
  353. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/entity.c +0 -0
  354. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/entity.h +0 -0
  355. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/md4c-html.c +0 -0
  356. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/md4c-html.h +0 -0
  357. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/md4c-html.pc.in +0 -0
  358. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/md4c.c +0 -0
  359. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/md4c.h +0 -0
  360. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/src/md4c.pc.in +0 -0
  361. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/LICENSE +0 -0
  362. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/cmark.py +0 -0
  363. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/coverage.txt +0 -0
  364. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/fuzz-input/commonmark.md +0 -0
  365. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/fuzz-input/gfm.md +0 -0
  366. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/fuzz-input/latex-math.md +0 -0
  367. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/fuzz-input/wiki.md +0 -0
  368. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/fuzzers/fuzz-mdhtml.c +0 -0
  369. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/heading-auto-identifier.txt +0 -0
  370. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/latex-math.txt +0 -0
  371. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/normalize.py +0 -0
  372. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/pathological_auto_ident_tests.py +0 -0
  373. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/pathological_tests.py +0 -0
  374. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/permissive-email-autolinks.txt +0 -0
  375. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/permissive-url-autolinks.txt +0 -0
  376. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/permissive-www-autolinks.txt +0 -0
  377. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/spec.txt +0 -0
  378. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/spec_tests.py +0 -0
  379. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/strikethrough.txt +0 -0
  380. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/tables.txt +0 -0
  381. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/tasklists.txt +0 -0
  382. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/toc-mark.txt +0 -0
  383. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/toc.txt +0 -0
  384. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/underline.txt +0 -0
  385. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/md4c/test/wiki-links.txt +0 -0
  386. {pyhtml2md-1.6.6/tests → pyhtml2md-1.7.0/tests/python}/test_basic.py +0 -0
  387. {pyhtml2md-1.6.6 → pyhtml2md-1.7.0}/tests/tables.md +0 -0
@@ -14,7 +14,7 @@ jobs:
14
14
  fail-fast: false
15
15
  matrix:
16
16
  include:
17
- - os: ubuntu-20.04
17
+ - os: ubuntu-latest
18
18
  files: |
19
19
  build/packages/html2md*.deb
20
20
  build/packages/html2md*.tar.gz
@@ -19,3 +19,4 @@ DerivedData/
19
19
  .swiftpm/configuration/registries.json
20
20
  .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
21
21
  .netrc
22
+ *.pyc
@@ -0,0 +1,7 @@
1
+ {
2
+ "cmake.configureArgs": [
3
+ "-DBUILD_TEST=ON",
4
+ "-DPYTHON_BINDINGS=ON",
5
+ "-G=Ninja",
6
+ ]
7
+ }
@@ -2,6 +2,16 @@
2
2
 
3
3
  [TOC]
4
4
 
5
+ ## 1.7.0
6
+ - Added API to add/remove HTML symbol conversions (see #158)
7
+ - Added HTML symbol conversion API to Python bindings
8
+ - Fixed attribute parsing with whitespace around equals sign (see #159)
9
+ - Added full support for uppercase tags/attributes
10
+ - Supported whitespace around tag names
11
+ - Fixed issues with self-closing tags
12
+ - Improved performance
13
+ - Improved blockquote handling (see #157)
14
+
5
15
  ## 1.6.6
6
16
  - Python: Fix wheels not uploaded
7
17
 
@@ -1,5 +1,5 @@
1
- cmake_minimum_required(VERSION 3.8)
2
- project(html2md VERSION 1.6.6 LANGUAGES CXX)
1
+ cmake_minimum_required(VERSION 3.8...3.31)
2
+ project(html2md VERSION 1.7.0 LANGUAGES CXX)
3
3
 
4
4
  set(PROJECT_HOMEPAGE_URL "https://tim-gromeyer.github.io/html2md/")
5
5
  set(html2md_HOMEPAGE_URL "${PROJECT_HOMEPAGE_URL}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyhtml2md
3
- Version: 1.6.6
3
+ Version: 1.7.0
4
4
  Summary: Transform your HTML into clean, easy-to-read markdown with pyhtml2md.
5
5
  Keywords: html,markdown,html-to-markdown,python3,cpp17,cpp-library,html2markdown,html2md
6
6
  Author-Email: Tim Gromeyer <sakul8826@gmail.com>
@@ -170,7 +170,7 @@ public:
170
170
  * You can use appendToMd() to append something to the beginning of the
171
171
  * generated output.
172
172
  */
173
- explicit inline Converter(std::string &html,
173
+ explicit inline Converter(const std::string &html,
174
174
  struct Options *options = nullptr) {
175
175
  *this = Converter(&html, options);
176
176
  }
@@ -217,6 +217,39 @@ public:
217
217
  */
218
218
  Converter *appendBlank();
219
219
 
220
+ /*!
221
+ * \brief Add an HTML symbol conversion
222
+ * \param htmlSymbol The HTML symbol to convert
223
+ * \param replacement The replacement string
224
+ * \note This is useful for converting HTML entities to their Markdown
225
+ * equivalents. For example, you can add a conversion for "&nbsp;" to
226
+ * " " (space) or "&lt;" to "<" (less than).
227
+ * \note This is not a standard feature of the Converter class, but it can
228
+ * be added to the class to allow for more flexibility in the conversion
229
+ * process. You can use this feature to add custom conversions for any HTML
230
+ * symbol that you want to convert to a specific Markdown representation.
231
+ */
232
+ void addHtmlSymbolConversion(const std::string &htmlSymbol,
233
+ const std::string &replacement) {
234
+ htmlSymbolConversions_[htmlSymbol] = replacement;
235
+ }
236
+
237
+ /*!
238
+ * \brief Remove an HTML symbol conversion
239
+ * \param htmlSymbol The HTML symbol to remove
240
+ * \note This is useful for removing custom conversions that you have added
241
+ * previously.
242
+ */
243
+ void removeHtmlSymbolConversion(const std::string &htmlSymbol) {
244
+ htmlSymbolConversions_.erase(htmlSymbol);
245
+ }
246
+
247
+ /*!
248
+ * \brief Clear all HTML symbol conversions
249
+ * \note This is useful for clearing the conversion map (it's empty afterwards).
250
+ */
251
+ void clearHtmlSymbolConversions() { htmlSymbolConversions_.clear(); }
252
+
220
253
  /*!
221
254
  * \brief Checks if everything was closed properly(in the HTML).
222
255
  * \return Returns false if there is a unclosed tag.
@@ -347,6 +380,10 @@ private:
347
380
 
348
381
  Options option;
349
382
 
383
+ std::unordered_map<std::string, std::string> htmlSymbolConversions_ = {
384
+ {"&quot;", "\""}, {"&lt;", "<"}, {"&gt;", ">"},
385
+ {"&amp;", "&"}, {"&nbsp;", " "}, {"&rarr;", "→"}};
386
+
350
387
  // Tag: base class for tag types
351
388
  struct Tag {
352
389
  virtual void OnHasLeftOpeningTag(Converter *c) = 0;
@@ -511,7 +548,7 @@ private:
511
548
 
512
549
  std::unordered_map<std::string, std::shared_ptr<Tag>> tags_;
513
550
 
514
- explicit Converter(std::string *html, struct Options *options);
551
+ explicit Converter(const std::string *html, struct Options *options);
515
552
 
516
553
  void CleanUpMarkdown();
517
554
 
@@ -594,7 +631,7 @@ private:
594
631
  * \param ok Optional: Pass a reference to a local bool to store the output of
595
632
  * Converter::ok() \return Returns the by Converter generated Markdown
596
633
  */
597
- inline std::string Convert(std::string &html, bool *ok = nullptr) {
634
+ inline std::string Convert(const std::string &html, bool *ok = nullptr) {
598
635
  Converter c(html);
599
636
  auto md = c.convert();
600
637
  if (ok != nullptr)
@@ -603,7 +640,7 @@ inline std::string Convert(std::string &html, bool *ok = nullptr) {
603
640
  }
604
641
 
605
642
  #ifndef PYTHON_BINDINGS
606
- inline std::string Convert(std::string &&html, bool *ok = nullptr) {
643
+ inline std::string Convert(const std::string &&html, bool *ok = nullptr) {
607
644
  return Convert(html, ok);
608
645
  }
609
646
  #endif
@@ -11,7 +11,7 @@ description = "Transform your HTML into clean, easy-to-read markdown with pyhtml
11
11
  readme = "python/README.md"
12
12
  requires-python = ">=3.7"
13
13
  license = { text = "MIT" }
14
- version = "1.6.6"
14
+ version = "1.7.0"
15
15
  classifiers = [
16
16
  "Intended Audience :: Developers",
17
17
  "License :: OSI Approved :: MIT License",
@@ -73,7 +73,7 @@ filterwarnings = ["error"]
73
73
  testpaths = ["tests"]
74
74
 
75
75
  [tool.cibuildwheel]
76
- test-command = "pytest {project}/tests"
76
+ test-command = "pytest {project}/tests/python"
77
77
  test-extras = ["test"]
78
78
  test-skip = ["*universal2:arm64"]
79
79
  # Setuptools bug causes collision between pypy and cpython artifacts
@@ -34,9 +34,19 @@ PYBIND11_MODULE(pyhtml2md, m) {
34
34
  "This function actually converts the HTML into Markdown.")
35
35
  .def("ok", &html2md::Converter::ok,
36
36
  "Checks if everything was closed properly(in the HTML).")
37
+ .def("add_html_symbol_conversion",
38
+ &html2md::Converter::addHtmlSymbolConversion,
39
+ "Add or modify an HTML symbol conversion", py::arg("html_symbol"),
40
+ py::arg("replacement"))
41
+ .def("remove_html_symbol_conversion",
42
+ &html2md::Converter::removeHtmlSymbolConversion,
43
+ "Remove an HTML symbol conversion", py::arg("html_symbol"))
44
+ .def("clear_html_symbol_conversions",
45
+ &html2md::Converter::clearHtmlSymbolConversions,
46
+ "Clear all HTML symbol conversions")
37
47
  .def("__call__", &html2md::Converter::operator bool);
38
48
 
39
49
  m.def("convert", &html2md::Convert,
40
50
  "Static wrapper around the Converter class", py::arg("html"),
41
51
  py::arg("ok") = py::none());
42
- }
52
+ }
@@ -74,14 +74,25 @@ string Repeat(const string &str, size_t amount) {
74
74
 
75
75
  return out;
76
76
  }
77
+
78
+ string toLower(const string &str) {
79
+ string lower;
80
+ lower.reserve(str.size());
81
+ for (char ch : str) {
82
+ lower += tolower(ch);
83
+ }
84
+ return lower;
85
+ }
86
+
77
87
  } // namespace
78
88
 
79
89
  namespace html2md {
80
90
 
81
- Converter::Converter(string *html, Options *options) : html_(*html) {
91
+ Converter::Converter(const string *html, Options *options) : html_(*html) {
82
92
  if (options)
83
93
  option = *options;
84
94
 
95
+ md_.reserve(html->size() * 0.8);
85
96
  tags_.reserve(41);
86
97
 
87
98
  // non-printing tags
@@ -144,22 +155,43 @@ Converter::Converter(string *html, Options *options) : html_(*html) {
144
155
 
145
156
  void Converter::CleanUpMarkdown() {
146
157
  TidyAllLines(&md_);
158
+ std::string buffer;
159
+ buffer.reserve(md_.size());
160
+
161
+ // Replace HTML symbols during the initial pass
162
+ for (size_t i = 0; i < md_.size();) {
163
+ bool replaced = false;
164
+
165
+ // C++11 compatible iteration over htmlSymbolConversions_
166
+ for (const auto &symbol_replacement : htmlSymbolConversions_) {
167
+ const std::string &symbol = symbol_replacement.first;
168
+ const std::string &replacement = symbol_replacement.second;
169
+
170
+ if (md_.compare(i, symbol.size(), symbol) == 0) {
171
+ buffer.append(replacement);
172
+ i += symbol.size();
173
+ replaced = true;
174
+ break;
175
+ }
176
+ }
147
177
 
148
- ReplaceAll(&md_, " , ", ", ");
178
+ if (!replaced) {
179
+ buffer.push_back(md_[i++]);
180
+ }
181
+ }
149
182
 
150
- ReplaceAll(&md_, "\n.\n", ".\n");
151
- ReplaceAll(&md_, "\n↵\n", " ↵\n");
152
- ReplaceAll(&md_, "\n*\n", "\n");
153
- ReplaceAll(&md_, "\n. ", ".\n");
183
+ // Use swap instead of move assignment for better pre-C++11 compatibility
184
+ md_.swap(buffer);
154
185
 
155
- ReplaceAll(&md_, "&quot;", '"');
156
- ReplaceAll(&md_, "&lt;", "<");
157
- ReplaceAll(&md_, "&gt;", ">");
158
- ReplaceAll(&md_, "&amp;", '&');
159
- ReplaceAll(&md_, "&nbsp;", ' ');
160
- ReplaceAll(&md_, "&rarr;", "→");
186
+ // Optimized replacement sequence
187
+ const char *replacements[][2] = {
188
+ {" , ", ", "}, {"\n.\n", ".\n"}, {"\n↵\n", " ↵\n"}, {"\n*\n", "\n"},
189
+ {"\n. ", ".\n"}, {"\t\t ", "\t\t"},
190
+ };
161
191
 
162
- ReplaceAll(&md_, "\t\t ", "\t\t");
192
+ for (const auto &replacement : replacements) {
193
+ ReplaceAll(&md_, replacement[0], replacement[1]);
194
+ }
163
195
  }
164
196
 
165
197
  Converter *Converter::appendToMd(char ch) {
@@ -286,9 +318,10 @@ void Converter::TidyAllLines(string *str) {
286
318
  string Converter::ExtractAttributeFromTagLeftOf(const string &attr) {
287
319
  // Extract the whole tag from current offset, e.g. from '>', backwards
288
320
  auto tag = html_.substr(offset_lt_, index_ch_in_html_ - offset_lt_);
321
+ string lowerTag = toLower(tag); // Convert tag to lowercase for comparison
289
322
 
290
- // locate given attribute
291
- auto offset_attr = tag.find(attr);
323
+ // locate given attribute (case-insensitive)
324
+ auto offset_attr = lowerTag.find(attr);
292
325
 
293
326
  if (offset_attr == string::npos)
294
327
  return "";
@@ -387,6 +420,7 @@ string Converter::convert() {
387
420
  void Converter::OnHasEnteredTag() {
388
421
  offset_lt_ = index_ch_in_html_;
389
422
  is_in_tag_ = true;
423
+ is_closing_tag_ = false;
390
424
  prev_tag_ = current_tag_;
391
425
  current_tag_ = "";
392
426
 
@@ -407,28 +441,55 @@ Converter *Converter::UpdatePrevChFromMd() {
407
441
  }
408
442
 
409
443
  bool Converter::ParseCharInTag(char ch) {
444
+ static bool skipping_leading_whitespace = true;
445
+
410
446
  if (ch == '/' && !is_in_attribute_value_) {
411
447
  is_closing_tag_ = current_tag_.empty();
412
448
  is_self_closing_tag_ = !is_closing_tag_;
413
-
449
+ skipping_leading_whitespace = true; // Reset for next tag
414
450
  return true;
415
451
  }
416
452
 
417
- if (ch == '>')
418
- return OnHasLeftTag();
453
+ if (ch == '>') {
454
+ // Trim trailing whitespace by removing characters from current_tag_
455
+ while (!current_tag_.empty() && std::isspace(current_tag_.back())) {
456
+ current_tag_.pop_back();
457
+ }
458
+ skipping_leading_whitespace = true; // Reset for next tag
459
+ if (!is_self_closing_tag_)
460
+ return OnHasLeftTag();
461
+ else {
462
+ OnHasLeftTag();
463
+ is_self_closing_tag_ = false;
464
+ is_closing_tag_ = true;
465
+ return OnHasLeftTag();
466
+ }
467
+ }
419
468
 
420
469
  if (ch == '"') {
421
470
  if (is_in_attribute_value_) {
422
471
  is_in_attribute_value_ = false;
423
- } else if (current_tag_[current_tag_.length() - 1] == '=') {
424
- is_in_attribute_value_ = true;
472
+ } else {
473
+ size_t pos = current_tag_.length();
474
+ while (pos > 0 && isspace(current_tag_[pos - 1])) {
475
+ pos--;
476
+ }
477
+ if (pos > 0 && current_tag_[pos - 1] == '=') {
478
+ is_in_attribute_value_ = true;
479
+ }
425
480
  }
426
-
481
+ skipping_leading_whitespace = false; // Stop skipping after attribute
427
482
  return true;
428
483
  }
429
484
 
430
- current_tag_ += ch;
485
+ // Handle whitespace: skip leading whitespace, keep others
486
+ if (isspace(ch) && skipping_leading_whitespace) {
487
+ return true; // Ignore leading whitespace
488
+ }
431
489
 
490
+ // Once we encounter a non-whitespace character, stop skipping
491
+ skipping_leading_whitespace = false;
492
+ current_tag_ += tolower(ch);
432
493
  return false;
433
494
  }
434
495
 
@@ -455,7 +516,7 @@ bool Converter::OnHasLeftTag() {
455
516
  if (!is_closing_tag_) {
456
517
  tag->OnHasLeftOpeningTag(this);
457
518
  }
458
- if (is_closing_tag_ || is_self_closing_tag_) {
519
+ else {
459
520
  is_closing_tag_ = false;
460
521
 
461
522
  tag->OnHasLeftClosingTag(this);
@@ -962,11 +1023,17 @@ void Converter::TagTableData::OnHasLeftClosingTag(Converter *c) {}
962
1023
 
963
1024
  void Converter::TagBlockquote::OnHasLeftOpeningTag(Converter *c) {
964
1025
  ++c->index_blockquote;
1026
+ c->appendToMd("\n");
1027
+ c->appendToMd(Repeat("> ", c->index_blockquote));
965
1028
  }
966
1029
 
967
1030
  void Converter::TagBlockquote::OnHasLeftClosingTag(Converter *c) {
968
1031
  --c->index_blockquote;
969
- c->ShortenMarkdown(2); // Remove the '> '
1032
+ // Only shorten if a "> " was added (i.e., a newline was processed in the blockquote)
1033
+ if (!c->md_.empty() && c->md_.length() >= 2 &&
1034
+ c->md_.substr(c->md_.length() - 2) == "> ") {
1035
+ c->ShortenMarkdown(2); // Remove the '> ' only if it exists
1036
+ }
970
1037
  }
971
1038
 
972
1039
  void Converter::reset() {
@@ -2,14 +2,11 @@ project(tests LANGUAGES C CXX)
2
2
 
3
3
  if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/md4c/src/)
4
4
  include(FindGit)
5
-
6
5
  if(NOT GIT_FOUND)
7
6
  message(WARNING "git not found. Please download md4c manually or disable tests.")
8
7
  return()
9
8
  endif()
10
-
11
9
  get_directory_property(dir PARENT_DIRECTORY)
12
-
13
10
  execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --depth=1
14
11
  WORKING_DIRECTORY ${dir})
15
12
  endif()
@@ -26,12 +23,19 @@ set(MD4C_FILES
26
23
  add_library(md4c-html STATIC ${MD4C_FILES})
27
24
  target_include_directories(md4c-html PUBLIC md4c/src)
28
25
 
26
+ # Existing test executable
29
27
  add_executable(test-exe main.cpp)
30
28
  target_link_libraries(test-exe md4c-html html2md-static)
31
29
  target_compile_definitions(test-exe PUBLIC DIR="${CMAKE_CURRENT_LIST_DIR}")
32
30
  set_target_properties(test-exe PROPERTIES OUTPUT_NAME "tests")
33
- target_compile_features(test-exe PUBLIC cxx_std_17) # Require at least c++17
31
+ target_compile_features(test-exe PUBLIC cxx_std_17)
34
32
 
33
+ # New benchmark executable
34
+ add_executable(benchmark-exe benchmark.cpp)
35
+ target_link_libraries(benchmark-exe md4c-html html2md-static)
36
+ target_compile_definitions(benchmark-exe PUBLIC DIR="${CMAKE_CURRENT_LIST_DIR}")
37
+ set_target_properties(benchmark-exe PROPERTIES OUTPUT_NAME "benchmarks")
38
+ target_compile_features(benchmark-exe PUBLIC cxx_std_17)
35
39
 
36
40
  if (CMAKE_VERSION VERSION_LESS 3.11.0)
37
41
  return()
@@ -39,6 +43,12 @@ endif()
39
43
 
40
44
  add_custom_target(test
41
45
  COMMAND $<TARGET_FILE:test-exe>
42
- COMMENT Runing tests..
46
+ COMMENT Running tests..
43
47
  DEPENDS test-exe
44
48
  )
49
+
50
+ add_custom_target(benchmark
51
+ COMMAND $<TARGET_FILE:benchmark-exe>
52
+ COMMENT Running benchmarks..
53
+ DEPENDS benchmark-exe
54
+ )
@@ -0,0 +1,184 @@
1
+ #include <algorithm>
2
+ #include <chrono>
3
+ #include <cmath>
4
+ #include <filesystem>
5
+ #include <fstream>
6
+ #include <iomanip>
7
+ #include <iostream>
8
+ #include <sstream>
9
+ #include <string>
10
+ #include <vector>
11
+
12
+ #include "html2md.h"
13
+ #include "md4c-html.h"
14
+ #include "table.h"
15
+
16
+ using std::cerr;
17
+ using std::cout;
18
+ using std::ifstream;
19
+ using std::string;
20
+ using std::stringstream;
21
+ using std::vector;
22
+ using std::chrono::duration;
23
+ using std::chrono::high_resolution_clock;
24
+ using std::chrono::microseconds;
25
+ namespace fs = std::filesystem;
26
+
27
+ // Markdown and HTML utility functions
28
+ namespace markdown {
29
+ void captureHtmlFragment(const MD_CHAR *data, const MD_SIZE data_size,
30
+ void *userData) {
31
+ auto *str = static_cast<stringstream *>(userData);
32
+ str->write(data, data_size);
33
+ }
34
+
35
+ string toHTML(const string &md) {
36
+ stringstream html;
37
+ static MD_TOC_OPTIONS options;
38
+ md_html(md.c_str(), md.size(), &captureHtmlFragment, &html, MD_DIALECT_GITHUB,
39
+ MD_HTML_FLAG_SKIP_UTF8_BOM, &options);
40
+ return html.str();
41
+ }
42
+
43
+ string fromHTML(string &html) {
44
+ static html2md::Options options;
45
+ options.splitLines = false;
46
+ html2md::Converter c(html, &options);
47
+ return c.convert();
48
+ }
49
+ } // namespace markdown
50
+
51
+ // Benchmark result structure
52
+ struct BenchmarkResult {
53
+ string test_name;
54
+ double avg_time_us; // Average time in microseconds
55
+ double std_dev_us; // Standard deviation in microseconds
56
+ size_t input_size; // Input size in bytes
57
+ double throughput_mbps; // Throughput in megabytes per second
58
+ };
59
+
60
+ // Benchmark runner class
61
+ class BenchmarkRunner {
62
+ public:
63
+ void addTest(const string &name, const string &input, bool is_markdown) {
64
+ tests_.push_back({name, input, is_markdown});
65
+ }
66
+
67
+ void run(int iterations) {
68
+ auto start_total = high_resolution_clock::now(); // Start total timer
69
+ for (const auto &test : tests_) {
70
+ runTest(test, iterations);
71
+ }
72
+ auto end_total = high_resolution_clock::now(); // End total timer
73
+ total_duration_ms_ =
74
+ duration<double, std::milli>(end_total - start_total).count();
75
+ printSummary();
76
+ }
77
+
78
+ private:
79
+ struct Test {
80
+ string name;
81
+ string input;
82
+ bool is_markdown; // false for HTML-to-Markdown
83
+ };
84
+
85
+ vector<Test> tests_;
86
+ vector<BenchmarkResult> results_;
87
+ double total_duration_ms_ = 0.0; // Total duration in milliseconds
88
+
89
+ void runTest(const Test &test, int iterations) {
90
+ vector<double> times_us(iterations);
91
+ size_t input_size = test.input.size();
92
+
93
+ for (int i = 0; i < iterations; ++i) {
94
+ auto start = high_resolution_clock::now();
95
+ if (test.is_markdown) {
96
+ markdown::toHTML(test.input);
97
+ } else {
98
+ string input_copy = test.input; // fromHTML modifies input
99
+ markdown::fromHTML(input_copy);
100
+ }
101
+ auto end = high_resolution_clock::now();
102
+ times_us[i] = duration<double, std::micro>(end - start).count();
103
+ }
104
+
105
+ // Calculate average and standard deviation
106
+ double sum = 0.0;
107
+ for (double t : times_us)
108
+ sum += t;
109
+ double avg_time_us = sum / iterations;
110
+
111
+ double variance_sum = 0.0;
112
+ for (double t : times_us) {
113
+ variance_sum += (t - avg_time_us) * (t - avg_time_us);
114
+ }
115
+ double std_dev_us = std::sqrt(variance_sum / iterations);
116
+
117
+ // Calculate throughput (MB/s)
118
+ double avg_time_s = avg_time_us / 1e6;
119
+ double throughput_mbps = (input_size / (1024.0 * 1024.0)) / avg_time_s;
120
+
121
+ results_.push_back(
122
+ {test.name, avg_time_us, std_dev_us, input_size, throughput_mbps});
123
+ }
124
+
125
+ void printSummary() {
126
+ cout << "\n=== Benchmark Summary ===\n";
127
+ cout << std::left << std::setw(30) << "Test Name" << std::setw(15)
128
+ << "Avg Time (us)" << std::setw(15) << "Std Dev (us)" << std::setw(15)
129
+ << "Input Size (B)" << std::setw(15) << "Throughput (MB/s)\n";
130
+ cout << std::string(90, '-') << "\n";
131
+
132
+ for (const auto &result : results_) {
133
+ cout << std::left << std::setw(30) << result.test_name << std::fixed
134
+ << std::setprecision(2) << std::setw(15) << result.avg_time_us
135
+ << std::setw(15) << result.std_dev_us << std::setw(15)
136
+ << result.input_size << std::setw(15) << result.throughput_mbps
137
+ << "\n";
138
+ }
139
+
140
+ cout << "\nTotal Benchmark Duration: " << std::fixed << std::setprecision(2)
141
+ << total_duration_ms_ << " ms\n";
142
+ }
143
+ };
144
+
145
+ namespace file {
146
+ string readAll(const string &name) {
147
+ ifstream in(name);
148
+ stringstream buffer;
149
+ buffer << in.rdbuf();
150
+ return buffer.str();
151
+ }
152
+ } // namespace file
153
+
154
+ int main() {
155
+ using namespace markdown;
156
+ BenchmarkRunner runner;
157
+ const int iterations = 10000; // Number of iterations per test
158
+
159
+ // Add tests for Markdown files in the directory
160
+ vector<string> files;
161
+ static vector<string> markdownExtensions = {".md", ".markdown", ".mkd"};
162
+ for (const auto &p : fs::recursive_directory_iterator(DIR)) {
163
+ if (std::find(markdownExtensions.begin(), markdownExtensions.end(),
164
+ p.path().extension()) != markdownExtensions.end() &&
165
+ p.path().parent_path() == DIR) {
166
+ files.emplace_back(p.path().string());
167
+ }
168
+ }
169
+ std::sort(files.begin(), files.end());
170
+
171
+ for (const auto &file : files) {
172
+ string md = file::readAll(file);
173
+ string html = markdown::toHTML(md);
174
+ string filename = fs::path(file).filename().string();
175
+ runner.addTest(filename, html, false);
176
+ }
177
+
178
+ // Run benchmarks
179
+ cout << "Running benchmarks with " << iterations
180
+ << " iterations per test...\n";
181
+ runner.run(iterations);
182
+
183
+ return 0;
184
+ }