├── .babelrc ├── .codecov.yml ├── .coveragerc ├── .eslintrc ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug.yml │ ├── config.yml │ └── feature.yml ├── dependabot.yml ├── labels.yml └── workflows │ ├── build.yml │ └── deploy.yml ├── .gitignore ├── .pyspelling.yml ├── .stylelintrc ├── LICENSE.md ├── README.md ├── SECURITY.md ├── docs ├── src │ ├── dictionary │ │ ├── en-custom.txt │ │ ├── en-javascript.txt │ │ └── en-python.txt │ ├── html │ │ ├── footer.html │ │ ├── header.html │ │ └── libs.html │ ├── js │ │ ├── arithmatex.js │ │ ├── extra-loader.js │ │ ├── material-extra-3rdparty.js │ │ ├── material-extra-theme.js │ │ └── uml.js │ ├── markdown │ │ ├── .snippets │ │ │ ├── abbr.md │ │ │ ├── blocksbeta.md │ │ │ ├── links.md │ │ │ ├── refs.md │ │ │ └── uml.md │ │ ├── about │ │ │ ├── changelog.md │ │ │ ├── contributing.md │ │ │ ├── development.md │ │ │ ├── license.md │ │ │ ├── releases │ │ │ │ ├── 6.0.md │ │ │ │ ├── 7.0.md │ │ │ │ ├── 8.0.md │ │ │ │ └── 9.0.md │ │ │ └── security.md │ │ ├── extensions │ │ │ ├── arithmatex.md │ │ │ ├── b64.md │ │ │ ├── betterem.md │ │ │ ├── blocks │ │ │ │ ├── api.md │ │ │ │ ├── index.md │ │ │ │ └── plugins │ │ │ │ │ ├── admonition.md │ │ │ │ │ ├── definition.md │ │ │ │ │ ├── details.md │ │ │ │ │ ├── html.md │ │ │ │ │ └── tab.md │ │ │ ├── caret.md │ │ │ ├── critic.md │ │ │ ├── details.md │ │ │ ├── emoji.md │ │ │ ├── escapeall.md │ │ │ ├── extra.md │ │ │ ├── highlight.md │ │ │ ├── inlinehilite.md │ │ │ ├── keys.md │ │ │ ├── magiclink.md │ │ │ ├── mark.md │ │ │ ├── pathconverter.md │ │ │ ├── progressbar.md │ │ │ ├── saneheaders.md │ │ │ ├── smartsymbols.md │ │ │ ├── snippets.md │ │ │ ├── striphtml.md │ │ │ ├── superfences.md │ │ │ ├── tabbed.md │ │ │ ├── tasklist.md │ │ │ └── tilde.md │ │ ├── extras │ │ │ ├── mermaid.md │ │ │ └── slugs.md │ │ ├── faq.md │ │ ├── images │ │ │ ├── mermaid-diagram.png │ │ │ ├── progress.png │ │ │ ├── tabbed-alternate.png │ │ │ ├── tabbed-default-narrow.png │ │ │ └── tabbed-default.png │ │ ├── index.md │ │ ├── installation.md │ │ └── usage_notes.md │ ├── mkdocs.yml │ └── scss │ │ ├── _config.scss │ │ ├── _general.scss │ │ ├── _material.scss │ │ ├── extensions │ │ ├── _admonition.scss │ │ ├── _arithmatex.scss │ │ ├── _critic.scss │ │ ├── _details.scss │ │ ├── _highlight.scss │ │ ├── _keys.scss │ │ ├── _magiclink.scss │ │ ├── _mark.scss │ │ ├── _progressbar.scss │ │ ├── _superfences.scss │ │ ├── _tabbed.scss │ │ ├── _tables.scss │ │ ├── _tasklist.scss │ │ └── _toc.scss │ │ ├── extra.scss │ │ ├── palette │ │ ├── _colors.scss │ │ └── _dracula.scss │ │ └── utilities │ │ ├── _break.scss │ │ ├── _color_tools.scss │ │ └── _convert.scss └── theme │ ├── announce.html │ ├── assets │ └── pymdownx-extras │ │ ├── extra-8611f6c398.css │ │ ├── extra-8611f6c398.css.map │ │ ├── extra-loader-iLQ-keay.js │ │ ├── extra-loader-iLQ-keay.js.map │ │ ├── material-extra-3rdparty-BUCF4rjN.js │ │ ├── material-extra-3rdparty-BUCF4rjN.js.map │ │ ├── material-extra-theme-2ek1P7jT.js │ │ └── material-extra-theme-2ek1P7jT.js.map │ ├── main.html │ └── partials │ ├── footer.html │ ├── header.html │ └── libs.html ├── gulpfile.babel.js ├── hatch_build.py ├── mkdocs.yml ├── package-lock.json ├── package.json ├── pymdownx ├── __init__.py ├── __meta__.py ├── _bypassnorm.py ├── arithmatex.py ├── b64.py ├── betterem.py ├── blocks │ ├── __init__.py │ ├── admonition.py │ ├── block.py │ ├── definition.py │ ├── details.py │ ├── html.py │ └── tab.py ├── caret.py ├── critic.py ├── details.py ├── emoji.py ├── emoji1_db.py ├── escapeall.py ├── extra.py ├── gemoji_db.py ├── highlight.py ├── inlinehilite.py ├── keymap_db.py ├── keys.py ├── magiclink.py ├── mark.py ├── pathconverter.py ├── progressbar.py ├── saneheaders.py ├── slugs.py ├── smartsymbols.py ├── snippets.py ├── striphtml.py ├── superfences.py ├── tabbed.py ├── tasklist.py ├── tilde.py ├── twemoji_db.py └── util.py ├── pyproject.toml ├── requirements ├── dev.txt ├── docs.txt ├── lint.txt ├── test.txt └── tools.txt ├── run_tests.py ├── tests ├── __init__.py ├── extensions │ ├── _assets │ │ ├── bg.png │ │ ├── headeranchor.css │ │ ├── progressbar.css │ │ ├── tabs.css │ │ ├── tasklist.css │ │ └── tasklist_custom.css │ ├── arithmatex │ │ ├── arithmatex (disable).html │ │ ├── arithmatex (disable).txt │ │ ├── arithmatex (dumb dollar).html │ │ ├── arithmatex (dumb dollar).txt │ │ ├── arithmatex (generic).html │ │ ├── arithmatex (generic).txt │ │ ├── arithmatex (no-preview).html │ │ ├── arithmatex (no-preview).txt │ │ ├── arithmatex.html │ │ ├── arithmatex.txt │ │ └── tests.yml │ ├── betterem │ │ ├── betterem (normal).html │ │ ├── betterem (normal).txt │ │ ├── betterem (reverse).html │ │ ├── betterem (reverse).txt │ │ └── tests.yml │ ├── caret │ │ ├── caret (dumb no sup).html │ │ ├── caret (dumb no sup).txt │ │ ├── caret (dumb).html │ │ ├── caret (dumb).txt │ │ ├── caret (no insert).html │ │ ├── caret (no insert).txt │ │ ├── caret (no sup).html │ │ ├── caret (no sup).txt │ │ ├── caret.html │ │ ├── caret.txt │ │ └── tests.yml │ ├── critic │ │ ├── critic (accept).html │ │ ├── critic (accept).txt │ │ ├── critic (reject).html │ │ ├── critic (reject).txt │ │ ├── critic (view).html │ │ ├── critic (view).txt │ │ └── tests.yml │ ├── emoji │ │ ├── emoji1 (entities).html │ │ ├── emoji1 (entities).txt │ │ ├── emoji1 (escaped).html │ │ ├── emoji1 (escaped).txt │ │ ├── emoji1 (long title).html │ │ ├── emoji1 (long title).txt │ │ ├── emoji1 (no title).html │ │ ├── emoji1 (no title).txt │ │ ├── emoji1 (png sprite).html │ │ ├── emoji1 (png sprite).txt │ │ ├── emoji1 (png).html │ │ ├── emoji1 (png).txt │ │ ├── emoji1 (svg sprite).html │ │ ├── emoji1 (svg sprite).txt │ │ ├── emoji1 (svg).html │ │ ├── emoji1 (svg).txt │ │ ├── gemoji (entities).html │ │ ├── gemoji (entities).txt │ │ ├── gemoji (png).html │ │ ├── gemoji (png).txt │ │ ├── tests.yml │ │ ├── twemoji (entities).html │ │ ├── twemoji (entities).txt │ │ ├── twemoji (png).html │ │ ├── twemoji (png).txt │ │ ├── twemoji (svg).html │ │ └── twemoji (svg).txt │ ├── escapeall │ │ ├── escapeall (critic).html │ │ ├── escapeall (critic).txt │ │ ├── escapeall (ws normal).html │ │ ├── escapeall (ws normal).txt │ │ ├── escapeall.html │ │ ├── escapeall.txt │ │ └── tests.yml │ ├── extra │ │ ├── extra (config).html │ │ ├── extra (config).txt │ │ ├── extra.html │ │ ├── extra.txt │ │ └── tests.yml │ ├── keys │ │ ├── keys (camel).html │ │ ├── keys (camel).txt │ │ ├── keys.html │ │ ├── keys.txt │ │ └── tests.yml │ ├── magiclink │ │ ├── magiclink (bitbucket).html │ │ ├── magiclink (bitbucket).txt │ │ ├── magiclink (extensions).html │ │ ├── magiclink (extensions).txt │ │ ├── magiclink (gitlab).html │ │ ├── magiclink (gitlab).txt │ │ ├── magiclink (invalid).html │ │ ├── magiclink (invalid).txt │ │ ├── magiclink (shorthand).html │ │ ├── magiclink (shorthand).txt │ │ ├── magiclink (shorthand-social).html │ │ ├── magiclink (shorthand-social).txt │ │ ├── magiclink.html │ │ ├── magiclink.txt │ │ ├── magiclink_hide_protocol.html │ │ ├── magiclink_hide_protocol.txt │ │ └── tests.yml │ ├── mark │ │ ├── mark (dumb).html │ │ ├── mark (dumb).txt │ │ ├── mark.html │ │ ├── mark.txt │ │ └── tests.yml │ ├── progressbar │ │ ├── progressbar.html │ │ ├── progressbar.txt │ │ └── tests.yml │ ├── striphtml │ │ ├── striphtml (no attr strip).html │ │ ├── striphtml (no attr strip).txt │ │ ├── striphtml.html │ │ ├── striphtml.txt │ │ └── tests.yml │ ├── superfences │ │ ├── superfences (custom).html │ │ ├── superfences (custom).txt │ │ ├── superfences (failures).html │ │ ├── superfences (failures).txt │ │ ├── superfences (no indent blocks).html │ │ ├── superfences (no indent blocks).txt │ │ ├── superfences (no pygments).html │ │ ├── superfences (no pygments).txt │ │ ├── superfences (normal).html │ │ ├── superfences (normal).txt │ │ ├── superfences (preserve tabs).html │ │ ├── superfences (preserve tabs).txt │ │ └── tests.yml │ ├── tasklist │ │ ├── tasklist (checkable).html │ │ ├── tasklist (checkable).txt │ │ ├── tasklist (custom checkable).html │ │ ├── tasklist (custom checkable).txt │ │ ├── tasklist (custom).html │ │ ├── tasklist (custom).txt │ │ ├── tasklist.html │ │ ├── tasklist.txt │ │ └── tests.yml │ └── tilde │ │ ├── tests.yml │ │ ├── tilde (dumb no sub).html │ │ ├── tilde (dumb no sub).txt │ │ ├── tilde (dumb).html │ │ ├── tilde (dumb).txt │ │ ├── tilde (no delete).html │ │ ├── tilde (no delete).txt │ │ ├── tilde (no sub).html │ │ ├── tilde (no sub).txt │ │ ├── tilde.html │ │ └── tilde.txt ├── test_extensions │ ├── __init__.py │ ├── _assets │ │ └── bg.png │ ├── _snippets │ │ ├── a.txt │ │ ├── b.txt │ │ ├── c.txt │ │ ├── d.txt │ │ ├── indented.txt │ │ ├── lines.txt │ │ ├── loop.txt │ │ ├── loop_block.txt │ │ ├── missing.txt │ │ ├── nested │ │ │ └── nested.txt │ │ ├── section.txt │ │ └── section_nested.txt │ ├── test_arithmatex.py │ ├── test_b64.py │ ├── test_betterem.py │ ├── test_blocks │ │ ├── __init__.py │ │ ├── test_admonitions.py │ │ ├── test_definition.py │ │ ├── test_details.py │ │ ├── test_general_blocks.py │ │ ├── test_html.py │ │ ├── test_legacy_tab.py │ │ └── test_tab.py │ ├── test_details.py │ ├── test_emoji.py │ ├── test_escapeall.py │ ├── test_highlight.py │ ├── test_inlinehilite.py │ ├── test_keys.py │ ├── test_legacy_slugs.py │ ├── test_magiclink.py │ ├── test_pathconverter.py │ ├── test_saneheaders.py │ ├── test_slugs.py │ ├── test_smartsymbols.py │ ├── test_snippets.py │ ├── test_striphmtl.py │ ├── test_superfences.py │ ├── test_tabbed.py │ └── test_tabbed_alternate.py ├── test_syntax.py ├── test_targeted.py ├── test_versions.py └── util.py └── tools ├── __init__.py ├── collapse_code.py ├── gen_emoji.py ├── gen_emoji1.py ├── gen_gemoji.py ├── gen_joypixels.py ├── gen_twemoji.py └── pymdownx_md_render.py /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } 4 | -------------------------------------------------------------------------------- /.codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | 3 | coverage: 4 | status: 5 | patch: false 6 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | omit= 3 | pymdownx/plainhtml.py 4 | 5 | [report] 6 | omit= 7 | pymdownx/plainhtml.py 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | tests/extensions/** linguist-vendored 2 | doc_theme/** linguist-vendored 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: facelessuser 2 | custom: 3 | - "https://www.paypal.me/facelessuser" 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.yml: -------------------------------------------------------------------------------- 1 | name: Bug Report 2 | description: Report a bug 3 | labels: 4 | - 'T: bug' 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Description 10 | description: A clear and concise description of the problem 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: reproduction 15 | attributes: 16 | label: Minimal Reproduction 17 | description: Provide steps to reproduce the problem 18 | placeholder: |- 19 | 1. ... 20 | 2. ... 21 | 3. ... 22 | validations: 23 | required: true 24 | - type: textarea 25 | id: versions 26 | attributes: 27 | label: Version(s) & System Info 28 | description: >- 29 | Please provide problematic package version, Python version, operating 30 | system, etc. 31 | value: |- 32 | - Operating System: ... 33 | - Python Version: ... 34 | - Package Version: ... 35 | validations: 36 | required: true 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Question 4 | url: https://github.com/facelessuser/pymdown-extensions/discussions 5 | about: Ask a question 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.yml: -------------------------------------------------------------------------------- 1 | name: Feature Request 2 | description: Request a feature 3 | labels: 4 | - 'T: feature' 5 | body: 6 | - type: textarea 7 | id: description 8 | attributes: 9 | label: Description 10 | description: A clear and concise description of the problem or missing capability 11 | validations: 12 | required: true 13 | - type: textarea 14 | id: benefits 15 | attributes: 16 | label: Benefits 17 | description: How would this benefit users in general? 18 | validations: 19 | required: true 20 | - type: textarea 21 | id: solution-idea 22 | attributes: 23 | label: Solution Idea 24 | description: >- 25 | Do you have an idea of how this might work? If so, provide details, 26 | examples, references, etc. 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: deploy 2 | 3 | on: 4 | push: 5 | tags: 6 | - '*' 7 | 8 | jobs: 9 | 10 | documents: 11 | strategy: 12 | max-parallel: 4 13 | matrix: 14 | python-version: ['3.11'] 15 | 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - uses: actions/checkout@v4 20 | with: 21 | fetch-depth: 0 22 | - name: Set up Python ${{ matrix.python-version }} 23 | uses: actions/setup-python@v5 24 | with: 25 | python-version: ${{ matrix.python-version }} 26 | - name: Install dependencies 27 | run: | 28 | python -m pip install --upgrade pip build 29 | python -m pip install -r requirements/docs.txt 30 | - name: Deploy documents 31 | run: | 32 | git config user.name ${{ secrets.GH_USER }} 33 | git config user.email "${{ secrets.GH_EMAIL }}" 34 | git remote add gh-token "https://${{ secrets.GH_TOKEN }}@github.com/facelessuser/pymdown-extensions.git" 35 | git fetch gh-token && git fetch gh-token gh-pages:gh-pages 36 | python -m mkdocs gh-deploy -v --clean --remote-name gh-token 37 | git push gh-token gh-pages 38 | 39 | pypi: 40 | runs-on: ubuntu-latest 41 | 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: actions/setup-python@v5 45 | with: 46 | python-version: '3.11' 47 | - name: Package 48 | run: | 49 | pip install --upgrade build 50 | python -m build -s -w 51 | - name: Publish 52 | uses: pypa/gh-action-pypi-publish@release/v1 53 | with: 54 | user: __token__ 55 | password: ${{ secrets.PYPI_TOKEN }} 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | 59 | tools/emoji.md 60 | 61 | site/ 62 | 63 | tools/tags/ 64 | 65 | tmp* 66 | 67 | node_modules/ 68 | 69 | manifest*.json 70 | *.dic 71 | 72 | # IDE 73 | .vscode/ 74 | 75 | # cache 76 | .pytest_cache 77 | 78 | # Patches 79 | *.patch 80 | docs/src/dictionary/hunspell/ 81 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-recommended", 4 | "stylelint-config-rational-order" 5 | ], 6 | "plugins": [ 7 | "stylelint-order", 8 | "stylelint-scss" 9 | ], 10 | "rules": { 11 | "at-rule-empty-line-before": null, 12 | "at-rule-no-unknown": null, 13 | "at-rule-no-vendor-prefix": true, 14 | "color-hex-length": "long", 15 | "color-named": "never", 16 | "comment-empty-line-before": ["always", { 17 | "ignore": ["stylelint-commands"] 18 | }], 19 | "font-family-name-quotes": "always-where-recommended", 20 | "font-weight-notation": "numeric", 21 | "function-url-quotes": "always", 22 | "media-query-no-invalid": null, 23 | "no-descending-specificity": null, 24 | "no-unknown-animations": true, 25 | "property-no-vendor-prefix": true, 26 | "selector-class-pattern": "^[a-z0-9]+(-[a-z0-9]+)*(__[a-z]+)?(--[a-z]+)?$", 27 | "selector-type-no-unknown": [true, {"ignore": ["custom-elements"]}], 28 | "unit-allowed-list": ["px", "em", "deg", "ms", "%", "mm", "vh", "dppx", "s"], 29 | "value-keyword-case": "lower", 30 | "value-no-vendor-prefix": true, 31 | "function-no-unknown": null, 32 | "annotation-no-unknown": [true, {"ignoreAnnotations": ["default"]}] 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Donate via PayPal][donate-image]][donate-link] 2 | [![Build][github-ci-image]][github-ci-link] 3 | [![Coverage Status][codecov-image]][codecov-link] 4 | [![PyPI Version][pypi-image]][pypi-link] 5 | [![PyPI Downloads][pypi-down]][pypi-link] 6 | [![PyPI - Python Version][python-image]][pypi-link] 7 | ![License][license-image-mit] 8 | 9 | # PyMdown Extensions 10 | 11 | Extensions for [Python Markdown](https://python-markdown.github.io). 12 | 13 | # Documentation 14 | 15 | Extension documentation is found here: https://facelessuser.github.io/pymdown-extensions/. 16 | 17 | # License 18 | 19 | License is MIT. See [LICENSE](https://github.com/facelessuser/pymdown-extensions/blob/master/LICENSE.md) for more info. 20 | 21 | [github-ci-image]: https://github.com/facelessuser/pymdown-extensions/workflows/build/badge.svg?branch=main&event=push 22 | [github-ci-link]: https://github.com/facelessuser/pymdown-extensions/actions?query=workflow%3Abuild+branch%3Amain 23 | [codecov-image]: https://img.shields.io/codecov/c/github/facelessuser/pymdown-extensions/main.svg?logo=codecov&logoColor=aaaaaa&labelColor=333333 24 | [codecov-link]: https://codecov.io/github/facelessuser/pymdown-extensions 25 | [pypi-image]: https://img.shields.io/pypi/v/pymdown-extensions.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 26 | [pypi-link]: https://pypi.python.org/pypi/pymdown-extensions 27 | [python-image]: https://img.shields.io/pypi/pyversions/pymdown-extensions?logo=python&logoColor=aaaaaa&labelColor=333333 28 | [pypi-down]: https://img.shields.io/pypi/dm/pymdown-extensions.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 29 | [license-image-mit]: https://img.shields.io/badge/license-MIT-blue.svg?labelColor=333333 30 | [donate-image]: https://img.shields.io/badge/Donate-PayPal-3fabd1?logo=paypal 31 | [donate-link]: https://www.paypal.me/facelessuser 32 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Vulnerabilities 2 | 3 | Our policy for security related issues is to fix related issues within our power on the most recent major release. 4 | 5 | ## Versioning 6 | 7 | Versioning follows [PEP440](https://peps.python.org/pep-0440/): `major.minior.patch`. 8 | 9 | Versions | Description 10 | -------- | ----------- 11 | Major | This reserved for releases that introduce breaking features. 12 | Minor | This reserved for releases that introduce new functionality. 13 | Patch | This is reserved for releases that only include bug fixes. 14 | 15 | Example 16 | 17 | ``` 18 | 8.0 19 | 8.1 20 | 8.1.3 21 | ``` 22 | 23 | ## Create Security Vulnerability Report 24 | 25 | If you have found a security vulnerability, you can create a draft "security advisory" on the GitHub repository, 26 | [instructions here](https://docs.github.com/en/code-security/security-advisories/repository-security-advisories/creating-a-repository-security-advisory). 27 | Such advisories are kept private as the issue is explored. 28 | 29 | ## Security Vulnerability Workflow 30 | 31 | We will strive to acknowledge the report in about two business days. 32 | 33 | Reports will be kept private until the issue is properly understood. 34 | 35 | If the report is accepted we will notify Tidelift (who we've partnered with), request a CVE from GitHub, and work with 36 | the reporter to find a resolution. Work will be done privately, and the final commit will not mention the security 37 | issue. 38 | 39 | The fix, announcement, and release will be negotiated with the reporter. 40 | 41 | Afterwards, a release will be made and the vulnerability will be made public as close to each other as possible. 42 | -------------------------------------------------------------------------------- /docs/src/dictionary/en-javascript.txt: -------------------------------------------------------------------------------- 1 | className 2 | param 3 | -------------------------------------------------------------------------------- /docs/src/dictionary/en-python.txt: -------------------------------------------------------------------------------- 1 | BOM 2 | BOMs 3 | Dedent 4 | LLC 5 | StackOverflow 6 | Twardoch 7 | UrlParse 8 | arithmatex 9 | autogen 10 | betterem 11 | bowtie 12 | bypassnorm 13 | chunking 14 | dedent 15 | escapeall 16 | extrarawhtml 17 | feelsgood 18 | finnadie 19 | fu 20 | goberserk 21 | godmode 22 | hurtrealbad 23 | inlinehilite 24 | magiclink 25 | neckbeard 26 | netpath 27 | octocat 28 | ord 29 | pathconverter 30 | plainhtml 31 | progressbar 32 | shipit 33 | smartstrong 34 | smartsymbols 35 | striphtml 36 | tasklist 37 | tasklists 38 | trollface 39 | tuple 40 | wildcard 41 | -------------------------------------------------------------------------------- /docs/src/html/libs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /docs/src/js/arithmatex.js: -------------------------------------------------------------------------------- 1 | export default (className, mode) => { 2 | if (mode === 'katex') { 3 | const maths = document.querySelectorAll(`.${className}`) 4 | 5 | for (let i = 0; i < maths.length; i++) { 6 | const tex = maths[i].textContent || maths[i].innerText 7 | 8 | if (tex.startsWith('\\(') && tex.endsWith('\\)')) { 9 | katex.render(tex.slice(2, -2), maths[i], {'displayMode': false}) 10 | } else if (tex.startsWith('\\[') && tex.endsWith('\\]')) { 11 | katex.render(tex.slice(2, -2), maths[i], {'displayMode': true}) 12 | } 13 | } 14 | } else if (mode === 'mathjax') { 15 | MathJax.startup.output.clearCache() 16 | MathJax.typesetClear() 17 | MathJax.texReset() 18 | MathJax.typesetPromise() 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/src/js/extra-loader.js: -------------------------------------------------------------------------------- 1 | import uml from "./uml" 2 | import arithmatex from "./arithmatex" 3 | 4 | // Main function 5 | (() => { 6 | let umlPromise = Promise.resolve() 7 | let mathPromise = Promise.resolve() 8 | 9 | const observer = new MutationObserver(mutations => { 10 | mutations.forEach(mutation => { 11 | if (mutation.type === "attributes") { 12 | let scheme = mutation.target.getAttribute("data-md-color-scheme") 13 | if (!scheme) { 14 | scheme = "default" 15 | } 16 | localStorage.setItem("data-md-color-scheme", scheme) 17 | if (typeof mermaid !== "undefined") { 18 | uml("diagram") 19 | } 20 | } 21 | }) 22 | }) 23 | 24 | const main = () => { 25 | observer.observe(document.querySelector("body"), {attributeFilter: ["data-md-color-scheme"]}) 26 | 27 | if (typeof mermaid !== "undefined") { 28 | umlPromise = umlPromise.then(() => { 29 | uml("diagram") 30 | }).catch(err => { 31 | console.log(`UML loading failed...${err}`) // eslint-disable-line no-console 32 | }) 33 | } 34 | 35 | if (typeof katex !== "undefined") { 36 | mathPromise = mathPromise.then(() => { 37 | arithmatex("arithmatex", "katex") 38 | }).catch(err => { 39 | console.log(`Math loading failed...${err}`) // eslint-disable-line no-console 40 | }) 41 | } else if (typeof MathJax !== "undefined" && 'typesetPromise' in MathJax) { 42 | mathPromise = mathPromise.then(() => { 43 | arithmatex("arithmatex", "mathjax") 44 | }).catch(err => { 45 | console.log(`Math loading failed...${err}`) // eslint-disable-line no-console 46 | }) 47 | } 48 | } 49 | 50 | if (window.document$) { 51 | // Material specific hook 52 | window.document$.subscribe(main) 53 | } else { 54 | // Normal non-Material specific hook 55 | document.addEventListener("DOMContentLoaded", main) 56 | } 57 | })() 58 | -------------------------------------------------------------------------------- /docs/src/js/material-extra-theme.js: -------------------------------------------------------------------------------- 1 | (() => { 2 | 3 | const preferToggle = e => { 4 | if (localStorage.getItem("data-md-prefers-color-scheme") === "true") { 5 | document.querySelector("body").setAttribute("data-md-color-scheme", (e.matches) ? "dracula" : "default") 6 | } 7 | } 8 | 9 | const setupTheme = body => { 10 | const preferSupported = window.matchMedia("(prefers-color-scheme)").media !== "not all" 11 | let scheme = localStorage.getItem("data-md-color-scheme") 12 | let prefers = localStorage.getItem("data-md-prefers-color-scheme") 13 | 14 | if (!scheme) { 15 | scheme = "dracula" 16 | } 17 | if (!prefers) { 18 | prefers = "false" 19 | } 20 | 21 | if (prefers === "true" && preferSupported) { 22 | scheme = (window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dracula" : "default" 23 | } else { 24 | prefers = "false" 25 | } 26 | 27 | body.setAttribute("data-md-prefers-color-scheme", prefers) 28 | body.setAttribute("data-md-color-scheme", scheme) 29 | 30 | if (preferSupported) { 31 | const matchListener = window.matchMedia("(prefers-color-scheme: dark)") 32 | matchListener.addListener(preferToggle) 33 | } 34 | } 35 | 36 | const observer = new MutationObserver(mutations => { 37 | mutations.forEach(mutation => { 38 | if (mutation.type === "childList") { 39 | if (mutation.addedNodes.length) { 40 | for (let i = 0; i < mutation.addedNodes.length; i++) { 41 | const el = mutation.addedNodes[i] 42 | 43 | if (el.nodeType === 1 && el.tagName.toLowerCase() === "body") { 44 | setupTheme(el) 45 | break 46 | } 47 | } 48 | } 49 | } 50 | }) 51 | }) 52 | 53 | observer.observe(document.querySelector("html"), {childList: true}) 54 | })() 55 | 56 | window.toggleScheme = () => { 57 | const body = document.querySelector("body") 58 | const preferSupported = window.matchMedia("(prefers-color-scheme)").media !== "not all" 59 | let scheme = body.getAttribute("data-md-color-scheme") 60 | let prefer = body.getAttribute("data-md-prefers-color-scheme") 61 | 62 | if (preferSupported && scheme === "default" && prefer !== "true") { 63 | prefer = "true" 64 | scheme = (window.matchMedia("(prefers-color-scheme: dark)").matches) ? "dracula" : "default" 65 | } else if (preferSupported && prefer === "true") { 66 | prefer = "false" 67 | scheme = "dracula" 68 | } else if (scheme === "dracula") { 69 | prefer = "false" 70 | scheme = "default" 71 | } else { 72 | prefer = "false" 73 | scheme = "dracula" 74 | } 75 | localStorage.setItem("data-md-prefers-color-scheme", prefer) 76 | body.setAttribute("data-md-prefers-color-scheme", prefer) 77 | body.setAttribute("data-md-color-scheme", scheme) 78 | } 79 | -------------------------------------------------------------------------------- /docs/src/markdown/.snippets/abbr.md: -------------------------------------------------------------------------------- 1 | *[Toc]: Table of Contents 2 | *[GFM]: GitHub Flavored Markdown 3 | *[FAQ]: Frequent Asked Questions 4 | -------------------------------------------------------------------------------- /docs/src/markdown/.snippets/blocksbeta.md: -------------------------------------------------------------------------------- 1 | /// new | 9.10 New Experimental Feature 2 | Blocks is currently a new, experimental extension type available in Pymdown Extensions that allows for writing a new 3 | kind of block extension in Python Markdown. With this new addition, we've added a number of new extensions utilizing 4 | this new extension type. While its intention is to hopefully replace extensions like Details and Tabbed, there are 5 | currently no immediate plans to deprecate those plugins. 6 | 7 | Any and all feedback regarding these new, experimental blocks is appreciated. Please provide feedback here: 8 | https://github.com/facelessuser/pymdown-extensions/discussions/1973. 9 | /// 10 | -------------------------------------------------------------------------------- /docs/src/markdown/.snippets/refs.md: -------------------------------------------------------------------------------- 1 | --8<-- 2 | links.md 3 | abbr.md 4 | --8<-- 5 | -------------------------------------------------------------------------------- /docs/src/markdown/about/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing & Support 2 | 3 | ## Become a Sponsor :octicons-heart-fill-16:{: .heart-throb} 4 | 5 | Open source projects take time and money. Help support the project by becoming a sponsor. You can add your support at 6 | any tier you feel comfortable with. No amount is too little. We also accept one time contributions via PayPal. 7 | 8 | [:octicons-mark-github-16: GitHub Sponsors](https://github.com/sponsors/facelessuser){: .md-button .md-button--primary } 9 | [:fontawesome-brands-paypal: PayPal](https://www.paypal.me/facelessuser){ .md-button} 10 | 11 | ## Bug Reports :material-bug: 12 | 13 | 1. Please **read the documentation** and **search the issue tracker** to try and find the answer to your question 14 | **before** posting an issue. 15 | 16 | 2. When creating an issue on the repository, please provide as much info as possible: 17 | 18 | - Version being used. 19 | - Operating system. 20 | - Version of Python. 21 | - Errors in console. 22 | - Detailed description of the problem. 23 | - Examples for reproducing the error. You can post pictures, but if specific text or code is required to 24 | reproduce the issue, please provide the text in a plain text format for easy copy/paste. 25 | 26 | The more info provided, the greater the chance someone will take the time to answer, implement, or fix the issue. 27 | 28 | 3. Be prepared to answer questions and provide additional information if required. Issues in which the creator refuses 29 | to respond to follow up questions will be marked as stale and closed. 30 | 31 | ## Reviewing Code :material-glasses: 32 | 33 | Take part in reviewing pull requests and/or reviewing direct commits. Make suggestions to improve the code and discuss 34 | solutions to overcome weakness in the algorithm. 35 | 36 | ## Answer Questions in Issues :material-comment-question: 37 | 38 | Take time and answer questions and offer suggestions to people who've created issues in the issue tracker. Often people 39 | will have questions that you might have an answer for. Or maybe you know how to help them accomplish a specific task 40 | they are asking about. Feel free to share your experience to help others out. 41 | 42 | ## Pull Requests :octicons-git-pull-request-24: 43 | 44 | Pull requests are welcome, and a great way to help fix bugs and add new features. If you you are interested in directly 45 | contributing to the code, please check out [Development](./development.md) for more info on the environment and process. 46 | 47 | ## Documentation Improvements :material-pencil: 48 | 49 | A ton of time has been spent not only creating and supporting this tool and related extensions, but also spent making 50 | this documentation. If you feel it is still lacking, show your appreciation for the tool and/or extensions by helping 51 | to improve the documentation. Check out [Development](./development.md) for more info on documentation. 52 | -------------------------------------------------------------------------------- /docs/src/markdown/about/license.md: -------------------------------------------------------------------------------- 1 | --8<-- "LICENSE.md" 2 | -------------------------------------------------------------------------------- /docs/src/markdown/about/releases/6.0.md: -------------------------------------------------------------------------------- 1 | # 6.0 Migration Notes {: #\6.0} 2 | 3 | ## Overview 4 | 5 | While there are a number of new features and bug fixes, the only backwards incompatible changes are with SuperFences' 6 | custom fences. In an effort to make custom fences more useful, we wanted to be able to pass the `Markdown` object to the 7 | formatters. This gives custom formats access to things like metadata if required. 8 | 9 | The format of custom fence formatters already had two different versions: ones without custom options and one with 10 | custom options. As adding yet another parameter would cause more complexity behind the scenes, we decided to introduce 11 | the breaking change of creating a unified format for formatters with custom options and without. In addition to unifying 12 | the format, we also now pass the `Markdown` object to the formatters as an additional parameter. 13 | 14 | While we were breaking custom formats, it seemed like a good time to go ahead and change the defaults for the 15 | `custom_fences` options. Most people who are using SuperFences aren't even using the default, niche `flow` and 16 | `sequence` custom fences. Instead of hijacking fence names that most people aren't even using, it seemed more 17 | appropriate to define no custom fences. 18 | 19 | Below are instructions on how to upgrade if you were relying on the either the default settings of `custom_fences` or if 20 | you had written your own custom fence formatters. 21 | 22 | 1. If you've written your own custom fence formatters, the number of parameters needed has changed, so you must update 23 | your existing formatters. The needed parameters are the same regardless of whether you are using an options 24 | validator or not. 25 | 26 | ```py3 27 | def custom_formatter(source, language, css_class, options, md): 28 | return string 29 | ``` 30 | 31 | 2. `flow` and `sequence` are no longer defined by default. If you were relying on the default custom fences, you will 32 | have to define them manually now. The needed settings are found below: 33 | 34 | ```py3 35 | extension_configs = { 36 | "pymdownx.superfences": { 37 | "custom_fences": [ 38 | { 39 | 'name': 'flow', 40 | 'class': 'uml-flowchart', 41 | 'format': pymdownx.superfences.fence_code_format 42 | }, 43 | { 44 | 'name': 'sequence', 45 | 'class': 'uml-sequence-diagram', 46 | 'format': pymdownx.superfences.fence_code_format 47 | } 48 | ] 49 | } 50 | } 51 | ``` 52 | 53 | If you are attempting to configure these options in a YAML based configuration (like in [MkDocs][mkdocs]), please 54 | see the [FAQ](../../faq.md#function-references-in-yaml) to see how to specify function references in YAML. 55 | -------------------------------------------------------------------------------- /docs/src/markdown/about/security.md: -------------------------------------------------------------------------------- 1 | --8<-- "SECURITY.md" 2 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/b64.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_b64]{: .source-link } 2 | 3 | # B64 4 | 5 | ## Overview 6 | 7 | B64 allows for the embedding of local PNG, JPEG, and GIF image references with base64 encoding. It simply needs a base 8 | path to resolve relative links in the Markdown source. The base path is the assumed location of the Markdown source at 9 | time of conversion. Using the base path, B64 will search and find the actual `img` tag references (both absolute and 10 | relative) and base64 encode and embed them in the HTML output. 11 | 12 | If you would like to distribute a Markdown output without having to also distribute the images separately, B64 can help. 13 | In a normal website, this would probably not be desired. 14 | 15 | ```text title="B64 Image" 16 | ![picture](../_assets/bg.png) 17 | ``` 18 | 19 | /// html | div.result 20 | ```html 21 |

picture 22 | ``` 23 | /// 24 | 25 | The B64 extension can be included in Python Markdown by using the following: 26 | 27 | ```py3 28 | import markdown 29 | md = markdown.Markdown(extensions=['pymdownx.b64']) 30 | ``` 31 | 32 | ## Options 33 | 34 | Option | Type | Default | Description 35 | ----------- | ------ | ----------- |------------ 36 | `base_path` | string | `#!py3 '.'` | A string indicating a base path to be used to resolve relative links. 37 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/caret.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_caret]{: .source-link } 2 | 3 | # Caret 4 | 5 | ## Overview 6 | 7 | Caret optionally adds two different features which are syntactically built around the `^` character. The first is 8 | **insert** which inserts `#!html ` tags. The second is **superscript** which inserts `#!html ` 9 | tags. 10 | 11 | The Caret extension can be included in Python Markdown by using the following: 12 | 13 | ```py3 14 | import markdown 15 | md = markdown.Markdown(extensions=['pymdownx.caret']) 16 | ``` 17 | 18 | ## Insert 19 | 20 | To wrap content in an **insert** tag, simply surround the text with double `^`. You can also enable `smart_insert` in 21 | the [options](#options). Smart behavior of **insert** models that of [BetterEm](betterem.md#differences). 22 | 23 | ```text title="Insert" 24 | ^^Insert me^^ 25 | ``` 26 | 27 | /// html | div.result 28 | ^^Insert me^^ 29 | /// 30 | 31 | ## Superscript 32 | 33 | To denote a superscript, you can surround the desired content in single `^`. It uses Pandoc style logic, so if your 34 | superscript needs to have spaces, you must escape the spaces. 35 | 36 | ```text title="Superscript" 37 | H^2^0 38 | 39 | text^a\ superscript^ 40 | ``` 41 | 42 | /// html | div.result 43 | H^2^0 44 | 45 | text^a\ superscript^ 46 | /// 47 | 48 | ## Options 49 | 50 | Option | Type | Default | Description 51 | -------------- | ---- | ------------ | ----------- 52 | `smart_insert` | bool | `#!py3 True` | Use smart logic with insert characters. 53 | `insert` | bool | `#!py3 True` | Enable insert feature. 54 | `superscript` | bool | `#!py3 True` | Enable superscript feature. 55 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/escapeall.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_escapeall]{: .source-link } 2 | 3 | # EscapeAll 4 | 5 | ## Overview 6 | 7 | If you ever have to stop and try to remember, *Can I escape this char?* or *Will a backslash escape this?*, you are not 8 | alone. EscapeAll makes `\` escape everything making such questions moot. Now instead of questioning or looking up what 9 | can be escaped, you can expect that `\` will escape the character following it. So if you need a literal `\`, just 10 | escape it: `\\`. Keep in mind this will not escape things in code blocks of any kind. 11 | 12 | ```text title="Escaping" 13 | \W\e\ \c\a\n\ \e\s\c\a\p\e 14 | \e\v\e\r\y\t\h\i\n\g\!\ \ 15 | \❤\😄 16 | ``` 17 | 18 | /// html | div.result 19 | \W\e\ \c\a\n\ \e\s\c\a\p\e 20 | \e\v\e\r\y\t\h\i\n\g\!\ \ 21 | \❤\😄 22 | /// 23 | 24 | There are two special escapes among all of these escapes though: escaping "space" characters and escaping "newline" 25 | characters. If `nbsp` is enabled, an escaped space will be converted into a non-breaking space: `#!html  `. If 26 | `hardbreak` is enabled, an escaped newline will be converted to a hard break `#!html
`. The advantage of `hardbreak` 27 | is that you can visually see the hard break opposed to Markdown's default method of two spaces at the end of a line. 28 | 29 | So in short, EscapeAll escapes all inline characters. 30 | 31 | /// question | Q & A 32 | **So all ASCII characters?** 33 | 34 | _It escapes everything._ 35 | 36 | **What about Unicode?** 37 | 38 | _It escapes everything!_ 39 | 40 | **What about...** 41 | 42 | _EVERYTHING! IT ESCAPES EVERYTHING!_ 43 | /// 44 | 45 | The EscapeAll extension can be included in Python Markdown by using the following: 46 | 47 | ```py3 48 | import markdown 49 | md = markdown.Markdown(extensions=['pymdownx.escapeall']) 50 | ``` 51 | 52 | ## Options 53 | 54 | Option | Type | Default | Description 55 | ----------- | ---- | --------------- | ---------- 56 | `hardbreak` | bool | `#!py3 False` | Escaped newlines will be hard breaks: `#!html
`. 57 | `nbsp` | bool | `#!py3 False` | Escaped spaces will be non-breaking spaces: `#!html  `. 58 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/extra.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_extra]{: .source-link } 2 | 3 | # Extra 4 | 5 | ## Overview 6 | 7 | Python Markdown has an `extra` extension that provides features similar to PHP Markdown Extra. PyMdown Extensions aims 8 | to provide not only new features, but to improve behavior in Python Markdown's existing feature set. Some of these 9 | things can be at odds. Python Markdown's `smartstrong` and `fenced_code` are not compatible with PyMdown Extensions' 10 | `betterem` and `superfences`. `smartstrong` should never be loaded at the same time as `betterem`, and `superfences` 11 | should not be loaded at the same time as `fenced_code`. For these reasons, it is not possible to use Python Markdown's 12 | `extra` and PyMdown Extensions' `superfences` and `betterem` at the same time. To make this less frustrating, PyMdown 13 | Extensions provides it's own implementation of `extra`. 14 | 15 | PyMdown Extensions' `extra` is just like Python Markdown's extra except `smartstrong` is replaced by `betterem` and 16 | `fenced_code` is replaced by `superfences`. All other features and extensions should be identical because we are using 17 | the same ones. 18 | 19 | This extension is a convenience extension, and it currently provides no other additional features. But remember **don't 20 | use `pymdownx.extra` while also using `markdown.extensions.extra`**! 21 | 22 | /// danger | Reminder 23 | Remember to read the [Usage Notes](../usage_notes.md) for information that may be relevant when using this 24 | extension! 25 | /// 26 | 27 | Extensions: 28 | 29 | Extension | Name 30 | ---------------------------------- |-------- 31 | [BetterEm](./betterem.md) | `pymdownx.betterem` 32 | [SuperFences](./superfences.md) | `pymdownx.superfences` 33 | [Footnotes][footnotes] | `markdown.extensions.footnotes` 34 | [Attribute Lists][attr-list] | `markdown.extensions.attr_list` 35 | [Definition Lists][def-list] | `markdown.extensions.def_list` 36 | [Tables][tables] | `markdown.extensions.tables` 37 | [Abbreviations][abbreviations] | `markdown.extensions.abbr` 38 | [Markdown in HTML][md-in-html] | `markdown.extensions.md_in_html` 39 | 40 | The Extra extension can be included in Python Markdown by using the following: 41 | 42 | ```py3 43 | import markdown 44 | md = markdown.Markdown(extensions=['pymdownx.extra']) 45 | ``` 46 | 47 | ## Options 48 | 49 | If you wish to configure the individual extensions included via this extensions, you can configure them by placing that 50 | sub extension's settings under a setting value that equals the sub extensions name. 51 | 52 | ```py3 53 | extension_configs = { 54 | 'pymdownx.extra': { 55 | 'markdown.extensions.footnotes': { 56 | 'BACKLINK_TEXT': 'link' 57 | } 58 | } 59 | } 60 | ``` 61 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/mark.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_mark]{: .source-link } 2 | 3 | # Mark 4 | 5 | ## Overview 6 | 7 | Mark adds the ability to insert `#!html ` tags. The syntax requires the text to be surrounded by double 8 | equal signs. It can optionally be configured to use smart logic. Syntax behavior for smart and non-smart variants of 9 | **mark** models that of [BetterEm](betterem.md#differences). 10 | 11 | To Mark some text, simply surround the text with double `=`. 12 | 13 | ```text title="Marking" 14 | ==mark me== 15 | 16 | ==smart==mark== 17 | ``` 18 | 19 | /// html | div.result 20 | ==mark me== 21 | 22 | ==smart==mark== 23 | /// 24 | 25 | The Mark extension can be included in Python Markdown by using the following: 26 | 27 | ```py3 28 | import markdown 29 | md = markdown.Markdown(extensions=['pymdownx.mark']) 30 | ``` 31 | 32 | ## Options 33 | 34 | Option | Type | Default | Description 35 | ------------ | ---- | ----------- |------------ 36 | `smart_mark` | bool | `#!py3 True` | Use smart logic with mark characters. 37 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/saneheaders.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_saneheaders]{: .source-link } 2 | 3 | # SaneHeaders 4 | 5 | ## Overview 6 | 7 | SaneHeaders is an extension that alters the default hashed headers extension to require headers to have spaces after the 8 | hashes (`#`) in order to be recognized as headers. This allows for other extension syntaxes to use `#` in their syntaxes 9 | as long as no spaces follow the `#` at the beginning of a line. For instance, 10 | [MagicLink's issue syntax](./magiclink.md#issues-and-pull-requests) issue syntax uses hashes followed by numbers 11 | (`#998`) to represent issue links. There may be extensions that use names after hashes to provide tags (`#tag`). With 12 | SaneHeaders, these syntaxes can coexist. Those familiar with CommonMark may recognize this behavior. 13 | 14 | ```py3 15 | import markdown 16 | md = markdown.Markdown(extensions=['pymdownx.saneheaders']) 17 | ``` 18 | 19 | ## Syntax 20 | 21 | The syntax when using SaneHeaders is exactly like Python Markdown's default logic with the only exception being that 22 | SaneHeaders will not treat hashes at the beginning of a line as a header if they do not have space after them. 23 | 24 | In Python Markdown, both of these are treated as headers: 25 | 26 | ``` 27 | ## Header 28 | 29 | ##Also a Header 30 | ``` 31 | 32 | With SaneHeaders, only the first is a header: 33 | 34 | ``` 35 | ## Header 36 | 37 | ##Not a Header 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/smartsymbols.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_smartsymbols]{: .source-link } 2 | 3 | # SmartSymbols 4 | 5 | ## Overview 6 | 7 | SmartSymbols adds syntax for creating special characters such as trademarks, arrows, fractions, etc. It basically 8 | allows for more "smarty-pants" like replacements. It is meant to be used along side Python Markdown's `smarty` 9 | extension not to replace. 10 | 11 | Markdown | Result 12 | -------------- |-------- 13 | `(tm)` | (tm) 14 | `(c)` | (c) 15 | `(r)` | (r) 16 | `c/o` | c/o 17 | `+/-` | +/- 18 | `-->` | --> 19 | `<--` | <-- 20 | `<-->` | <--> 21 | `=/=` | =/= 22 | `1/4, etc.` | 1/4, etc. 23 | `1st 2nd etc.` |1st 2nd etc. 24 | 25 | The SmartSymbols extension can be included in Python Markdown by using the following: 26 | 27 | ```py3 28 | import markdown 29 | md = markdown.Markdown(extensions=['pymdownx.smartsymbols']) 30 | ``` 31 | 32 | ## Options 33 | 34 | Option | Type | Default | Description 35 | ----------------- | ---- | ----------- |------------ 36 | `trademark` | bool | `#!py3 True` | Add syntax for trademark symbol. 37 | `copyright` | bool | `#!py3 True` | Add syntax for copyright symbol. 38 | `registered` | bool | `#!py3 True` | Add syntax for registered symbol. 39 | `care_of` | bool | `#!py3 True` | Add syntax for care / of. 40 | `plusminus` | bool | `#!py3 True` | Add syntax for plus / minus. 41 | `arrows` | bool | `#!py3 True` | Add syntax for creating arrows. 42 | `notequal` | bool | `#!py3 True` | Add syntax for not equal symbol. 43 | `fractions` | bool | `#!py3 True` | Add syntax for common fractions. 44 | `ordinal_numbers` | bool | `#!py3 True` | Add syntax for ordinal numbers. 45 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/striphtml.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_striphtml]{: .source-link } 2 | 3 | # StripHTML 4 | 5 | ## Overview 6 | 7 | StripHTML (formally known as PlainHTML) is a simple extension that is run at the end of post-processing. It searches 8 | the final output stripping out unwanted comments and/or tag attributes. Though it does its best to be loaded at the very 9 | end of the process, it helps to include this one last when loading up your extensions. 10 | 11 | ```text title="Stripping Comments" 12 | 14 | 15 | Here is a test. 16 | ``` 17 | 18 | /// html | div.result 19 | ```html 20 |

Here is a test.

21 | ``` 22 | /// 23 | 24 | Because comments aren't stripped until the end in a post-processing step, they are present throughout the entire 25 | Markdown conversion process and could possibly affect parsing, so be careful how you generally insert comments. 26 | 27 | /// warning 28 | This is not meant to be a sanitizer for HTML. This is just meant to try and strip out style, script, classes, etc. 29 | to provide a plain HTML output for the times this is desired; this is not meant as a security extension. If you 30 | want something to secure the output, you should consider running a sanitizer like [Bleach][bleach]. 31 | /// 32 | 33 | The StripHTML extension can be included in Python Markdown by using the following: 34 | 35 | ```py3 36 | import markdown 37 | md = markdown.Markdown(extensions=['pymdownx.striphtml']) 38 | ``` 39 | 40 | ## Options 41 | 42 | By default, StripHTML strips the following attributes: `style`, `id`, `class`, and `on`. StripHTML also strips 43 | HTML comments. If desired, its behavior can be configured to strip less or even more, but it is limited to attributes 44 | and comments. 45 | 46 | Option | Type | Default | Description 47 | ------------------------ |--------- | ------------ | ----------- 48 | `strip_comments` | bool | `#!py3 True` | Strip HTML comments during post process. 49 | `strip_js_on_attributes` | bool | `#!py3 True` | Strip JavaScript script attributes with the pattern on* during post process. 50 | `strip_attributes` | [string] | `#!py3 []` | A list of tag attribute names to strip. 51 | -------------------------------------------------------------------------------- /docs/src/markdown/extensions/tilde.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_tilde]{: .source-link } 2 | 3 | # Tilde 4 | 5 | ## Overview 6 | 7 | Tilde optionally adds two different features which are syntactically built around the `~` character: **delete** which 8 | inserts `#!html ` tags and **subscript** which inserts `#!html ` tags. 9 | 10 | The Tilde extension can be included in Python Markdown by using the following: 11 | 12 | ```py3 13 | import markdown 14 | md = markdown.Markdown(extensions=['pymdownx.tilde']) 15 | ``` 16 | 17 | ## Delete 18 | 19 | To wrap content in a **delete** tag, simply surround the text with double `~`. You can also enable `smart_delete` in the 20 | [options](#options). Smart behavior of **delete** models that of [BetterEm](betterem.md#differences). 21 | 22 | ```text title="Delete" 23 | ~~Delete me~~ 24 | ``` 25 | 26 | /// html | div.result 27 | ~~Delete me~~ 28 | /// 29 | 30 | ## Subscript 31 | 32 | To denote a subscript, you can surround the desired content in single `~`. It uses Pandoc style logic, so if your 33 | subscript needs to have spaces, you must escape the spaces. 34 | 35 | ```text title="Subscript" 36 | CH~3~CH~2~OH 37 | 38 | text~a\ subscript~ 39 | ``` 40 | 41 | /// html | div.result 42 | CH~3~CH~2~OH 43 | 44 | text~a\ subscript~ 45 | /// 46 | 47 | ## Options 48 | 49 | Option | Type | Default | Description 50 | -------------- | ---- | ----------- | ----------- 51 | `smart_delete` | bool | `#!py3 True` | Use smart logic with delete characters. 52 | `delete` | bool | `#!py3 True` | Enable delete feature. 53 | `subscript` | bool | `#!py3 True` | Enable subscript feature. 54 | -------------------------------------------------------------------------------- /docs/src/markdown/extras/slugs.md: -------------------------------------------------------------------------------- 1 | [:octicons-file-code-24:][_slugs]{: .source-link } 2 | 3 | # Slugs 4 | 5 | ## Alternate Slugify 6 | 7 | Python Markdown's default slugify used to strip out all Unicode chars. While this is not necessarily true anymore, 8 | PyMdown Extensions offers a configurable slugify to help those with picker preferences. These are very simple slugify 9 | options. There are many slugify options out there, some of which are very sophisticated. Some may prefer using one of 10 | those, but if you just want something simple, this might fill that requirement. 11 | 12 | ## Using Slugify 13 | 14 | `slugify` is a simple Unicode slugify option. It takes various parameters to control how casing is performed in slugs, 15 | what kind of Unicode normalization is preferred, and whether percent encoding of Unicode is preferred. 16 | 17 | The available key word options are found below: 18 | 19 | Parameter | Default | Description 20 | ---------------- | -------------- | ----------- 21 | `case` | `#!py3 'none'` | Control case normalization of characters. See case options below. 22 | `percent_encode` | `#!py3 False` | Percent encode all Unicode characters after case normalization. 23 | `normalize` | `#!py3 'NFC'` | Unicode normalization method. For instance, `NFD` will strip diacritics, but `NFC` does not. 24 | 25 | Case options are described below: 26 | 27 | Option | Description 28 | ------------- | ----------- 29 | `none` | Performs no case normalization preserving whatever case is provided. 30 | `lower` | Performs simple lower casing on the slug which will operate on Unicode and ASCII alike. 31 | `lower-ascii` | Performs simple lower casing on only ASCII upper case characters. 32 | `fold` | Applies Python's case folding function on the slug. 33 | 34 | Configuration is straight forward. Simply import the slug module and configure how you desire the Toc's extension to 35 | utilize the slugs. 36 | 37 | ```py 38 | extension = ['markdown.extensions.toc'] 39 | extension_configs = { 40 | 'markdown.extensions.toc': { 41 | "slugify": slugs.slugify(case="lower", percent_encode=True) 42 | } 43 | } 44 | ``` 45 | 46 | If you are using something like [MkDocs][mkdocs], check out our [FAQ](../faq.md#function-references-in-yaml) which gives 47 | guidance on how to specify configurable functions in the YAML configuration. 48 | -------------------------------------------------------------------------------- /docs/src/markdown/images/mermaid-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/docs/src/markdown/images/mermaid-diagram.png -------------------------------------------------------------------------------- /docs/src/markdown/images/progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/docs/src/markdown/images/progress.png -------------------------------------------------------------------------------- /docs/src/markdown/images/tabbed-alternate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/docs/src/markdown/images/tabbed-alternate.png -------------------------------------------------------------------------------- /docs/src/markdown/images/tabbed-default-narrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/docs/src/markdown/images/tabbed-default-narrow.png -------------------------------------------------------------------------------- /docs/src/markdown/images/tabbed-default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/docs/src/markdown/images/tabbed-default.png -------------------------------------------------------------------------------- /docs/src/markdown/index.md: -------------------------------------------------------------------------------- 1 | # PyMdown Extensions 2 | 3 | ## Overview 4 | 5 | PyMdown Extensions is a collection of extensions for Python Markdown. They were originally written to make writing 6 | documentation more enjoyable. They cover a wide range of solutions, and while not every extension is needed by all 7 | people, there is usually at least one useful extension for everybody. 8 | 9 | ## Usage 10 | 11 | All extensions are found under the module namespace of `pymdownx`. Assuming we wanted to specify the use of the 12 | MagicLink extension, we would include it in Python Markdown like so: 13 | 14 | ```pycon3 15 | >>> import markdown 16 | >>> text = "A link https://google.com" 17 | >>> html = markdown.markdown(text, extensions=['pymdownx.magiclink']) 18 | '

A link https://google.com

' 19 | ``` 20 | 21 | Check out documentation on each extension to learn more about how to configure and use each one. 22 | 23 | /// danger | Reminder 24 | Please read the [Usage Notes](usage_notes.md) for information on extension compatibility and general notes to be 25 | aware of when using these extensions. 26 | /// 27 | 28 | ## Extensions 29 | 30 |   | Extensions |   31 | -------------------------------------------- | ---------------------------------------- | ------ 32 | [Arithmatex](extensions/arithmatex.md) | [B64](extensions/b64.md) | [BetterEm](extensions/betterem.md) 33 | [Blocks](extensions/blocks/index.md) | [Caret](extensions/caret.md) | [Critic](extensions/critic.md) 34 | [Details](extensions/details.md) | [Emoji](extensions/emoji.md) | [EscapeAll](extensions/escapeall.md) 35 | [Extra](extensions/extra.md) | [Highlight](extensions/highlight.md) | [InlineHilite](extensions/inlinehilite.md) 36 | [Keys](extensions/keys.md) | [MagicLink](extensions/magiclink.md) | [Mark](extensions/mark.md) 37 | [PathConverter](extensions/pathconverter.md) | [ProgressBar](extensions/progressbar.md) | [SaneHeaders](extensions/saneheaders.md) 38 | [SmartSymbols](extensions/smartsymbols.md) | [Snippets](extensions/snippets.md) | [StripHTML](extensions/striphtml.md) 39 | [SuperFences](extensions/superfences.md) | [Tabbed](extensions/tabbed.md) | [Tasklist](extensions/tasklist.md) 40 | [Tilde](extensions/tilde.md) | | 41 | -------------------------------------------------------------------------------- /docs/src/markdown/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Requirements 4 | 5 | In order for PyMdown Extensions to work, there are a couple of prerequisites. 6 | 7 | Name | Required | Details 8 | ---------------------------------- | -------- | ------- 9 | [Python Markdown][python-markdown] | Yes | Python Markdown must be installed as it is the Markdown parser that is being used. 10 | [Pygments (optional)][pygments] | No | If Pygments Syntax highlighting is desired, Pygments must be installed. This can be omitted, and code blocks will be formatted for use with JavaScript code highlighters. 11 | 12 | ## Installation 13 | 14 | Installation is easy with pip: 15 | 16 | ```console 17 | $ pip install pymdown-extensions 18 | ``` 19 | 20 | If you want to manually install it, run: 21 | 22 | ```console 23 | $ python setup.py build 24 | $ python setup.py install 25 | ``` 26 | 27 | After installing, you should be able to access the extensions in Python Markdown under the namespace 28 | `pymdownx.`. 29 | 30 | If you would like to modify the code, you can install it via: 31 | 32 | ```console 33 | $ pip install --editable . 34 | ``` 35 | 36 | This method will allow you to instantly see your changes without reinstalling. If you want to do this in a virtual 37 | environment, you can. 38 | -------------------------------------------------------------------------------- /docs/src/markdown/usage_notes.md: -------------------------------------------------------------------------------- 1 | # Usage Notes 2 | 3 | ## Incompatible Extensions 4 | 5 | PyMdown Extensions includes three extensions that are meant to **replace** their counterpart in the default Python 6 | Markdown extensions. You don't have to use all of PyMdown Extensions' extensions, but if you choose to use one of the 7 | packages below, you should use it instead of the Python Markdown one; **they cannot be loaded at the same time**. 8 | 9 | Also, you shouldn't include an extension more than once. If you try to include more than one extension at the same time, 10 | you may get unexpected results. Also, be aware of that some of the extensions are convenience extensions that include 11 | multiple extensions; be aware of what they include so you do not accidentally re-include them individually. 12 | 13 | - `pymdownx.superfences` replaces `markdown.extensions.fenced_code`. 14 | 15 | - `pymdownx.betterem` replaces `markdown.extensions.smartstrong`. 16 | 17 | - `pymdownx.extra` replaces `markdown.extensions.extra`, but remember, `pymdown.extra` is a convenience extension 18 | which is just a wrapper and includes a number of extensions. Remember to avoid including this and then including 19 | conflicting extensions or doubles of extensions. Here is the full list of included extensions: 20 | 21 | ``` 22 | pymdownx.betterem 23 | pymdownx.superfences 24 | markdown.extensions.footnotes 25 | markdown.extensions.attr_list 26 | markdown.extensions.def_list 27 | markdown.extensions.tables 28 | markdown.extensions.abbr 29 | markdown.extensions.md_in_html 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/src/scss/_config.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Copyright (c) 2016-2020 Martin Donath 3 | /// 4 | /// Permission is hereby granted, free of charge, to any person obtaining a 5 | /// copy of this software and associated documentation files (the "Software"), 6 | /// to deal in the Software without restriction, including without limitation 7 | /// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | /// and/or sell copies of the Software, and to permit persons to whom the 9 | /// Software is furnished to do so, subject to the following conditions: 10 | /// 11 | /// The above copyright notice and this permission notice shall be included in 12 | /// all copies or substantial portions of the Software. 13 | /// 14 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | /// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | /// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | /// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | /// DEALINGS 21 | //// 22 | 23 | // ---------------------------------------------------------------------------- 24 | // Variables: breakpoints 25 | // ---------------------------------------------------------------------------- 26 | 27 | // Device-specific breakpoints 28 | $break-devices: ( 29 | mobile: ( 30 | portrait: px2em(220px) px2em(479px), 31 | landscape: px2em(480px) px2em(719px) 32 | ), 33 | tablet: ( 34 | portrait: px2em(720px) px2em(959px), 35 | landscape: px2em(960px) px2em(1219px) 36 | ), 37 | screen: ( 38 | small: px2em(1220px) px2em(1599px), 39 | medium: px2em(1600px) px2em(1999px), 40 | large: px2em(2000px) 41 | ) 42 | ); 43 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_arithmatex.scss: -------------------------------------------------------------------------------- 1 | mjx-container[display=true] { 2 | font-size: 120% !important; 3 | } 4 | 5 | mjx-container:not([display]) { 6 | font-size: 100% !important; 7 | } 8 | 9 | [data-md-color-scheme="slate"], 10 | [data-md-color-scheme="dracula"] { 11 | /* stylelint-disable selector-class-pattern */ 12 | .CtxtMenu_InfoSignature input, 13 | .CtxtMenu_InfoContent pre { 14 | color: rgb(0, 0, 0); 15 | } 16 | .CtxtMenu_Info, 17 | .CtxtMenu_Menu { 18 | box-shadow: 0px 10px 20px rgb(0 0 0 / 0.5); 19 | } 20 | /* stylelint-enable selector-class-pattern */ 21 | } 22 | 23 | .md-typeset .arithmatex { 24 | overflow-x: auto !important; 25 | overflow-y: hidden !important; 26 | } 27 | 28 | // Fix tag overlap in `KaTeX` 29 | .katex-display { 30 | .katex-html { 31 | display: flex !important; 32 | flex-direction: row; 33 | flex-wrap: nowrap; 34 | align-items: baseline; 35 | justify-content: space-between; 36 | // overflow-x: auto; 37 | 38 | .base { 39 | display: inline !important; 40 | } 41 | 42 | .tag { 43 | position: relative !important; 44 | display: inline !important; 45 | margin-left: var(--margin-small); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_critic.scss: -------------------------------------------------------------------------------- 1 | /* Don't use box shadows */ 2 | .md-typeset { 3 | del, 4 | ins, 5 | mark { 6 | &.critic { 7 | padding: 0 px2em(4px, 16px); 8 | color: unset; 9 | box-shadow: none; 10 | } 11 | } 12 | 13 | .critic.break { 14 | margin: 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_details.scss: -------------------------------------------------------------------------------- 1 | /* Inherit admonition style */ 2 | .md-typeset { 3 | details { 4 | @extend .admonition; 5 | 6 | overflow: hidden; 7 | 8 | // Title 9 | > summary { 10 | @extend .admonition-title; 11 | 12 | // Disable accessibility focus 13 | &:focus { 14 | outline-style: none; 15 | } 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_keys.scss: -------------------------------------------------------------------------------- 1 | .md-typeset { 2 | 3 | // Keyboard key 4 | .keys { 5 | 6 | // Define keyboard keys with left icon 7 | @each $name, $code in ( 8 | // Extra Keys 9 | "power": "\23FB", 10 | "fingerprint": "\261D", 11 | ) { 12 | .key-#{$name}::before { 13 | padding-right: px2em(6.4px); 14 | content: $code; 15 | } 16 | } 17 | 18 | // Define keyboard keys with right icon 19 | @each $name, $code in ( 20 | // Extra Keys 21 | ) { 22 | .key-#{$name}::after { 23 | padding-left: px2em(6.4px); 24 | content: $code; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_magiclink.scss: -------------------------------------------------------------------------------- 1 | // General styling for repository link icons 2 | :root > * { 3 | --magiclink-email-icon: svg-load("@mdi/svg/svg/mail.svg"); 4 | --magiclink-github-icon: svg-load("@mdi/svg/svg/github.svg"); 5 | --magiclink-bitbucket-icon: svg-load("@mdi/svg/svg/bitbucket.svg"); 6 | --magiclink-gitlab-icon: svg-load("@mdi/svg/svg/gitlab.svg"); 7 | --magiclink-commit-icon: svg-load("@primer/octicons/build/svg/git-commit-24.svg"); 8 | --magiclink-compare-icon: svg-load("@primer/octicons/build/svg/file-diff-24.svg"); 9 | --magiclink-pull-icon: svg-load("@primer/octicons/build/svg/git-pull-request-24.svg"); 10 | --magiclink-issue-icon: svg-load("@primer/octicons/build/svg/issue-opened-24.svg"); 11 | --magiclink-discussion-icon: svg-load("@primer/octicons/build/svg/comment-discussion-24.svg"); 12 | } 13 | 14 | .md-typeset { 15 | a[href^="mailto:"]:not(.magiclink-ignore)::before { 16 | mask-image: var(--magiclink-email-icon); 17 | } 18 | 19 | .magiclink-repository, 20 | .magiclink-compare, 21 | .magiclink-commit, 22 | .magiclink-pull, 23 | .magiclink-issue, 24 | .magiclink-discussion, 25 | a[href^="mailto:"] { 26 | &:not(.magiclink-ignore) { 27 | position: relative; 28 | padding-left: px2em(22px); 29 | 30 | &::before { 31 | position: absolute; 32 | top: 0; 33 | left: 0; 34 | display: block; 35 | box-sizing: border-box; 36 | width: px2em(20px); 37 | height: px2em(20px); 38 | background-color: var(--md-typeset-a-color); 39 | background-size: px2em(20px); 40 | transition: background-color 125ms; 41 | mask-repeat: no-repeat; 42 | mask-size: contain; 43 | content: ""; 44 | } 45 | 46 | &:hover::before { 47 | background-color: var(--md-accent-fg-color); 48 | } 49 | } 50 | } 51 | } 52 | 53 | // Assign icons to repository links 54 | @each $name, $icon in ( 55 | "commit": "commit", 56 | "compare": "compare", 57 | "pull": "pull", 58 | "issue": "issue", 59 | "discussion": "discussion" 60 | ) { 61 | .md-typeset { 62 | .magiclink-#{$name}:not(.magiclink-ignore) { 63 | &::before { 64 | mask-image: var(--magiclink-#{$icon}-icon); 65 | } 66 | } 67 | } 68 | } 69 | 70 | // Assign icons to repository links 71 | @each $name, $icon in ( 72 | "github": "github", 73 | "gitlab": "gitlab", 74 | "bitbucket": "bitbucket" 75 | ) { 76 | .md-typeset { 77 | .magiclink-repository.magiclink-#{$name}:not(.magiclink-ignore) { 78 | &::before { 79 | mask-image: var(--magiclink-#{$icon}-icon); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_mark.scss: -------------------------------------------------------------------------------- 1 | /* Shadow boxes sometimes give issues, so just pad. */ 2 | .md-typeset mark:not(.critic) { 3 | box-shadow: none; 4 | } 5 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_progressbar.scss: -------------------------------------------------------------------------------- 1 | .md-typeset { 2 | 3 | /* Progress Bars */ 4 | .progress-label { 5 | position: absolute; 6 | width: 100%; 7 | margin: 0; 8 | color: var(--md-text-color); 9 | font-weight: 700; 10 | line-height: px2rem(28px); 11 | white-space: nowrap; 12 | text-align: center; 13 | text-shadow: 14 | px2em(-1px) px2em(-1px) px2em(6px) var(--md-default-bg-color--light), 15 | px2em(1px) px2em(-1px) px2em(6px) var(--md-default-bg-color--light), 16 | px2em(-1px) px2em(1px) px2em(6px) var(--md-default-bg-color--light), 17 | px2em(1px) px2em(1px) px2em(6px) var(--md-default-bg-color--light); 18 | } 19 | 20 | .progress-bar { 21 | float: left; 22 | height: px2rem(24px); 23 | background-color: $clr-blue-a400; 24 | } 25 | 26 | /* Stripe animation */ 27 | .candystripe-animate { 28 | .progress-bar{ 29 | animation: animate-stripes 3s linear infinite; 30 | } 31 | } 32 | 33 | .progress { 34 | position: relative; 35 | display: block; 36 | width: 100%; 37 | height: px2rem(24px); 38 | margin: px2rem(10px) 0; 39 | background-color: var(--md-default-fg-color--lightest); 40 | 41 | &.thin { 42 | height: px2rem(8px); 43 | margin-top: px2rem(18px); 44 | 45 | .progress-label { 46 | margin-top: px2rem(-8px); 47 | } 48 | 49 | .progress-bar { 50 | height: px2rem(8px); 51 | } 52 | } 53 | 54 | &.candystripe .progress-bar { 55 | background-image: 56 | linear-gradient( 57 | 135deg, 58 | var(--md-progress-stripe) 27%, 59 | transparent 27%, 60 | transparent 52%, 61 | var(--md-progress-stripe) 52%, 62 | var(--md-progress-stripe) 77%, 63 | transparent 77%, 64 | transparent 65 | ); 66 | background-size: px2rem(40px) px2rem(40px); 67 | } 68 | } 69 | 70 | @each $percent, $color in ( 71 | "100": var(--md-progress-100), 72 | "80": var(--md-progress-80), 73 | "60": var(--md-progress-60), 74 | "40": var(--md-progress-40), 75 | "20": var(--md-progress-20), 76 | "0": var(--md-progress-0) 77 | ) { 78 | .progress-#{$percent}plus { 79 | .progress-bar { 80 | background-color: $color; 81 | } 82 | } 83 | } 84 | 85 | @keyframes animate-stripes { 86 | 0% { 87 | background-position: 0 0; 88 | } 89 | 90 | 100% { 91 | background-position: px2rem(120px) 0; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_superfences.scss: -------------------------------------------------------------------------------- 1 | /* Special handling of Mermaid content. */ 2 | diagram-div { 3 | overflow: auto; 4 | } 5 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_tabbed.scss: -------------------------------------------------------------------------------- 1 | /* Dark mode changes */ 2 | [data-md-color-scheme="dracula"] { 3 | .md-typeset { 4 | .tabbed-set > .tabbed-labels { 5 | box-shadow: 0 px2rem(-1px) var(--md-default-fg-color--lighter) inset; 6 | } 7 | } 8 | } 9 | 10 | /* Style code blocks to fill full tab, 11 | but otherwise, pad content. */ 12 | .md-typeset { 13 | .tabbed-alternate { 14 | &.tabbed-set .tabbed-control { 15 | width: px2rem(40px); 16 | 17 | &[hidden] { 18 | width: px2rem(24px); 19 | opacity: 0; 20 | } 21 | } 22 | 23 | &.tabbed-set > .tabbed-content > .tabbed-block { 24 | padding: 0 px2rem(12px); 25 | 26 | > { 27 | pre, 28 | .codehilite, 29 | .codehilitetable, 30 | .highlight, 31 | .highlighttable { 32 | 33 | &:only-child { 34 | margin-right: px2rem(-24px); 35 | margin-left: px2rem(-24px); 36 | padding-right: px2rem(12px); 37 | padding-left: px2rem(12px); 38 | 39 | span.filename { 40 | margin-top: 0; 41 | } 42 | } 43 | } 44 | 45 | .collapse-code:only-child { 46 | margin-top: 0; 47 | 48 | margin-right: px2rem(-24px); 49 | margin-left: px2rem(-24px); 50 | padding-right: px2rem(12px); 51 | padding-left: px2rem(12px); 52 | 53 | > .code-footer { 54 | left: px2rem(12px) 55 | } 56 | } 57 | 58 | diagram-div:only-child { 59 | margin-right: px2rem(-24px); 60 | margin-left: px2rem(-24px); 61 | padding-right: px2rem(12px); 62 | padding-left: px2rem(12px); 63 | } 64 | } 65 | } 66 | } 67 | } 68 | 69 | .js .md-typeset .tabbed-labels::before { 70 | background-color: var(--md-accent-fg-color); 71 | } 72 | 73 | /* Ignore mobile overflow styling that extends the tab bar */ 74 | @include break-to-device(mobile) { 75 | [dir=ltr] .md-content__inner > .tabbed-set .tabbed-labels { 76 | padding-left: 0; 77 | } 78 | 79 | .md-content__inner > .tabbed-set .tabbed-labels { 80 | max-width: 100%; 81 | margin: 0; 82 | padding-inline-start: 0; 83 | scroll-padding-inline-start: 0; 84 | 85 | &::after { 86 | padding-inline-end: 0; 87 | content: none; 88 | } 89 | 90 | // Tabbed control previous 91 | ~ .tabbed-control--prev { 92 | margin-inline-start: 0; 93 | padding-inline-start: 0; 94 | } 95 | 96 | // Tabbed control next 97 | ~ .tabbed-control--next { 98 | margin-inline-end: 0; 99 | padding-inline-end: 0; 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_tables.scss: -------------------------------------------------------------------------------- 1 | /* Dark mode changes */ 2 | [data-md-color-scheme="dracula"] { 3 | .md-typeset table:not([class]) { 4 | box-shadow: var(--md-shadow-z2); 5 | 6 | tr:hover { 7 | background-color: rgba(0,0,0,.08); 8 | } 9 | 10 | th { 11 | color: var(--md-text-color); 12 | background-color: var(--md-default-bg-color--ultra-dark); 13 | border-bottom: px2rem(1px) solid var(--md-primary-fg-color); 14 | } 15 | 16 | td { 17 | border-top: px2rem(1px) solid var(--md-default-fg-color--lighter); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_tasklist.scss: -------------------------------------------------------------------------------- 1 | /* Dark mode changes */ 2 | [data-md-color-scheme="dracula"] { 3 | .md-typeset .task-list-control { 4 | .task-list-indicator::before { 5 | background-color: var(--md-default-fg-color--lighter); 6 | } 7 | 8 | [type=checkbox]:checked + .task-list-indicator::before { 9 | background-color: $drac-green; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /docs/src/scss/extensions/_toc.scss: -------------------------------------------------------------------------------- 1 | // Header anchors 2 | .md-typeset { 3 | .headerlink { 4 | width: px2em(16px); 5 | height: px2em(16px); 6 | vertical-align: middle; 7 | background-color: var(--md-default-fg-color--lighter); 8 | background-size: px2em(16px); 9 | mask-size: px2em(16px); 10 | mask-repeat: no-repeat; 11 | visibility: visible; 12 | mask-image: svg-load("@mdi/svg/svg/link.svg"); 13 | } 14 | 15 | .headerlink:hover, 16 | [id]:target .headerlink { 17 | background-color: var(--md-accent-fg-color); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /docs/src/scss/extra.scss: -------------------------------------------------------------------------------- 1 | @import "material-color"; 2 | @import "material-shadows"; 3 | 4 | @import "utilities/break"; 5 | @import "utilities/convert"; 6 | @import "utilities/color_tools"; 7 | 8 | @import "config"; 9 | 10 | @import "palette/colors"; 11 | 12 | @import "general"; 13 | 14 | @import "extensions/admonition"; 15 | @import "extensions/arithmatex"; 16 | @import "extensions/critic"; 17 | @import "extensions/details"; 18 | @import "extensions/highlight"; 19 | @import "extensions/keys"; 20 | @import "extensions/magiclink"; 21 | @import "extensions/mark"; 22 | @import "extensions/progressbar"; 23 | @import "extensions/tabbed"; 24 | @import "extensions/tables"; 25 | @import "extensions/tasklist"; 26 | @import "extensions/toc"; 27 | @import "extensions/superfences"; 28 | 29 | @import "material"; 30 | -------------------------------------------------------------------------------- /docs/src/scss/palette/_dracula.scss: -------------------------------------------------------------------------------- 1 | $drac-fg: hsl(60, 30%, 96%); 2 | $drac-bg: hsl(231, 15%, 18%); 3 | $drac-highlight: hsl(66, 94%, 73%); 4 | $drac-selection: hsl(231, 25%, 25%); 5 | $drac-blue: hsl(225, 27%, 51%); 6 | $drac-cyan: hsl(191, 97%, 77%); 7 | $drac-green: hsl(135, 94%, 65%); 8 | $drac-orange: hsl(31, 100%, 71%); 9 | $drac-pink: hsl(326, 100%, 74%); 10 | $drac-purple: hsl(265, 89%, 78%); 11 | $drac-red: hsl(0, 100%, 67%); 12 | $drac-yellow: hsl(65, 92%, 76%); 13 | 14 | // Non-standard Dracula colors 15 | $drac-grey: hsl(225, 8%, 51%); 16 | $drac-teal: hsl(161, 97%, 77%); 17 | $drac-light-blue: hsl(190, 94%, 87%); 18 | $drac-light-green: hsl(135, 92%, 79%); 19 | $drac-dark-pink: hsl(325, 100%, 64%); 20 | $drac-dark-red: hsl(0, 100%, 59%); 21 | $drac-dark-yellow: hsl(51, 94%, 73%); 22 | 23 | $drac-default-bg: lighten($drac-bg, 5%); 24 | -------------------------------------------------------------------------------- /docs/src/scss/utilities/_color_tools.scss: -------------------------------------------------------------------------------- 1 | @function tint($color, $percentage) { 2 | @return mix(white, $color, $percentage); 3 | } 4 | 5 | 6 | @function shade($color, $percentage) { 7 | @return mix(black, $color, $percentage); 8 | } 9 | -------------------------------------------------------------------------------- /docs/src/scss/utilities/_convert.scss: -------------------------------------------------------------------------------- 1 | //// 2 | /// Copyright (c) 2016-2020 Martin Donath 3 | /// 4 | /// Permission is hereby granted, free of charge, to any person obtaining a 5 | /// copy of this software and associated documentation files (the "Software"), 6 | /// to deal in the Software without restriction, including without limitation 7 | /// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | /// and/or sell copies of the Software, and to permit persons to whom the 9 | /// Software is furnished to do so, subject to the following conditions: 10 | /// 11 | /// The above copyright notice and this permission notice shall be included in 12 | /// all copies or substantial portions of the Software. 13 | /// 14 | /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | /// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 17 | /// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | /// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | /// DEALINGS 21 | //// 22 | 23 | @use "sass:math"; 24 | 25 | // ---------------------------------------------------------------------------- 26 | // Helpers 27 | // ---------------------------------------------------------------------------- 28 | 29 | /// 30 | /// Convert color in HEX to HSL 31 | /// 32 | @function hex2hsl($color) { 33 | @return 34 | round(hue($color)), 35 | round(saturation($color)), 36 | round(lightness($color)); 37 | } 38 | 39 | // ---------------------------------------------------------------------------- 40 | 41 | /// 42 | /// Convert font size in px to em 43 | /// 44 | @function px2em($size, $base: 16px) { 45 | @if unit($size) == px { 46 | @if unit($base) == px { 47 | @return math.div($size, $base) * 1em; 48 | } @else { 49 | @error "Invalid base: #{$base} - unit must be 'px'"; 50 | } 51 | } @else { 52 | @error "Invalid size: #{$size} - unit must be 'px'"; 53 | } 54 | } 55 | 56 | /// 57 | /// Convert font size in px to rem 58 | /// 59 | @function px2rem($size, $base: 20px) { 60 | @if unit($size) == px { 61 | @if unit($base) == px { 62 | @return math.div($size, $base) * 1.0rem; 63 | } @else { 64 | @error "Invalid base: #{$base} - unit must be 'px'"; 65 | } 66 | } @else { 67 | @error "Invalid size: #{$size} - unit must be 'px'"; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /docs/theme/announce.html: -------------------------------------------------------------------------------- 1 | Sponsorship 2 | is now available! 3 | 4 | {% set icon = "octicons/heart-fill-16" %} 5 | {% include ".icons/" ~ icon ~ ".svg" %} 6 | 7 | -------------------------------------------------------------------------------- /docs/theme/assets/pymdownx-extras/material-extra-theme-2ek1P7jT.js: -------------------------------------------------------------------------------- 1 | !function(){"use strict";var e;e=function(e){"true"===localStorage.getItem("data-md-prefers-color-scheme")&&document.querySelector("body").setAttribute("data-md-color-scheme",e.matches?"dracula":"default")},new MutationObserver((function(t){t.forEach((function(t){if("childList"===t.type&&t.addedNodes.length)for(var a=0;a 14 |
15 | 16 | 17 | {% set icon = "octicons/heart-fill-16" %} 18 | {% include ".icons/" ~ icon ~ ".svg" %} 19 | 20 | 21 |
22 | 23 | {% endif %} 24 | {% endblock %} 25 | -------------------------------------------------------------------------------- /docs/theme/partials/footer.html: -------------------------------------------------------------------------------- 1 | 2 | {% import "partials/language.html" as lang with context %} 3 | 70 | -------------------------------------------------------------------------------- /docs/theme/partials/libs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /hatch_build.py: -------------------------------------------------------------------------------- 1 | """Dynamically define some metadata.""" 2 | import os 3 | from hatchling.metadata.plugin.interface import MetadataHookInterface 4 | 5 | 6 | def get_version_dev_status(root): 7 | """Get version_info without importing the entire module.""" 8 | 9 | import importlib.util 10 | 11 | path = os.path.join(root, "pymdownx", "__meta__.py") 12 | spec = importlib.util.spec_from_file_location("__meta__", path) 13 | module = importlib.util.module_from_spec(spec) 14 | spec.loader.exec_module(module) 15 | return module.__version_info__._get_dev_status() 16 | 17 | 18 | class CustomMetadataHook(MetadataHookInterface): 19 | """Our metadata hook.""" 20 | 21 | def update(self, metadata): 22 | """See https://ofek.dev/hatch/latest/plugins/metadata-hook/ for more information.""" 23 | 24 | metadata["classifiers"] = [ 25 | f"Development Status :: {get_version_dev_status(self.root)}", 26 | "Environment :: Console", 27 | "Intended Audience :: Developers", 28 | "License :: OSI Approved :: MIT License", 29 | "Operating System :: OS Independent", 30 | "Programming Language :: Python :: 3", 31 | "Programming Language :: Python :: 3.8", 32 | "Programming Language :: Python :: 3.9", 33 | "Programming Language :: Python :: 3.10", 34 | "Programming Language :: Python :: 3.11", 35 | "Programming Language :: Python :: 3.12", 36 | "Programming Language :: Python :: 3.13", 37 | "Topic :: Internet :: WWW/HTTP :: Dynamic Content", 38 | "Topic :: Software Development :: Libraries :: Python Modules", 39 | "Topic :: Text Processing :: Filters", 40 | "Topic :: Text Processing :: Markup :: HTML", 41 | ] 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pymdown-extensions", 3 | "version": "8.1.2", 4 | "description": "Extensions for Python Markdown", 5 | "repository": "https://github.com/facelessuser/pymdown-extensions.git", 6 | "author": "Isaac Muse ", 7 | "license": "MIT", 8 | "type": "module", 9 | "scripts": { 10 | "build": "node_modules/.bin/gulp build --compress --lint --buildmkdocs --revision --sourcemaps", 11 | "compile": "node_modules/.bin/gulp build --compress --buildmkdocs --revision", 12 | "clean_all": "node_modules/.bin/gulp clean", 13 | "serve": "node_modules/.bin/gulp serve", 14 | "lint": "node_modules/.bin/gulp lint" 15 | }, 16 | "engines": { 17 | "node": ">= 10", 18 | "yarn": "YARN NO LONGER USED - use npm instead." 19 | }, 20 | "devDependencies": { 21 | "@babel/cli": "^7.25.6", 22 | "@babel/core": "^7.25.2", 23 | "@babel/eslint-parser": "^7.25.1", 24 | "@babel/plugin-external-helpers": "^7.24.7", 25 | "@babel/preset-env": "^7.25.4", 26 | "@babel/register": "^7.24.6", 27 | "@fortawesome/fontawesome-free": "^6.6.0", 28 | "@mdi/svg": "^7.4.47", 29 | "@primer/octicons": "^19.11.0", 30 | "@rollup/plugin-babel": "^6.0.4", 31 | "@rollup/plugin-terser": "^0.4.4", 32 | "autoprefixer": "^10.4.20", 33 | "babel-core": "^7.0.0-bridge.0", 34 | "clean-css": "^5.3.3", 35 | "css-mqpacker": "^7.0.0", 36 | "del": "^7.1.0", 37 | "eslint": "^9.10.0", 38 | "gulp": "^5.0.0", 39 | "gulp-clean-css": "^4.3.0", 40 | "gulp-concat": "^2.6.1", 41 | "gulp-eslint": "^6.0.0", 42 | "gulp-if": "^3.0.0", 43 | "gulp-postcss": "^10.0.0", 44 | "gulp-replace": "^1.1.4", 45 | "gulp-rev": "^11.0.0", 46 | "gulp-rev-replace": "^0.4.4", 47 | "gulp-sass": "^5.1.0", 48 | "gulp-sourcemaps": "^3.0.0", 49 | "gulp-stylelint": "^13.0.0", 50 | "gulp-touch-fd": "github:funkedigital/gulp-touch-fd", 51 | "material-design-color": "^2.3.2", 52 | "material-shadows": "^3.0.1", 53 | "postcss-inline-svg": "^6.0.0", 54 | "postcss-pseudo-classes": "^0.4.0", 55 | "postcss-scss": "^4.0.9", 56 | "postcss-svgo": "^7.0.1", 57 | "promise": "^8.3.0", 58 | "rollup": "^4.21.2", 59 | "rollup-plugin-output-manifest": "^2.0.0", 60 | "sass": "^1.78.0", 61 | "stylelint": "^15.11.0", 62 | "stylelint-config-rational-order": "^0.1.2", 63 | "stylelint-config-standard": "^36.0.1", 64 | "stylelint-order": "^6.0.4", 65 | "stylelint-scss": "^6.5.1", 66 | "terser": "^5.31.6", 67 | "vinyl-paths": "^5.0.0", 68 | "yargs": "^17.7.2" 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /pymdownx/__init__.py: -------------------------------------------------------------------------------- 1 | """PyMdown extra extensions.""" 2 | from .__meta__ import __version__, __version_info__ # noqa: F401 3 | 4 | # Nothing to import with all 5 | __all__ = () 6 | -------------------------------------------------------------------------------- /pymdownx/_bypassnorm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Bypass whitespace normalization. 3 | 4 | pymdownx._bypassnorm 5 | 6 | Strips `SOH` and `EOT` characters before whitespace normalization 7 | allowing other extensions to then create preprocessors that stash HTML 8 | with `SOH` and `EOT` After whitespace normalization, all `SOH` and 9 | `EOT` characters will be converted to the Python Markdown standard 10 | `STX` and `ETX` convention since whitespace normalization usually 11 | strips out the `STX` and `ETX` characters. 12 | 13 | Copyright 2014 - 2018 Isaac Muse 14 | """ 15 | 16 | from markdown import Extension 17 | from markdown.util import STX, ETX 18 | from markdown.preprocessors import Preprocessor 19 | 20 | SOH = '\u0001' # start 21 | EOT = '\u0004' # end 22 | 23 | 24 | class PreNormalizePreprocessor(Preprocessor): 25 | """Preprocessor to remove workaround symbols.""" 26 | 27 | def run(self, lines): 28 | """Remove workaround placeholder markers before adding actual workaround placeholders.""" 29 | 30 | source = '\n'.join(lines) 31 | source = source.replace(SOH, '').replace(EOT, '') 32 | return source.split('\n') 33 | 34 | 35 | class PostNormalizePreprocessor(Preprocessor): 36 | """Preprocessor to clean up normalization bypass hack.""" 37 | 38 | def run(self, lines): 39 | """Convert alternate placeholder symbols to actual placeholder symbols.""" 40 | 41 | source = '\n'.join(lines) 42 | source = source.replace(SOH, STX).replace(EOT, ETX) 43 | return source.split('\n') 44 | 45 | 46 | class BypassNormExtension(Extension): 47 | """Bypass whitespace normalization.""" 48 | 49 | def __init__(self, *args, **kwargs): 50 | """Initialize.""" 51 | 52 | self.inlinehilite = [] 53 | self.config = {} 54 | super().__init__(*args, **kwargs) 55 | 56 | def extendMarkdown(self, md): 57 | """Add extensions that help with bypassing whitespace normalization.""" 58 | 59 | md.preprocessors.register(PreNormalizePreprocessor(md), "pymdownx-pre-norm-ws", 35) 60 | md.preprocessors.register(PostNormalizePreprocessor(md), "pymdownx-post-norm-ws", 29.9) 61 | 62 | 63 | def makeExtension(*args, **kwargs): 64 | """Return extension.""" 65 | 66 | return BypassNormExtension(*args, **kwargs) 67 | -------------------------------------------------------------------------------- /pymdownx/blocks/definition.py: -------------------------------------------------------------------------------- 1 | """Definition.""" 2 | import xml.etree.ElementTree as etree 3 | from .block import Block 4 | from ..blocks import BlocksExtension 5 | 6 | 7 | class Definition(Block): 8 | """ 9 | Definition. 10 | 11 | Converts non `ul`, `ol` blocks (ideally `p` tags) into `dt` 12 | and will convert first level `li` elements of `ul` and `ol` 13 | elements to `dd` tags. When done, the `ul`, and `ol` elements 14 | will be removed. 15 | """ 16 | 17 | NAME = 'define' 18 | 19 | def on_create(self, parent): 20 | """Create the element.""" 21 | 22 | return etree.SubElement(parent, 'dl') 23 | 24 | def on_end(self, block): 25 | """Convert non list items to details.""" 26 | 27 | remove = [] 28 | offset = 0 29 | for i, child in enumerate(list(block)): 30 | if child.tag.lower() in ('dt', 'dd'): 31 | continue 32 | 33 | elif child.tag.lower() not in ('ul', 'ol'): 34 | if child.tag.lower() == 'p': 35 | child.tag = 'dt' 36 | else: 37 | dt = etree.Element('dt') 38 | dt.append(child) 39 | block.insert(i + offset, dt) 40 | block.remove(child) 41 | else: 42 | for li in list(child): 43 | offset += 1 44 | li.tag = 'dd' 45 | block.insert(i + offset, li) 46 | child.remove(li) 47 | remove.append(child) 48 | 49 | for el in remove: 50 | block.remove(el) 51 | 52 | 53 | class DefinitionExtension(BlocksExtension): 54 | """Definition Blocks Extension.""" 55 | 56 | def extendMarkdownBlocks(self, md, block_mgr): 57 | """Extend Markdown blocks.""" 58 | 59 | block_mgr.register(Definition, self.getConfigs()) 60 | 61 | 62 | def makeExtension(*args, **kwargs): 63 | """Return extension.""" 64 | 65 | return DefinitionExtension(*args, **kwargs) 66 | -------------------------------------------------------------------------------- /pymdownx/extra.py: -------------------------------------------------------------------------------- 1 | """ 2 | Extra. 3 | 4 | pymdown.extra 5 | A wrapper that emulate PHP Markdown Extra. 6 | Re-packages Python Markdowns 'extra' extensions, 7 | but substitutes a few extensions with PyMdown extensions: 8 | 9 | - fenced_code --> superfences 10 | - smartstrong --> betterem 11 | 12 | MIT license. 13 | 14 | Copyright (c) 2015 - 2017 Isaac Muse 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 17 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation 18 | the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 19 | and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all copies or substantial portions 22 | of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 25 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 27 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 28 | DEALINGS IN THE SOFTWARE. 29 | """ 30 | from markdown import Extension 31 | 32 | extra_extensions = [ 33 | 'pymdownx.betterem', 34 | 'pymdownx.superfences', 35 | 'markdown.extensions.footnotes', 36 | 'markdown.extensions.attr_list', 37 | 'markdown.extensions.def_list', 38 | 'markdown.extensions.tables', 39 | 'markdown.extensions.abbr', 40 | 'markdown.extensions.md_in_html' 41 | ] 42 | 43 | extra_extension_configs = {} 44 | 45 | 46 | class ExtraExtension(Extension): 47 | """Add various extensions to Markdown class.""" 48 | 49 | def __init__(self, *args, **kwargs): 50 | """Initialize.""" 51 | 52 | self.config = kwargs.pop('configs', {}) 53 | self.config.update(extra_extension_configs) 54 | self.config.update(kwargs) 55 | 56 | def extendMarkdown(self, md): 57 | """Register extension instances.""" 58 | 59 | md.registerExtensions(extra_extensions, self.config) 60 | 61 | 62 | def makeExtension(*args, **kwargs): 63 | """Return extension.""" 64 | 65 | return ExtraExtension(*args, **kwargs) 66 | -------------------------------------------------------------------------------- /pymdownx/saneheaders.py: -------------------------------------------------------------------------------- 1 | """ 2 | Sane headers. 3 | 4 | Allow for a header implementation that requires `#` headers to have a space 5 | after the `#` portion. This allows for things like Magiclink issues to work 6 | at the beginning of lines, and potentially other things like tag extensions 7 | etc. 8 | """ 9 | import re 10 | from markdown import Extension 11 | from markdown.blockprocessors import HashHeaderProcessor 12 | 13 | 14 | class SaneHeadersProcessor(HashHeaderProcessor): 15 | """Process hash headers syntax.""" 16 | 17 | RE = re.compile(r'(?:^|\n)(?P#{1,6})(?=[ ])(?P
(?:\\.|[^\\])*?)#*(?:\n|$)') 18 | 19 | 20 | class SaneHeadersExtension(Extension): 21 | """Adds the sane headers extension.""" 22 | 23 | def extendMarkdown(self, md): 24 | """Extend the inline and block processor objects.""" 25 | 26 | md.parser.blockprocessors.register(SaneHeadersProcessor(md.parser), 'hashheader', 70) 27 | md.registerExtension(self) 28 | 29 | 30 | def makeExtension(*args, **kwargs): 31 | """Return extension.""" 32 | 33 | return SaneHeadersExtension(*args, **kwargs) 34 | -------------------------------------------------------------------------------- /requirements/dev.txt: -------------------------------------------------------------------------------- 1 | build 2 | tox 3 | -------------------------------------------------------------------------------- /requirements/docs.txt: -------------------------------------------------------------------------------- 1 | mkdocs_pymdownx_material_extras>=2.1 2 | pymdown_lexers @ git+https://github.com/facelessuser/pymdown-lexers.git 3 | mkdocs-git-revision-date-localized-plugin 4 | mkdocs-minify-plugin 5 | pyspelling 6 | -------------------------------------------------------------------------------- /requirements/lint.txt: -------------------------------------------------------------------------------- 1 | ruff 2 | -------------------------------------------------------------------------------- /requirements/test.txt: -------------------------------------------------------------------------------- 1 | PyYAML>=3.10 2 | pytest 3 | pytest-cov 4 | coverage 5 | -------------------------------------------------------------------------------- /requirements/tools.txt: -------------------------------------------------------------------------------- 1 | requests 2 | -------------------------------------------------------------------------------- /run_tests.py: -------------------------------------------------------------------------------- 1 | """Run the unittests or update unitest compare files.""" 2 | import argparse 3 | from tests import test_syntax 4 | from tests import test_targeted 5 | import sys 6 | import os 7 | 8 | 9 | def main(): 10 | """Main function.""" 11 | 12 | parser = argparse.ArgumentParser(prog='run_tests', description='Run extension tests.') 13 | # Flag arguments 14 | parser.add_argument('--update', '-u', action='store_true', default=False, help="Update expected HTML output.") 15 | parser.add_argument( 16 | '--test-target', '-t', nargs=1, action='store', default="", choices=['syntax', 'targeted'], 17 | help="Test specific enivronment." 18 | ) 19 | parser.add_argument( 20 | '--file', '-f', nargs=1, action='store', default="", help="Test or update specific test." 21 | ) 22 | args = parser.parse_args() 23 | sys.argv = sys.argv[0:1] 24 | 25 | if args.file: 26 | abs_path = os.path.abspath(args.file[0]) 27 | if os.path.exists(abs_path): 28 | test_syntax.set_target_file(abs_path) 29 | 30 | # Format and Viewing 31 | if args.update: 32 | for config, test in test_syntax.gather_test_params(): 33 | test_syntax.compare_results(config, test, args.update) 34 | else: 35 | if not args.test_target or args.test_target[0] == 'syntax': 36 | test_syntax.run() 37 | if not args.test_target or args.test_target[0] == 'targeted': 38 | test_targeted.run() 39 | 40 | 41 | if __name__ == '__main__': 42 | main() 43 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """Unit Tests.""" 2 | -------------------------------------------------------------------------------- /tests/extensions/_assets/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/tests/extensions/_assets/bg.png -------------------------------------------------------------------------------- /tests/extensions/_assets/headeranchor.css: -------------------------------------------------------------------------------- 1 | /* Header Anchors */ 2 | .markdown-body { 3 | padding-left: 30px; 4 | } 5 | 6 | .markdown-body .headeranchor-link { 7 | position: absolute; 8 | top: 0; 9 | bottom: 0; 10 | left: 0; 11 | display: block; 12 | padding-right: 6px; 13 | padding-left: 30px; 14 | margin-left: -30px; 15 | } 16 | 17 | .markdown-body .headeranchor-link:focus { 18 | outline: none; 19 | } 20 | 21 | .markdown-body h1, 22 | .markdown-body h2, 23 | .markdown-body h3, 24 | .markdown-body h4, 25 | .markdown-body h5, 26 | .markdown-body h6 { 27 | position: relative; 28 | } 29 | 30 | .markdown-body h1 .headeranchor, 31 | .markdown-body h2 .headeranchor, 32 | .markdown-body h3 .headeranchor, 33 | .markdown-body h4 .headeranchor, 34 | .markdown-body h5 .headeranchor, 35 | .markdown-body h6 .headeranchor { 36 | display: none; 37 | color: #000; 38 | vertical-align: middle; 39 | } 40 | 41 | .markdown-body h1:hover .headeranchor-link, 42 | .markdown-body h2:hover .headeranchor-link, 43 | .markdown-body h3:hover .headeranchor-link, 44 | .markdown-body h4:hover .headeranchor-link, 45 | .markdown-body h5:hover .headeranchor-link, 46 | .markdown-body h6:hover .headeranchor-link { 47 | height: 1em; 48 | padding-left: 8px; 49 | margin-left: -30px; 50 | line-height: 1; 51 | text-decoration: none; 52 | } 53 | 54 | .markdown-body h1:hover .headeranchor-link .headeranchor, 55 | .markdown-body h2:hover .headeranchor-link .headeranchor, 56 | .markdown-body h3:hover .headeranchor-link .headeranchor, 57 | .markdown-body h4:hover .headeranchor-link .headeranchor, 58 | .markdown-body h5:hover .headeranchor-link .headeranchor, 59 | .markdown-body h6:hover .headeranchor-link .headeranchor { 60 | display: inline-block; 61 | } 62 | 63 | .markdown-body .headeranchor { 64 | font-size: 16px; 65 | line-height: 1; 66 | display: inline-block; 67 | text-decoration: none; 68 | -webkit-font-smoothing: antialiased; 69 | -moz-osx-font-smoothing: grayscale; 70 | -webkit-user-select: none; 71 | -moz-user-select: none; 72 | -ms-user-select: none; 73 | user-select: none; 74 | } 75 | 76 | .headeranchor:before { 77 | content: '\00B6'; 78 | } 79 | -------------------------------------------------------------------------------- /tests/extensions/_assets/tabs.css: -------------------------------------------------------------------------------- 1 | .superfences-tabs { 2 | display: flex; 3 | position: relative; 4 | flex-wrap: wrap; 5 | } 6 | 7 | .superfences-tabs .highlight { 8 | background: #ddd; 9 | } 10 | 11 | .superfences-tabs .superfences-content { 12 | display: none; 13 | order: 99; 14 | width: 100%; 15 | } 16 | 17 | .superfences-tabs label { 18 | width: auto; 19 | margin: 0 0.5em; 20 | padding: 0.25em; 21 | font-size: 120%; 22 | cursor: pointer; 23 | } 24 | 25 | .superfences-tabs input { 26 | position: absolute; 27 | opacity: 0; 28 | } 29 | 30 | .superfences-tabs input:nth-child(n+1) { 31 | color: #333333; 32 | } 33 | 34 | .superfences-tabs input:nth-child(n+1):checked + label { 35 | color: #FF5252; 36 | } 37 | 38 | .superfences-tabs input:nth-child(n+1):checked + label + .superfences-content { 39 | display: block; 40 | } 41 | -------------------------------------------------------------------------------- /tests/extensions/_assets/tasklist.css: -------------------------------------------------------------------------------- 1 | .markdown-body .task-list-item { 2 | list-style-type: none; 3 | } 4 | 5 | .markdown-body .task-list-item input[type="checkbox"] { 6 | margin: 0 4px 0.25em -20px; 7 | vertical-align: middle; 8 | } 9 | -------------------------------------------------------------------------------- /tests/extensions/_assets/tasklist_custom.css: -------------------------------------------------------------------------------- 1 | .markdown-body .task-list-item { 2 | list-style-type: none; 3 | } 4 | 5 | .markdown-body .task-list-item input[type="checkbox"] { 6 | margin: 0 4px 0.25em -20px; 7 | vertical-align: middle; 8 | } 9 | 10 | .markdown-body .task-list-control { 11 | position: relative; 12 | display: inline-block; 13 | color: #555; 14 | cursor: pointer; 15 | } 16 | 17 | .markdown-body .task-list-control input[type="checkbox"] { 18 | position: absolute; 19 | opacity: 0; 20 | z-index: -1; /* Put the input behind the label so it doesn't overlay text */ 21 | } 22 | 23 | .markdown-body .task-list-indicator { 24 | position: absolute; 25 | top: -8px; 26 | left: -18px; 27 | display: block; 28 | width: 14px; 29 | height: 14px; 30 | color: #eee; 31 | background-color: #eee; 32 | border-radius: .25rem; 33 | } 34 | 35 | .markdown-body .task-list-control input[type="checkbox"]:checked + .task-list-indicator::before { 36 | display: block; 37 | margin-top: -4px; 38 | margin-left: 2px; 39 | font-size: 16px; 40 | line-height: 1; 41 | border-radius: 2px; 42 | content: "✔"; 43 | color: #1EBB52; 44 | } 45 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex (disable).html: -------------------------------------------------------------------------------- 1 |

