edwh-editorjs 2.3.2__py3-none-any.whl → 2.5.0__py3-none-any.whl

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.
editorjs/__about__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "2.3.2"
1
+ __version__ = "2.5.0"
editorjs/blocks.py CHANGED
@@ -8,6 +8,7 @@ import typing as t
8
8
  from html.parser import HTMLParser
9
9
  from urllib.parse import urlparse
10
10
 
11
+ import html2markdown
11
12
  import humanize
12
13
  import markdown2
13
14
 
@@ -53,6 +54,7 @@ def process_styled_content(item: MDChildNode, strict: bool = True) -> str:
53
54
  A formatted HTML string based on the item type.
54
55
  """
55
56
  _type = item.get("type")
57
+
56
58
  html_wrappers = {
57
59
  "text": "{value}",
58
60
  "html": "{value}",
@@ -82,9 +84,16 @@ def process_styled_content(item: MDChildNode, strict: bool = True) -> str:
82
84
 
83
85
 
84
86
  def default_to_text(node: MDChildNode):
85
- return "".join(
86
- process_styled_content(child) for child in node.get("children", [])
87
- ) or process_styled_content(node)
87
+ if node["type"] == "paragraph":
88
+ return "".join(
89
+ process_styled_content(child) for child in node.get("children", [])
90
+ )
91
+ else:
92
+ return process_styled_content(node)
93
+
94
+ # return "".join(
95
+ # process_styled_content(child) for child in node.get("children", [])
96
+ # ) or process_styled_content(node)
88
97
 
89
98
 
90
99
  @block("heading", "header")
@@ -173,6 +182,9 @@ class ParagraphBlock(EditorJSBlock):
173
182
  }
174
183
  )
175
184
 
185
+ # deal with bold etc:
186
+ text = html2markdown.convert(text)
187
+
176
188
  return f"{text}\n\n"
177
189
 
178
190
  @classmethod
@@ -384,7 +396,7 @@ class CodeBlock(EditorJSBlock):
384
396
  @classmethod
385
397
  def to_markdown(cls, data: EditorChildData) -> str:
386
398
  code = data.get("code", "")
387
- return f"```\n" f"{code}" f"\n```\n"
399
+ return f"```\n{code}\n```\n"
388
400
 
389
401
  @classmethod
390
402
  def to_json(cls, node: MDChildNode) -> list[dict]:
@@ -406,7 +418,17 @@ class ImageBlock(EditorJSBlock):
406
418
  def to_markdown(cls, data: EditorChildData) -> str:
407
419
  url = data.get("url", "") or data.get("file", {}).get("url", "")
408
420
  caption = data.get("caption", "")
409
- return f"""![{caption}]({url} "{caption}")\n\n"""
421
+
422
+ with_border = "1" if data.get("withBorder") else ""
423
+ with_background = "1" if data.get("withBackground") else ""
424
+ stretched = "1" if data.get("stretched") else ""
425
+
426
+ # always custom type so we can render as <figure> instead of markdown2's default (simple <img>)
427
+ return f"""<editorjs type="image" caption="{caption}" border="{with_border}" background="{with_background}" stretched="{stretched}" url="{url}" />\n\n"""
428
+
429
+ @classmethod
430
+ def _caption(cls, node: MDChildNode):
431
+ return node.get("alt") or node.get("caption") or ""
410
432
 
411
433
  @classmethod
412
434
  def to_json(cls, node: MDChildNode) -> list[dict]:
@@ -414,15 +436,37 @@ class ImageBlock(EditorJSBlock):
414
436
  {
415
437
  "type": "image",
416
438
  "data": {
417
- "caption": cls.to_text(node),
418
439
  "file": {"url": node.get("url")},
440
+ "caption": cls._caption(node),
441
+ "withBorder": bool(node.get("border", False)),
442
+ "stretched": bool(node.get("stretched", False)),
443
+ "withBackground": bool(node.get("background", False)),
419
444
  },
420
445
  }
421
446
  ]
422
447
 
423
448
  @classmethod
424
449
  def to_text(cls, node: MDChildNode) -> str:
425
- return node.get("alt") or node.get("caption") or ""
450
+ caption = cls._caption(node)
451
+ url = node.get("url")
452
+
453
+ background = node.get("background") or ""
454
+ stretched = node.get("stretched") or ""
455
+ border = node.get("border") or ""
456
+
457
+ return f"""
458
+ <div class="ce-block {stretched and "ce-block--stretched"}">
459
+ <div class="ce-block__content">
460
+ <div class="cdx-block image-tool image-tool--filled {background and "image-tool--withBackground"} {stretched and "image-tool--stretched"} {border and "image-tool--withBorder"}">
461
+ <div class="image-tool__image">
462
+ <figure>
463
+ <img class="image-tool__image-picture" src="{url}" title="{caption}" alt="{caption}">
464
+ <figcaption>{caption}</figcaption>
465
+ </figure>
466
+ </div>
467
+ </div>
468
+ </div>
469
+ """
426
470
 
427
471
 
428
472
  @block("blockquote", "quote")
@@ -435,7 +479,7 @@ class QuoteBlock(EditorJSBlock):
435
479
  result = f"> {text}\n"
436
480
  if caption := data.get("caption", ""):
437
481
  result += f"> <cite>{caption}</cite>\n"
438
- return result
482
+ return result + "\n"
439
483
 
440
484
  @classmethod
441
485
  def to_json(cls, node: MDChildNode) -> list[dict]:
@@ -461,12 +505,13 @@ class QuoteBlock(EditorJSBlock):
461
505
 
462
506
  @classmethod
463
507
  def to_text(cls, node: MDChildNode) -> str:
464
- return default_to_text(node)
508
+ return "".join(
509
+ process_styled_content(child) for child in node.get("children", [])
510
+ )
465
511
 
466
512
 
467
513
  @block("raw", "html")
468
514
  class RawBlock(EditorJSBlock):
469
-
470
515
  @classmethod
471
516
  def to_markdown(cls, data: EditorChildData) -> str:
472
517
  text = data.get("html", "")
@@ -489,7 +534,6 @@ class RawBlock(EditorJSBlock):
489
534
 
490
535
  @block("table")
491
536
  class TableBlock(EditorJSBlock):
492
-
493
537
  @classmethod
494
538
  def to_markdown(cls, data: EditorChildData) -> str:
495
539
  """
