-
Notifications
You must be signed in to change notification settings - Fork 86
👌 IMPROVE: MarkdownIt config and documentation #136
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ python: | |
| - method: pip | ||
| path: . | ||
| extra_requirements: | ||
| - linkify | ||
| - rtd | ||
|
|
||
| sphinx: | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,36 +27,50 @@ | |
| linkify_it = None | ||
|
|
||
|
|
||
| _PRESETS = AttrDict( | ||
| { | ||
| "default": presets.default.make(), | ||
| "zero": presets.zero.make(), | ||
| "commonmark": presets.commonmark.make(), | ||
| } | ||
| ) | ||
| _PRESETS = { | ||
| "default": presets.default.make(), | ||
| "js-default": presets.js_default.make(), | ||
| "zero": presets.zero.make(), | ||
| "commonmark": presets.commonmark.make(), | ||
| "gfm-like": presets.gfm_like.make(), | ||
| } | ||
|
|
||
|
|
||
| class MarkdownIt: | ||
| def __init__( | ||
| self, config: Union[str, Mapping] = "commonmark", renderer_cls=RendererHTML | ||
| self, | ||
| config: Union[str, Mapping] = "commonmark", | ||
| options_update: Optional[Mapping] = None, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One neat trick I've recently started to use in my APIs is from types import MappingProxyType
# This is basically just an immutable empty mapping
EMPTY_MAP = MappingProxyType({})
def func(options: Mapping = EMPTY_MAP):
...This convention saves me a bunch of Could be applied here if you like it 😄 You basically just need to create one global
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for the tip, I will have a look but probably not add it in this PR |
||
| *, | ||
| renderer_cls=RendererHTML, | ||
| ): | ||
| """Main parser class | ||
|
|
||
| :param config: name of configuration to load or a pre-defined dictionary | ||
| :param options_update: dictionary that will be merged into ``config["options"]`` | ||
| :param renderer_cls: the class to load as the renderer: | ||
| ``self.renderer = renderer_cls(self) | ||
| """ | ||
| # add modules | ||
| self.utils = utils | ||
| self.helpers: Any = helpers | ||
|
|
||
| # initialise classes | ||
| self.inline = ParserInline() | ||
| self.block = ParserBlock() | ||
| self.core = ParserCore() | ||
| self.renderer = renderer_cls(self) | ||
| self.linkify = linkify_it.LinkifyIt() if linkify_it else None | ||
|
|
||
| self.utils = utils | ||
| self.helpers: Any = helpers | ||
| # set the configuration | ||
| if options_update and not isinstance(options_update, Mapping): | ||
| # catch signature change where renderer_cls was not used as a key-word | ||
| raise TypeError( | ||
| f"options_update should be a mapping: {options_update}" | ||
| "\n(Perhaps you intended this to be the renderer_cls?)" | ||
| ) | ||
| self.options = AttrDict() | ||
| self.configure(config) | ||
|
|
||
| self.linkify = linkify_it.LinkifyIt() if linkify_it else None | ||
| self.configure(config, options_update=options_update) | ||
|
|
||
| def __repr__(self) -> str: | ||
| return f"{self.__class__.__module__}.{self.__class__.__name__}()" | ||
|
|
@@ -79,7 +93,9 @@ def set(self, options: AttrDict) -> None: | |
| """ | ||
| self.options = options | ||
|
|
||
| def configure(self, presets: Union[str, Mapping]) -> "MarkdownIt": | ||
| def configure( | ||
| self, presets: Union[str, Mapping], options_update: Optional[Mapping] = None | ||
| ) -> "MarkdownIt": | ||
| """Batch load of all options and component settings. | ||
| This is an internal method, and you probably will not need it. | ||
| But if you will - see available presets and data structure | ||
|
|
@@ -89,21 +105,24 @@ def configure(self, presets: Union[str, Mapping]) -> "MarkdownIt": | |
| That will give better compatibility with next versions. | ||
| """ | ||
| if isinstance(presets, str): | ||
| presetName = presets | ||
| presets = _PRESETS.get(presetName, None) | ||
| if not presets: | ||
| raise KeyError( | ||
| 'Wrong `markdown-it` preset "' + presetName + '", check name' | ||
| ) | ||
| if not presets: | ||
| raise ValueError("Wrong `markdown-it` preset, can't be empty") | ||
| config = AttrDict(presets) | ||
|
|
||
| if "options" in config: | ||
| self.set(config.options) | ||
| if presets not in _PRESETS: | ||
| raise KeyError(f"Wrong `markdown-it` preset '{presets}', check name") | ||
| config = _PRESETS[presets] | ||
| else: | ||
| config = presets | ||
|
|
||
| if not config: | ||
| raise ValueError("Wrong `markdown-it` config, can't be empty") | ||
|
|
||
| options = config.get("options", {}) or {} | ||
| if options_update: | ||
| options = {**options, **options_update} | ||
chrisjsewell marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if options: | ||
| self.set(AttrDict(options)) | ||
|
|
||
| if "components" in config: | ||
| for name, component in config.components.items(): | ||
| for name, component in config["components"].items(): | ||
| rules = component.get("rules", None) | ||
| if rules: | ||
| self[name].ruler.enableOnly(rules) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,25 @@ | ||
| from . import commonmark, default, zero # noqa: F401 | ||
|
|
||
| js_default = default | ||
|
|
||
|
|
||
| class gfm_like: | ||
| """GitHub Flavoured Markdown (GFM) like. | ||
|
|
||
| This adds the linkify, table and strikethrough components to CommmonMark. | ||
|
|
||
| Note, it lacks task-list items and raw HTML filtering, | ||
| to meet the the full GFM specification | ||
| (see https://github.github.com/gfm/#autolinks-extension-). | ||
| """ | ||
|
|
||
| @staticmethod | ||
| def make(): | ||
| config = commonmark.make() | ||
| config["components"]["core"]["rules"].append("linkify") | ||
| config["components"]["block"]["rules"].append("table") | ||
| config["components"]["inline"]["rules"].append("strikethrough") | ||
| config["components"]["inline"]["rules2"].append("strikethrough") | ||
| config["options"]["linkify"] = True | ||
| config["options"]["html"] = True | ||
| return config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a heads-up, I made a PR (#132) which would change this syntax to
node = SyntaxTreeNode(tokens)so if we merge that then one of the PRs needs to adapt depending on merge order.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have a look