$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j$

2 |

(3+3) 3 | \(3+3) 4 | \(3+3)

5 |

$$ 6 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 7 | $$

8 |

[ 9 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 10 | ]

11 |

$$ 12 | \begin{align} 13 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \ 14 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 15 | \end{align} 16 | $$

17 | 27 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex (disable).txt: -------------------------------------------------------------------------------- 1 | \$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j\$ 2 | 3 | \(3+3\) 4 | \\(3+3\) 5 | \\\(3+3\) 6 | 7 | $$ 8 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 9 | $$ 10 | 11 | \[ 12 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 13 | \] 14 | 15 | $$ 16 | \begin{align} 17 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 18 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 19 | \end{align} 20 | $$ 21 | 22 | 32 | 33 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex (generic).html: -------------------------------------------------------------------------------- 1 |

Dollar Sign Not Trigger

2 |

I have $3.00 and you have $5.00.

3 |

Dollar Sign Escape

4 |

$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j$

5 |

Dollar Sign Escaped Escape

6 |

\\(3+3\)

7 |

Dollar Double escaped escape

8 |

\$3+3$

9 |

Use Dollar sign

10 |

\(\$3.00 + \$5.00 = \$8.00\)

11 |

Keep equations separate

12 |

\(3+3\) 13 | \(3+3) 14 | \\(3+3\)

