edwh-editorjs 2.0.0b1__tar.gz → 2.0.0b3__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.
Files changed (29) hide show
  1. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/CHANGELOG.md +12 -0
  2. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/LICENSE +1 -0
  3. edwh_editorjs-2.0.0b3/PKG-INFO +28 -0
  4. edwh_editorjs-2.0.0b3/README.md +2 -0
  5. edwh_editorjs-2.0.0b3/editorjs/__about__.py +1 -0
  6. edwh_editorjs-2.0.0b3/editorjs/__init__.py +5 -0
  7. edwh_editorjs-2.0.0b3/editorjs/blocks.py +382 -0
  8. edwh_editorjs-2.0.0b3/editorjs/core.py +116 -0
  9. edwh_editorjs-2.0.0b3/editorjs/exceptions.py +3 -0
  10. edwh_editorjs-2.0.0b3/editorjs/helpers.py +5 -0
  11. edwh_editorjs-2.0.0b3/editorjs/types.py +43 -0
  12. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/pyproject.toml +9 -7
  13. edwh_editorjs-2.0.0b3/tests/test_core.py +74 -0
  14. edwh_editorjs-2.0.0b1/PKG-INFO +0 -104
  15. edwh_editorjs-2.0.0b1/README.md +0 -79
  16. edwh_editorjs-2.0.0b1/pyeditorjs/__about__.py +0 -1
  17. edwh_editorjs-2.0.0b1/pyeditorjs/__init__.py +0 -30
  18. edwh_editorjs-2.0.0b1/pyeditorjs/blocks.py +0 -313
  19. edwh_editorjs-2.0.0b1/pyeditorjs/exceptions.py +0 -19
  20. edwh_editorjs-2.0.0b1/pyeditorjs/parser.py +0 -75
  21. edwh_editorjs-2.0.0b1/scripts/build_documentation.sh +0 -4
  22. edwh_editorjs-2.0.0b1/scripts/compile_everything.sh +0 -4
  23. edwh_editorjs-2.0.0b1/scripts/compile_for_pypi.sh +0 -4
  24. edwh_editorjs-2.0.0b1/tests/test_parser.py +0 -42
  25. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/.github/workflows/build_documentation.yml +0 -0
  26. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/.github/workflows/publish_to_pypi.yml +0 -0
  27. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/.github/workflows/pytest.yml +0 -0
  28. {edwh_editorjs-2.0.0b1 → edwh_editorjs-2.0.0b3}/.gitignore +0 -0
  29. /edwh_editorjs-2.0.0b1/requirements.txt → /edwh_editorjs-2.0.0b3/tests/__init__.py +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  <!--next-version-placeholder-->
4
4
 