@@ -608,7 +652,6 @@ class LinkBlock(EditorJSBlock):
608
652
 
609
653
  @block("attaches")
610
654
  class AttachmentBlock(EditorJSBlock):
611
-
612
655
  @classmethod
613
656
  def to_markdown(cls, data: EditorChildData) -> str:
614
657
  title = data.get("title", "")
@@ -673,7 +716,7 @@ class AttachmentBlock(EditorJSBlock):
673
716
  </div>
674
717
  {file_size}
675
718
  </div>
676
- <a class="cdx-attaches__download-button" href="{node.get('file', '')}" target="_blank" rel="nofollow noindex noreferrer" title="{node.get('name', '')}">
719
+ <a class="cdx-attaches__download-button" href="{node.get("file", "")}" target="_blank" rel="nofollow noindex noreferrer" title="{node.get("name", "")}">
677
720
  <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24"><path stroke="currentColor" stroke-linecap="round" stroke-width="2" d="M7 10L11.8586 14.8586C11.9367 14.9367 12.0633 14.9367 12.1414 14.8586L17 10"></path></svg>
678
721
  </a>
679
722
  </div>
@@ -725,7 +768,6 @@ class AlignmentBlock(EditorJSBlock):
725
768
 
726
769
  @block("embed")
727
770
  class EmbedBlock(EditorJSBlock):
728
-
729
771
  @classmethod
730
772
  def to_markdown(cls, data: EditorChildData) -> str:
731
773
  service = data.get("service", "")
editorjs/core.py CHANGED
@@ -1,11 +1,13 @@
1
1
  import json
2
2
  import typing as t
3
+ import warnings
3
4
 
4
5
  import markdown2
5
6
  import mdast
6
7
  from typing_extensions import Self
7
8
 
8
9
  from .blocks import BLOCKS
10
+ from .exceptions import TODO
9
11
  from .helpers import unix_timestamp
10
12
  from .types import MDRootNode
11
13
 
@@ -41,13 +43,26 @@ class EditorJS:
41
43
  for child in blocks:
42
44
  _type = child["type"]
43
45
  if not (block := BLOCKS.get(_type)):
44
- raise TypeError(f"from_json: Unsupported block type `{_type}`")
45
-
46
- data = child.get("data", {})
47
- # forward any 'tunes' via data:
48
- data["tunes"] = data.get("tunes") or child.get("tunes") or {}
49
-
50
- markdown_items.append(block.to_markdown(data))
46
+ warnings.warn(
47
+ f"from_json: Unsupported block type `{_type}`",
48
+ category=RuntimeWarning,
49
+ )
50
+ continue
51
+
52
+ try:
53
+ data = child.get("data", {})
54
+ # forward any 'tunes' via data:
55
+ data["tunes"] = data.get("tunes") or child.get("tunes") or {}
56
+
57
+ markdown_items.append(block.to_markdown(data))
58
+ except Exception as e:
59
+ warnings.warn(
60
+ "from_json: Oh oh, unexpected block failure!",
61
+ category=RuntimeWarning,
62
+ source=e,
63
+ )
64
+ # if isinstance(e, TODO):
65
+ # raise e
51
66
 
52
67
  markdown = "".join(markdown_items)
53
68
  return cls.from_markdown(markdown)