15 |

Equations

16 |
\[ 17 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 18 | \]
19 |
\[ 20 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 21 | \]
22 |
    23 |
  • 24 |

    Here are some more equations:

    25 |
    \[ 26 | \begin{align} 27 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 28 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 29 | \end{align} 30 | \]
    31 |
  • 32 |
  • 33 |

    Inline equations: \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\), \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\).

    34 |
  • 35 |
36 |

Code

37 |

$$ 38 | \begin{align} 39 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 40 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 41 | \end{align} 42 | $$

43 |

Indented Code

44 |
$$
45 |     \begin{align}
46 |         p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
47 |         p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
48 |     \end{align}
49 | $$
50 | 
51 | 65 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex (generic).txt: -------------------------------------------------------------------------------- 1 | # Dollar Sign Not Trigger 2 | I have $3.00 and you have $5.00. 3 | 4 | # Dollar Sign Escape 5 | \$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j\$ 6 | 7 | # Dollar Sign Escaped Escape 8 | \\$3+3$ 9 | 10 | # Dollar Double escaped escape 11 | \\\$3+3$ 12 | 13 | # Use Dollar sign 14 | $\$3.00 + \$5.00 = \$8.00$ 15 | 16 | # Keep equations separate 17 | 18 | \(3+3\) 19 | \\(3+3\) 20 | \\\(3+3\) 21 | 22 | # Equations 23 | 24 | $$ 25 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 26 | $$ 27 | 28 | \[ 29 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 30 | \] 31 | 32 | - Here are some more equations: 33 | 34 | $$ 35 | \begin{align} 36 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 37 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 38 | \end{align} 39 | $$ 40 | 41 | - Inline equations: $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\). 42 | 43 | # Code 44 | 45 | ``` 46 | $$ 47 | \begin{align} 48 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 49 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 50 | \end{align} 51 | $$ 52 | ``` 53 | 54 | 55 | # Indented Code 56 | 57 | $$ 58 | \begin{align} 59 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 60 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 61 | \end{align} 62 | $$ 63 | 64 | 78 | 79 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex (no-preview).html: -------------------------------------------------------------------------------- 1 |

