pax_global_header00006660000000000000000000000064145274506340014524gustar00rootroot0000000000000052 comment=4a4d2598a4fcac1a9c187882d368ca138be7a8c1 mkdocs-material-extensions-1.3.1/000077500000000000000000000000001452745063400167775ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/.codecov.yml000066400000000000000000000000651452745063400212230ustar00rootroot00000000000000comment: false coverage: status: patch: false mkdocs-material-extensions-1.3.1/.coveragerc000066400000000000000000000001201452745063400211110ustar00rootroot00000000000000[run] omit= materialx/__meta__.py [report] omit= materialx/__meta__.py mkdocs-material-extensions-1.3.1/.dictionary000066400000000000000000000003221452745063400211420ustar00rootroot00000000000000Accessors Changelog FontAwesome MERCHANTABILITY MkDocs NONINFRINGEMENT Octicons PyMdown PyPI SVG Twemoji accessor dedent glob inlined inlining macOS namespace pre pre prerelease prereleases sublicense unittest mkdocs-material-extensions-1.3.1/.github/000077500000000000000000000000001452745063400203375ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/.github/labels.yml000066400000000000000000000005741452745063400223320ustar00rootroot00000000000000template: 'facelessuser:master-labels:labels.yml:master' # Wildcard labels brace_expansion: true extended_glob: true rules: - labels: ['C: infrastructure'] patterns: ['*|@(requirements|.github)/**|-*.md'] - labels: ['C: source'] patterns: ['materialx/**'] - labels: ['C: tests'] patterns: ['tests/**'] - labels: ['C: docs'] patterns: ['docs/**|*.md'] mkdocs-material-extensions-1.3.1/.github/workflows/000077500000000000000000000000001452745063400223745ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/.github/workflows/build.yml000066400000000000000000000035361452745063400242250ustar00rootroot00000000000000name: build on: push: branches: - 'master' tags: - '**' pull_request: branches: - '**' jobs: tests: strategy: fail-fast: false max-parallel: 5 matrix: platform: [ubuntu-latest, windows-latest] python-version: [3.8, 3.9, '3.10', 3.11, 3.12] env: TOXENV: ${{ matrix.tox-env }} runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} allow-prereleases: true - name: Install dependencies run: | python -m pip install --upgrade pip build tox coverage codecov - name: Test run: | python -m tox -e py - name: Upload Results if: success() uses: codecov/codecov-action@v1 with: file: ./coverage.xml flags: unittests name: ${{ matrix.platform }}-${{ matrix.python-version }} fail_ci_if_error: false lint: env: TOXENV: lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: 3.11 - name: Install dependencies run: | python -m pip install --upgrade pip build tox - name: Lint run: | python -m tox documents: env: TOXENV: documents runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: 3.11 - name: Install dependencies run: | python -m pip install --upgrade pip build tox - name: Install Aspell run: | sudo apt-get install aspell aspell-en - name: Build documents run: | python -m tox mkdocs-material-extensions-1.3.1/.github/workflows/deploy.yml000066400000000000000000000007471452745063400244230ustar00rootroot00000000000000name: deploy on: push: tags: - '*' jobs: pypi: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: python-version: '3.11' - name: Package run: | pip install --upgrade build python -m build -s -w - name: Publish uses: pypa/gh-action-pypi-publish@release/v1 with: user: __token__ password: ${{ secrets.PYPI_TOKEN }} mkdocs-material-extensions-1.3.1/.gitignore000066400000000000000000000034221452745063400207700ustar00rootroot00000000000000.DS_Store # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ wheels/ pip-wheel-metadata/ share/python-wheels/ *.egg-info/ .installed.cfg *.egg MANIFEST # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *.cover *.py,cover .hypothesis/ .pytest_cache/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py db.sqlite3 db.sqlite3-journal # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # Jupyter Notebook .ipynb_checkpoints # IPython profile_default/ ipython_config.py # pyenv .python-version # pipenv # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. # However, in case of collaboration, if having platform-specific dependencies or dependencies # having no cross-platform support, pipenv may install dependencies that don't work, or not # install all needed dependencies. #Pipfile.lock # PEP 582; used by e.g. github.com/David-OConnor/pyflow __pypackages__/ # Celery stuff celerybeat-schedule celerybeat.pid # SageMath parsed files *.sage.py # Environments .env .venv env/ venv/ ENV/ env.bak/ venv.bak/ # Spyder project settings .spyderproject .spyproject # Rope project settings .ropeproject # mkdocs documentation /site # mypy .mypy_cache/ .dmypy.json dmypy.json # Pyre type checker .pyre/ mkdocs-material-extensions-1.3.1/.pyspelling.yml000066400000000000000000000030041452745063400217630ustar00rootroot00000000000000matrix: - name: markdown sources: - '*.md' aspell: lang: en dictionary: wordlists: - .dictionary output: build/dictionary/markdown.dic pipeline: - pyspelling.filters.markdown: markdown_extensions: - pymdownx.superfences: - pymdownx.highlight: - pyspelling.filters.html: comments: false attributes: - title - alt ignores: - 'code, pre' - pyspelling.filters.url: - name: python sources: - materialx/**/*.py - tests/**/*.py aspell: lang: en dictionary: wordlists: - .dictionary output: build/dictionary/python.dic pipeline: - pyspelling.filters.python: group_comments: true - pyspelling.flow_control.wildcard: allow: - py-comment - pyspelling.filters.context: context_visible_first: true delimiters: # Ignore lint (noqa) and coverage (pragma) as well as shebang (#!) - open: '^(?: *(?:noqa\b|pragma: no cover)|!)' close: '$' # Ignore Python encoding string -*- encoding stuff -*- - open: '^ *-\*-' close: '-\*-$' - pyspelling.filters.context: context_visible_first: true escapes: '\\[\\`]' delimiters: # Ignore multiline content between fences (fences can have 3 or more back ticks) # ``` # content # ``` - open: '(?s)^(?P *`{3,})$' close: '^(?P=open)$' # Ignore text between inline back ticks - open: '(?P`+)' close: '(?P=open)' - pyspelling.filters.url: mkdocs-material-extensions-1.3.1/LICENSE.md000066400000000000000000000020531452745063400204030ustar00rootroot00000000000000MIT License Copyright (c) 2021 Isaac Muse Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. mkdocs-material-extensions-1.3.1/README.md000066400000000000000000000131731452745063400202630ustar00rootroot00000000000000[![Donate via PayPal][donate-image]][donate-link] [![Build][github-ci-image]][github-ci-link] [![Coverage Status][codecov-image]][codecov-link] [![PyPI Version][pypi-image]][pypi-link] [![PyPI - Python Version][python-image]][pypi-link] ![License][license-image-mit] # MkDocs Material Extensions > NOTE: This project is now deprecated as MkDocs for Material now implements this logic directly. > Users should migrate to using `mkdocs-material`'s `material.extensions.emoji.twemoji` and > `material.extensions.emoji.to_svg` in place of the respective `materialx.emoji.twemoji` and `materialx.emoji.to_svg` > functions provided by this library. Markdown extension resources for [MkDocs for Material][mkdocs-material] ## Install Generally, just installing MkDocs Material will automatically install `mkdocs-material-extensions`. But if you had a need to manually install it, you can use pip. ``` pip install mkdocs-material-extensions ``` But make sure you've also installed MkDocs Material as well as this won't work without it. ``` pip install mkdocs-material ``` ## Inline SVG Icons MkDocs Material provides numerous icons from Material, FontAwesome, and Octicons, but it does so by inlining the SVG icons into the source. Currently there is no easy way access these icons and arbitrarily insert them into Markdown content. Users must include the icon fonts themselves and do it with HTML. This module allows you to use PyMdown Extensions' [Emoji][emoji] extension to enable easy insertion of MkDocs Material's SVG assets using simple `:emoji-syntax:`. This is done by creating our own [emoji index][emoji-index] and [emoji generator][emoji-generator]. The custom index provides a modified version of the Emoji extensions Twemoji index. In addition to the custom index, you must also specify the associated custom generator. This will will find the appropriate icon and insert it into your Markdown content as an inlined SVG. Example: ```yaml markdown_extensions: - pymdownx.emoji: emoji_index: !!python/name:materialx.emoji.twemoji emoji_generator: !!python/name:materialx.emoji.to_svg ``` Then, using the folder structure of Material's `.icons` folder, you can specify icons: ``` We can use Material Icons :material-airplane:. We can also use Fontawesome Icons :fontawesome-solid-ambulance:. That's not all, we can also use Octicons :octicons-octoface:. ``` ## Using Local Custom Icons In MkDocs, you can override theme assets locally, and even add assets to the theme. Unfortunately, the Markdown parsing process isn't aware of the MkDocs environment. Luckily, if you are using PyMdown Extensions 7.1, you can pass in custom icon paths that will be used when constructing the emoji index and include your custom SVG assets. If a folder path of `theme/my_icons` was given to the index builder, all icons under `my_project/my_icons`, even in sub-folders, would become part of the index. ```yaml markdown_extensions: - pymdownx.emoji: emoji_index: !!python/name:materialx.emoji.twemoji emoji_generator: !!python/name:materialx.emoji.to_svg options: custom_icons: - theme/my_icons ``` If given an icon at `my_project/my_icons/animals/bird.svg`, the icon would be available using the emoji syntax as `:animals-bird:`. Notice that the base folder that is provided doesn't contribute to the icon's name. Also, folders are separated with `-`. Folder names and icon names should be compatible with the emoji syntax, so special characters should be avoided -- `-` and `_` are okay. You can provide as many paths as you would like, and they will be evaluated in the order that they are specified. The Material theme's own icons will be evaluated after all custom paths. This allows a user to override Material's icons if desired. If an icon name is already in the index, the icon will not be added. It is recommended to always have your icons in sub-folders to help namespace them to avoid name collisions. In the example above, `bird` was under `animals` which created the name `:animals-bird:` and helped create a more unique name with less of a chance of creating a duplicate name with existing emoji and Material icons. [emoji]: https://facelessuser.github.io/pymdown-extensions/extensions/emoji/ [emoji-index]: https://facelessuser.github.io/pymdown-extensions/extensions/emoji/#custom-emoji-indexes [emoji-generator]: https://facelessuser.github.io/pymdown-extensions/extensions/emoji/#custom-emoji-generators [mkdocs-material]: https://github.com/squidfunk/mkdocs-material [donate-image]: https://img.shields.io/badge/Donate-PayPal-3fabd1?logo=paypal [donate-link]: https://www.paypal.me/facelessuser [github-ci-image]: https://github.com/facelessuser/mkdocs-material-extensions/workflows/build/badge.svg?branch=master&event=push [github-ci-link]: https://github.com/facelessuser/mkdocs-material-extensions/actions?query=workflow%3Abuild+branch%3Amaster [discord-image]: https://img.shields.io/discord/678289859768745989?logo=discord&logoColor=aaaaaa&color=mediumpurple&labelColor=333333 [discord-link]: https://discord.gg/TWs8Tgr [codecov-image]: https://img.shields.io/codecov/c/github/facelessuser/mkdocs-material-extensions/master.svg?logo=codecov&logoColor=aaaaaa&labelColor=333333 [codecov-link]: https://codecov.io/github/facelessuser/mkdocs-material-extensions [pypi-image]: https://img.shields.io/pypi/v/mkdocs-material-extensions.svg?logo=pypi&logoColor=aaaaaa&labelColor=333333 [pypi-link]: https://pypi.python.org/pypi/mkdocs-material-extensions [python-image]: https://img.shields.io/pypi/pyversions/mkdocs-material-extensions?logo=python&logoColor=aaaaaa&labelColor=333333 [license-image-mit]: https://img.shields.io/badge/license-MIT-blue.svg?labelColor=333333 mkdocs-material-extensions-1.3.1/changelog.md000066400000000000000000000027211452745063400212520ustar00rootroot00000000000000# Changelog ## 1.3.1 - **FIX**: Better deprecation warning. ## 1.3 - **NEW**: The final release. `mkdocs-material` (version 9.4) now has this library's logic built-in making this library obsolete. Users should migrate to using `mkdocs-material`'s `material.extensions.emoji.twemoji` and `material.extensions.emoji.to_svg` in place of the respective `materialx.emoji.twemoji` and `materialx.emoji.to_svg` functions. ## 1.2 - **NEW**: Add official support for Python 3.11 and 3.12. - **NEW**: Remove support for Python 3.7. - **FIX**: Update to support latest Material. ## 1.1.1 - **FIX**: Properly handle special glob characters in path. ## 1.1 - **NEW**: Drop Python 3.6 and officially support 3.10. - **NEW**: Cache emoji table to reduce build times. ## 1.0.3 - **FIX**: Remove version check which is not compatible with Material Insiders. Material will completely be responsible for ensuring the correct version of `mkdocs-material-extensions`. ## 1.0.2 - **FIX**: No longer specify `mkdocs-material` as a dependency as `mkdocs-material` specifies these extensions as a dependency. This created a circular dependency. While `pip` has no issues with such scenarios, this created issues for some versioning packages. `mkdocs-material` (the only package this works with) will now manage which version of `mkdocs-material-extensions` it needs. ## 1.0.1 - **FIX**: Ensure we don't modify the original icon path setting. ## 1.0 - **NEW**: First stable release. mkdocs-material-extensions-1.3.1/hatch_build.py000066400000000000000000000030761452745063400216250ustar00rootroot00000000000000"""Dynamically define some metadata.""" import os from hatchling.metadata.plugin.interface import MetadataHookInterface def get_version_dev_status(root): """Get version_info without importing the entire module.""" import importlib.util path = os.path.join(root, "materialx", "__meta__.py") spec = importlib.util.spec_from_file_location("__meta__", path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module.__version_info__._get_dev_status() class CustomMetadataHook(MetadataHookInterface): """Our metadata hook.""" def update(self, metadata): """See https://ofek.dev/hatch/latest/plugins/metadata-hook/ for more information.""" metadata["classifiers"] = [ f"Development Status :: {get_version_dev_status(self.root)}", "Environment :: Console", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", "Topic :: Text Processing :: Filters", "Topic :: Text Processing :: Markup :: HTML", ] mkdocs-material-extensions-1.3.1/materialx/000077500000000000000000000000001452745063400207655ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/materialx/__init__.py000066400000000000000000000000421452745063400230720ustar00rootroot00000000000000"""MkDocs Material Extensions.""" mkdocs-material-extensions-1.3.1/materialx/__meta__.py000066400000000000000000000150251452745063400230640ustar00rootroot00000000000000"""Meta related things.""" from collections import namedtuple import re RE_VER = re.compile( r'''(?x) (?P\d+)(?:\.(?P\d+))?(?:\.(?P\d+))? (?:(?Pa|b|rc)(?P
\d+))?
    (?:\.post(?P\d+))?
    (?:\.dev(?P\d+))?
    '''
)

REL_MAP = {
    ".dev": "",
    ".dev-alpha": "a",
    ".dev-beta": "b",
    ".dev-candidate": "rc",
    "alpha": "a",
    "beta": "b",
    "candidate": "rc",
    "final": ""
}

DEV_STATUS = {
    ".dev": "2 - Pre-Alpha",
    ".dev-alpha": "2 - Pre-Alpha",
    ".dev-beta": "2 - Pre-Alpha",
    ".dev-candidate": "2 - Pre-Alpha",
    "alpha": "3 - Alpha",
    "beta": "4 - Beta",
    "candidate": "4 - Beta",
    "final": "5 - Production/Stable"
}

PRE_REL_MAP = {"a": 'alpha', "b": 'beta', "rc": 'candidate'}


class Version(namedtuple("Version", ["major", "minor", "micro", "release", "pre", "post", "dev"])):
    """
    Get the version (PEP 440).

    A biased approach to the PEP 440 semantic version.

    Provides a tuple structure which is sorted for comparisons `v1 > v2` etc.
      (major, minor, micro, release type, pre-release build, post-release build, development release build)
    Release types are named in is such a way they are comparable with ease.
    Accessors to check if a development, pre-release, or post-release build. Also provides accessor to get
    development status for setup files.

    How it works (currently):

    - You must specify a release type as either `final`, `alpha`, `beta`, or `candidate`.
    - To define a development release, you can use either `.dev`, `.dev-alpha`, `.dev-beta`, or `.dev-candidate`.
      The dot is used to ensure all development specifiers are sorted before `alpha`.
      You can specify a `dev` number for development builds, but do not have to as implicit development releases
      are allowed.
    - You must specify a `pre` value greater than zero if using a prerelease as this project (not PEP 440) does not
      allow implicit prereleases.
    - You can optionally set `post` to a value greater than zero to make the build a post release. While post releases
      are technically allowed in prereleases, it is strongly discouraged, so we are rejecting them. It should be
      noted that we do not allow `post0` even though PEP 440 does not restrict this. This project specifically
      does not allow implicit post releases.
    - It should be noted that we do not support epochs `1!` or local versions `+some-custom.version-1`.

    Acceptable version releases:

    ```
    Version(1, 0, 0, "final")                    1.0
    Version(1, 2, 0, "final")                    1.2
    Version(1, 2, 3, "final")                    1.2.3
    Version(1, 2, 0, "alpha", pre=4)             1.2a4
    Version(1, 2, 0, "beta", pre=4)              1.2b4
    Version(1, 2, 0, "candidate", pre=4)         1.2rc4
    Version(1, 2, 0, "final", post=1)            1.2.post1
    Version(1, 2, 3, ".dev")                     1.2.3.dev0
    Version(1, 2, 3, ".dev", dev=1)              1.2.3.dev1
    ```

    """

    def __new__(cls, major, minor, micro, release="final", pre=0, post=0, dev=0):
        """Validate version info."""

        # Ensure all parts are positive integers.
        for value in (major, minor, micro, pre, post):
            if not (isinstance(value, int) and value >= 0):
                raise ValueError("All version parts except 'release' should be integers.")

        if release not in REL_MAP:
            raise ValueError("'{}' is not a valid release type.".format(release))

        # Ensure valid pre-release (we do not allow implicit pre-releases).
        if ".dev-candidate" < release < "final":
            if pre == 0:
                raise ValueError("Implicit pre-releases not allowed.")
            elif dev:
                raise ValueError("Version is not a development release.")
            elif post:
                raise ValueError("Post-releases are not allowed with pre-releases.")

        # Ensure valid development or development/pre release
        elif release < "alpha":
            if release > ".dev" and pre == 0:
                raise ValueError("Implicit pre-release not allowed.")
            elif post:
                raise ValueError("Post-releases are not allowed with pre-releases.")

        # Ensure a valid normal release
        else:
            if pre:
                raise ValueError("Version is not a pre-release.")
            elif dev:
                raise ValueError("Version is not a development release.")

        return super().__new__(cls, major, minor, micro, release, pre, post, dev)

    def _is_pre(self):
        """Is prerelease."""

        return bool(self.pre > 0)

    def _is_dev(self):
        """Is development."""

        return bool(self.release < "alpha")

    def _is_post(self):
        """Is post."""

        return bool(self.post > 0)

    def _get_dev_status(self):  # pragma: no cover
        """Get development status string."""

        return DEV_STATUS[self.release]

    def _get_canonical(self):
        """Get the canonical output string."""

        # Assemble major, minor, micro version and append `pre`, `post`, or `dev` if needed..
        if self.micro == 0 and self.major != 0:
            ver = "{}.{}".format(self.major, self.minor)
        else:
            ver = "{}.{}.{}".format(self.major, self.minor, self.micro)
        if self._is_pre():
            ver += '{}{}'.format(REL_MAP[self.release], self.pre)
        if self._is_post():
            ver += ".post{}".format(self.post)
        if self._is_dev():
            ver += ".dev{}".format(self.dev)

        return ver


def parse_version(ver):
    """Parse version into a comparable Version tuple."""

    m = RE_VER.match(ver)

    if m is None:
        raise ValueError("'{}' is not a valid version".format(ver))

    # Handle major, minor, micro
    major = int(m.group('major'))
    minor = int(m.group('minor')) if m.group('minor') else 0
    micro = int(m.group('micro')) if m.group('micro') else 0

    # Handle pre releases
    if m.group('type'):
        release = PRE_REL_MAP[m.group('type')]
        pre = int(m.group('pre'))
    else:
        release = "final"
        pre = 0

    # Handle development releases
    dev = m.group('dev') if m.group('dev') else 0
    if m.group('dev'):
        dev = int(m.group('dev'))
        release = '.dev-' + release if pre else '.dev'
    else:
        dev = 0

    # Handle post
    post = int(m.group('post')) if m.group('post') else 0

    return Version(major, minor, micro, release, pre, post, dev)


__version_info__ = Version(1, 3, 1, "final")
__version__ = __version_info__._get_canonical()
mkdocs-material-extensions-1.3.1/materialx/emoji.py000066400000000000000000000115001452745063400224370ustar00rootroot00000000000000"""
Emoji extras for Material.

Override the indexes with an extended version that includes short names for Material icons, FontAwesome, etc.
"""
import os
import glob
import copy
import codecs
import functools
import inspect
import material
import pymdownx
from pymdownx.emoji import TWEMOJI_SVG_CDN, add_attriubtes
import xml.etree.ElementTree as etree  # noqa: N813
import warnings
from functools import wraps
import logging

log = logging.getLogger('mkdocs')

DEPRECATED = """\
Material emoji logic has been officially moved into mkdocs-material
version 9.4. Please use Material's '{}'
instead of '{}' in your 'mkdocs.yml' file.

```
markdown_extensions:
  - pymdownx.emoji:
      emoji_index: !!python/name:material.extensions.emoji.twemoji
      emoji_generator: !!python/name:material.extensions.emoji.to_svg
```

'mkdocs_material_extensions' is deprecated and will no longer be
supported moving forward. This is the last release.
"""


OPTION_SUPPORT = pymdownx.__version_info__ >= (7, 1, 0)
RESOURCES = os.path.dirname(inspect.getfile(material))
if os.path.exists(os.path.join(RESOURCES, 'templates', '.icons')):  # pragma: no cover
    RES_PATH = os.path.join(RESOURCES, 'templates', '.icons')
else:  # pragma: no cover
    RES_PATH = os.path.join(RESOURCES, '.icons')


@functools.lru_cache(maxsize=None)
def log_msg(message):
    """Log message."""

    log.warning(message)


def deprecated(message, stacklevel=2, name=None):  # pragma: no cover
    """
    Raise a `DeprecationWarning` when wrapped function/method is called.

    Usage:

        @deprecated("This method will be removed in version X; use Y instead.")
        def some_method()"
            pass
    """

    def _wrapper(func):
        @wraps(func)
        def _deprecated_func(*args, **kwargs):
            warnings.warn(
                f"'{func.__name__ if name is None else name}' is deprecated.\n{message}",
                category=DeprecationWarning,
                stacklevel=stacklevel
            )

            log_msg(message)
            return func(*args, **kwargs)
        return _deprecated_func
    return _wrapper


@deprecated(
    DEPRECATED.format('material.extensions.emoji.twemoji', 'materialx.emoji.twemoji'),
    name='materialx.emoji.twemoji'
)
def _patch_index(options):
    """Patch the given index."""

    icon_locations = options.get('custom_icons', [])[:]
    icon_locations.append(RES_PATH)
    return _patch_index_for_locations(tuple(icon_locations))


@functools.lru_cache(maxsize=None)
def _patch_index_for_locations(icon_locations):
    import pymdownx.twemoji_db as twemoji_db

    # Copy the Twemoji index
    index = {
        "name": 'twemoji',
        "emoji": copy.deepcopy(twemoji_db.emoji) if not OPTION_SUPPORT else twemoji_db.emoji,
        "aliases": copy.deepcopy(twemoji_db.aliases) if not OPTION_SUPPORT else twemoji_db.aliases
    }

    # Find our icons
    for icon_path in icon_locations:
        norm_base = icon_path.replace('\\', '/') + '/'
        for result in glob.glob(glob.escape(icon_path.replace('\\', '/')) + '/**/*.svg', recursive=True):
            name = ':{}:'.format(result.replace('\\', '/').replace(norm_base, '', 1).replace('/', '-').lstrip('.')[:-4])
            if name not in index['emoji'] and name not in index['aliases']:
                # Easiest to just store the path and pull it out from the index
                index["emoji"][name] = {'name': name, 'path': result}
    return index


if OPTION_SUPPORT:  # pragma: no cover
    def twemoji(options, md):
        """Provide a copied Twemoji index with additional codes for Material included icons."""

        return _patch_index(options)

else:  # pragma: no cover
    def twemoji():
        """Provide a copied Twemoji index with additional codes for Material included icons."""

        return _patch_index({})


@deprecated(
    DEPRECATED.format('material.extensions.emoji.to_svg', 'materialx.emoji.to_svg'),
    1,
    name='materialx.emoji.to_svg'
)
def to_svg(index, shortname, alias, uc, alt, title, category, options, md):
    """Return SVG element."""

    is_unicode = uc is not None

    if is_unicode:
        # Handle Twemoji emoji.
        svg_path = TWEMOJI_SVG_CDN

        attributes = {
            "class": options.get('classes', index),
            "alt": alt,
            "src": "%s%s.svg" % (
                options.get('image_path', svg_path),
                uc
            )
        }

        if title:
            attributes['title'] = title

        add_attriubtes(options, attributes)

        return etree.Element("img", attributes)
    else:
        # Handle Material SVG assets.
        el = etree.Element('span', {"class": options.get('classes', index)})
        svg_path = md.inlinePatterns['emoji'].emoji_index['emoji'][shortname]['path']
        with codecs.open(svg_path, 'r', encoding='utf-8') as f:
            el.text = md.htmlStash.store(f.read())
        return el
mkdocs-material-extensions-1.3.1/pyproject.toml000066400000000000000000000016601452745063400217160ustar00rootroot00000000000000[build-system]
requires = [
    "hatchling>=0.21.1",
]
build-backend = "hatchling.build"

[project]
name = "mkdocs-material-extensions"
description = "Extension pack for Python Markdown and MkDocs Material."
readme = "README.md"
license = "MIT"
requires-python = ">=3.8"
authors = [
    { name = "Isaac Muse", email = "Isaac.Muse@gmail.com" },
]
keywords = [
    "extensions",
    "markdown",
]
dynamic = [
    "classifiers",
    "dependencies",
    "version",
]

[project.urls]
Homepage = "https://github.com/facelessuser/mkdocs-material-extensions"

[tool.hatch.version]
source = "code"
path = "materialx/__meta__.py"

[tool.hatch.build.targets.sdist]
include = [
    "/requirements/*.txt",
    "/materialx/**/*.py",
    "/tests/**/*.py",
    "/.pyspelling.yml",
    "/.coveragerc",
    "/tox.ini",
    "/LICENSE.md",
    "/changelog.md"
]

[tool.hatch.build.targets.wheel]
include = [
    "/materialx",
]

[tool.hatch.metadata.hooks.custom]
mkdocs-material-extensions-1.3.1/requirements/000077500000000000000000000000001452745063400215225ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/requirements/docs.txt000066400000000000000000000000431452745063400232100ustar00rootroot00000000000000pymdown-extensions>=7.0
pyspelling
mkdocs-material-extensions-1.3.1/requirements/lint.txt000066400000000000000000000001041452745063400232240ustar00rootroot00000000000000flake8
flake8_docstrings
pep8-naming
flake8-mutable
flake8-builtins
mkdocs-material-extensions-1.3.1/requirements/test.txt000066400000000000000000000001011452745063400232320ustar00rootroot00000000000000pytest
pytest-cov
coverage
mkdocs-material>=5.0.0
beautifulsoup4
mkdocs-material-extensions-1.3.1/tests/000077500000000000000000000000001452745063400201415ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/tests/__init__.py000066400000000000000000000000151452745063400222460ustar00rootroot00000000000000"""Tests."""
mkdocs-material-extensions-1.3.1/tests/extensions/000077500000000000000000000000001452745063400223405ustar00rootroot00000000000000mkdocs-material-extensions-1.3.1/tests/extensions/__init__.py000066400000000000000000000000271452745063400244500ustar00rootroot00000000000000"""Extension tests."""
mkdocs-material-extensions-1.3.1/tests/extensions/test_emoji.py000066400000000000000000000027641452745063400250650ustar00rootroot00000000000000"""Test emoji indexes and generators."""
from .. import util
from materialx import emoji
from bs4 import BeautifulSoup
import markdown
from pymdownx.emoji import TWEMOJI_SVG_CDN


class TestEmoji(util.MdCase):
    """Test extra raw HTML."""

    extension = ['pymdownx.emoji']
    extension_configs = {
        'pymdownx.emoji': {
            "emoji_index": emoji.twemoji,
            "emoji_generator": emoji.to_svg
        }
    }

    def test_material_svg_injection(self):
        """Test that we inject icons for all the Material icon types."""

        text = r'''
        We can use Material Icons :material-airplane:.

        We can also use Fontawesome Icons :fontawesome-solid-hand:.

        That's not all, we can also use Octicons :octicons-alert-16:.
        '''

        html = markdown.markdown(
            self.dedent(text, True),
            extensions=self.extension,
            extension_configs=self.extension_configs
        )

        soup = BeautifulSoup(html, 'html.parser')

        p = soup.select('p')
        self.assertTrue(len(p) == 3)
        self.assertTrue(p[0].select('span.twemoji > svg'))
        self.assertTrue(p[1].select('span.twemoji > svg'))
        self.assertTrue(p[2].select('span.twemoji > svg'))

    def test_twemoji(self):
        """Test that normal Twemoji emoji work."""

        self.check_markdown(
            ':smile:',
            '

\U0001f604

'.format(TWEMOJI_SVG_CDN) # noqa: E501 ) mkdocs-material-extensions-1.3.1/tests/util.py000066400000000000000000000043731452745063400214770ustar00rootroot00000000000000"""Utilities.""" import sys import os import unittest import textwrap import markdown import difflib CURRENT_DIR = os.path.abspath(os.path.dirname(__file__)) if sys.platform.startswith('win'): _PLATFORM = "windows" elif sys.platform == "darwin": _PLATFORM = "osx" else: _PLATFORM = "linux" def is_win(): # pragma: no cover """Is Windows.""" return _PLATFORM == "windows" def is_linux(): # pragma: no cover """Is Linux.""" return _PLATFORM == "linux" def is_mac(): # pragma: no cover """Is macOS.""" return _PLATFORM == "osx" class MdCase(unittest.TestCase): """Markdown unittest test case base.""" extension = [] extension_configs = {} base = CURRENT_DIR def setUp(self): """Setup.""" for k1, v1 in self.extension_configs.items(): if v1 is not None: for k2, v2 in v1.items(): if isinstance(v2, str): v1[k2] = v2.replace( '{{BASE}}', self.base ).replace( '{{RELATIVE}}', CURRENT_DIR ) self.extension_configs[k1] = v1 self.md = markdown.Markdown(extensions=self.extension, extension_configs=self.extension_configs) def dedent(self, text, strip=False): """Reduce indentation.""" return textwrap.dedent(text).strip('\n') if strip else textwrap.dedent(text) def check_markdown(self, text, expected, dedent=False): """Check the markdown.""" if dedent: # For markdown, beginning and ending new lines get stripped out with # no issues, but for HTML (expected), we need to trim. # If there are tests that are newline sensitive, it may make sense # to call dedent directly to control this. text = self.dedent(text) expected = self.dedent(expected, True) results = self.md.convert(text) diff = [ l for l in difflib.unified_diff( expected.splitlines(True), results.splitlines(True), 'Expected', 'Actual', n=3 ) ] print(''.join(diff)) self.assertTrue(not diff) mkdocs-material-extensions-1.3.1/tox.ini000066400000000000000000000013371452745063400203160ustar00rootroot00000000000000[tox] isolated_build = true envlist = {py38,py39,py310,py311,py312}, lint, documents [testenv] passenv = LANG deps= -rrequirements/test.txt commands= {envbindir}/py.test --cov materialx --cov-append {toxinidir} {envbindir}/coverage html -d {envtmpdir}/coverage {envbindir}/coverage xml {envbindir}/coverage report --show-missing [testenv:documents] deps= -rrequirements/docs.txt commands= {envpython} -m pip install . ; {envpython} -m mkdocs build --clean --verbose --strict {envpython} -m pyspelling [testenv:lint] deps= -rrequirements/lint.txt commands= {envbindir}/flake8 {toxinidir} [flake8] exclude=build/*,.tox/*,site/* max-line-length=120 ignore=D202,N802,D203,D401,W504,E741