5
+ ## v2.0.0-beta.3 (2024-11-06)
6
+
7
+ ### Fix
8
+
9
+ * Various fixes with nested lists ([`52a7773`](https://github.com/educationwarehouse/edwh-editorjs/commit/52a7773470dce3eee6a2d17d46b594551ed043a5))
10
+
11
+ ## v2.0.0-beta.2 (2024-11-06)
12
+
13
+ ### Feature
14
+
15
+ * Work in progress to do a rebuild based on mdast ([`28c12f1`](https://github.com/educationwarehouse/edwh-editorjs/commit/28c12f1f74c71a995f9f8097f1b26be45f835ad4))
16
+
5
17
  ## v2.0.0-beta.1 (2024-11-06)
6
18
 
7
19
 
@@ -1,6 +1,7 @@
1
1
  MIT License
2
2
 
3
3
  Copyright (c) 2021 SKevo
4
+ Copyright (c) 2024 Education Warehouse
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,28 @@
1
+ Metadata-Version: 2.3
2
+ Name: edwh-editorjs
3
+ Version: 2.0.0b3
4
+ Summary: EditorJS.py
5
+ Project-URL: Homepage, https://github.com/educationwarehouse/edwh-EditorJS
6
+ Author-email: SKevo <skevo.cw@gmail.com>, Robin van der Noord <robin.vdn@educationwarehouse.nl>
7
+ License: MIT
8
+ License-File: LICENSE
9
+ Keywords: bleach,clean,editor,editor.js,html,javascript,json,parser,wysiwyg
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: markdown2
19
+ Requires-Dist: mdast
20
+ Provides-Extra: dev
21
+ Requires-Dist: edwh; extra == 'dev'
22
+ Requires-Dist: hatch; extra == 'dev'
23
+ Requires-Dist: su6[all]; extra == 'dev'
24
+ Requires-Dist: types-bleach; extra == 'dev'
25
+ Description-Content-Type: text/markdown
26
+
27
+ # edwh-editorjs
28
+
@@ -0,0 +1,2 @@
1
+ # edwh-editorjs
2
+
@@ -0,0 +1 @@
1
+ __version__ = "2.0.0-beta.3"
@@ -0,0 +1,5 @@
1
+ from .core import EditorJS
2
+
3
+ __all__ = [
4
+ "EditorJS",
5
+ ]
@@ -0,0 +1,382 @@
1
+ """
2
+ mdast to editorjs
3
+ """
4
+
5
+ import abc
6
+ import re
7
+ import typing as t
8
+
9
+ from .exceptions import TODO
10
+ from .types import EditorChildData, MDChildNode
11
+
12
+
13
+ class EditorJSBlock(abc.ABC):
14
+ @classmethod
15
+ @abc.abstractmethod
16
+ def to_markdown(cls, data: EditorChildData) -> str: ...
17
+
18
+ @classmethod
19
+ @abc.abstractmethod
20
+ def to_json(cls, node: MDChildNode) -> list[dict]: ...
21
+
22
+ @classmethod
23
+ @abc.abstractmethod
24
+ def to_text(cls, node: MDChildNode) -> str: ...
25
+
26
+
27
+ BLOCKS: dict[str, EditorJSBlock] = {}
28
+
29
+
30
+ def block(*names: str):
31
+ def wrapper(cls):
32
+ for name in names:
33
+ BLOCKS[name] = cls
34
+ return cls
35
+
36
+ return wrapper
37
+
38
+
39
+ def process_styled_content(item: MDChildNode, strict: bool = True) -> str:
40
+ """
41
+ Processes styled content (e.g., bold, italic) within a list item.
42
+
43
+ Args:
44
+ item: A ChildNode dictionary representing an inline element or text.
45
+ strict: Raise if 'type' is not one defined in 'html_wrappers'
46
+
47
+ Returns:
48
+ A formatted HTML string based on the item type.
49
+ """
50
+ _type = item.get("type")
51
+ html_wrappers = {
52
+ "text": "{value}",
53
+ "html": "{value}",
54
+ "emphasis": "<i>{value}</i>",
55
+ "strong": "<b>{value}</b>",
56
+ "strongEmphasis": "<b><i>{value}</i></b>",
57
+ "link": '<a href="{url}">{value}</a>',
58
+ "inlineCode": '<code class="inline-code">{value}</code>',
59
+ # todo: <mark>
60
+ }
61
+
62
+ if _type in BLOCKS:
63
+ return BLOCKS[_type].to_text(item)
64
+
65
+ if strict and _type not in html_wrappers:
66
+ raise ValueError(f"Unsupported type {_type} in paragraph")
67
+
68
+ # Process children recursively if they exist, otherwise use the direct value
69
+ if children := item.get("children"):
70
+ value = "".join(process_styled_content(child) for child in children)
71
+ else:
72
+ value = item.get("value", "")
73
+
74
+ template = html_wrappers.get(_type, "{value}")
75
+ return template.format(
76
+ value=value, url=item.get("url", ""), caption=item.get("caption", "")
77
+ )
78
+
79
+
80
+ def default_to_text(node: MDChildNode):
81
+ return "".join(
82
+ process_styled_content(child) for child in node.get("children", [])
83
+ ) or process_styled_content(node)
84
+
85
+
86
+ @block("heading", "header")
87
+ class HeadingBlock(EditorJSBlock):
88
+ @classmethod
89
+ def to_markdown(cls, data: EditorChildData) -> str:
90
+ level = data.get("level", 1)
91
+ text = data.get("text", "")
92
+
93
+ if not (1 <= level <= 6):
94
+ raise ValueError("Header level must be between 1 and 6.")
95
+
96
+ return f"{'#' * level} {text}\n"
97
+
98
+ @classmethod
99
+ def to_json(cls, node: MDChildNode) -> list[dict]:
100
+ """
101
+ Converts a Markdown header block into structured block data.
102
+
103
+ Args:
104
+ node: A RootNode dictionary with 'depth' and 'children'.
105
+
106
+ Returns:
107
+ A ChildNode dictionary representing the header data, or None if no children exist.
108
+
109
+ Raises:
110
+ ValueError: If an unsupported heading depth is provided.
111
+ """
112
+
113
+ depth = node.get("depth")
114
+
115
+ if depth is None or not (1 <= depth <= 6):
116
+ raise ValueError("Heading depth must be between 1 and 6.")
117
+
118
+ return [{"data": {"level": depth, "text": cls.to_text(node)}, "type": "header"}]
119
+
120
+ @classmethod
121
+ def to_text(cls, node: MDChildNode) -> str:
122
+ children = node.get("children", [])
123
+ if children is None or not len(children) == 1:
124
+ raise ValueError("Header block must have exactly one child element")
125
+ child = children[0]
126
+ return child.get("value", "")
127
+
128
+
129
+ @block("paragraph")
130
+ class ParagraphBlock(EditorJSBlock):
131
+ @classmethod
132
+ def to_markdown(cls, data: EditorChildData) -> str:
133
+ text = data.get("text", "")
134
+ return f"{text}\n"
135
+
136
+ @classmethod
137
+ def to_json(cls, node: MDChildNode) -> list[dict]:
138
+ result = []
139
+ current_text = ""
140
+
141
+ for child in node.get("children"):
142
+ _type = child.get("type")
143
+ if _type == "image":
144
+ if current_text:
145
+ result.append({"data": {"text": current_text}, "type": "paragraph"})
146
+ current_text = ""
147
+
148
+ result.extend(ImageBlock.to_json(child))
149
+ else:
150
+ current_text += cls.to_text(child)
151
+
152
+ # final text after image:
153
+ if current_text:
154
+ result.append({"data": {"text": current_text}, "type": "paragraph"})
155
+
156
+ return result
157
+
158
+ @classmethod
159
+ def to_text(cls, node: MDChildNode) -> str:
160
+ return default_to_text(node)
161
+
162
+
163
+ @block("list")
164
+ class ListBlock(EditorJSBlock):
165
+ @classmethod
166
+ def to_markdown(cls, data: EditorChildData) -> str:
167
+ style = data.get("style", "unordered")
168
+ items = data.get("items", [])
169
+
170
+ def parse_items(subitems: list[dict[str, t.Any]], depth: int = 0) -> str:
171
+ markdown_items = []
172
+ for index, item in enumerate(subitems):
173
+ prefix = f"{index + 1}." if style == "ordered" else "-"
174
+ line = f"{'\t' * depth}{prefix} {item['content']}"
175
+ markdown_items.append(line)
176
+
177
+ # Recurse if there are nested items
178
+ if item.get("items"):
179
+ markdown_items.append(parse_items(item["items"], depth + 1))
180
+
181
+ return "\n".join(markdown_items)
182
+
183
+ return "\n" + parse_items(items) + "\n"
184
+
185
+ @classmethod
186
+ def to_json(cls, node: MDChildNode) -> list[dict]:
187
+ """
188
+ Converts a Markdown list block with nested items and styling into structured block data.
189
+
190
+ Args:
191
+ node: A RootNode dictionary with 'ordered' and 'children'.
192
+
193
+ Returns:
194
+ A dictionary representing the structured list data with 'items' and 'style'.
195
+ """
196
+ items = []
197
+ # checklists are not supported (well) by mdast
198
+ # so we detect it ourselves:
199
+ could_be_checklist = True
200
+
201
+ def is_checklist(value: str) -> bool:
202
+ return value.strip().startswith(("[ ]", "[x]"))
203
+
204
+ for child in node["children"]:
205
+ content = ""
206
+ subitems = []
207
+ # child can have content and/or items
208
+ for grandchild in child["children"]:
209
+ _type = grandchild.get("type", "")
210
+ if _type == "paragraph":
211
+ subcontent = ParagraphBlock.to_text(grandchild)
212
+ could_be_checklist = could_be_checklist and is_checklist(subcontent)
213
+ content += "" + subcontent
214
+ elif _type == "list":
215
+ could_be_checklist = False
216
+ subitems.extend(ListBlock.to_json(grandchild)[0]["data"]["items"])
217
+ else:
218
+ raise ValueError(f"Unsupported type {_type} in list")
219
+
220
+ items.append(
221
+ {
222
+ "content": content,
223
+ "items": subitems,
224
+ }
225
+ )
226
+
227
+ # todo: detect 'checklist':
228
+ """
229
+ type: checklist
230
+ data: {items: [{text: "a", checked: false}, {text: "b", checked: false}, {text: "c", checked: true},…]}
231
+ """
232
+
233
+ if could_be_checklist:
234
+ return [
235
+ {
236
+ "type": "checklist",
237
+ "data": {
238
+ "items": [
239
+ {
240
+ "text": x["content"]
241
+ .removeprefix("[ ] ")
242
+ .removeprefix("[x] "),
243
+ "checked": x["content"].startswith("[x]"),
244
+ }
245
+ for x in items
246
+ ]
247
+ },
248
+ }
249
+ ]
250
+ else:
251
+ return [
252
+ {
253
+ "data": {
254
+ "items": items,
255
+ "style": "ordered" if node.get("ordered") else "unordered",
256
+ },
257
+ "type": "list",
258
+ }
259
+ ]
260
+
261
+ @classmethod
262
+ def to_text(cls, node: MDChildNode) -> str:
263
+ return ""
264
+
265
+
266
+ @block("checklist")
267
+ class ChecklistBlock(ListBlock):
268
+ @classmethod
269
+ def to_markdown(cls, data: EditorChildData) -> str:
270
+ markdown_items = []
271
+
272
+ for item in data.get("items", []):
273
+ text = item.get("text", "").strip()
274
+ char = "x" if item.get("checked", False) else " "
275
+ markdown_items.append(f"- [{char}] {text}")
276
+
277
+ return "\n" + "\n".join(markdown_items) + "\n"
278
+
279
+
280
+ @block("thematicBreak", "delimiter")
281
+ class DelimiterBlock(EditorJSBlock):
282
+ @classmethod
283
+ def to_markdown(cls, data: EditorChildData) -> str:
284
+ return "***\n"
285
+
286
+ @classmethod
287
+ def to_json(cls, node: MDChildNode) -> list[dict]:
288
+ return [
289
+ {
290
+ "type": "delimiter",
291
+ "data": {},
292
+ }
293
+ ]
294
+
295
+ @classmethod
296
+ def to_text(cls, node: MDChildNode) -> str:
297
+ return ""
298
+
299
+
300
+ @block("code")
301
+ class CodeBlock(EditorJSBlock):
302
+ @classmethod
303
+ def to_markdown(cls, data: EditorChildData) -> str:
304
+ code = data.get("code", "")
305
+ return f"```\n" f"{code}" f"\n```\n"
306
+
307
+ @classmethod
308
+ def to_json(cls, node: MDChildNode) -> list[dict]:
309
+ return [
310
+ {
311
+ "data": {"code": cls.to_text(node)},
312
+ "type": "code",
313
+ }
314
+ ]
315
+
316
+ @classmethod
317
+ def to_text(cls, node: MDChildNode) -> str:
318
+ return node.get("value", "")
319
+
320
+
321
+ @block("image")
322
+ class ImageBlock(EditorJSBlock):
323
+ @classmethod
324
+ def to_markdown(cls, data: EditorChildData) -> str:
325
+ url = data.get("url", "") or data.get("file", {}).get("url", "")
326
+ caption = data.get("caption", "")
327
+ return f"""![{caption}]({url} "{caption}")\n"""
328
+
329
+ @classmethod
330
+ def to_json(cls, node: MDChildNode) -> list[dict]:
331
+ return [
332
+ {
333
+ "type": "image",
334
+ "data": {
335
+ "caption": cls.to_text(node),
336
+ "file": {"url": node.get("url")},
337
+ },
338
+ }
339
+ ]
340
+
341
+ @classmethod
342
+ def to_text(cls, node: MDChildNode) -> str:
343
+ return node.get("alt") or node.get("caption") or ""
344
+
345
+
346
+ @block("blockquote", "quote")
347
+ class QuoteBlock(EditorJSBlock):
348
+ re_cite = re.compile(r"<cite>(.+?)<\/cite>")
349
+
350
+ @classmethod
351
+ def to_markdown(cls, data: EditorChildData) -> str:
352
+ text = data.get("text", "")
353
+ result = f"> {text}\n"
354
+ if caption := data.get("caption", ""):
355
+ result += f"> <cite>{caption}</cite>\n"
356
+ return result
357
+
358
+ @classmethod
359
+ def to_json(cls, node: MDChildNode) -> list[dict]:
360
+ caption = ""
361
+ text = cls.to_text(node).replace("\n", "<br/>\n")
362
+
363
+ if cite := re.search(cls.re_cite, text):
364
+ # Capture the value of the first group
365
+ caption = cite.group(1)
366
+ # Remove the <cite>...</cite> tags from the text
367
+ text = re.sub(cls.re_cite, "", text)
368
+
369
+ return [
370
+ {
371
+ "data": {
372
+ "alignment": "left",
373
+ "caption": caption,
374
+ "text": text,
375
+ },
376
+ "type": "quote",
377
+ }
378
+ ]
379
+
380
+ @classmethod
381
+ def to_text(cls, node: MDChildNode) -> str:
382
+ return default_to_text(node)
@@ -0,0 +1,116 @@
1
+ import json
2
+ import textwrap
3
+ import typing as t
4
+
5
+ import markdown2
6
+ import mdast
7
+ from typing_extensions import Self
8
+
9
+ from .blocks import BLOCKS
10
+ from .exceptions import TODO
11
+ from .helpers import unix_timestamp
12
+ from .types import MDRootNode
13
+
14
+ EDITORJS_VERSION = "2.30.6"
15
+
16
+
17
+ class EditorJS:
18
+ # internal representation is mdast, because we can convert to other types
19
+ _mdast: MDRootNode
20
+
21
+ def __init__(self, _mdast: str | dict, extras: list = ("task_list", "fenced-code-blocks")):
22
+ if not isinstance(_mdast, str | dict):
23
+ raise TypeError("Only `str` or `dict` is supported!")
24
+
25
+ self._mdast = t.cast(
26
+ MDRootNode, json.loads(_mdast) if isinstance(_mdast, str) else _mdast
27
+ )
28
+
29
+ self._md = markdown2.Markdown(extras=extras) # todo: striketrough, table, ?
30
+
31
+ @classmethod
32
+ def from_json(cls, data: str | dict) -> Self:
33
+ """
34
+ Load from EditorJS JSON Blocks
35
+ """
36
+ data = data if isinstance(data, dict) else json.loads(data)
37
+ markdown_items = []
38
+ for child in data["blocks"]:
39
+ _type = child["type"]
40
+ if not (block := BLOCKS.get(_type)):
41
+ raise TypeError(f"Unsupported block type `{_type}`")
42
+
43
+ markdown_items.append(block.to_markdown(child.get("data", {})))
44
+
45
+ markdown = "".join(markdown_items)
46
+ return cls.from_markdown(markdown)
47
+
48
+ @classmethod
49
+ def from_markdown(cls, data: str) -> Self:
50
+ """
51
+ Load from markdown string
52
+ """
53
+
54
+ return cls(mdast.md_to_json(data))
55
+
56
+ @classmethod
57
+ def from_mdast(cls, data: str | dict) -> Self:
58
+ """
59
+ Existing mdast representation
60
+ """
61
+ return cls(data)
62
+
63
+ def to_json(self) -> str:
64
+ """
65
+ Export EditorJS JSON Blocks
66
+ """
67
+ # logic based on https://github.com/carrara88/editorjs-md-parser/blob/main/src/MarkdownImporter.js
68
+ blocks = []
69
+ for child in self._mdast["children"]:
70
+ _type = child["type"]
71
+ if not (block := BLOCKS.get(_type)):
72
+ raise TypeError(f"Unsupported block type `{_type}`")
73
+
74
+ blocks.extend(block.to_json(child))
75
+
76
+ data = {"time": unix_timestamp(), "blocks": blocks, "version": EDITORJS_VERSION}
77
+
78
+ return json.dumps(data)
79
+
80
+ def to_markdown(self) -> str:
81
+ """
82
+ Export Markdown string
83
+ """
84
+ md = mdast.json_to_md(self.to_mdast())
85
+ # idk why this happens:
86
+ md = md.replace(r"\[ ]", "[ ]")
87
+ md = md.replace(r"\[x]", "[x]")
88
+ return md
89
+
90
+ def to_mdast(self) -> str:
91
+ """
92
+ Export mdast representation
93
+ """
94
+ return json.dumps(self._mdast)
95
+
96
+ def to_html(self) -> str:
97
+ """
98
+ Export HTML string
99
+ """
100
+ md = self.to_markdown()
101
+ return self._md.convert(md)
102
+
103
+ def __repr__(self):
104
+ md = self.to_markdown()
105
+ md = md.replace("\n", "\\n")
106
+ return f"EditorJS({md})"
107
+
108
+ def __str__(self):
109
+ return self.to_markdown()
110
+
111
+ # def __eq__(self, other: Self) -> bool:
112
+ # a = self.to_markdown()
113
+ # b = other.to_markdown()
114
+ #
115
+ # remove = string.punctuation + string.whitespace
116
+ # return a.translate(remove) == b.translate(remove)
@@ -0,0 +1,3 @@
1
+ class TODO(NotImplementedError):
2
+ def __init__(self, msg: str = "todo"):
3
+ super().__init__(msg)
@@ -0,0 +1,5 @@
1
+ import time
2
+
3
+
4
+ def unix_timestamp():
5
+ return round(time.time() * 1000)
@@ -0,0 +1,43 @@
1
+ import typing as t
2
+
3
+
4
+ class MDPosition(t.TypedDict):
5
+ line: int
6
+ column: int
7
+ offset: int
8
+
9
+
10
+ class MDPositionRange(t.TypedDict):
11
+ start: MDPosition
12
+ end: MDPosition
13
+
14
+
15
+ class MDChildNode(t.TypedDict, total=False):
16
+ type: str # General identifier for node types
17
+ children: list["MDChildNode"] # Recursive children of any node type
18
+ position: MDPositionRange
19
+ value: str # Optional, for nodes like text that hold a value
20
+ depth: int # Optional, for nodes like headings that have a depth
21
+ url: t.NotRequired[str]
22
+
23
+
24
+ class MDRootNode(t.TypedDict):
25
+ type: t.Literal["root"] # Constrains to 'root' for the root node
26
+ children: list[MDChildNode] # Allows any ChildNode type in children
27
+ position: MDPositionRange
28
+
29
+
30
+ class EditorChildData(t.TypedDict, total=False):
31
+ text: str
32
+ items: list["EditorChildNode"]
33
+
34
+
35
+ class EditorChildNode(t.TypedDict):
36
+ type: str
37
+ data: EditorChildData
38
+
39
+
40
+ class EditorRootNode(t.TypedDict):
41
+ time: int
42
+ blocks: list[EditorChildNode]
43
+ version: str
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
  name = "edwh-editorjs"
7
7
  dynamic = ["version"]
8
8
 
9
- description = "pyEditorJS"
9
+ description = "EditorJS.py"
10
10
  readme = "README.md"
11
11
  authors = [
12
12
  { name = "SKevo", email = "skevo.cw@gmail.com" },
@@ -26,7 +26,9 @@ classifiers = [
26
26
  requires-python = ">=3.10"
27
27
 
28
28
  dependencies = [
29
- "bleach"
29
+ # "bleach",
30
+ "mdast",
31
+ "markdown2",
30
32
  ]
31
33
 
32
34
  [project.optional-dependencies]
@@ -42,23 +44,23 @@ Homepage = "https://github.com/educationwarehouse/edwh-EditorJS"
42
44
 
43
45
  [tool.semantic_release]
44
46
  branch = "master"
45
- version_variable = "pyeditorjs/__about__.py:__version__"
47
+ version_variable = "editorjs/__about__.py:__version__"
46
48
  change_log = "CHANGELOG.md"
47
49
  upload_to_repository = false
48
50
  upload_to_release = false
49
51
  build_command = "hatch build"
50
52
 
51
53
  [tool.hatch.version]
52
- path = "pyeditorjs/__about__.py"
54
+ path = "editorjs/__about__.py"
53
55
 
54
56
  [tool.hatch.build.targets.wheel]
55
- packages = ["pyeditorjs"]
57
+ packages = ["editorjs"]
56
58
 
57
59
 
58
60
  [tool.setuptools.packages.find]
59
- include = ["pyeditorjs"]
61
+ include = ["editorjs"]
60
62
  exclude = ["tests"]
61
63
 
62
64
  [tool.su6]
63
- directory = "pyeditorjs"
65
+ directory = "editorjs"
64
66
  stop-after-first-failure = true