Dollar Sign Not Trigger

2 |

I have $3.00 and you have $5.00.

3 |

Dollar Sign Escape

4 |

$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j$

5 |

Use Dollar sign

6 |

7 |

Dollar Sign Escaped Escape

8 |

\

9 |

Dollar Double escaped escape

10 |

\$3+3$

11 |

Keep equations separate

12 |

13 | \(3+3) 14 | \

15 |

Equations

16 |
17 | 20 |
21 |
22 | 25 |
26 |
    27 |
  • 28 |

    Here are some more equations:

    29 |
    30 | 36 |
    37 |
  • 38 |
  • 39 |

    Inline equations: , .

    40 |
  • 41 |
42 |

Code

43 |

$$ 44 | \begin{align} 45 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 46 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 47 | \end{align} 48 | $$

49 |

Indented Code

50 |
$$
51 |     \begin{align}
52 |         p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\
53 |         p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right)
54 |     \end{align}
55 | $$
56 | 
57 | 67 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex (no-preview).txt: -------------------------------------------------------------------------------- 1 | # Dollar Sign Not Trigger 2 | I have $3.00 and you have $5.00. 3 | 4 | # Dollar Sign Escape 5 | \$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j\$ 6 | 7 | # Use Dollar sign 8 | $\$3.00 + \$5.00 = \$8.00$ 9 | 10 | # Dollar Sign Escaped Escape 11 | \\$3+3$ 12 | 13 | # Dollar Double escaped escape 14 | \\\$3+3$ 15 | 16 | # Keep equations separate 17 | 18 | \(3+3\) 19 | \\(3+3\) 20 | \\\(3+3\) 21 | 22 | # Equations 23 | 24 | $$ 25 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 26 | $$ 27 | 28 | \[ 29 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 30 | \] 31 | 32 | - Here are some more equations: 33 | 34 | $$ 35 | \begin{align} 36 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 37 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 38 | \end{align} 39 | $$ 40 | 41 | - Inline equations: $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\). 42 | 43 | # Code 44 | 45 | ``` 46 | $$ 47 | \begin{align} 48 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 49 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 50 | \end{align} 51 | $$ 52 | ``` 53 | 54 | 55 | # Indented Code 56 | 57 | $$ 58 | \begin{align} 59 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 60 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 61 | \end{align} 62 | $$ 63 | 64 | 74 | 75 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/arithmatex.txt: -------------------------------------------------------------------------------- 1 | # Dollar Sign Not Trigger 2 | I have $3.00 and you have $5.00. 3 | 4 | # Dollar Sign Escape 5 | \$E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j\$ 6 | 7 | # Dollar Sign Escaped Escape 8 | \\$3+3$ 9 | 10 | # Dollar Double escaped escape 11 | \\\$3+3$ 12 | 13 | # Use Dollar sign 14 | $\$3.00 + \$5.00 = \$8.00$ 15 | 16 | # Keep equations separate 17 | 18 | \(3+3\) 19 | \\(3+3\) 20 | \\\(3+3\) 21 | 22 | # Equations 23 | 24 | $$ 25 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 26 | $$ 27 | 28 | \[ 29 | E(\mathbf{v}, \mathbf{h}) = -\sum_{i,j}w_{ij}v_i h_j - \sum_i b_i v_i - \sum_j c_j h_j 30 | \] 31 | 32 | - Here are some more equations: 33 | 34 | $$ 35 | \begin{align} 36 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 37 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 38 | \end{align} 39 | $$ 40 | 41 | - Inline equations: $p(x|y) = \frac{p(y|x)p(x)}{p(y)}$, \(p(x|y) = \frac{p(y|x)p(x)}{p(y)}\). 42 | 43 | # Code 44 | 45 | ``` 46 | $$ 47 | \begin{align} 48 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 49 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 50 | \end{align} 51 | $$ 52 | ``` 53 | 54 | 55 | # Indented Code 56 | 57 | $$ 58 | \begin{align} 59 | p(v_i=1|\mathbf{h}) & = \sigma\left(\sum_j w_{ij}h_j + b_i\right) \\ 60 | p(h_j=1|\mathbf{v}) & = \sigma\left(\sum_i w_{ij}v_i + c_j\right) 61 | \end{align} 62 | $$ 63 | 64 | 74 | 75 | -------------------------------------------------------------------------------- /tests/extensions/arithmatex/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | arithmatex: 4 | extensions: 5 | pymdownx.arithmatex: 6 | 7 | arithmatex (dumb dollar): 8 | extensions: 9 | pymdownx.arithmatex: 10 | generic: true 11 | smart_dollar: false 12 | 13 | arithmatex (generic): 14 | extensions: 15 | pymdownx.arithmatex: 16 | generic: true 17 | 18 | arithmatex (disable): 19 | extensions: 20 | pymdownx.arithmatex: 21 | block_syntax: [] 22 | inline_syntax: [] 23 | 24 | arithmatex (no-preview): 25 | extensions: 26 | pymdownx.arithmatex: 27 | preview: false 28 | -------------------------------------------------------------------------------- /tests/extensions/betterem/betterem (normal).html: -------------------------------------------------------------------------------- 1 |