@@ -76,9 +91,22 @@ class EditorJS:
76
91
  for child in self._mdast["children"]:
77
92
  _type = child["type"]
78
93
  if not (block := BLOCKS.get(_type)):
79
- raise TypeError(f"to_json: Unsupported block type `{_type}`")
80
-
81
- blocks.extend(block.to_json(child))
94
+ warnings.warn(
95
+ f"to_json: Unsupported block type `{_type}`",
96
+ category=RuntimeWarning,
97
+ )
98
+ continue
99
+
100
+ try:
101
+ blocks.extend(block.to_json(child))
102
+ except Exception as e:
103
+ warnings.warn(
104
+ "to_json: Oh oh, unexpected block failure!",
105
+ category=RuntimeWarning,
106
+ source=e,
107
+ )
108
+ # if isinstance(e, TODO):
109
+ # raise e
82
110
 
83
111
  data = {"time": unix_timestamp(), "blocks": blocks, "version": EDITORJS_VERSION}
84
112
 
@@ -107,7 +135,6 @@ class EditorJS:
107
135
  Export HTML string
108
136
  """
109
137
  md = self.to_markdown()
110
- # todo: deal with custom elements like linktool, attaches
111
138
  return self._md.convert(md)
112
139
 
113
140
  def __repr__(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: edwh-editorjs
3
- Version: 2.3.2
3
+ Version: 2.5.0
4
4
  Summary: EditorJS.py
5
5
  Project-URL: Homepage, https://github.com/educationwarehouse/edwh-EditorJS
6
6
  Author-email: SKevo <skevo.cw@gmail.com>, Robin van der Noord <robin.vdn@educationwarehouse.nl>
@@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
15
  Requires-Python: >=3.10
16
+ Requires-Dist: html2markdown
16
17
  Requires-Dist: humanize
17
18
  Requires-Dist: markdown2
18
19
  Requires-Dist: mdast
@@ -0,0 +1,10 @@
1
+ editorjs/__about__.py,sha256=fMbNgIJqxiZEaSBLadLBt4rZpCHqarzb4Okt-aWsp2E,22
2
+ editorjs/__init__.py,sha256=-OHUf7ZXfkbdFB1r85eIjpHRfql-GCNUCKuBEdEt2Rc,58
3
+ editorjs/blocks.py,sha256=e46ZTxx4M_t2K3o3-bSDjhOfj9OWvSwTTQLK4r_7fv4,29061
4
+ editorjs/core.py,sha256=4igv2l8Rm1S92kxKrIXGIUlNHh6pnjq8F28XQr91I9o,4510
5
+ editorjs/exceptions.py,sha256=oKuWqi4CSnFGZfVZWtTZ2XZeHXm5xF-nAtX_1YLm6sI,230
6
+ editorjs/helpers.py,sha256=q861o5liNibMTp-Ozay17taF7CTNsRe901lYhhxdwHg,73
7
+ editorjs/types.py,sha256=W7IZWMWgzJaQulybIt0Gx5N63rVj4mEy73VJWo4VAQA,1029
8
+ edwh_editorjs-2.5.0.dist-info/METADATA,sha256=Qv3LORc9vuDoS8Z_1yVms5DZOyhP8tMuiuVzcE7nPGE,1025
9
+ edwh_editorjs-2.5.0.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
+ edwh_editorjs-2.5.0.dist-info/RECORD,,
@@ -1,10 +0,0 @@
1
- editorjs/__about__.py,sha256=J4CRnpR3v72FGOMp8gqSua_XWZpAfXuqgVWiQFB-gTY,22
2
- editorjs/__init__.py,sha256=-OHUf7ZXfkbdFB1r85eIjpHRfql-GCNUCKuBEdEt2Rc,58
3
- editorjs/blocks.py,sha256=dT54-wCL4sm9fO7OiJO8Q0SgTuHq3wtv7KQiOF81oks,27138
4
- editorjs/core.py,sha256=WSBmAIKwSqHIP_NFmUVUJiyHPgq7D8902Jm9HRf1nSk,3669
5
- editorjs/exceptions.py,sha256=oKuWqi4CSnFGZfVZWtTZ2XZeHXm5xF-nAtX_1YLm6sI,230
6
- editorjs/helpers.py,sha256=q861o5liNibMTp-Ozay17taF7CTNsRe901lYhhxdwHg,73
7
- editorjs/types.py,sha256=W7IZWMWgzJaQulybIt0Gx5N63rVj4mEy73VJWo4VAQA,1029
8
- edwh_editorjs-2.3.2.dist-info/METADATA,sha256=798OipvvgiexYoOa7x3KFac2MouJVMYQA5KzF6bR1ss,996
9
- edwh_editorjs-2.3.2.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
- edwh_editorjs-2.3.2.dist-info/RECORD,,