diff --git a/myst_parser/config/main.py b/myst_parser/config/main.py index 2b088b56..c1e65588 100644 --- a/myst_parser/config/main.py +++ b/myst_parser/config/main.py @@ -307,6 +307,20 @@ def __repr__(self) -> str: }, ) + fully_normalize_name_slug_func: Callable[[str], str] | None = dc.field( + default=None, + metadata={ + "validator": check_heading_slug_func, + "help": ( + "Function for normalizing text to valid html id value, " + "or a python import path e.g. `my_package.my_module.my_function` " + "It can be used to transliterate any language to valid stable html identifiers" + ), + "global_only": True, + "doc_type": "None | Callable[[str], str] | str", + }, + ) + html_meta: dict[str, str] = dc.field( default_factory=dict, metadata={ diff --git a/myst_parser/mdit_to_docutils/base.py b/myst_parser/mdit_to_docutils/base.py index 3778dd31..d82c068b 100644 --- a/myst_parser/mdit_to_docutils/base.py +++ b/myst_parser/mdit_to_docutils/base.py @@ -772,7 +772,11 @@ def generate_heading_target( # during ref resolution, and is not stored in the document. # TODO this is purely to mimic docutils, but maybe we don't need it? # (since we have the slugify logic below) - name = nodes.fully_normalize_name(implicit_text) + + if self.md_config.fully_normalize_name_slug_func is not None: + name = self.md_config.fully_normalize_name_slug_func(implicit_text) + else: + name = nodes.fully_normalize_name(implicit_text) node["names"].append(name) self.document.note_implicit_target(node, node) diff --git a/myst_parser/parsers/docutils_.py b/myst_parser/parsers/docutils_.py index e17de44b..73acf08c 100644 --- a/myst_parser/parsers/docutils_.py +++ b/myst_parser/parsers/docutils_.py @@ -139,7 +139,10 @@ def _attr_to_optparse_option(at: Field, default: Any) -> tuple[dict[str, Any], s "metavar": "", "validator": frontend.validate_boolean, }, str(default) - if at.type is str or at.name == "heading_slug_func": + if at.type is str or at.name in ( + "heading_slug_func", + "fully_normalize_name_slug_func", + ): return { "metavar": "", }, f"(default: '{default}')"