Test: * Won't highlight *

2 |

Test: Will highlight

3 |

Test: I'm italic and bold I am just bold.

4 |

Test: I'm bold and italic! I am just italic.

5 |

Test: A lot of underscores____________is okay

6 |

Test: This will all be bold __because of the placement of the center underscores.

7 |

Test: This will all be bold __ because of the placement of the center underscores.

8 |

Test: This will NOT all be bold because of the placement of the center underscores.__

9 |

Test: This will all be bold_ because the token is less than that of the surrounding.

10 |

Test: This is text bold italic bold with more text

11 |

Test: All will * be italic

12 |

Test: All will *be italic

13 |

Test: All will not be italic*

14 |

Test: All will not ** be italic

15 |

Test: All will * be bold

16 |

Test: All will *be italic*

17 |

Test: All will not* be bold**

18 |

Test: All will not *** be bold

19 |

Test: This is text bold italic bold with more text

20 |

Test: test test test test

21 |

Test: test test *test*

22 |

Test: test * test

23 |

Test: test ** test

24 |

Test: test test test test

25 |

Test: test_ test _test

26 |

Test: test _ test

27 |

Test: test __ test

28 |

Test: test (test) test

29 |

Test: test (test) test

30 |

One asterisk: *

31 |

One underscore: _

32 |

Two asterisks: **

33 |

With spaces: * *

34 |

Two underscores __

35 |

with spaces: _ _

36 |

three asterisks: ***

37 |

with spaces: * * *

38 |

three underscores: ___

39 |

with spaces: _ _ _

40 |

One char: a

-------------------------------------------------------------------------------- /tests/extensions/betterem/betterem (normal).txt: -------------------------------------------------------------------------------- 1 | Test: * Won't highlight * 2 | 3 | Test: *Will highlight* 4 | 5 | Test: ***I'm italic and bold* I am just bold.** 6 | 7 | Test: ***I'm bold and italic!** I am just italic.* 8 | 9 | Test: ___A lot of underscores____________is okay___ 10 | 11 | Test: __This will all be bold __because of the placement of the center underscores.__ 12 | 13 | Test: __This will all be bold __ because of the placement of the center underscores.__ 14 | 15 | Test: __This will NOT all be bold__ because of the placement of the center underscores.__ 16 | 17 | Test: __This will all be bold_ because the token is less than that of the surrounding.__ 18 | 19 | Test: This is text __bold _italic bold___ with more text 20 | 21 | Test: *All will * be italic* 22 | 23 | Test: *All will *be italic* 24 | 25 | Test: *All will not* be italic* 26 | 27 | Test: *All will not ** be italic* 28 | 29 | Test: **All will * be bold** 30 | 31 | Test: *All will *be italic** 32 | 33 | Test: **All will not*** be bold** 34 | 35 | Test: **All will not *** be bold** 36 | 37 | Test: This is text **bold *italic bold*** with more text 38 | 39 | Test: **test *test* *test* test** 40 | 41 | Test: ***test* test *test*** 42 | 43 | Test: *test * test* 44 | 45 | Test: **test ** test** 46 | 47 | Test: __test _test_ _test_ test__ 48 | 49 | Test: ___test_ test _test___ 50 | 51 | Test: _test _ test_ 52 | 53 | Test: __test __ test__ 54 | 55 | Test: **test *(test)* test** 56 | 57 | Test: __test _(test)_ test__ 58 | 59 | One asterisk: * 60 | 61 | One underscore: _ 62 | 63 | Two asterisks: ** 64 | 65 | With spaces: * * 66 | 67 | Two underscores __ 68 | 69 | with spaces: _ _ 70 | 71 | three asterisks: *** 72 | 73 | with spaces: * * * 74 | 75 | three underscores: ___ 76 | 77 | with spaces: _ _ _ 78 | 79 | One char: _a_ 80 | -------------------------------------------------------------------------------- /tests/extensions/betterem/betterem (reverse).html: -------------------------------------------------------------------------------- 1 |

Test: _ Won't highlight _

2 |

Test: Will highlight

3 |

Test: I'm italic and bold I am just bold.

4 |

Test: I'm bold and italic! I am just italic.

5 |

Test: A lot of asterisks************is okay

6 |

Test: This will all be bold **because of the placement of the center asterisk.

7 |

Test: This will all be bold ** because of the placement of the center asterisk.

8 |

Test: This will NOT all be bold because of the placement of the center asterisk.**

9 |

Test: This will all be bold* because the token is less than that of the surrounding.

10 |

Test: This is text bold italic bold with more text

11 |

Test: All will _ be italic

12 |

Test: All will _be italic

13 |

Test: All will not be italic_

14 |

Test: All will not __ be italic

15 |

Test: All will _ be bold

16 |

Test: All will _be italic_

17 |

Test: All will not_ be bold__

18 |

Test: All will not ___ be bold

19 |

Test: This is text bold italic bold with more text

20 |

Test: test test test test

21 |

Test: test* test *test

22 |

Test: test * test

23 |

Test: test ** test

24 |

Test: test test test test

25 |

Test: test test _test_

26 |

Test: test _ test

27 |

Test: test __ test

28 |

Test: test (test) test

29 |

Test: test (test) test

-------------------------------------------------------------------------------- /tests/extensions/betterem/betterem (reverse).txt: -------------------------------------------------------------------------------- 1 | Test: _ Won't highlight _ 2 | 3 | Test: _Will highlight_ 4 | 5 | Test: ___I'm italic and bold_ I am just bold.__ 6 | 7 | Test: ___I'm bold and italic!__ I am just italic._ 8 | 9 | Test: ***A lot of asterisks************is okay*** 10 | 11 | Test: **This will all be bold **because of the placement of the center asterisk.** 12 | 13 | Test: **This will all be bold ** because of the placement of the center asterisk.** 14 | 15 | Test: **This will NOT all be bold** because of the placement of the center asterisk.** 16 | 17 | Test: **This will all be bold* because the token is less than that of the surrounding.** 18 | 19 | Test: This is text **bold *italic bold*** with more text 20 | 21 | Test: _All will _ be italic_ 22 | 23 | Test: _All will _be italic_ 24 | 25 | Test: _All will not_ be italic_ 26 | 27 | Test: _All will not __ be italic_ 28 | 29 | Test: __All will _ be bold__ 30 | 31 | Test: _All will _be italic__ 32 | 33 | Test: __All will not___ be bold__ 34 | 35 | Test: __All will not ___ be bold__ 36 | 37 | Test: This is text __bold _italic bold___ with more text 38 | 39 | Test: **test *test* *test* test** 40 | 41 | Test: ***test* test *test*** 42 | 43 | Test: *test * test* 44 | 45 | Test: **test ** test** 46 | 47 | Test: __test _test_ _test_ test__ 48 | 49 | Test: ___test_ test _test___ 50 | 51 | Test: _test _ test_ 52 | 53 | Test: __test __ test__ 54 | 55 | Test: **test *(test)* test** 56 | 57 | Test: __test _(test)_ test__ 58 | -------------------------------------------------------------------------------- /tests/extensions/betterem/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | betterem (normal): 4 | extensions: 5 | pymdownx.betterem: 6 | 7 | betterem (reverse): 8 | extensions: 9 | pymdownx.betterem: 10 | smart_enable: asterisk 11 | -------------------------------------------------------------------------------- /tests/extensions/caret/caret (dumb no sup).html: -------------------------------------------------------------------------------- 1 |

Test: ^^ Won't insert ^^

2 |

Test: Will insert

3 |

Test: ^^Escaped^^

4 |

Test: All will ^ be insert

5 |

Test: All will^ not be insert^^

6 |

Test: All will ^^^ be insert

-------------------------------------------------------------------------------- /tests/extensions/caret/caret (dumb no sup).txt: -------------------------------------------------------------------------------- 1 | Test: ^^ Won't insert ^^ 2 | 3 | Test: ^^Will insert^^ 4 | 5 | Test: \^\^Escaped\^\^ 6 | 7 | Test: ^^All will ^ be insert^^ 8 | 9 | Test: ^^All will^^^ not be insert^^ 10 | 11 | Test: ^^All will ^^^ be insert^^ 12 | -------------------------------------------------------------------------------- /tests/extensions/caret/caret (dumb).html: -------------------------------------------------------------------------------- 1 |

x2 + y2 = 4

2 |

Textsuperscript

3 |

Text^superscript failed^

4 |

Textsuperscript success

5 |

Test: ^^ Won't insert ^^

6 |

Test: Will insert

7 |

Test: ^^Escaped^^

8 |

Test: All will ^ be insert

9 |

Test: All will^ be insert with superscript in middle

10 |

Test: All will ^ be insert with superscript in middle

-------------------------------------------------------------------------------- /tests/extensions/caret/caret (dumb).txt: -------------------------------------------------------------------------------- 1 | x^2^ + y^2^ = 4 2 | 3 | Text^superscript^ 4 | 5 | Text^superscript failed^ 6 | 7 | Text^superscript\ success^ 8 | 9 | Test: ^^ Won't insert ^^ 10 | 11 | Test: ^^Will insert^^ 12 | 13 | Test: \^\^Escaped\^\^ 14 | 15 | Test: ^^All will ^ be insert^^ 16 | 17 | Test: ^^All will^\^^ be insert with superscript in middle^^ 18 | 19 | Test: ^^All will ^\^^ be insert with superscript in middle^^ 20 | -------------------------------------------------------------------------------- /tests/extensions/caret/caret (no insert).html: -------------------------------------------------------------------------------- 1 |

x2 + y2 = 4

2 |

Textsuperscript

3 |

Text^superscript failed^

4 |

Textsuperscript success

5 |

Test: ^^Won't insert^^

-------------------------------------------------------------------------------- /tests/extensions/caret/caret (no insert).txt: -------------------------------------------------------------------------------- 1 | x^2^ + y^2^ = 4 2 | 3 | Text^superscript^ 4 | 5 | Text^superscript failed^ 6 | 7 | Text^superscript\ success^ 8 | 9 | Test: ^^Won't insert^^ 10 | -------------------------------------------------------------------------------- /tests/extensions/caret/caret (no sup).html: -------------------------------------------------------------------------------- 1 |

Test: ^^ Won't insert ^^

2 |

Test: Will insert

3 |

Test: ^^Escaped^^

4 |

Test: This will all be inserted ^^because of the placement of the center carets.

5 |

Test: This will all be inserted ^^ because of the placement of the center carets.

6 |

Test: This will NOT all be inserted because of the placement of the center caret.^^

7 |

Test: This will all be inserted^ because of the token is less than that of the caret.

-------------------------------------------------------------------------------- /tests/extensions/caret/caret (no sup).txt: -------------------------------------------------------------------------------- 1 | Test: ^^ Won't insert ^^ 2 | 3 | Test: ^^Will insert^^ 4 | 5 | Test: \^\^Escaped\^\^ 6 | 7 | Test: ^^This will all be inserted ^^because of the placement of the center carets.^^ 8 | 9 | Test: ^^This will all be inserted ^^ because of the placement of the center carets.^^ 10 | 11 | Test: ^^This will NOT all be inserted^^ because of the placement of the center caret.^^ 12 | 13 | Test: ^^This will all be inserted^ because of the token is less than that of the caret.^^ 14 | -------------------------------------------------------------------------------- /tests/extensions/caret/caret.html: -------------------------------------------------------------------------------- 1 |

x2 + y2 = 4

2 |

Textsuperscript

3 |

Text^superscript failed^

4 |

Textsuperscript success

5 |

Test: ^^ Won't insert ^^

6 |

Test: Will insert

7 |

Test: ^^Escaped^^

8 |

Test: This will all be inserted ^^because of the placement of the center carets.

9 |

Test: This will all be inserted ^^ because of the placement of the center carets.

10 |

Test: This will NOT all be inserted because of the placement of the center caret.^^

11 |

Test: This will all be inserted^ because of the token is less than that of the caret.

-------------------------------------------------------------------------------- /tests/extensions/caret/caret.txt: -------------------------------------------------------------------------------- 1 | x^2^ + y^2^ = 4 2 | 3 | Text^superscript^ 4 | 5 | Text^superscript failed^ 6 | 7 | Text^superscript\ success^ 8 | 9 | Test: ^^ Won't insert ^^ 10 | 11 | Test: ^^Will insert^^ 12 | 13 | Test: \^\^Escaped\^\^ 14 | 15 | Test: ^^This will all be inserted ^^because of the placement of the center carets.^^ 16 | 17 | Test: ^^This will all be inserted ^^ because of the placement of the center carets.^^ 18 | 19 | Test: ^^This will NOT all be inserted^^ because of the placement of the center caret.^^ 20 | 21 | Test: ^^This will all be inserted^ because of the token is less than that of the caret.^^ 22 | -------------------------------------------------------------------------------- /tests/extensions/caret/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | caret: 4 | extensions: 5 | pymdownx.caret: 6 | 7 | caret (dumb): 8 | extensions: 9 | pymdownx.caret: 10 | smart_insert: false 11 | 12 | caret (dumb no sup): 13 | extensions: 14 | pymdownx.caret: 15 | smart_insert: false 16 | superscript: false 17 | 18 | caret (no insert): 19 | extensions: 20 | pymdownx.caret: 21 | insert: false 22 | 23 | caret (no sup): 24 | extensions: 25 | pymdownx.caret: 26 | superscript: false 27 | -------------------------------------------------------------------------------- /tests/extensions/critic/critic (accept).html: -------------------------------------------------------------------------------- 1 |

Here is some Markdown. I am adding this here.. Here is some more text. And here is even more text that I 2 | am adding. Paragraph was deleted and replaced with some spaces.

3 |

Spaces were removed and a paragraph was added.

4 |

And here is a comment on some 5 | ==text== . Substitutions are great!

6 |

General block handling.

7 |
    8 |
  • test
      9 |
    • test
    • 10 |
    11 |
  • 12 |
  • test
  • 13 |
  • test
  • 14 |
  • test
  • 15 |
-------------------------------------------------------------------------------- /tests/extensions/critic/critic (accept).txt: -------------------------------------------------------------------------------- 1 | Here is some {--*incorrect*--} Markdown. I am adding this{++ here.++}. Here is some more {--text 2 | that I am removing--}text. And here is even more {++text that I 3 | am ++}adding.{~~ 4 | 5 | ~> ~~}Paragraph was deleted and replaced with some spaces.{~~ ~> 6 | 7 | ~~}Spaces were removed and a paragraph was added. 8 | 9 | And here is a comment on {==some 10 | ==text== ==}{>>This works quite well. I just wanted to comment on it.<<}. Substitutions {~~is~>are~~} great! 11 | 12 | General block handling. 13 | 14 | {-- 15 | 16 | * test 17 | * test 18 | * test 19 | * test 20 | * test 21 | 22 | --} 23 | 24 | {++ 25 | 26 | * test 27 | * test 28 | * test 29 | * test 30 | * test 31 | 32 | ++} 33 | -------------------------------------------------------------------------------- /tests/extensions/critic/critic (reject).html: -------------------------------------------------------------------------------- 1 |

Here is some incorrect Markdown. I am adding this. Here is some more text 2 | that I am removingtext. And here is even more adding.

3 |

Paragraph was deleted and replaced with some spaces. Spaces were removed and a paragraph was added.

4 |

And here is a comment on some 5 | ==text== . Substitutions is great!

6 |

General block handling.

7 |
    8 |
  • test
  • 9 |
  • test
  • 10 |
  • test
      11 |
    • test
    • 12 |
    13 |
  • 14 |
  • test
  • 15 |
