draftjs_exporter 5.2.0__tar.gz → 7.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- draftjs_exporter-7.1.0/PKG-INFO +75 -0
- draftjs_exporter-7.1.0/README.md +38 -0
- draftjs_exporter-7.1.0/draftjs_exporter/__init__.py +178 -0
- draftjs_exporter-7.1.0/draftjs_exporter/command.py +69 -0
- draftjs_exporter-7.1.0/draftjs_exporter/composite_decorators.py +137 -0
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/draftjs_exporter/constants.py +29 -0
- draftjs_exporter-7.1.0/draftjs_exporter/contentstate_filter/__init__.py +267 -0
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/draftjs_exporter/defaults.py +14 -7
- draftjs_exporter-7.1.0/draftjs_exporter/dom.py +183 -0
- draftjs_exporter-7.1.0/draftjs_exporter/engines/__init__.py +1 -0
- draftjs_exporter-7.1.0/draftjs_exporter/engines/base.py +79 -0
- draftjs_exporter-7.1.0/draftjs_exporter/engines/html5lib.py +89 -0
- draftjs_exporter-7.1.0/draftjs_exporter/engines/lxml.py +108 -0
- draftjs_exporter-7.1.0/draftjs_exporter/engines/markdown.py +244 -0
- draftjs_exporter-7.1.0/draftjs_exporter/engines/string.py +188 -0
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/draftjs_exporter/engines/string_compat.py +38 -7
- draftjs_exporter-7.1.0/draftjs_exporter/entity_state.py +155 -0
- draftjs_exporter-7.1.0/draftjs_exporter/error.py +30 -0
- draftjs_exporter-7.1.0/draftjs_exporter/html.py +263 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/__init__.py +222 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/blocks.py +66 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/code.py +41 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/entities.py +64 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/escape.py +209 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/fallbacks.py +50 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/helpers.py +62 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/lists.py +114 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown/styles.py +34 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown_importer/__init__.py +63 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown_parser/__init__.py +129 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown_parser/blocks.py +346 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown_parser/builder.py +88 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown_parser/inline.py +526 -0
- draftjs_exporter-7.1.0/draftjs_exporter/markdown_parser/resolvers.py +129 -0
- draftjs_exporter-7.1.0/draftjs_exporter/options.py +185 -0
- draftjs_exporter-7.1.0/draftjs_exporter/style_state.py +143 -0
- draftjs_exporter-7.1.0/draftjs_exporter/types.py +111 -0
- draftjs_exporter-7.1.0/draftjs_exporter/utils/__init__.py +1 -0
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/draftjs_exporter/utils/module_loading.py +16 -7
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/draftjs_exporter/wrapper_state.py +115 -30
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/pyproject.toml +60 -19
- draftjs_exporter-5.2.0/LICENSE +0 -9
- draftjs_exporter-5.2.0/PKG-INFO +0 -376
- draftjs_exporter-5.2.0/README.md +0 -330
- draftjs_exporter-5.2.0/draftjs_exporter/__init__.py +0 -5
- draftjs_exporter-5.2.0/draftjs_exporter/command.py +0 -56
- draftjs_exporter-5.2.0/draftjs_exporter/composite_decorators.py +0 -93
- draftjs_exporter-5.2.0/draftjs_exporter/dom.py +0 -129
- draftjs_exporter-5.2.0/draftjs_exporter/engines/__init__.py +0 -0
- draftjs_exporter-5.2.0/draftjs_exporter/engines/base.py +0 -50
- draftjs_exporter-5.2.0/draftjs_exporter/engines/html5lib.py +0 -45
- draftjs_exporter-5.2.0/draftjs_exporter/engines/lxml.py +0 -49
- draftjs_exporter-5.2.0/draftjs_exporter/engines/string.py +0 -116
- draftjs_exporter-5.2.0/draftjs_exporter/entity_state.py +0 -108
- draftjs_exporter-5.2.0/draftjs_exporter/error.py +0 -6
- draftjs_exporter-5.2.0/draftjs_exporter/html.py +0 -180
- draftjs_exporter-5.2.0/draftjs_exporter/options.py +0 -105
- draftjs_exporter-5.2.0/draftjs_exporter/style_state.py +0 -49
- draftjs_exporter-5.2.0/draftjs_exporter/types.py +0 -35
- draftjs_exporter-5.2.0/draftjs_exporter/utils/__init__.py +0 -0
- {draftjs_exporter-5.2.0 → draftjs_exporter-7.1.0}/draftjs_exporter/py.typed +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: draftjs_exporter
|
|
3
|
+
Version: 7.1.0
|
|
4
|
+
Summary: Library to convert rich text from Draft.js raw ContentState to HTML
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Classifier: Environment :: Web Environment
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
18
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
19
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
20
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
22
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
|
+
Classifier: Topic :: Text Editors :: Word Processors
|
|
24
|
+
Classifier: Typing :: Typed
|
|
25
|
+
Requires-Dist: beautifulsoup4>=4.4.1,<5 ; extra == 'html5lib'
|
|
26
|
+
Requires-Dist: html5lib>=0.999,<2 ; extra == 'html5lib'
|
|
27
|
+
Requires-Dist: lxml>=4.6.5,<7 ; extra == 'lxml'
|
|
28
|
+
Requires-Python: >=3.10
|
|
29
|
+
Project-URL: Documentation, https://wagtail.github.io/draftjs_exporter/
|
|
30
|
+
Project-URL: Source, https://github.com/wagtail/draftjs_exporter
|
|
31
|
+
Project-URL: Tracker, https://github.com/wagtail/draftjs_exporter/issues
|
|
32
|
+
Project-URL: Changelog, https://github.com/wagtail/draftjs_exporter/blob/main/CHANGELOG.md
|
|
33
|
+
Project-URL: llms.txt, https://wagtail.github.io/draftjs_exporter/llms.txt
|
|
34
|
+
Provides-Extra: html5lib
|
|
35
|
+
Provides-Extra: lxml
|
|
36
|
+
Description-Content-Type: text/markdown
|
|
37
|
+
|
|
38
|
+
# [Draft.js exporter](https://pypi.org/project/draftjs_exporter/)
|
|
39
|
+
|
|
40
|
+
> Library to convert rich text from Draft.js raw ContentState to HTML.
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html), and [measures performance](https://thib.me/python-memory-profiling-for-the-draft-js-exporter) and [code coverage](https://coveralls.io/github/wagtail/draftjs_exporter). Code is checked with [mypy](https://mypy.readthedocs.io/en/latest/index.html).
|
|
45
|
+
|
|
46
|
+
- Extensive configuration of the generated HTML.
|
|
47
|
+
- Default, extensible block & inline style maps for common HTML elements.
|
|
48
|
+
- Convert line breaks to `<br>` elements with decorators.
|
|
49
|
+
- Define any attribute in the block map – custom class names for elements.
|
|
50
|
+
- React-like API to create custom components.
|
|
51
|
+
- Automatic conversion of entity data to HTML attributes (int & boolean to string, style object to style string).
|
|
52
|
+
- Nested lists (`<li>` elements go inside `<ul>` or `<ol>`, with multiple levels).
|
|
53
|
+
- Output inline styles as inline elements (`<em>`, `<strong>`, pick and choose, with any attribute).
|
|
54
|
+
- Overlapping inline style and entity ranges.
|
|
55
|
+
- Static type annotations.
|
|
56
|
+
|
|
57
|
+
It is developed alongside the [Draftail](https://www.draftail.org/) rich text editor, for [Wagtail](https://github.com/wagtail/wagtail). Check out the [online demo](http://playground.draftail.org/), and our [introductory blog post](https://www.draftail.org/blog/2018/03/13/rethinking-rich-text-pipelines-with-draft-js).
|
|
58
|
+
|
|
59
|
+
## When to use the exporter
|
|
60
|
+
|
|
61
|
+
[Draft.js](https://draftjs.org/) is a rich text editor framework for [React](https://reactjs.org/). Its approach is different from most rich text editors because it does not store data as HTML, but rather in its own representation called ContentState. This exporter is useful when the ContentState to HTML conversion has to be done in a Python ecosystem.
|
|
62
|
+
|
|
63
|
+
The initial use case was to gain more control over the content managed by rich text editors in a Wagtail/Django site. If you want to read the full story, have a look at our blog post: [Rethinking rich text pipelines with Draft.js](https://www.draftail.org/blog/2018/03/13/rethinking-rich-text-pipelines-with-draft-js).
|
|
64
|
+
|
|
65
|
+
## Documentation
|
|
66
|
+
|
|
67
|
+
The full documentation is available at [on the docs website](https://wagtail.github.io/draftjs_exporter/). For LLM-assisted tooling, there is also a concise [`llms.txt`](https://wagtail.github.io/draftjs_exporter/llms.txt) and a complete [`llms-full.txt`](https://wagtail.github.io/draftjs_exporter/llms-full.txt).
|
|
68
|
+
|
|
69
|
+
## Contributing
|
|
70
|
+
|
|
71
|
+
See anything you like in here? Anything missing? We welcome all support, whether on bug reports, feature requests, code, design, reviews, tests, documentation, and more. Please have a look at our [contribution guidelines](docs/CONTRIBUTING.md).
|
|
72
|
+
|
|
73
|
+
## Credits
|
|
74
|
+
|
|
75
|
+
Draftail was created by [Springload](https://github.com/springload/), and is now maintained by Wagtail contributors. View the full list of [contributors](https://github.com/wagtail/draftjs_exporter/graphs/contributors). MIT licensed.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# [Draft.js exporter](https://pypi.org/project/draftjs_exporter/)
|
|
2
|
+
|
|
3
|
+
> Library to convert rich text from Draft.js raw ContentState to HTML.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html), and [measures performance](https://thib.me/python-memory-profiling-for-the-draft-js-exporter) and [code coverage](https://coveralls.io/github/wagtail/draftjs_exporter). Code is checked with [mypy](https://mypy.readthedocs.io/en/latest/index.html).
|
|
8
|
+
|
|
9
|
+
- Extensive configuration of the generated HTML.
|
|
10
|
+
- Default, extensible block & inline style maps for common HTML elements.
|
|
11
|
+
- Convert line breaks to `<br>` elements with decorators.
|
|
12
|
+
- Define any attribute in the block map – custom class names for elements.
|
|
13
|
+
- React-like API to create custom components.
|
|
14
|
+
- Automatic conversion of entity data to HTML attributes (int & boolean to string, style object to style string).
|
|
15
|
+
- Nested lists (`<li>` elements go inside `<ul>` or `<ol>`, with multiple levels).
|
|
16
|
+
- Output inline styles as inline elements (`<em>`, `<strong>`, pick and choose, with any attribute).
|
|
17
|
+
- Overlapping inline style and entity ranges.
|
|
18
|
+
- Static type annotations.
|
|
19
|
+
|
|
20
|
+
It is developed alongside the [Draftail](https://www.draftail.org/) rich text editor, for [Wagtail](https://github.com/wagtail/wagtail). Check out the [online demo](http://playground.draftail.org/), and our [introductory blog post](https://www.draftail.org/blog/2018/03/13/rethinking-rich-text-pipelines-with-draft-js).
|
|
21
|
+
|
|
22
|
+
## When to use the exporter
|
|
23
|
+
|
|
24
|
+
[Draft.js](https://draftjs.org/) is a rich text editor framework for [React](https://reactjs.org/). Its approach is different from most rich text editors because it does not store data as HTML, but rather in its own representation called ContentState. This exporter is useful when the ContentState to HTML conversion has to be done in a Python ecosystem.
|
|
25
|
+
|
|
26
|
+
The initial use case was to gain more control over the content managed by rich text editors in a Wagtail/Django site. If you want to read the full story, have a look at our blog post: [Rethinking rich text pipelines with Draft.js](https://www.draftail.org/blog/2018/03/13/rethinking-rich-text-pipelines-with-draft-js).
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
The full documentation is available at [on the docs website](https://wagtail.github.io/draftjs_exporter/). For LLM-assisted tooling, there is also a concise [`llms.txt`](https://wagtail.github.io/draftjs_exporter/llms.txt) and a complete [`llms-full.txt`](https://wagtail.github.io/draftjs_exporter/llms-full.txt).
|
|
31
|
+
|
|
32
|
+
## Contributing
|
|
33
|
+
|
|
34
|
+
See anything you like in here? Anything missing? We welcome all support, whether on bug reports, feature requests, code, design, reviews, tests, documentation, and more. Please have a look at our [contribution guidelines](docs/CONTRIBUTING.md).
|
|
35
|
+
|
|
36
|
+
## Credits
|
|
37
|
+
|
|
38
|
+
Draftail was created by [Springload](https://github.com/springload/), and is now maintained by Wagtail contributors. View the full list of [contributors](https://github.com/wagtail/draftjs_exporter/graphs/contributors). MIT licensed.
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""Public API and metadata of draftjs_exporter.
|
|
2
|
+
|
|
3
|
+
This module gathers metadata, core classes, default configuration maps,
|
|
4
|
+
type aliases, and helpers so callers can import everything from
|
|
5
|
+
``draftjs_exporter`` directly.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
__title__ = "draftjs_exporter"
|
|
9
|
+
__version__ = "7.1.0"
|
|
10
|
+
__uri__ = "https://wagtail.github.io/draftjs_exporter/"
|
|
11
|
+
__author__ = "Springload and Contributors"
|
|
12
|
+
__license__ = "MIT"
|
|
13
|
+
__copyright__ = "Copyright 2016-present Springload and Contributors"
|
|
14
|
+
|
|
15
|
+
from draftjs_exporter.constants import BLOCK_TYPES as BLOCK_TYPES
|
|
16
|
+
from draftjs_exporter.constants import ENTITY_TYPES as ENTITY_TYPES
|
|
17
|
+
from draftjs_exporter.constants import INLINE_STYLES as INLINE_STYLES
|
|
18
|
+
from draftjs_exporter.contentstate_filter import (
|
|
19
|
+
ContentStateFilter as ContentStateFilter,
|
|
20
|
+
)
|
|
21
|
+
from draftjs_exporter.contentstate_filter import FilterRule as FilterRule
|
|
22
|
+
from draftjs_exporter.defaults import BLOCK_MAP as BLOCK_MAP
|
|
23
|
+
from draftjs_exporter.defaults import STYLE_MAP as STYLE_MAP
|
|
24
|
+
from draftjs_exporter.defaults import code_block as code_block
|
|
25
|
+
from draftjs_exporter.defaults import render_children as render_children
|
|
26
|
+
from draftjs_exporter.dom import DOM as DOM
|
|
27
|
+
from draftjs_exporter.error import MarkdownParseError as MarkdownParseError
|
|
28
|
+
from draftjs_exporter.html import HTML as HTML
|
|
29
|
+
from draftjs_exporter.html import ExporterConfig as ExporterConfig
|
|
30
|
+
from draftjs_exporter.markdown import CONFIG as MARKDOWN_CONFIG
|
|
31
|
+
from draftjs_exporter.markdown import MarkdownOptions as MarkdownOptions
|
|
32
|
+
from draftjs_exporter.markdown import build_markdown_config as build_markdown_config
|
|
33
|
+
from draftjs_exporter.markdown.blocks import md_list_wrapper as md_list_wrapper
|
|
34
|
+
from draftjs_exporter.markdown.blocks import md_make_ol as md_make_ol
|
|
35
|
+
from draftjs_exporter.markdown.blocks import md_make_ul as md_make_ul
|
|
36
|
+
from draftjs_exporter.markdown.blocks import md_ol as md_ol
|
|
37
|
+
from draftjs_exporter.markdown.blocks import md_prefixed_block as md_prefixed_block
|
|
38
|
+
from draftjs_exporter.markdown.blocks import md_ul as md_ul
|
|
39
|
+
from draftjs_exporter.markdown.code import md_code_element as md_code_element
|
|
40
|
+
from draftjs_exporter.markdown.code import md_code_wrapper as md_code_wrapper
|
|
41
|
+
from draftjs_exporter.markdown.code import md_make_code_element as md_make_code_element
|
|
42
|
+
from draftjs_exporter.markdown.code import md_make_code_wrapper as md_make_code_wrapper
|
|
43
|
+
from draftjs_exporter.markdown.entities import md_horizontal_rule as md_horizontal_rule
|
|
44
|
+
from draftjs_exporter.markdown.entities import md_image as md_image
|
|
45
|
+
from draftjs_exporter.markdown.entities import md_link as md_link
|
|
46
|
+
from draftjs_exporter.markdown.entities import (
|
|
47
|
+
md_make_horizontal_rule as md_make_horizontal_rule,
|
|
48
|
+
)
|
|
49
|
+
from draftjs_exporter.markdown.fallbacks import md_block_fallback as md_block_fallback
|
|
50
|
+
from draftjs_exporter.markdown.fallbacks import md_entity_fallback as md_entity_fallback
|
|
51
|
+
from draftjs_exporter.markdown.fallbacks import md_style_fallback as md_style_fallback
|
|
52
|
+
from draftjs_exporter.markdown.helpers import md_block as md_block
|
|
53
|
+
from draftjs_exporter.markdown.helpers import md_inline as md_inline
|
|
54
|
+
from draftjs_exporter.markdown.helpers import md_link_destination as md_link_destination
|
|
55
|
+
from draftjs_exporter.markdown.helpers import md_mark_safe as md_mark_safe
|
|
56
|
+
from draftjs_exporter.markdown.styles import md_code_span as md_code_span
|
|
57
|
+
from draftjs_exporter.markdown.styles import md_inline_style as md_inline_style
|
|
58
|
+
from draftjs_exporter.markdown_importer import ImporterConfig as ImporterConfig
|
|
59
|
+
from draftjs_exporter.markdown_importer import MarkdownImporter as MarkdownImporter
|
|
60
|
+
from draftjs_exporter.markdown_parser import EntityResolution as EntityResolution
|
|
61
|
+
from draftjs_exporter.markdown_parser import EntityResolver as EntityResolver
|
|
62
|
+
from draftjs_exporter.markdown_parser import MarkdownParser as MarkdownParser
|
|
63
|
+
from draftjs_exporter.markdown_parser import ParserConfig as ParserConfig
|
|
64
|
+
from draftjs_exporter.markdown_parser import scheme_resolver as scheme_resolver
|
|
65
|
+
from draftjs_exporter.types import Block as Block
|
|
66
|
+
from draftjs_exporter.types import Component as Component
|
|
67
|
+
from draftjs_exporter.types import CompositeDecorators as CompositeDecorators
|
|
68
|
+
from draftjs_exporter.types import ConfigMap as ConfigMap
|
|
69
|
+
from draftjs_exporter.types import ContentState as ContentState
|
|
70
|
+
from draftjs_exporter.types import Decorator as Decorator
|
|
71
|
+
from draftjs_exporter.types import Element as Element
|
|
72
|
+
from draftjs_exporter.types import Entity as Entity
|
|
73
|
+
from draftjs_exporter.types import EntityKey as EntityKey
|
|
74
|
+
from draftjs_exporter.types import EntityMap as EntityMap
|
|
75
|
+
from draftjs_exporter.types import EntityRange as EntityRange
|
|
76
|
+
from draftjs_exporter.types import InlineStyleRange as InlineStyleRange
|
|
77
|
+
from draftjs_exporter.types import Mutability as Mutability
|
|
78
|
+
from draftjs_exporter.types import Props as Props
|
|
79
|
+
from draftjs_exporter.types import RenderableConfig as RenderableConfig
|
|
80
|
+
from draftjs_exporter.types import RenderableType as RenderableType
|
|
81
|
+
from draftjs_exporter.types import Tag as Tag
|
|
82
|
+
|
|
83
|
+
__all__ = [
|
|
84
|
+
# Metadata
|
|
85
|
+
"__title__",
|
|
86
|
+
"__version__",
|
|
87
|
+
"__uri__",
|
|
88
|
+
"__author__",
|
|
89
|
+
"__license__",
|
|
90
|
+
"__copyright__",
|
|
91
|
+
# Core
|
|
92
|
+
"Exporter",
|
|
93
|
+
"HTML",
|
|
94
|
+
"HTMLExporter",
|
|
95
|
+
"ExporterConfig",
|
|
96
|
+
"ContentState",
|
|
97
|
+
"DOM",
|
|
98
|
+
# Configs
|
|
99
|
+
"HTML_CONFIG",
|
|
100
|
+
"MARKDOWN_CONFIG",
|
|
101
|
+
"MarkdownOptions",
|
|
102
|
+
"build_markdown_config",
|
|
103
|
+
# Markdown helpers
|
|
104
|
+
"md_block",
|
|
105
|
+
"md_block_fallback",
|
|
106
|
+
"md_code_element",
|
|
107
|
+
"md_code_span",
|
|
108
|
+
"md_code_wrapper",
|
|
109
|
+
"md_entity_fallback",
|
|
110
|
+
"md_horizontal_rule",
|
|
111
|
+
"md_image",
|
|
112
|
+
"md_inline",
|
|
113
|
+
"md_inline_style",
|
|
114
|
+
"md_link",
|
|
115
|
+
"md_link_destination",
|
|
116
|
+
"md_list_wrapper",
|
|
117
|
+
"md_make_code_element",
|
|
118
|
+
"md_make_code_wrapper",
|
|
119
|
+
"md_make_horizontal_rule",
|
|
120
|
+
"md_make_ol",
|
|
121
|
+
"md_make_ul",
|
|
122
|
+
"md_mark_safe",
|
|
123
|
+
"md_ol",
|
|
124
|
+
"md_prefixed_block",
|
|
125
|
+
"md_style_fallback",
|
|
126
|
+
"md_ul",
|
|
127
|
+
# Importer
|
|
128
|
+
"MarkdownImporter",
|
|
129
|
+
"ImporterConfig",
|
|
130
|
+
"MarkdownParser",
|
|
131
|
+
"ParserConfig",
|
|
132
|
+
"ContentStateFilter",
|
|
133
|
+
"FilterRule",
|
|
134
|
+
"MarkdownParseError",
|
|
135
|
+
"EntityResolution",
|
|
136
|
+
"EntityResolver",
|
|
137
|
+
"scheme_resolver",
|
|
138
|
+
# Constants
|
|
139
|
+
"BLOCK_TYPES",
|
|
140
|
+
"ENTITY_TYPES",
|
|
141
|
+
"INLINE_STYLES",
|
|
142
|
+
# Defaults
|
|
143
|
+
"BLOCK_MAP",
|
|
144
|
+
"STYLE_MAP",
|
|
145
|
+
"code_block",
|
|
146
|
+
"render_children",
|
|
147
|
+
# Types
|
|
148
|
+
"Block",
|
|
149
|
+
"Component",
|
|
150
|
+
"CompositeDecorators",
|
|
151
|
+
"ConfigMap",
|
|
152
|
+
"ContentState",
|
|
153
|
+
"Decorator",
|
|
154
|
+
"Element",
|
|
155
|
+
"Entity",
|
|
156
|
+
"EntityKey",
|
|
157
|
+
"EntityMap",
|
|
158
|
+
"EntityRange",
|
|
159
|
+
"InlineStyleRange",
|
|
160
|
+
"Mutability",
|
|
161
|
+
"Props",
|
|
162
|
+
"RenderableConfig",
|
|
163
|
+
"RenderableType",
|
|
164
|
+
"Tag",
|
|
165
|
+
]
|
|
166
|
+
|
|
167
|
+
Exporter = HTML
|
|
168
|
+
"""Compatibility alias for the HTML exporter."""
|
|
169
|
+
|
|
170
|
+
HTMLExporter = HTML
|
|
171
|
+
"""Compatibility alias for the HTML exporter."""
|
|
172
|
+
|
|
173
|
+
HTML_CONFIG: ExporterConfig = {
|
|
174
|
+
"block_map": BLOCK_MAP,
|
|
175
|
+
"style_map": STYLE_MAP,
|
|
176
|
+
"engine": DOM.STRING,
|
|
177
|
+
}
|
|
178
|
+
"""Default exporter configuration using the built-in maps and string engine."""
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Represent and build rendering commands derived from Draft.js ranges."""
|
|
2
|
+
|
|
3
|
+
from draftjs_exporter.types import Block
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Command:
|
|
7
|
+
"""Represent an operation applied while converting a block to HTML nodes."""
|
|
8
|
+
|
|
9
|
+
__slots__ = ("name", "index", "data")
|
|
10
|
+
|
|
11
|
+
def __init__(self, name: str, index: int, data: str = "") -> None:
|
|
12
|
+
"""Initialize a command.
|
|
13
|
+
|
|
14
|
+
Parameters:
|
|
15
|
+
name: The operation name, such as ``start_entity`` or ``stop_inline_style``.
|
|
16
|
+
index: The character offset at which the command applies.
|
|
17
|
+
data: The payload for the command, such as an entity key or style name.
|
|
18
|
+
"""
|
|
19
|
+
self.name = name
|
|
20
|
+
self.index = index
|
|
21
|
+
self.data = data
|
|
22
|
+
|
|
23
|
+
def __str__(self) -> str:
|
|
24
|
+
"""Return a human-readable representation of the command."""
|
|
25
|
+
return f"<Command {self.name} {self.index} {self.data}>"
|
|
26
|
+
|
|
27
|
+
def __repr__(self) -> str:
|
|
28
|
+
"""Return the same representation as ``__str__`` for debugging."""
|
|
29
|
+
return str(self)
|
|
30
|
+
|
|
31
|
+
@staticmethod
|
|
32
|
+
def from_entity_ranges(block: Block) -> list["Command"]:
|
|
33
|
+
"""Create start and stop commands from a block's entity ranges.
|
|
34
|
+
|
|
35
|
+
Parameters:
|
|
36
|
+
block: The block containing ``entityRanges``.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
A list of start_entity and stop_entity commands.
|
|
40
|
+
"""
|
|
41
|
+
commands: list["Command"] = []
|
|
42
|
+
for r in block.get("entityRanges", []):
|
|
43
|
+
# Entity key is an integer in entity ranges, while a string in the entity map.
|
|
44
|
+
data = str(r["key"])
|
|
45
|
+
start = r["offset"]
|
|
46
|
+
stop = start + r["length"]
|
|
47
|
+
commands.append(Command("start_entity", start, data))
|
|
48
|
+
commands.append(Command("stop_entity", stop, data))
|
|
49
|
+
|
|
50
|
+
return commands
|
|
51
|
+
|
|
52
|
+
@staticmethod
|
|
53
|
+
def from_style_ranges(block: Block) -> list["Command"]:
|
|
54
|
+
"""Create start and stop commands from a block's inline style ranges.
|
|
55
|
+
|
|
56
|
+
Parameters:
|
|
57
|
+
block: The block containing ``inlineStyleRanges``.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
A list of start_inline_style and stop_inline_style commands.
|
|
61
|
+
"""
|
|
62
|
+
commands: list["Command"] = []
|
|
63
|
+
for r in block.get("inlineStyleRanges", []):
|
|
64
|
+
data = r["style"]
|
|
65
|
+
start = r["offset"]
|
|
66
|
+
stop = start + r["length"]
|
|
67
|
+
commands.append(Command("start_inline_style", start, data))
|
|
68
|
+
commands.append(Command("stop_inline_style", stop, data))
|
|
69
|
+
return commands
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""Apply regex-based composite decorators to text while rendering blocks."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from collections.abc import Generator
|
|
5
|
+
from operator import itemgetter
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from draftjs_exporter.dom import DOM
|
|
9
|
+
from draftjs_exporter.engines.base import DOMEngine
|
|
10
|
+
from draftjs_exporter.types import Block, CompositeDecorators, Decorator, Element
|
|
11
|
+
|
|
12
|
+
br = "\n"
|
|
13
|
+
"""Line-break character handled by the default decorator strategy."""
|
|
14
|
+
|
|
15
|
+
br_strategy = re.compile(r"\n")
|
|
16
|
+
"""Default decorator strategy matching single line breaks."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_decorations(
|
|
20
|
+
decorators: CompositeDecorators, text: str
|
|
21
|
+
) -> list[tuple[int, int, Any, Decorator]]:
|
|
22
|
+
"""Collect non-overlapping decorator matches for the given text.
|
|
23
|
+
|
|
24
|
+
Parameters:
|
|
25
|
+
decorators: Composite decorator definitions.
|
|
26
|
+
text: The block text to decorate.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
A sorted list of decorations as ``(start, end, match, decorator)`` tuples.
|
|
30
|
+
"""
|
|
31
|
+
occupied: dict[int, int] = {}
|
|
32
|
+
decorations: list[tuple[int, int, Any, Decorator]] = []
|
|
33
|
+
|
|
34
|
+
for decorator in decorators:
|
|
35
|
+
for match in decorator["strategy"].finditer(text):
|
|
36
|
+
begin, end = match.span()
|
|
37
|
+
if not any(occupied.get(i) for i in range(begin, end)):
|
|
38
|
+
for i in range(begin, end):
|
|
39
|
+
occupied[i] = 1
|
|
40
|
+
decorations.append((begin, end, match, decorator))
|
|
41
|
+
|
|
42
|
+
decorations.sort(key=itemgetter(0))
|
|
43
|
+
|
|
44
|
+
return decorations
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def apply_decorators(
|
|
48
|
+
decorators: CompositeDecorators,
|
|
49
|
+
text: str,
|
|
50
|
+
block: Block,
|
|
51
|
+
blocks: list[Block],
|
|
52
|
+
) -> Generator[str, None, None]:
|
|
53
|
+
"""Yield decorated text segments and decorator elements for a block.
|
|
54
|
+
|
|
55
|
+
Parameters:
|
|
56
|
+
decorators: Composite decorator definitions.
|
|
57
|
+
text: The block text to decorate.
|
|
58
|
+
block: The block currently being rendered.
|
|
59
|
+
blocks: All blocks in the content state.
|
|
60
|
+
|
|
61
|
+
Yields:
|
|
62
|
+
Plain text or decorator element nodes covering the full block text.
|
|
63
|
+
"""
|
|
64
|
+
decorations = get_decorations(decorators, text)
|
|
65
|
+
|
|
66
|
+
pointer = 0
|
|
67
|
+
for begin, end, match, decorator in decorations:
|
|
68
|
+
if pointer < begin:
|
|
69
|
+
yield text[pointer:begin]
|
|
70
|
+
|
|
71
|
+
yield DOM.create_element(
|
|
72
|
+
decorator["component"],
|
|
73
|
+
{"match": match, "block": block, "blocks": blocks},
|
|
74
|
+
match.group(0),
|
|
75
|
+
)
|
|
76
|
+
pointer = end
|
|
77
|
+
|
|
78
|
+
if pointer < len(text):
|
|
79
|
+
yield text[pointer:]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def render_decorators(
|
|
83
|
+
decorators: CompositeDecorators,
|
|
84
|
+
text: str,
|
|
85
|
+
block: Block,
|
|
86
|
+
blocks: list[Block],
|
|
87
|
+
dom: type[DOMEngine],
|
|
88
|
+
) -> Element:
|
|
89
|
+
"""Render all decorator output for a block into a single element.
|
|
90
|
+
|
|
91
|
+
Parameters:
|
|
92
|
+
decorators: Composite decorator definitions.
|
|
93
|
+
text: The block text to decorate.
|
|
94
|
+
block: The block currently being rendered.
|
|
95
|
+
blocks: All blocks in the content state.
|
|
96
|
+
dom: The active DOM engine.
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
A single element containing all decorated text, or the text itself.
|
|
100
|
+
"""
|
|
101
|
+
decorated_children = list(apply_decorators(decorators, text, block, blocks))
|
|
102
|
+
|
|
103
|
+
if len(decorated_children) == 1:
|
|
104
|
+
decorated_node = decorated_children[0]
|
|
105
|
+
else:
|
|
106
|
+
decorated_node = DOM.create_element()
|
|
107
|
+
for decorated_child in decorated_children:
|
|
108
|
+
dom.append_child(decorated_node, decorated_child)
|
|
109
|
+
|
|
110
|
+
return decorated_node
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def should_render_decorators(
|
|
114
|
+
decorators: CompositeDecorators,
|
|
115
|
+
text: str,
|
|
116
|
+
) -> bool:
|
|
117
|
+
"""Return whether decorators need to be processed for the given text.
|
|
118
|
+
|
|
119
|
+
Parameters:
|
|
120
|
+
decorators: Composite decorator definitions.
|
|
121
|
+
text: The block text to check.
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
True when there are decorators and the default newline-only optimization does not apply.
|
|
125
|
+
"""
|
|
126
|
+
nb_decorators = len(decorators)
|
|
127
|
+
|
|
128
|
+
if nb_decorators == 0:
|
|
129
|
+
return False
|
|
130
|
+
|
|
131
|
+
is_skippable_br = (
|
|
132
|
+
nb_decorators == 1
|
|
133
|
+
and decorators[0]["strategy"] == br_strategy
|
|
134
|
+
and br not in text
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
return not is_skippable_br
|
|
@@ -1,11 +1,36 @@
|
|
|
1
|
+
"""Draft.js-compatible constants used by the exporter.
|
|
2
|
+
|
|
3
|
+
Defines the block types, inline styles, and entity categories supported
|
|
4
|
+
by Draft.js, plus a small enum helper.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
|
|
1
8
|
# http://stackoverflow.com/a/22723724/1798491
|
|
2
9
|
class Enum:
|
|
10
|
+
"""Minimal enum-like container exposing a fixed set of string attributes.
|
|
11
|
+
|
|
12
|
+
Accessing a registered attribute returns its name. Accessing any other
|
|
13
|
+
attribute raises ``AttributeError``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
3
16
|
__slots__ = "elements"
|
|
4
17
|
|
|
5
18
|
def __init__(self, *elements: str) -> None:
|
|
19
|
+
"""Store the allowed attribute names for the enum."""
|
|
6
20
|
self.elements = tuple(elements)
|
|
7
21
|
|
|
8
22
|
def __getattr__(self, name: str) -> str:
|
|
23
|
+
"""Return the attribute name if it is a registered enum element.
|
|
24
|
+
|
|
25
|
+
Parameters:
|
|
26
|
+
name: Attribute name being accessed.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
The requested attribute name.
|
|
30
|
+
|
|
31
|
+
Raises:
|
|
32
|
+
AttributeError: If the name is not a registered element.
|
|
33
|
+
"""
|
|
9
34
|
if name not in self.elements:
|
|
10
35
|
raise AttributeError(f"'Enum' has no attribute '{name}'")
|
|
11
36
|
|
|
@@ -14,6 +39,8 @@ class Enum:
|
|
|
14
39
|
|
|
15
40
|
# https://github.com/facebook/draft-js/blob/master/src/model/constants/DraftBlockType.js
|
|
16
41
|
class BLOCK_TYPES:
|
|
42
|
+
"""Draft.js block types mapped to HTML elements."""
|
|
43
|
+
|
|
17
44
|
UNSTYLED = "unstyled"
|
|
18
45
|
HEADER_ONE = "header-one"
|
|
19
46
|
HEADER_TWO = "header-two"
|
|
@@ -40,6 +67,7 @@ ENTITY_TYPES = Enum(
|
|
|
40
67
|
# Special type to configure handling of missing components.
|
|
41
68
|
"FALLBACK",
|
|
42
69
|
)
|
|
70
|
+
"""Draft.js entity categories."""
|
|
43
71
|
|
|
44
72
|
INLINE_STYLES = Enum(
|
|
45
73
|
"BOLD",
|
|
@@ -59,3 +87,4 @@ INLINE_STYLES = Enum(
|
|
|
59
87
|
# Special type to configure handling of missing components.
|
|
60
88
|
"FALLBACK",
|
|
61
89
|
)
|
|
90
|
+
"""Draft.js inline style names."""
|