-------------------------------------------------------------------------------- /tests/extensions/critic/critic (reject).txt: -------------------------------------------------------------------------------- 1 | Here is some {--*incorrect*--} Markdown. I am adding this{++ here.++}. Here is some more {--text 2 | that I am removing--}text. And here is even more {++text that I 3 | am ++}adding.{~~ 4 | 5 | ~> ~~}Paragraph was deleted and replaced with some spaces.{~~ ~> 6 | 7 | ~~}Spaces were removed and a paragraph was added. 8 | 9 | And here is a comment on {==some 10 | ==text== ==}{>>This works quite well. I just wanted to comment on it.<<}. Substitutions {~~is~>are~~} great! 11 | 12 | General block handling. 13 | 14 | {-- 15 | 16 | * test 17 | * test 18 | * test 19 | * test 20 | * test 21 | 22 | --} 23 | 24 | {++ 25 | 26 | * test 27 | * test 28 | * test 29 | * test 30 | * test 31 | 32 | ++} 33 | -------------------------------------------------------------------------------- /tests/extensions/critic/critic (view).html: -------------------------------------------------------------------------------- 1 |

Here is some incorrect Markdown. I am adding this here.. Here is some more text 2 | that I am removingtext. And here is even more text that I 3 | am adding.  Paragraph was deleted and replaced with some spaces.

4 |   5 |

Spaces were removed and a paragraph was added.

6 |

And here is a comment on some 7 | ==text== This works quite well. I just wanted to comment on it.. Substitutions isare great!

8 |

General block handling.

9 | 10 |
    11 |
  • test
  • 12 |
  • test
  • 13 |
  • test
      14 |
    • test
    • 15 |
    16 |
  • 17 |
  • test
  • 18 |
19 |
20 | 21 |
    22 |
  • test
      23 |
    • test
    • 24 |
    25 |
  • 26 |
  • test
  • 27 |
  • test
  • 28 |
  • test
  • 29 |
30 |
-------------------------------------------------------------------------------- /tests/extensions/critic/critic (view).txt: -------------------------------------------------------------------------------- 1 | Here is some {--*incorrect*--} Markdown. I am adding this{++ here.++}. Here is some more {--text 2 | that I am removing--}text. And here is even more {++text that I 3 | am ++}adding.{~~ 4 | 5 | ~> ~~}Paragraph was deleted and replaced with some spaces.{~~ ~> 6 | 7 | ~~}Spaces were removed and a paragraph was added. 8 | 9 | And here is a comment on {==some 10 | ==text== ==}{>>This works quite well. I just wanted to comment on it.<<}. Substitutions {~~is~>are~~} great! 11 | 12 | General block handling. 13 | 14 | {-- 15 | 16 | * test 17 | * test 18 | * test 19 | * test 20 | * test 21 | 22 | --} 23 | 24 | {++ 25 | 26 | * test 27 | * test 28 | * test 29 | * test 30 | * test 31 | 32 | ++} 33 | -------------------------------------------------------------------------------- /tests/extensions/critic/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | critic (accept): 4 | extensions: 5 | pymdownx.critic: 6 | mode: accept 7 | 8 | critic (reject): 9 | extensions: 10 | pymdownx.critic: 11 | mode: reject 12 | 13 | critic (view): 14 | extensions: 15 | pymdownx.critic: 16 | mode: view 17 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (entities).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

100 💯
3 | 1234 🔢
4 | 8ball 🎱
5 | a 🅰
6 | ab 🆎
7 | abc 🔤
8 | abcd 🔡
9 | accept 🉑
10 | aerial_tramway 🚡
11 | airplane ✈

-------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (entities).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abc :abc:
8 | abcd :abcd:
9 | accept :accept:
10 | aerial_tramway :aerial_tramway:
11 | airplane :airplane:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (escaped).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

: 3 | 😄
4 | :smile:
5 | \😄
6 | \:smile:

-------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (escaped).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | \: 3 | :smile:
4 | \:smile:
5 | \\:smile:
6 | \\\:smile:
7 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (long title).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

100 💯
3 | 1234 🔢
4 | 8ball 🎱
5 | a 🅰
6 | ab 🆎
7 | abc 🔤
8 | abcd 🔡
9 | accept 🉑
10 | aerial_tramway 🚡
11 | airplane ✈️

-------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (long title).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abc :abc:
8 | abcd :abcd:
9 | accept :accept:
10 | aerial_tramway :aerial_tramway:
11 | airplane :airplane:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (no title).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

100 💯
3 | 1234 🔢
4 | 8ball 🎱
5 | a 🅰
6 | ab 🆎
7 | abc 🔤
8 | abcd 🔡
9 | accept 🉑
10 | aerial_tramway 🚡
11 | airplane ✈️

-------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (no title).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abc :abc:
8 | abcd :abcd:
9 | accept :accept:
10 | aerial_tramway :aerial_tramway:
11 | airplane :airplane:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (png sprite).html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

Emojis

9 |

100 💯
10 | 1234 🔢
11 | 8ball 🎱
12 | a 🅰
13 | ab 🆎
14 | abc 🔤
15 | abcd 🔡
16 | accept 🉑
17 | aerial_tramway 🚡
18 | airplane ✈️

19 |
20 | 21 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (png sprite).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abc :abc:
8 | abcd :abcd:
9 | accept :accept:
10 | aerial_tramway :aerial_tramway:
11 | airplane :airplane:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (svg sprite).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

100 💯
3 | 1234 🔢
4 | 8ball 🎱
5 | a 🅰
6 | ab 🆎
7 | abc 🔤
8 | abcd 🔡
9 | accept 🉑
10 | aerial_tramway 🚡
11 | airplane ✈️

-------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (svg sprite).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abc :abc:
8 | abcd :abcd:
9 | accept :accept:
10 | aerial_tramway :aerial_tramway:
11 | airplane :airplane:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (svg).html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

Emojis

9 |

100 💯
10 | 1234 🔢
11 | 8ball 🎱
12 | a 🅰
13 | ab 🆎
14 | abc 🔤
15 | abcd 🔡
16 | accept 🉑
17 | aerial_tramway 🚡
18 | airplane ✈️

19 |
20 | 21 | -------------------------------------------------------------------------------- /tests/extensions/emoji/emoji1 (svg).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abc :abc:
8 | abcd :abcd:
9 | accept :accept:
10 | aerial_tramway :aerial_tramway:
11 | airplane :airplane:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/gemoji (entities).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

+1 👍
3 | -1 👎
4 | 100 💯
5 | 1234 🔢
6 | 1st_place_medal 🥇
7 | 2nd_place_medal 🥈
8 | 3rd_place_medal 🥉
9 | 8ball 🎱
10 | a 🅰️
11 | ab 🆎

-------------------------------------------------------------------------------- /tests/extensions/emoji/gemoji (entities).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | +1 :+1:
3 | -1 :-1:
4 | 100 :100:
5 | 1234 :1234:
6 | 1st_place_medal :1st_place_medal:
7 | 2nd_place_medal :2nd_place_medal:
8 | 3rd_place_medal :3rd_place_medal:
9 | 8ball :8ball:
10 | a :a:
11 | ab :ab:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | emoji1 (entities): 4 | extensions: 5 | pymdownx.emoji: 6 | emoji_generator: !!python/name:pymdownx.emoji.to_alt 7 | alt: html_entity 8 | remove_variation_selector: True 9 | 10 | emoji1 (escaped): 11 | extensions: 12 | pymdownx.emoji: 13 | 14 | emoji1 (long title): 15 | extensions: 16 | pymdownx.emoji: 17 | title: long 18 | 19 | emoji1 (no title): 20 | extensions: 21 | pymdownx.emoji: 22 | title: none 23 | 24 | emoji1 (png): 25 | css: 26 | - https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.7/assets/css/emojione.min.css 27 | extensions: 28 | pymdownx.emoji: 29 | 30 | emoji1 (png sprite): 31 | css: 32 | - https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.7/assets/sprites/emojione.sprites.css 33 | extensions: 34 | pymdownx.emoji: 35 | emoji_generator: !!python/name:pymdownx.emoji.to_png_sprite 36 | 37 | emoji1 (svg): 38 | css: 39 | - https://cdnjs.cloudflare.com/ajax/libs/emojione/2.2.7/assets/css/emojione.min.css 40 | extensions: 41 | pymdownx.emoji: 42 | emoji_generator: !!python/name:pymdownx.emoji.to_svg 43 | 44 | emoji1 (svg sprite): 45 | extensions: 46 | pymdownx.emoji: 47 | emoji_generator: !!python/name:pymdownx.emoji.to_svg_sprite 48 | 49 | gemoji (entities): 50 | extensions: 51 | pymdownx.emoji: 52 | emoji_index: !!python/name:pymdownx.emoji.gemoji 53 | emoji_generator: !!python/name:pymdownx.emoji.to_alt 54 | alt: html_entity 55 | 56 | gemoji (png): 57 | extensions: 58 | pymdownx.emoji: 59 | emoji_index: !!python/name:pymdownx.emoji.gemoji 60 | alt: short 61 | options: 62 | attributes: 63 | align: absmiddle 64 | height: 20px 65 | width: 20px 66 | 67 | twemoji (entities): 68 | extensions: 69 | pymdownx.emoji: 70 | emoji_generator: !!python/name:pymdownx.emoji.to_alt 71 | alt: html_entity 72 | emoji_index: !!python/name:pymdownx.emoji.twemoji 73 | 74 | twemoji (png): 75 | extensions: 76 | pymdownx.emoji: 77 | emoji_index: !!python/name:pymdownx.emoji.twemoji 78 | alt: short 79 | options: 80 | attributes: 81 | align: absmiddle 82 | height: 20px 83 | width: 20px 84 | 85 | twemoji (svg): 86 | extensions: 87 | pymdownx.emoji: 88 | emoji_index: !!python/name:pymdownx.emoji.twemoji 89 | emoji_generator: !!python/name:pymdownx.emoji.to_svg 90 | alt: short 91 | options: 92 | attributes: 93 | align: absmiddle 94 | height: 20px 95 | width: 20px 96 | -------------------------------------------------------------------------------- /tests/extensions/emoji/twemoji (entities).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

100 💯
3 | 1234 🔢
4 | 8ball 🎱
5 | a 🅰
6 | ab 🆎
7 | abacus 🧮
8 | abc 🔤
9 | abcd 🔡
10 | accept 🉑
11 | accordion 🪗

-------------------------------------------------------------------------------- /tests/extensions/emoji/twemoji (entities).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abacus :abacus:
8 | abc :abc:
9 | abcd :abcd:
10 | accept :accept:
11 | accordion :accordion:
12 | -------------------------------------------------------------------------------- /tests/extensions/emoji/twemoji (svg).html: -------------------------------------------------------------------------------- 1 |

Emojis

2 |

100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abacus :abacus:
8 | abc :abc:
9 | abcd :abcd:
10 | accept :accept:
11 | accordion :accordion:

-------------------------------------------------------------------------------- /tests/extensions/emoji/twemoji (svg).txt: -------------------------------------------------------------------------------- 1 | # Emojis 2 | 100 :100:
3 | 1234 :1234:
4 | 8ball :8ball:
5 | a :a:
6 | ab :ab:
7 | abacus :abacus:
8 | abc :abc:
9 | abcd :abcd:
10 | accept :accept:
11 | accordion :accordion:
12 | -------------------------------------------------------------------------------- /tests/extensions/escapeall/escapeall (critic).html: -------------------------------------------------------------------------------- 1 |

We shouldn't escape STX and ETX characters:

2 |

Don't escape crtiic placeholder: comment

-------------------------------------------------------------------------------- /tests/extensions/escapeall/escapeall (critic).txt: -------------------------------------------------------------------------------- 1 | We shouldn't escape STX and ETX characters: 2 | 3 | Don't escape crtiic placeholder: \{>>comment<<} 4 | -------------------------------------------------------------------------------- /tests/extensions/escapeall/escapeall (ws normal).html: -------------------------------------------------------------------------------- 1 |

We can escape everything 2 | 3 | ❤✓☀☆☂♞☯☭☢€☎∞❄♫ 4 | 😄 5 | \

-------------------------------------------------------------------------------- /tests/extensions/escapeall/escapeall (ws normal).txt: -------------------------------------------------------------------------------- 1 | \W\e\ \c\a\n\ \e\s\c\a\p\e\ \e\v\e\r\y\t\h\i\n\g 2 | \ 3 | \❤\✓\☀\☆\☂\♞\☯\☭\☢\€\☎\∞\❄\♫ 4 | \😄 5 | \\ 6 | -------------------------------------------------------------------------------- /tests/extensions/escapeall/escapeall.html: -------------------------------------------------------------------------------- 1 |

We can escape everything 2 |
3 | ❤✓☀☆☂♞☯☭☢€☎∞❄♫ 4 | 😄 5 | \

-------------------------------------------------------------------------------- /tests/extensions/escapeall/escapeall.txt: -------------------------------------------------------------------------------- 1 | \W\e\ \c\a\n\ \e\s\c\a\p\e\ \e\v\e\r\y\t\h\i\n\g 2 | \ 3 | \❤\✓\☀\☆\☂\♞\☯\☭\☢\€\☎\∞\❄\♫ 4 | \😄 5 | \\ 6 | -------------------------------------------------------------------------------- /tests/extensions/escapeall/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | escapeall: 4 | extensions: 5 | pymdownx.escapeall: 6 | hardbreak: True 7 | nbsp: True 8 | 9 | escapeall (critic): 10 | extensions: 11 | pymdownx.escapeall: 12 | pymdownx.critic: 13 | mode: view 14 | 15 | escapeall (ws normal): 16 | extensions: 17 | pymdownx.escapeall: 18 | -------------------------------------------------------------------------------- /tests/extensions/extra/extra (config).html: -------------------------------------------------------------------------------- 1 |

Footnotes1 have a label2 and the footnote's content.

2 |
3 |
4 |
    5 |
  1. 6 |

    This is a footnote content. link

    7 |
  2. 8 |
  3. 9 |

    A footnote on the label: "@#$%". link

    10 |
  4. 11 |
12 |
-------------------------------------------------------------------------------- /tests/extensions/extra/extra (config).txt: -------------------------------------------------------------------------------- 1 | Footnotes[^1] have a label[^@#$%] and the footnote's content. 2 | 3 | [^1]: This is a footnote content. 4 | [^@#$%]: A footnote on the label: "@#$%". 5 | -------------------------------------------------------------------------------- /tests/extensions/extra/extra.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
Col1Col2
Abbreviationsabr
Emphasisemphasis works
Footnote1
Attr ListTest
27 |
28 |

This will be processed.

29 |
30 |
31 |
Definition
32 |
Some text
33 |
34 |
35 |
36 |
    37 |
  1. 38 |

    This is a footnote. 

    39 |
  2. 40 |
41 |
-------------------------------------------------------------------------------- /tests/extensions/extra/extra.txt: -------------------------------------------------------------------------------- 1 | | Col1 | Col2 | 2 | | ---- | ---- | 3 | | Abbreviations | abr | 4 | | Emphasis | **emphasis works** | 5 | | Footnote[^1] | | 6 | | Attr List | **Test**{: style="color: red;"} | 7 | 8 |
9 | This **will** be processed. 10 |
11 | 12 | Definition 13 | : Some text 14 | 15 | *[abr]: abbreviations 16 | 17 | [^1]: This is a footnote. 18 | -------------------------------------------------------------------------------- /tests/extensions/extra/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | extra: 4 | extensions: 5 | pymdownx.extra: 6 | 7 | extra (config): 8 | extensions: 9 | pymdownx.extra: 10 | markdown.extensions.footnotes: 11 | BACKLINK_TEXT: link 12 | -------------------------------------------------------------------------------- /tests/extensions/keys/keys (camel).html: -------------------------------------------------------------------------------- 1 |

Keys

2 |

Alt

3 |

Down

4 |

Left

5 |

Right

6 |

Aliases

7 |

Num +

8 |

Menu

9 |

Backspace

10 |

Combos

11 |

Win+Shift+S

12 |

Cmd+Ctrl+D

13 |

Ctrl+Alt+Page Down

-------------------------------------------------------------------------------- /tests/extensions/keys/keys (camel).txt: -------------------------------------------------------------------------------- 1 | ## Keys 2 | 3 | ++Alt++ 4 | 5 | ++ArrowDown++ 6 | 7 | ++ArrowLeft++ 8 | 9 | ++ArrowRight++ 10 | 11 | ## Aliases 12 | ++Add++ 13 | 14 | ++Apps++ 15 | 16 | ++Back++ 17 | 18 | ## Combos 19 | 20 | ++Win+Shift+s++ 21 | 22 | ++cmd+ctrl+d++ 23 | 24 | ++Ctrl+Alt+PgDn++ 25 | -------------------------------------------------------------------------------- /tests/extensions/keys/keys.txt: -------------------------------------------------------------------------------- 1 | ## Keys 2 | 3 | ++alt++ 4 | 5 | ++arrow-down++ 6 | 7 | ++arrow-left++ 8 | 9 | ++arrow-right++ 10 | 11 | ++arrow-up++ 12 | 13 | ++backslash++ 14 | 15 | ++backspace++ 16 | 17 | ++backtab++ 18 | 19 | ++bar++ 20 | 21 | ++brace-left++ 22 | 23 | ++brace-right++ 24 | 25 | ++bracket-left++ 26 | 27 | ++bracket-right++ 28 | 29 | ++break++ 30 | 31 | ++browser-back++ 32 | 33 | ++browser-favorites++ 34 | 35 | ++browser-forward++ 36 | 37 | ++browser-home++ 38 | 39 | ++browser-refresh++ 40 | 41 | ++browser-search++ 42 | 43 | ++browser-stop++ 44 | 45 | ## Aliases 46 | ++add++ 47 | 48 | ++apps++ 49 | 50 | ++back++ 51 | 52 | ++bksp++ 53 | 54 | ++bktab++ 55 | 56 | ++cancel++ 57 | 58 | ## Combos 59 | 60 | ++win+shift+s++ 61 | 62 | ++cmd+ctrl+d++ 63 | 64 | ## On the Fly Special Key 65 | 66 | ++ctrl+alt+"Special"++ 67 | 68 | ## Special Key Added to Key Map 69 | 70 | ++ctrl+alt+custom++ 71 | 72 | ## Override Original 73 | 74 | ++option+shift+s++ 75 | 76 | ## Escape Plus 77 | 78 | ++ctrl+alt+"Special with \+ sign"++ 79 | 80 | \++ctrl+alt+delete++ 81 | 82 | \\++ctrl+alt+delete++ 83 | 84 | \\\++ctrl+alt+delete++ 85 | 86 | ++ctrl+alt+delete\++ 87 | 88 | ++ctrl\+alt+delete++ 89 | 90 | ## Bad Key 91 | 92 | ++ctrl+alt+bad++ 93 | -------------------------------------------------------------------------------- /tests/extensions/keys/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | keys: 4 | extensions: 5 | pymdownx.keys: 6 | key_map: { 7 | 'custom': 'Custom Key', 8 | 'option': 'Opt' 9 | } 10 | 11 | keys (camel): 12 | extensions: 13 | pymdownx.keys: 14 | camel_case: true 15 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (bitbucket).txt: -------------------------------------------------------------------------------- 1 | Mention @some-bodies_name 2 | 3 | Commit some-bodies_name/some_repository@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 4 | 5 | Compare some-bodies_name/some_repository@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 6 | 7 | Issue some-bodies_name/some_repository#33 8 | 9 | Pull request some-bodies_name/some_repository!33 10 | 11 | Commit 3f6b07a8eeaa9d606115758d90f55fec565d4e2a 12 | 13 | Compare e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 14 | 15 | Issue #33 16 | 17 | Pull request !33 18 | 19 | Commit MyRepo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 20 | 21 | Compare e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 22 | 23 | Issue MyRepo#33 24 | 25 | Pull MyRepo!33 26 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (extensions).html: -------------------------------------------------------------------------------- 1 |

Magic link mixed with other extensions

2 |

http://www.google.com

3 |

http://www.google.com

4 |

http://www.google.com

5 |

http://www.google.com

6 |

fake.mail@gmail.com

7 |

fake.mail@gmail.com

8 |

fake.mail@gmail.com

9 |

fake.mail@gmail.com

10 |

These aren't guarunteed to work without being enclosed as 11 | we allow links to trail with = and emails can lead with _.

12 |

http://www.google.com

13 |

fake.mail@gmail.com

-------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (extensions).txt: -------------------------------------------------------------------------------- 1 | Magic link mixed with other extensions 2 | 3 | ~~http://www.google.com~~ 4 | 5 | **http://www.google.com** 6 | 7 | __http://www.google.com__ 8 | 9 | ^^http://www.google.com^^ 10 | 11 | ~~fake.mail@gmail.com~~ 12 | 13 | **fake.mail@gmail.com** 14 | 15 | ^^fake.mail@gmail.com^^ 16 | 17 | ==fake.mail@gmail.com== 18 | 19 | These aren't guarunteed to work without being enclosed as 20 | we allow links to trail with = and emails can lead with _. 21 | 22 | ==== 23 | 24 | ____ 25 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (gitlab).txt: -------------------------------------------------------------------------------- 1 | Mention @some-bodies_name 2 | 3 | Commit some-bodies_name/some_repository@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 4 | 5 | Compare some-bodies_name/some_repository@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 6 | 7 | Issue some-bodies_name/some_repository#33 8 | 9 | Pull request some-bodies_name/some_repository!33 10 | 11 | Commit 3f6b07a8eeaa9d606115758d90f55fec565d4e2a 12 | 13 | Compare e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 14 | 15 | Issue #33 16 | 17 | Pull request !33 18 | 19 | Commit MyRepo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 20 | 21 | Compare MyRepo@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 22 | 23 | Issue MyRepo#33 24 | 25 | Pull MyRepo!33 26 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (invalid).txt: -------------------------------------------------------------------------------- 1 | Mention @some-bodies_name 2 | 3 | Mention @some-bodies_name/some_repository 4 | 5 | Mention @facelessuser/some_repository 6 | 7 | Commit some-bodies_name/some_repository@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 8 | 9 | Compare some-bodies_name/some_repository@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 10 | 11 | Issue some-bodies_name/some_repository#33 12 | 13 | Pull request some-bodies_name/some_repository!33 14 | 15 | Commit 3f6b07a8eeaa9d606115758d90f55fec565d4e2a 16 | 17 | Compare e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 18 | 19 | Issue #33 20 | 21 | Pull request !33 22 | 23 | Commit MyRepo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 24 | 25 | Compare MyRepo@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 26 | 27 | Issue MyRepo#33 28 | 29 | Pull MyRepo!33 30 | 31 | Mention @gitlab:some-user 32 | 33 | Mention @gitlab:some-bodies_name/some_repository 34 | 35 | Mention @bitbucket:facelessuser/some_repository 36 | 37 | Issue github:some-user/some-repo#1 38 | 39 | Pull request bitbucket:some-user/some-repo!2 40 | 41 | Commit gitlab:some-user/some-repo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 42 | 43 | Compare gitlab:some-user/some-repo@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 44 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (shorthand).txt: -------------------------------------------------------------------------------- 1 | Mention @some-bodies_name 2 | 3 | Mention @some-bodies_name/some_repository 4 | 5 | Mention @facelessuser/some_repository 6 | 7 | Commit some-bodies_name/some_repository@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 8 | 9 | Compare some-bodies_name/some_repository@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 10 | 11 | Issue some-bodies_name/some_repository#33 12 | 13 | Pull request some-bodies_name/some_repository!33 14 | 15 | Commit 3f6b07a8eeaa9d606115758d90f55fec565d4e2a 16 | 17 | Compare e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 18 | 19 | Issue #33 20 | 21 | Pull request !33 22 | 23 | Commit MyRepo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 24 | 25 | Compare MyRepo@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 26 | 27 | Issue MyRepo#33 28 | 29 | Pull MyRepo!33 30 | 31 | Mention @gitlab:some-user 32 | 33 | Mention @gitlab:some-bodies_name/some_repository 34 | 35 | Mention @bitbucket:facelessuser/some_repository 36 | 37 | Issue github:some-user/some-repo#1 38 | 39 | Pull request bitbucket:some-user/some-repo!2 40 | 41 | Commit gitlab:some-user/some-repo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 42 | 43 | Compare gitlab:some-user/some-repo@e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 44 | 45 | --- 46 | 47 | @x:username 48 | 49 | --- 50 | 51 | No issue \#33 52 | 53 | No issue # 54 | 55 | No pull request \!33 56 | 57 | No mention \@some-bodies_name 58 | 59 | No issue some-bodies_name/some_repository\#33 60 | 61 | No pull request some-bodies_name/some_repository\!33 62 | 63 | No commit @3f6b07a8eeaa9d606115758d90f55fec565d4e2a 64 | 65 | No compare @e2ed7e0b3973f3f9eb7a26b8ef7ae514eebfe0d2...90b6fb8711e75732f987982cc024e9bb0111beac 66 | 67 | [No mention @facelessuser](http://google.com) 68 | 69 | [No issue #33](http://google.com) 70 | 71 | [No issue some-bodies_name/some_repository#33](http://google.com) 72 | 73 | [@facelessuser](http://google.com) 74 | 75 | [No repo @facelessuser/pymdown-extensions](http://google.com) 76 | 77 | [No link http://google.com](http://google.com) 78 | 79 | [No email fakeemail@mail.com](http://google.com) 80 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink (shorthand-social).txt: -------------------------------------------------------------------------------- 1 | Mention @some-bodies_name 2 | 3 | Not a repo mention @some-bodies_name/some_repository 4 | 5 | Not a repo mention @facelessuser/some_repository 6 | 7 | No Commit some-bodies_name/some_repository@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 8 | 9 | No Issue some-bodies_name/some_repository#33 10 | 11 | No Pull request some-bodies_name/some_repository!33 12 | 13 | No Commit 3f6b07a8eeaa9d606115758d90f55fec565d4e2a 14 | 15 | No Issue #33 16 | 17 | No Pull request !33 18 | 19 | No Commit MyRepo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 20 | 21 | No Issue MyRepo#33 22 | 23 | No Pull MyRepo!33 24 | 25 | Mention @gitlab:some-user 26 | 27 | Mention @gitlab:some-bodies_name/some_repository 28 | 29 | Mention @bitbucket:facelessuser/some_repository 30 | 31 | Issue github:some-user/some-repo#1 32 | 33 | Pull request bitbucket:some-user/some-repo!2 34 | 35 | Commit gitlab:some-user/some-repo@3f6b07a8eeaa9d606115758d90f55fec565d4e2a 36 | 37 | --- 38 | 39 | @x:username 40 | 41 | --- 42 | 43 | No issue \#33 44 | 45 | No pull request \!33 46 | 47 | No mention \@some-bodies_name 48 | 49 | No issue some-bodies_name/some_repository\#33 50 | 51 | No pull request some-bodies_name/some_repository\!33 52 | 53 | No commit @3f6b07a8eeaa9d606115758d90f55fec565d4e2a 54 | 55 | --- 56 | 57 | https://github.com/facelessuser/pymdown-extensions/issues/49 58 | 59 | https://github.com/facelessuser/pymdown-extensions/pull/87 60 | 61 | https://github.com/facelessuser/pymdown-extensions/commit/6a09fde5c1cad66c660c3aa7792385c52c49e819 62 | 63 | https://github.com/fake-user/fake-repository/issues/538 64 | 65 | https://github.com/fake-user/fake-repository/pull/539 66 | 67 | https://github.com/fake-user/fake-repository/commit/594b25d53798c30735da5a9be19c06cc94052a16 68 | 69 | https://gitlab.com/fake-user/fake-repository/issues/538 70 | 71 | https://gitlab.com/fake-user/fake-repository/merge_requests/539 72 | 73 | https://gitlab.com/fake-user/fake-repository/commit/594b25d53798c30735da5a9be19c06cc94052a16 74 | 75 | https://bitbucket.org/fake-user/fake-repository/issues/538/ 76 | 77 | https://bitbucket.org/fake-user/fake-repository/pull-requests/539/ 78 | 79 | https://bitbucket.org/fake-user/fake-repository/issues/538/optional-title 80 | 81 | https://bitbucket.org/fake-user/fake-repository/pull-requests/539/optional-title 82 | 83 | https://bitbucket.org/fake-user/fake-repository/commits/commit/594b25d53798c30735da5a9be19c06cc94052a16 84 | 85 | 86 | 87 | https://github.com/facelessuser/fake-repository/issues/87 88 | 89 | https://github.com/facelessuser/fake-repository/commit/594b25d53798c30735da5a9be19c06cc94052a16 90 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/magiclink_hide_protocol.txt: -------------------------------------------------------------------------------- 1 | http://foo.com/blah_blah_wikipedia_again 2 | 3 | https://www.example.com/foo/?bar=baz&inga=42&quux 4 | 5 | ftp://foo.bar/baz 6 | 7 | mailto@unaffected.org 8 | 9 | # Repo Links 10 | 11 | https://github.com/facelessuser/pymdown-extensions/issues/49 12 | 13 | https://github.com/facelessuser/pymdown-extensions/commit/6a09fde5c1cad66c660c3aa7792385c52c49e819 14 | 15 | https://github.com/fake-user/fake-repository/issues/538 16 | 17 | https://github.com/fake-user/fake-repository/commit/594b25d53798c30735da5a9be19c06cc94052a16 18 | 19 | https://gitlab.com/fake-user/fake-repository/issues/538 20 | 21 | https://gitlab.com/fake-user/fake-repository/commit/594b25d53798c30735da5a9be19c06cc94052a16 22 | 23 | https://bitbucket.org/fake-user/fake-repository/issues/538/ 24 | 25 | https://bitbucket.org/fake-user/fake-repository/issues/538/optional-title 26 | 27 | https://bitbucket.org/fake-user/fake-repository/commits/commit/594b25d53798c30735da5a9be19c06cc94052a16 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /tests/extensions/magiclink/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | magiclink: 4 | extensions: 5 | pymdownx.magiclink: 6 | hide_protocol: false 7 | repo_url_shortener: true 8 | user: facelessuser 9 | repo: pymdown-extensions 10 | 11 | magiclink (bitbucket): 12 | extensions: 13 | pymdownx.magiclink: 14 | hide_protocol: false 15 | provider: bitbucket 16 | repo_url_shortener: true 17 | repo_url_shorthand: true 18 | social_url_shorthand: true 19 | user: facelessuser 20 | repo: pymdown-extensions 21 | 22 | magiclink (extensions): 23 | extensions: 24 | pymdownx.magiclink: 25 | hide_protocol: false 26 | repo_url_shortener: true 27 | repo_url_shorthand: true 28 | social_url_shorthand: true 29 | user: facelessuser 30 | repo: pymdown-extensions 31 | pymdownx.betterem: 32 | pymdownx.tilde: 33 | pymdownx.caret: 34 | pymdownx.mark: 35 | 36 | magiclink (gitlab): 37 | extensions: 38 | pymdownx.magiclink: 39 | hide_protocol: false 40 | provider: gitlab 41 | repo_url_shortener: true 42 | repo_url_shorthand: true 43 | social_url_shorthand: true 44 | user: facelessuser 45 | repo: pymdown-extensions 46 | 47 | magiclink (invalid): 48 | extensions: 49 | pymdownx.magiclink: 50 | hide_protocol: false 51 | provider: invalid 52 | repo_url_shortener: true 53 | repo_url_shorthand: true 54 | social_url_shorthand: true 55 | 56 | magiclink (shorthand): 57 | extensions: 58 | pymdownx.magiclink: 59 | hide_protocol: false 60 | repo_url_shortener: true 61 | repo_url_shorthand: true 62 | social_url_shorthand: true 63 | user: facelessuser 64 | repo: pymdown-extensions 65 | 66 | magiclink (shorthand-social): 67 | extensions: 68 | pymdownx.magiclink: 69 | hide_protocol: false 70 | repo_url_shortener: true 71 | repo_url_shorthand: true 72 | social_url_shorthand: true 73 | provider: x 74 | user: facelessuser 75 | repo: pymdown-extensions 76 | 77 | magiclink_hide_protocol: 78 | extensions: 79 | pymdownx.magiclink: 80 | hide_protocol: true 81 | repo_url_shortener: true 82 | repo_url_shorthand: true 83 | social_url_shorthand: true 84 | user: facelessuser 85 | repo: pymdown-extensions 86 | -------------------------------------------------------------------------------- /tests/extensions/mark/mark (dumb).html: -------------------------------------------------------------------------------- 1 |

Test: == Won't mark ==

2 |

Test: Will mark

3 |

Test: All will = be marked

4 |

Test: All will not= be marked==

5 |

Test: All will === be marked

-------------------------------------------------------------------------------- /tests/extensions/mark/mark (dumb).txt: -------------------------------------------------------------------------------- 1 | Test: == Won't mark == 2 | 3 | Test: ==Will mark== 4 | 5 | Test: ==All will = be marked== 6 | 7 | Test: ==All will not=== be marked== 8 | 9 | Test: ==All will === be marked== 10 | -------------------------------------------------------------------------------- /tests/extensions/mark/mark.html: -------------------------------------------------------------------------------- 1 |

Test: == Won't mark ==

2 |

Test: Will mark

3 |

Test: A lot of equals=============is okay

4 |

Test: This will all be marked ==because of the placement of the center equal signs.

5 |

Test: This will all be marked == because of the placement of the center equal sings.

6 |

Test: This will NOT all be marked because of the placement of the center equal sings.==

7 |

Test: This will all be marked= because of the token is less than that of the surrounding.

-------------------------------------------------------------------------------- /tests/extensions/mark/mark.txt: -------------------------------------------------------------------------------- 1 | Test: == Won't mark == 2 | 3 | Test: ==Will mark== 4 | 5 | Test: ==A lot of equals=============is okay== 6 | 7 | Test: ==This will all be marked ==because of the placement of the center equal signs.== 8 | 9 | Test: ==This will all be marked == because of the placement of the center equal sings.== 10 | 11 | Test: ==This will NOT all be marked== because of the placement of the center equal sings.== 12 | 13 | Test: ==This will all be marked= because of the token is less than that of the surrounding.== 14 | -------------------------------------------------------------------------------- /tests/extensions/mark/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | mark: 4 | extensions: 5 | pymdownx.mark: 6 | 7 | mark (dumb): 8 | extensions: 9 | pymdownx.mark: 10 | smart_mark: false 11 | -------------------------------------------------------------------------------- /tests/extensions/progressbar/progressbar.txt: -------------------------------------------------------------------------------- 1 | [=0% "0%"]{: .candystripe-animate} 2 | 3 | [=5% "5%"]{: .candystripe-animate} 4 | 5 | [=25% "25%"]{: .candystripe-animate} 6 | 7 | [=45% "45%"]{: .candystripe-animate} 8 | 9 | [=65% "65%"]{: .candystripe-animate} 10 | 11 | [=85% "85%"]{: .candystripe-animate} 12 | 13 | [=100% "100%"]{: .candystripe-animate} 14 | 15 | [= 212.2/537 "212.2/537 Testing division"] 16 | 17 | [=== 50%] 18 | 19 | Before[= 50% "I'm a block!"]After 20 | 21 | [= 50% "Glossy"]{: .candystripe-animate .gloss} 22 | 23 | [= 0%] 24 | 25 | [= 3/0 "Divide by 0"] 26 | 27 | [= 300/100 "Greater than 0"] 28 | -------------------------------------------------------------------------------- /tests/extensions/progressbar/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | progressbar: 4 | css: 5 | - ../_assets/progressbar.css 6 | extensions: 7 | pymdownx.progressbar: 8 | markdown.extensions.attr_list: 9 | -------------------------------------------------------------------------------- /tests/extensions/striphtml/striphtml (no attr strip).html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 |

15 | 16 | 17 | 18 | 19 |

20 |

link 21 | 26 | Some text 27 |

-------------------------------------------------------------------------------- /tests/extensions/striphtml/striphtml (no attr strip).txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | link 28 | 33 | Some text 34 | 35 | -------------------------------------------------------------------------------- /tests/extensions/striphtml/striphtml.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | 13 | 14 |

15 | 16 | 17 | 18 | 19 |

20 |

link 21 | 22 | Some text 23 |

-------------------------------------------------------------------------------- /tests/extensions/striphtml/striphtml.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 11 | 12 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | link 28 | 33 | Some text 34 | 35 | -------------------------------------------------------------------------------- /tests/extensions/striphtml/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | striphtml: 4 | extensions: 5 | pymdownx.striphtml: 6 | strip_attributes: 7 | - id 8 | - style 9 | - class 10 | 11 | striphtml (no attr strip): 12 | extensions: 13 | pymdownx.striphtml: 14 | strip_js_on_attributes: false 15 | -------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (custom).html: -------------------------------------------------------------------------------- 1 |
content
2 |
content
3 |
content
-------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (custom).txt: -------------------------------------------------------------------------------- 1 | ```test 2 | content 3 | ``` 4 | 5 | ```{.test .class #id} 6 | content 7 | ``` 8 | 9 | ```{.test2 .class #id} 10 | content 11 | ``` 12 | -------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (failures).html: -------------------------------------------------------------------------------- 1 |
    2 |
  • Test bad indentation 1:
    ```
      3 | 
    4 |

    Here is some text. 5 | ```

    6 |
  • 7 |
8 |
9 |
    10 |
  • 11 |

    Test bad indentation 2:

    12 |

    Here is some text.

    13 |
  • 14 |
15 |
16 |
    17 |
  • 18 |

    Test bad indentation 3:

    19 |

    Here is some text.

    20 |
  • 21 |
22 |
23 |
    24 |
  • 25 |

    Test bad indentation 4:

    26 |

    Here is some text.

    27 |
  • 28 |
29 |
30 |
    31 |
  • This will not work.
  • 32 |
33 |
34 |
35 |

``` 36 | Test

37 |
38 |

will break. 39 | ```

40 |
41 |
    42 |
  • 43 |

    Test bad indentation blockquote

    44 |
    45 |

    Test 46 | will break

    47 |
    48 |
  • 49 |
50 |
51 |
    52 |
  • 53 |

    Test block quote exceeding start level

    54 |
    55 |

    ``` 56 | Test

    57 |
    58 |

    will 59 | break 60 | ```

    61 |
    62 |
    63 |
  • 64 |
65 |
66 |
    67 |
  • 68 |

    Unexpected block quote

    69 |

    ``` 70 | Test 71 | will

    72 |
    73 |

    break 74 | ```

    75 |
    76 |
  • 77 |
78 |
79 |
    80 |
  • 81 |

    Block quote unalignment

    82 |
    83 |

    Test 84 | Will 85 | break

    86 |
    87 |
  • 88 |
89 |
90 |
    91 |
  • 92 |

    Block quote unalignment

    93 |
    94 |

    Test 95 | Will 96 | break

    97 |
    98 |
  • 99 |
100 |
101 |
    102 |
  • 103 |

    Bad attribute list

    104 |
    import test
    105 | 
    106 |
  • 107 |
108 |
109 |
    110 |
  • 111 |

    Missing closing bracket

    112 |

    { .python 113 | import test

    114 |
  • 115 |
116 |
117 |
    118 |
  • 119 |

    Missing opening bracket

    120 |

    .python } 121 | import test

    122 |
  • 123 |
124 |
125 |
    126 |
  • 127 |

    Additional class outside of attribute list

    128 |

    python .class 129 | import test

    130 |
  • 131 |
-------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (failures).txt: -------------------------------------------------------------------------------- 1 | - Test bad indentation 1: 2 | 3 | ``` 4 | Here is some text. 5 | ``` 6 | 7 | --- 8 | 9 | - Test bad indentation 2: 10 | 11 | ``` 12 | Here is some text. 13 | ``` 14 | 15 | --- 16 | 17 | - Test bad indentation 3: 18 | 19 | ``` 20 | Here is some text. 21 | ``` 22 | 23 | --- 24 | 25 | - Test bad indentation 4: 26 | 27 | ``` 28 | Here is some text. 29 | ``` 30 | 31 | --- 32 | 33 | - ``` 34 | This will not work. 35 | ``` 36 | 37 | --- 38 | 39 | > ``` 40 | Test 41 | 42 | will break. 43 | ``` 44 | 45 | --- 46 | 47 | - Test bad indentation blockquote 48 | 49 | > ``` 50 | > Test 51 | > will break 52 | > ``` 53 | 54 | --- 55 | 56 | - Test block quote exceeding start level 57 | 58 | > ``` 59 | > Test 60 | >>will 61 | >>break 62 | >>``` 63 | 64 | --- 65 | 66 | - Unexpected block quote 67 | 68 | ``` 69 | Test 70 | will 71 | > break 72 | ``` 73 | 74 | --- 75 | 76 | - Block quote unalignment 77 | 78 | >``` 79 | Test 80 | Will 81 | break 82 | ``` 83 | 84 | --- 85 | 86 | - Block quote unalignment 87 | 88 | >``` 89 | Test 90 | Will 91 | break 92 | ``` 93 | 94 | --- 95 | 96 | - Bad attribute list 97 | 98 | ``` { python } 99 | import test 100 | ``` 101 | 102 | --- 103 | 104 | - Missing closing bracket 105 | 106 | ``` { .python 107 | import test 108 | ``` 109 | 110 | --- 111 | 112 | - Missing opening bracket 113 | 114 | ``` .python } 115 | import test 116 | ``` 117 | 118 | --- 119 | 120 | - Additional class outside of attribute list 121 | 122 | ```python .class 123 | import test 124 | ``` 125 | -------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (no indent blocks).html: -------------------------------------------------------------------------------- 1 |

This will not be parsed 2 | as a normal indented code block. 3 | It will be parsed as a fenced block.

-------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (no indent blocks).txt: -------------------------------------------------------------------------------- 1 | This will not be parsed 2 | as a normal indented code block. 3 | It will be parsed as a fenced block. 4 | -------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (no pygments).html: -------------------------------------------------------------------------------- 1 |
import test
2 |

Text after code.

3 |
import test
4 |

Attribute List

5 |
"""Some file."""
6 | import foo.bar
7 | import boo.baz
8 | import foo.bar.baz
-------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (no pygments).txt: -------------------------------------------------------------------------------- 1 | ```python 2 | import test 3 | ``` 4 | 5 | Text after code. 6 | 7 | ```python 8 | import test 9 | ``` 10 | 11 | # Attribute List 12 | 13 | ```{ .python #id .another-class linenums="1" } 14 | """Some file.""" 15 | import foo.bar 16 | import boo.baz 17 | import foo.bar.baz 18 | ``` 19 | -------------------------------------------------------------------------------- /tests/extensions/superfences/superfences (preserve tabs).txt: -------------------------------------------------------------------------------- 1 | # Neseted Fences: 2 | 3 | ``` 4 | This will still be parsed 5 | as a normal indented code block. 6 | ``` 7 | 8 | ``` 9 | This will still be parsed 10 | as a fenced code block. 11 | ``` 12 | 13 | - 14 | ``` 15 | This will work. 16 | ``` 17 | 18 | - This is a list that contains multiple code blocks. 19 | 20 | - Here is an indented block 21 | 22 | ``` 23 | This will still be parsed 24 | as a normal indented code block. 25 | ``` 26 | 27 | - Here is a fenced code block: 28 | 29 | ``` 30 | This will still be parsed 31 | as a fenced code block. 32 | ``` 33 | 34 | > ``` 35 | > Blockquotes? 36 | 37 | > Not a problem! 38 | > ``` 39 | 40 | - Fenced block with lesser child fence. 41 | 42 | ```` 43 | ``` 44 | Fenced block containing fenced syntax. 45 | ``` 46 | ```` 47 | 48 | ```` 49 | ``` 50 | Fenced block containing fenced syntax. 51 | ``` 52 | ```` 53 | 54 | - Fenced block with greater child fence: 55 | 56 | ``` 57 | ```` 58 | Fenced block containing fenced syntax. 59 | ```` 60 | ``` 61 | 62 | ``` 63 | ```` 64 | Fenced block containing fenced syntax. 65 | ```` 66 | ``` 67 | 68 | - Fenced block with indented child fence: 69 | 70 | ``` 71 | ``` 72 | Fenced block containing fenced syntax. 73 | ``` 74 | ``` 75 | 76 | - Tabs 77 | 78 | ``` 79 | Test with tabs. 80 | Test with tabs. 81 | Test tabs. 82 | ``` 83 | 84 | ``` 85 | ============================================================ 86 | T Tp Sp D Dp S D7 T 87 | ------------------------------------------------------------ 88 | A F#m Bm E C#m D E7 A 89 | A# Gm Cm F Dm D# F7 A# 90 | B♭ Gm Cm F Dm E♭m F7 B♭ 91 | ``` 92 | 93 | - Here is a highlighted code block with line numbers: 94 | 95 | ```python linenums="1" 96 | """Some file.""" 97 | import foo.bar 98 | import boo.baz 99 | import foo.bar.baz 100 | ``` 101 | 102 | - Here is a highlighted code block with line numbers and line highlighting: 103 | 104 | ```python hl_lines="2 3" linenums="1" 105 | """Some file.""" 106 | import foo.bar 107 | import boo.baz 108 | import foo.bar.baz 109 | ``` 110 | 111 | - Highlight extended language: 112 | 113 | ```php-inline 114 | $a = array("foo" => 0, "bar" => 1); 115 | ``` 116 | 117 | # UML Flow Charts 118 | 119 | ```flow 120 | st=>start: Start:>http://www.google.com[blank] 121 | e=>end:>http://www.google.com 122 | op1=>operation: My Operation 123 | sub1=>subroutine: My Subroutine 124 | cond=>condition: Yes 125 | or No?:>http://www.google.com 126 | io=>inputoutput: catch something... 127 | 128 | st->op1->cond 129 | cond(yes)->io->e 130 | cond(no)->sub1(right)->op1 131 | ``` 132 | 133 | # UML Sequence Diagrams 134 | 135 | ```sequence 136 | Title: Here is a title 137 | A->B: Normal line 138 | B-->C: Dashed line 139 | C->>D: Open arrow 140 | D-->>A: Dashed open arrow 141 | ``` 142 | -------------------------------------------------------------------------------- /tests/extensions/tasklist/tasklist (checkable).html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 |

Task List

9 |
    10 |
  • item 1
      11 |
    • item A
    • 12 |
    • item B 13 | more text
        14 |
      • item a
      • 15 |
      • item b
      • 16 |
      • item c
      • 17 |
      18 |
    • 19 |
    • item C
    • 20 |
    21 |
  • 22 |
  • item 2
  • 23 |
  • item 3
  • 24 |
25 |

Mixed Lists

26 |
    27 |
  • item 1
      28 |
    • item A
    • 29 |
    • item B 30 | more text
        31 |
      1. item a
      2. 32 |
      3. item b
      4. 33 |
      5. item c
      6. 34 |
      35 |
    • 36 |
    • item C
    • 37 |
    38 |
  • 39 |
  • item 2
  • 40 |
  • item 3
  • 41 |
42 |

Really Mixed Lists

43 |
    44 |
  • item 1
      45 |
    • item A
    • 46 |
    • item B 47 | more text
        48 |
      1. item a
      2. 49 |
      3. item b
      4. 50 |
      5. item c
      6. 51 |
      52 |
    • 53 |
    • item C
    • 54 |
    55 |
  • 56 |
  • item 2
  • 57 |
  • item 3
  • 58 |
59 |

Test Tasklists in Subparagraphs

60 |
    61 |
  • 62 |

    item 1

    63 |
      64 |
    • 65 |

      item A

      66 |
    • 67 |
    • 68 |

      item a

      69 |
    • 70 |
    71 |
  • 72 |
73 |
74 | 75 | -------------------------------------------------------------------------------- /tests/extensions/tasklist/tasklist (checkable).txt: -------------------------------------------------------------------------------- 1 | # Task List 2 | 3 | - [X] item 1 4 | * [X] item A 5 | * [ ] item B 6 | more text 7 | + [x] item a 8 | + [ ] item b 9 | + [x] item c 10 | * [X] item C 11 | - [ ] item 2 12 | - [ ] item 3 13 | 14 | # Mixed Lists 15 | 16 | - item 1 17 | * [X] item A 18 | * [ ] item B 19 | more text 20 | 1. item a 21 | 2. item b 22 | 3. item c 23 | * [X] item C 24 | - item 2 25 | - item 3 26 | 27 | # Really Mixed Lists 28 | 29 | - item 1 30 | * [X] item A 31 | - item B 32 | more text 33 | 1. item a 34 | + item b 35 | + [ ] item c 36 | 3. item C 37 | 2. item 2 38 | - [X] item 3 39 | 40 | # Test Tasklists in Subparagraphs 41 | 42 | - [X] item 1 43 | 44 | - [X] item A 45 | 46 | - item a 47 | -------------------------------------------------------------------------------- /tests/extensions/tasklist/tasklist (custom checkable).txt: -------------------------------------------------------------------------------- 1 | # Task List 2 | 3 | - [X] item 1 4 | * [X] item A 5 | * [ ] item B 6 | more text 7 | + [x] item a 8 | + [ ] item b 9 | + [x] item c 10 | * [X] item C 11 | - [ ] item 2 12 | - [ ] item 3 13 | 14 | # Mixed Lists 15 | 16 | - item 1 17 | * [X] item A 18 | * [ ] item B 19 | more text 20 | 1. item a 21 | 2. item b 22 | 3. item c 23 | * [X] item C 24 | - item 2 25 | - item 3 26 | 27 | # Really Mixed Lists 28 | 29 | - item 1 30 | * [X] item A 31 | - item B 32 | more text 33 | 1. item a 34 | + item b 35 | + [ ] item c 36 | 3. item C 37 | 2. item 2 38 | - [X] item 3 39 | 40 | # Test Tasklists in Subparagraphs 41 | 42 | - [X] item 1 43 | 44 | - [X] item A 45 | 46 | - item a 47 | -------------------------------------------------------------------------------- /tests/extensions/tasklist/tasklist (custom).txt: -------------------------------------------------------------------------------- 1 | # Task List 2 | 3 | - [X] item 1 4 | * [X] item A 5 | * [ ] item B 6 | more text 7 | + [x] item a 8 | + [ ] item b 9 | + [x] item c 10 | * [X] item C 11 | - [ ] item 2 12 | - [ ] item 3 13 | 14 | # Mixed Lists 15 | 16 | - item 1 17 | * [X] item A 18 | * [ ] item B 19 | more text 20 | 1. item a 21 | 2. item b 22 | 3. item c 23 | * [X] item C 24 | - item 2 25 | - item 3 26 | 27 | # Really Mixed Lists 28 | 29 | - item 1 30 | * [X] item A 31 | - item B 32 | more text 33 | 1. item a 34 | + item b 35 | + [ ] item c 36 | 3. item C 37 | 2. item 2 38 | - [X] item 3 39 | 40 | # Test Tasklists in Subparagraphs 41 | 42 | - [X] item 1 43 | 44 | - [X] item A 45 | 46 | - item a 47 | -------------------------------------------------------------------------------- /tests/extensions/tasklist/tasklist.txt: -------------------------------------------------------------------------------- 1 | # Task List 2 | 3 | - [X] item 1 4 | * [X] item A 5 | * [ ] item B 6 | more text 7 | + [x] item a 8 | + [ ] item b 9 | + [x] item c 10 | * [X] item C 11 | - [ ] item 2 12 | - [ ] item 3 13 | 14 | # Mixed Lists 15 | 16 | - item 1 17 | * [X] item A 18 | * [ ] item B 19 | more text 20 | 1. item a 21 | 2. item b 22 | 3. item c 23 | * [X] item C 24 | - item 2 25 | - item 3 26 | 27 | # Really Mixed Lists 28 | 29 | - item 1 30 | * [X] item A 31 | - item B 32 | more text 33 | 1. item a 34 | + item b 35 | + [ ] item c 36 | 3. item C 37 | 2. item 2 38 | - [X] item 3 39 | 40 | # Test Tasklists in Subparagraphs 41 | 42 | - [X] item 1 43 | 44 | - [X] item A 45 | 46 | - item a 47 | 48 | # Test Tasklists Spanning Multiple Lines 49 | 50 | * [ ] The text on this line will be rendered, and the text on the 51 | second line should work as well. 52 | * [ ] It should also still work if you do any kind of 53 | special content. For instance, *right here* it should still continue 54 | working. And using `preformatted` or some 55 | other type of content should work too. 56 | -------------------------------------------------------------------------------- /tests/extensions/tasklist/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | tasklist: 4 | css: 5 | - ../_assets/tasklist.css 6 | extensions: 7 | pymdownx.tasklist: 8 | 9 | tasklist (custom): 10 | css: 11 | - ../_assets/tasklist_custom.css 12 | extensions: 13 | pymdownx.tasklist: 14 | custom_checkbox: true 15 | 16 | tasklist (checkable): 17 | css: 18 | - ../_assets/tasklist.css 19 | extensions: 20 | pymdownx.tasklist: 21 | clickable_checkbox: true 22 | 23 | tasklist (custom checkable): 24 | css: 25 | - ../_assets/tasklist_custom.css 26 | extensions: 27 | pymdownx.tasklist: 28 | custom_checkbox: true 29 | clickable_checkbox: true 30 | 31 | -------------------------------------------------------------------------------- /tests/extensions/tilde/tests.yml: -------------------------------------------------------------------------------- 1 | __default__: {} 2 | 3 | tilde: 4 | extensions: 5 | pymdownx.tilde: 6 | 7 | tilde (dumb): 8 | extensions: 9 | pymdownx.tilde: 10 | smart_delete: false 11 | 12 | tilde (dumb no sub): 13 | extensions: 14 | pymdownx.tilde: 15 | smart_delete: false 16 | subscript: false 17 | 18 | tilde (no delete): 19 | extensions: 20 | pymdownx.tilde: 21 | delete: false 22 | 23 | tilde (no sub): 24 | extensions: 25 | pymdownx.tilde: 26 | subscript: false 27 | -------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (dumb no sub).html: -------------------------------------------------------------------------------- 1 |

Test: ~~ Won't delete ~~

2 |

Test: Will delete

3 |

Test: ~~Escaped~~

4 |

Test: All will ~ be deleted

5 |

Test: All will~ not be deleted~~

6 |

Test: All will ~~~ be deleted

-------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (dumb no sub).txt: -------------------------------------------------------------------------------- 1 | Test: ~~ Won't delete ~~ 2 | 3 | Test: ~~Will delete~~ 4 | 5 | Test: \~\~Escaped\~\~ 6 | 7 | Test: ~~All will ~ be deleted~~ 8 | 9 | Test: ~~All will~~~ not be deleted~~ 10 | 11 | Test: ~~All will ~~~ be deleted~~ 12 | -------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (dumb).html: -------------------------------------------------------------------------------- 1 |

CH3CH2OH

2 |

Textsubscript

3 |

Text~subscript failed~

4 |

Textsubscript success

5 |

Test: ~~ Won't delete ~~

6 |

Test: Will delete

7 |

Test: ~~Escaped~~

8 |

Test: All will ~ be deleted

9 |

Test: All will~ be deleted with subscript in middle

10 |

Test: All will ~ be deleted with subscript in middle

11 |

Test: Subscript ~~~

-------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (dumb).txt: -------------------------------------------------------------------------------- 1 | CH~3~CH~2~OH 2 | 3 | Text~subscript~ 4 | 5 | Text~subscript failed~ 6 | 7 | Text~subscript\ success~ 8 | 9 | Test: ~~ Won't delete ~~ 10 | 11 | Test: ~~Will delete~~ 12 | 13 | Test: \~\~Escaped\~\~ 14 | 15 | Test: ~~All will ~ be deleted~~ 16 | 17 | Test: ~~All will~\~~ be deleted with subscript in middle~~ 18 | 19 | Test: ~~All will ~\~~ be deleted with subscript in middle~~ 20 | 21 | Test: Subscript ~~~ 22 | -------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (no delete).html: -------------------------------------------------------------------------------- 1 |

CH3CH2OH

2 |

Textsubscript

3 |

Text~subscript failed~

4 |

Textsubscript success

5 |

Test: ~~Won't delete~~

-------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (no delete).txt: -------------------------------------------------------------------------------- 1 | CH~3~CH~2~OH 2 | 3 | Text~subscript~ 4 | 5 | Text~subscript failed~ 6 | 7 | Text~subscript\ success~ 8 | 9 | Test: ~~Won't delete~~ 10 | -------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (no sub).html: -------------------------------------------------------------------------------- 1 |

Test: ~~ Won't delete ~~

2 |

Test: Will delete

3 |

Test: ~~Escaped~~

4 |

Test: This will all be deleted ~~because of the placement of the center tilde.

5 |

Test: This will all be deleted ~~ because of the placement of the center tilde.

6 |

Test: This will NOT all be deleted because of the placement of the center tilde.~~

7 |

Test: This will all be deleted~ because of the token is less than that of the tilde.

-------------------------------------------------------------------------------- /tests/extensions/tilde/tilde (no sub).txt: -------------------------------------------------------------------------------- 1 | Test: ~~ Won't delete ~~ 2 | 3 | Test: ~~Will delete~~ 4 | 5 | Test: \~\~Escaped\~\~ 6 | 7 | Test: ~~This will all be deleted ~~because of the placement of the center tilde.~~ 8 | 9 | Test: ~~This will all be deleted ~~ because of the placement of the center tilde.~~ 10 | 11 | Test: ~~This will NOT all be deleted~~ because of the placement of the center tilde.~~ 12 | 13 | Test: ~~This will all be deleted~ because of the token is less than that of the tilde.~~ 14 | -------------------------------------------------------------------------------- /tests/extensions/tilde/tilde.html: -------------------------------------------------------------------------------- 1 |

CH3CH2OH

2 |

Textsubscript

3 |

Text~subscript failed~

4 |

Textsubscript success

5 |

Test: ~~ Won't delete ~~

6 |

Test: Will delete

7 |

Test: ~~Escaped~~

8 |

Test: This will all be deleted ~~because of the placement of the center tilde.

9 |

Test: This will all be deleted ~~ because of the placement of the center tilde.

10 |

Test: This will NOT all be deleted because of the placement of the center tilde.~~

11 |

Test: This will all be deleted~ because of the token is less than that of the tilde.

-------------------------------------------------------------------------------- /tests/extensions/tilde/tilde.txt: -------------------------------------------------------------------------------- 1 | CH~3~CH~2~OH 2 | 3 | Text~subscript~ 4 | 5 | Text~subscript failed~ 6 | 7 | Text~subscript\ success~ 8 | 9 | Test: ~~ Won't delete ~~ 10 | 11 | Test: ~~Will delete~~ 12 | 13 | Test: \~\~Escaped\~\~ 14 | 15 | Test: ~~This will all be deleted ~~because of the placement of the center tilde.~~ 16 | 17 | Test: ~~This will all be deleted ~~ because of the placement of the center tilde.~~ 18 | 19 | Test: ~~This will NOT all be deleted~~ because of the placement of the center tilde.~~ 20 | 21 | Test: ~~This will all be deleted~ because of the token is less than that of the tilde.~~ 22 | -------------------------------------------------------------------------------- /tests/test_extensions/__init__.py: -------------------------------------------------------------------------------- 1 | """Test Extensions.""" 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_assets/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tiangolo/pymdown-extensions/6d2d8e5bee0b7c68732618cbc016e78fb3908de2/tests/test_extensions/_assets/bg.png -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/a.txt: -------------------------------------------------------------------------------- 1 | ---8<--- "b.txt" 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/b.txt: -------------------------------------------------------------------------------- 1 | Snippet 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/c.txt: -------------------------------------------------------------------------------- 1 | ---8<--- 2 | b.txt 3 | ---8<--- 4 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/d.txt: -------------------------------------------------------------------------------- 1 | Snippet 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/indented.txt: -------------------------------------------------------------------------------- 1 | class SomeClass: 2 | """Docstring.""" 3 | 4 | # --8<-- [start: py-section] 5 | def some_method(self, param): 6 | """Docstring.""" 7 | 8 | return param 9 | # --8<-- [end: py-section] 10 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/lines.txt: -------------------------------------------------------------------------------- 1 | This is a multi-line 2 | snippet. 3 | 4 | Content resides on various lines. 5 | If we use line specifiers, 6 | we can select any number of lines we want. 7 | 8 | This is the end of the file. 9 | There is no more. 10 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/loop.txt: -------------------------------------------------------------------------------- 1 | ---8<--- "loop.txt" 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/loop_block.txt: -------------------------------------------------------------------------------- 1 | ---8<--- 2 | loop_block.txt 3 | ---8<--- 4 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/missing.txt: -------------------------------------------------------------------------------- 1 | --8<-- "not-here.txt" 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/nested/nested.txt: -------------------------------------------------------------------------------- 1 | Snippet 2 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/section.txt: -------------------------------------------------------------------------------- 1 | /* --8<-- [start: css-section] */ 2 | div { 3 | color: red; 4 | } 5 | /* --8<-- [end: css-section] */ 6 | 7 | 8 |

content

9 | 10 | 11 | /* --8<-- [end: css-section2] */ 12 | /* --8<-- [start: css-section2] */ 13 | div { 14 | color: red; 15 | } 16 | /* --8<-- [end: css-section2] */ 17 | 18 | 19 |

content

20 | -------------------------------------------------------------------------------- /tests/test_extensions/_snippets/section_nested.txt: -------------------------------------------------------------------------------- 1 | /* --8<-- [start: css-section] */ 2 | div { 3 | color: red; 4 | /* --8<-- [start: css-section2] */ 5 | background-color: white; 6 | padding: 16px 7 | /* --8<-- [end: css-section2] */ 8 | } 9 | /* --8<-- [end: css-section] */ 10 | 11 | 12 | /* --8<-- [start: css-section3] */ 13 | div { 14 | color: red; 15 | /* ;--8<-- [start: css-section4] */ 16 | background-color: white; 17 | padding: 16px 18 | /* ;--8<-- [end: css-section4] */ 19 | } 20 | /* --8<-- [end: css-section3] */ 21 | 22 | /* --8<-- [start: css-section5] */ 23 | div { 24 | color: red; 25 | /* --8<-- [start: css-section5] */ 26 | background-color: white; 27 | padding: 16px 28 | } 29 | /* --8<-- [end: css-section5] */ 30 | -------------------------------------------------------------------------------- /tests/test_extensions/test_blocks/__init__.py: -------------------------------------------------------------------------------- 1 | """Test blocks.""" 2 | -------------------------------------------------------------------------------- /tests/test_extensions/test_emoji.py: -------------------------------------------------------------------------------- 1 | """Test cases for Highlight.""" 2 | from .. import util 3 | import pytest 4 | import pymdownx.emoji as emoji 5 | import markdown 6 | 7 | 8 | def _old_style_index(): 9 | """Custom index with no arguments (old style).""" 10 | 11 | return emoji.twemoji({}, None) 12 | 13 | 14 | def _new_style_index(options, md): 15 | """Custom index with arguments (new style).""" 16 | 17 | index = emoji.twemoji({}, None) 18 | 19 | if 'append_alias' in options: 20 | for alias, original in options['append_alias']: 21 | index['aliases'][alias] = original 22 | 23 | return index 24 | 25 | 26 | class TestEmojiOldIndex(util.MdCase): 27 | """Test old style index.""" 28 | 29 | extension = [ 30 | 'pymdownx.emoji' 31 | ] 32 | extension_configs = { 33 | 'pymdownx.emoji': { 34 | 'emoji_index': _old_style_index 35 | } 36 | } 37 | 38 | @pytest.mark.filterwarnings("ignore") 39 | def test_old_index(self): 40 | """Test that index works.""" 41 | 42 | with pytest.warns(DeprecationWarning): 43 | self.assertEqual( 44 | markdown.Markdown( 45 | extensions=self.extension, 46 | extension_configs=self.extension_configs 47 | ).convert(':smile:'), 48 | '

\U0001f604

' # noqa: E501 49 | ) 50 | 51 | 52 | class TestEmojiNewIndex(util.MdCase): 53 | """Test new style index.""" 54 | 55 | extension = [ 56 | 'pymdownx.emoji' 57 | ] 58 | extension_configs = { 59 | 'pymdownx.emoji': { 60 | 'emoji_index': _new_style_index, 61 | 'options': {'append_alias': [(':grin:', ":smile:")]} 62 | } 63 | } 64 | 65 | def test_new_index(self): 66 | """Test that we can pass options using the new style.""" 67 | 68 | self.check_markdown( 69 | ':grin:', 70 | '

\U0001f604

' # noqa: E501 71 | ) 72 | -------------------------------------------------------------------------------- /tests/test_extensions/test_escapeall.py: -------------------------------------------------------------------------------- 1 | """Test cases for BetterEm.""" 2 | from .. import util 3 | 4 | 5 | class TestEscapeAll(util.MdCase): 6 | """Test escaping cases.""" 7 | 8 | extension = [ 9 | 'pymdownx.escapeall' 10 | ] 11 | extension_configs = {} 12 | 13 | def test_html_special_char_lt(self): 14 | """Test `<`.""" 15 | 16 | self.check_markdown( 17 | r'\
foo',
18 |             '

<pre>foo

' 19 | ) 20 | 21 | def test_html_special_char_gt(self): 22 | """Test `>`.""" 23 | 24 | self.check_markdown( 25 | r'foo', 26 | '

<span>foo

' 27 | ) 28 | 29 | def test_html_special_char_amp(self): 30 | """Test `&`.""" 31 | 32 | self.check_markdown( 33 | r'This \& that', 34 | '

This & that

' 35 | ) 36 | 37 | def test_normal_escape(self): 38 | """Test normal escapes.""" 39 | 40 | self.check_markdown( 41 | r'This & \that', 42 | '

This & that

' 43 | ) 44 | -------------------------------------------------------------------------------- /tests/test_extensions/test_keys.py: -------------------------------------------------------------------------------- 1 | """Test cases for Keys.""" 2 | from .. import util 3 | 4 | 5 | class TestKeys(util.MdCase): 6 | """Tests for Keys.""" 7 | 8 | extension = [ 9 | 'pymdownx.keys' 10 | ] 11 | 12 | def test_avoid_base64(self): 13 | """Test complex case where `**text*text***` may be detected on accident.""" 14 | 15 | self.check_markdown( 16 | "![](data:image/png;base64,aaaaa++a++aaaa) ++ctrl+a++ ++ctrl+'custom'++", 17 | '

Ctrl+A Ctrl+custom

' # noqa: E501 18 | ) 19 | -------------------------------------------------------------------------------- /tests/test_extensions/test_saneheaders.py: -------------------------------------------------------------------------------- 1 | """Test cases for SaneHeaders.""" 2 | from .. import util 3 | 4 | 5 | class TestSaneHeadersWithMagicLink(util.MdCase): 6 | """Test cases for SaneHeaders and MagicLink (the motivation behind creating SaneHeaders).""" 7 | 8 | extension = [ 9 | 'pymdownx.saneheaders', 10 | 'pymdownx.magiclink', 11 | ] 12 | 13 | extension_configs = { 14 | 'pymdownx.magiclink': { 15 | 'repo_url_shorthand': True, 16 | 'user': 'facelessuser', 17 | 'repo': 'pymdown-extensions' 18 | } 19 | } 20 | 21 | def test_header1(self): 22 | """Test header level 1.""" 23 | 24 | self.check_markdown( 25 | r'# Header', 26 | r'

Header

' 27 | ) 28 | 29 | def test_header2(self): 30 | """Test header level 2.""" 31 | 32 | self.check_markdown( 33 | r'## Header', 34 | r'

Header

' 35 | ) 36 | 37 | def test_header3(self): 38 | """Test header level 3.""" 39 | 40 | self.check_markdown( 41 | r'### Header', 42 | r'

Header

' 43 | ) 44 | 45 | def test_header4(self): 46 | """Test header level 4.""" 47 | 48 | self.check_markdown( 49 | r'#### Header', 50 | r'

Header

' 51 | ) 52 | 53 | def test_header5(self): 54 | """Test header level 5.""" 55 | 56 | self.check_markdown( 57 | r'##### Header', 58 | r'
Header
' 59 | ) 60 | 61 | def test_header6(self): 62 | """Test header level 6.""" 63 | 64 | self.check_markdown( 65 | r'###### Header', 66 | r'
Header
' 67 | ) 68 | 69 | def test_header_trailing(self): 70 | """Test header trailing hashes.""" 71 | 72 | self.check_markdown( 73 | r'## Header ##', 74 | r'

Header

' 75 | ) 76 | 77 | def test_too_many_hashes(self): 78 | """Test header with too many hashes.""" 79 | 80 | self.check_markdown( 81 | r'####### Header', 82 | r'

####### Header

' 83 | ) 84 | 85 | def test_no_header(self): 86 | """Test no header match.""" 87 | 88 | self.check_markdown( 89 | r'##Header', 90 | r'

##Header

' 91 | ) 92 | 93 | def test_header_with_magiclink(self): 94 | """Test no header match.""" 95 | 96 | self.check_markdown( 97 | r'#3', 98 | r'

#3

' # noqa: E501 99 | ) 100 | -------------------------------------------------------------------------------- /tests/test_extensions/test_striphmtl.py: -------------------------------------------------------------------------------- 1 | """Test cases for StripHTML.""" 2 | from .. import util 3 | 4 | 5 | class TestStripHTML(util.MdCase): 6 | """Test legacy stripping in HTML.""" 7 | 8 | extension = ['pymdownx.striphtml'] 9 | extension_configs = {} 10 | 11 | def test_multiple_inline(self): 12 | """Test multiple inline.""" 13 | 14 | self.check_markdown( 15 | r''' 16 | Comments test: 17 | 18 | 19 | - One 20 | - Two 21 | - Three 22 | 23 | 24 | ## Paragraph 25 | 26 | 27 | - One 28 | - Two 29 | - Three 30 | 31 | Comments test end 32 | ''', 33 | r''' 34 |

Comments test:

35 |
    36 |
  • One
  • 37 |
  • Two
  • 38 |
  • Three
  • 39 |
40 |

Paragraph

41 |
    42 |
  • One
  • 43 |
  • Two
  • 44 |
  • Three
  • 45 |
46 |

Comments test end

47 | ''', 48 | True 49 | ) 50 | -------------------------------------------------------------------------------- /tools/__init__.py: -------------------------------------------------------------------------------- 1 | """Tools.""" 2 | -------------------------------------------------------------------------------- /tools/gen_emoji1.py: -------------------------------------------------------------------------------- 1 | """Generate emojione data.""" 2 | import os 3 | import json 4 | current_dir = os.path.dirname(os.path.abspath(__file__)) 5 | LICENSE = """ 6 | MIT license. 7 | 8 | Copyright (c) http://www.emojione.com 9 | """ 10 | 11 | 12 | def get_unicode_alt(value): 13 | """Get alternate Unicode form or return the original.""" 14 | 15 | return value['unicode_alt'] 16 | 17 | 18 | def parse(repo, tag): 19 | """Save test files.""" 20 | # Load emoji database 21 | with open(os.path.join(current_dir, 'tags', repo, repo, 'emoji.json')) as f: 22 | emojis = json.loads(f.read()) 23 | 24 | emoji_db = {} 25 | shortnames = set() 26 | aliases = {} 27 | for v in emojis.values(): 28 | shortnames.add(v['shortname']) 29 | emoji_db[v['shortname']] = { 30 | 'name': v['name'], 31 | 'unicode': v['unicode'], 32 | 'category': v['category'] 33 | } 34 | alt = get_unicode_alt(v) 35 | if alt: 36 | emoji_db[v['shortname']]['unicode_alt'] = alt 37 | 38 | for alias in v['aliases']: 39 | aliases[alias] = v['shortname'] 40 | 41 | # Save test files 42 | for test in ('png', 'png sprite', 'svg', 'svg sprite', 'entities', 'long title', 'no title'): 43 | with open('../tests/extensions/emoji/emoji1 (%s).txt' % test, 'w') as f: 44 | f.write('# Emojis\n') 45 | count = 0 46 | for emoji in sorted(shortnames): 47 | f.write(''.join('{} {}
\n'.format(emoji[1:-1], emoji))) 48 | count += 1 49 | if test != 'png' and count == 10: 50 | break 51 | 52 | # Write out essential info 53 | with open('../pymdownx/emoji1_db.py', 'w') as f: 54 | # Dump emoji db to file and strip out PY2 unicode specifiers 55 | f.write('"""Emojione autogen.\n\nGenerated from emojione source. Do not edit by hand.\n%s"""\n' % LICENSE) 56 | f.write('version = "%s"\n' % tag) 57 | f.write('name = "emojione"\n') 58 | f.write('emoji = %s\n' % json.dumps(emoji_db, sort_keys=True, indent=4, separators=(',', ': '))) 59 | f.write('aliases = %s\n' % json.dumps(aliases, sort_keys=True, indent=4, separators=(',', ': '))) 60 | -------------------------------------------------------------------------------- /tools/gen_joypixels.py: -------------------------------------------------------------------------------- 1 | """Generate emojione data.""" 2 | import os 3 | import json 4 | current_dir = os.path.dirname(os.path.abspath(__file__)) 5 | LICENSE = """ 6 | MIT license. 7 | 8 | Copyright (c) http://www.emojione.com 9 | """ 10 | 11 | 12 | def get_unicode_alt(value): 13 | """Get alternate Unicode form or return the original.""" 14 | 15 | return value['code_points']['fully_qualified'] 16 | 17 | 18 | def parse(repo, tag): 19 | """Save test files.""" 20 | # Load emoji database 21 | with open(os.path.join(current_dir, 'tags', repo, repo, 'emoji.json')) as f: 22 | emojis = json.loads(f.read()) 23 | 24 | emoji_db = {} 25 | shortnames = set() 26 | aliases = {} 27 | for v in emojis.values(): 28 | shortnames.add(v['shortname']) 29 | emoji_db[v['shortname']] = { 30 | 'name': v['name'], 31 | 'unicode': v['code_points']['base'], 32 | 'category': v['category'] 33 | } 34 | alt = get_unicode_alt(v) 35 | if alt and alt != v['code_points']['base']: 36 | emoji_db[v['shortname']]['unicode_alt'] = alt 37 | 38 | for alias in v['shortname_alternates']: 39 | aliases[alias] = v['shortname'] 40 | 41 | return emoji_db, aliases 42 | -------------------------------------------------------------------------------- /tools/pymdownx_md_render.py: -------------------------------------------------------------------------------- 1 | """Generate Markdown isolated from our current document options.""" 2 | import markdown 3 | import yaml 4 | import re 5 | from collections import OrderedDict 6 | 7 | 8 | def yaml_load(stream, loader=yaml.Loader): 9 | """ 10 | Custom YAML loader. 11 | 12 | Load all strings as Unicode. 13 | http://stackoverflow.com/a/2967461/3609487 14 | """ 15 | 16 | def construct_yaml_str(self, node): 17 | """Override the default string handling function to always return Unicode objects.""" 18 | 19 | return self.construct_scalar(node) 20 | 21 | class Loader(loader): 22 | """Custom Loader.""" 23 | 24 | Loader.add_constructor( 25 | 'tag:yaml.org,2002:str', 26 | construct_yaml_str 27 | ) 28 | 29 | return yaml.load(stream, Loader) 30 | 31 | 32 | def get_frontmatter(text): 33 | """Get front matter from string.""" 34 | 35 | frontmatter = OrderedDict() 36 | 37 | if text.startswith("---"): 38 | m = re.search(r'^(-{3}\r?\n(?!\r?\n)(.*?)(?<=\n)(?:-{3}|\.{3})\r?\n)', text, re.DOTALL) 39 | if m: 40 | yaml_okay = True 41 | try: 42 | frontmatter = yaml_load(m.group(2)) 43 | if frontmatter is None: 44 | frontmatter = OrderedDict() 45 | # If we didn't get a dictionary, we don't want this as it isn't front matter. 46 | assert isinstance(frontmatter, (dict, OrderedDict)), TypeError 47 | except Exception: 48 | # We had a parsing error. This is not the YAML we are looking for. 49 | yaml_okay = False 50 | frontmatter = OrderedDict() 51 | 52 | if yaml_okay: 53 | text = text[m.end(1):] 54 | 55 | return frontmatter, text 56 | 57 | 58 | def md_sub_render(src="", language="", class_name=None, options=None, md="", **kwargs): 59 | """Formatter wrapper.""" 60 | try: 61 | fm, text = get_frontmatter(src) 62 | md = markdown.markdown( 63 | text, 64 | extensions=fm.get('extensions', []), 65 | extension_configs=fm.get('extension_configs', {}) 66 | ) 67 | return md 68 | except Exception: 69 | import traceback 70 | print(traceback.format_exc()) 71 | raise 72 | --------------------------------------------------------------------------------