edwh-editorjs 2.2.2__tar.gz → 2.3.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.
Files changed (30) hide show
  1. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/CHANGELOG.md +7 -0
  2. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/PKG-INFO +2 -1
  3. edwh_editorjs-2.3.0/editorjs/__about__.py +1 -0
  4. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/editorjs/blocks.py +86 -11
  5. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/pyproject.toml +1 -0
  6. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/tests/test_core.py +20 -0
  7. edwh_editorjs-2.2.2/editorjs/__about__.py +0 -1
  8. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/.github/workflows/build_documentation.yml +0 -0
  9. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/.github/workflows/publish_to_pypi.yml +0 -0
  10. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/.github/workflows/pytest.yml +0 -0
  11. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/.gitignore +0 -0
  12. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/README.md +0 -0
  13. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/editorjs/__init__.py +0 -0
  14. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/editorjs/core.py +0 -0
  15. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/editorjs/exceptions.py +0 -0
  16. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/editorjs/helpers.py +0 -0
  17. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/editorjs/types.py +0 -0
  18. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/.gitignore +0 -0
  19. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/class_index.html +0 -0
  20. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/favicon_32_cb_58284776.png +0 -0
  21. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/function_index.html +0 -0
  22. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/index.html +0 -0
  23. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/keybd_closed_cb_ce680311.png +0 -0
  24. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/status.json +0 -0
  25. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/style_cb_8e611ae1.css +0 -0
  26. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/z_a93c8aeb4b8fa1f9___init___py.html +0 -0
  27. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/z_a93c8aeb4b8fa1f9_blocks_py.html +0 -0
  28. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/z_a93c8aeb4b8fa1f9_exceptions_py.html +0 -0
  29. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/htmlcov/z_a93c8aeb4b8fa1f9_parser_py.html +0 -0
  30. {edwh_editorjs-2.2.2 → edwh_editorjs-2.3.0}/tests/__init__.py +0 -0
@@ -2,6 +2,13 @@
2
2
 
3
3
  <!--next-version-placeholder-->
4
4
 
5
+ ## v2.3.0 (2024-11-27)
6
+
7
+ ### Feature
8
+
9
+ * **attachment:** Support more optional fields such as extension, size ([`212cf7e`](https://github.com/educationwarehouse/edwh-editorjs/commit/212cf7e871f3b9b5137234fea050e24b268229f5))
10
+ * Support `embed` block ([`99f0ffe`](https://github.com/educationwarehouse/edwh-editorjs/commit/99f0ffe257efb11eab76f266cf86e72c2f9df2eb))
11
+
5
12
  ## v2.2.2 (2024-11-26)
6
13
 
7
14
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: edwh-editorjs
3
- Version: 2.2.2
3
+ Version: 2.3.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: humanize
16
17
  Requires-Dist: markdown2
17
18
  Requires-Dist: mdast
18
19
  Provides-Extra: dev
@@ -0,0 +1 @@
1
+ __version__ = "2.3.0"
@@ -4,10 +4,12 @@ mdast to editorjs
4
4
 
5
5
  import abc
6
6
  import re
7
+ import traceback
7
8
  import typing as t
8
9
  from html.parser import HTMLParser
9
10
  from urllib.parse import urlparse
10
11
 
12
+ import humanize
11
13
  import markdown2
12
14
 
13
15
  from .exceptions import TODO
@@ -199,7 +201,6 @@ class ParagraphBlock(EditorJSBlock):
199
201
  if child.get("value", "").endswith("/>"):
200
202
  # self-closing
201
203
  result.append(EditorJSCustom.to_json(node))
202
- continue
203
204
  else:
204
205
  # <editorjs>something</editorjs> = 3 children
205
206
  result.extend(
@@ -207,7 +208,8 @@ class ParagraphBlock(EditorJSBlock):
207
208
  )
208
209
 
209
210
  skip = 2
210
- continue
211
+
212
+ continue
211
213
 
212
214
  elif _type == "image":
213
215
  if current_text:
@@ -480,7 +482,13 @@ class RawBlock(EditorJSBlock):
480
482
 
481
483
  @classmethod
482
484
  def to_json(cls, node: MDChildNode) -> list[dict]:
483
- return [raw_block(cls.to_text(node))]
485
+ # todo: apply same logic as paragraph block to find <editorjs/> items!!!
486
+ raw = cls.to_text(node)
487
+
488
+ if raw.startswith("<editorjs"):
489
+ return EditorJSCustom.to_json({"children": [node]})
490
+ else:
491
+ return [raw_block(raw)]
484
492
 
485
493
  @classmethod
486
494
  def to_text(cls, node: MDChildNode) -> str:
@@ -610,9 +618,14 @@ class AttachmentBlock(EditorJSBlock):
610
618
 
611
619
  @classmethod
612
620
  def to_markdown(cls, data: EditorChildData) -> str:
613
- file = data.get("file", {}).get("url", "")
614
621
  title = data.get("title", "")
615
- return f"""<editorjs type="attaches" file="{file}">{title}</editorjs>\n\n"""
622
+ file = data.get("file", {})
623
+ url = file.get("url", "")
624
+ name = file.get("name", "")
625
+ extension = file.get("extension", "")
626
+ size = file.get("size", "")
627
+
628
+ return f"""<editorjs type="attaches" file="{url}" name="{name}" extension="{extension}" size="{size}">{title}</editorjs>\n\n"""
616
629
 
617
630
  @classmethod
618
631
  def to_json(cls, node: MDChildNode) -> list[dict]:
@@ -620,7 +633,12 @@ class AttachmentBlock(EditorJSBlock):
620
633
  {
621
634
  "type": "attaches",
622
635
  "data": {
623
- "file": {"url": node.get("file", "")},
636
+ "file": {
637
+ "url": node.get("file", ""),
638
+ "name": node.get("name", ""),
639
+ "extension": node.get("extension", ""),
640
+ "size": node.get("size", ""),
641
+ },
624
642
  "title": node.get("body", ""),
625
643
  },
626
644
  }
@@ -628,19 +646,41 @@ class AttachmentBlock(EditorJSBlock):
628
646
 
629
647
  @classmethod
630
648
  def to_text(cls, node: MDChildNode) -> str:
649
+ # {'type': 'attaches', 'file': 'https://py4web.leiden.dockers.local/img/upload/8.deb?hash=778760cf05483147b2ff0fa0ddeab2b22d9343e8', 'name': 'gemistdownloadermd5-08d0e3cdb4f7e81986bdd0c60294dec03.0.0.5-1.deb', 'extension': 'deb', 'size': '1613660', 'body': 'gemistdownloader...
650
+
651
+ extension = node.get("extension", "")
652
+
653
+ file_icon = (
654
+ f"""
655
+ <div class="cdx-attaches__file-icon-background"></div>
656
+ <div class="cdx-attaches__file-icon-label" title="{extension}">{extension}</div>
657
+ """
658
+ if extension
659
+ else """
660
+ <div class="cdx-attaches__file-icon-background">
661
+ <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-linejoin="round" stroke-width="2" d="M13.3236 8.43554L9.49533 12.1908C9.13119 12.5505 8.93118 13.043 8.9393 13.5598C8.94741 14.0767 9.163 14.5757 9.53862 14.947C9.91424 15.3182 10.4191 15.5314 10.9422 15.5397C11.4653 15.5479 11.9637 15.3504 12.3279 14.9908L16.1562 11.2355C16.8845 10.5161 17.2845 9.53123 17.2682 8.4975C17.252 7.46376 16.8208 6.46583 16.0696 5.72324C15.3184 4.98066 14.3086 4.55425 13.2624 4.53782C12.2162 4.52138 11.2193 4.91627 10.4911 5.63562L6.66277 9.39093C5.57035 10.4699 4.97032 11.9473 4.99467 13.4979C5.01903 15.0485 5.66578 16.5454 6.79264 17.6592C7.9195 18.7731 9.43417 19.4127 11.0034 19.4374C12.5727 19.462 14.068 18.8697 15.1604 17.7907L18.9887 14.0354"></path></svg>
662
+ </div>
663
+ """
664
+ )
665
+
666
+ file_size = (
667
+ f"""<div class="cdx-attaches__size">{humanize.naturalsize(int(size))}</div>"""
668
+ if (size := node.get("size", ""))
669
+ else ""
670
+ )
671
+
631
672
  return f"""
632
673
  <div class="cdx-attaches cdx-attaches--with-file">
633
674
  <div class="cdx-attaches__file-icon">
634
- <div class="cdx-attaches__file-icon-background">
635
- <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-linejoin="round" stroke-width="2" d="M13.3236 8.43554L9.49533 12.1908C9.13119 12.5505 8.93118 13.043 8.9393 13.5598C8.94741 14.0767 9.163 14.5757 9.53862 14.947C9.91424 15.3182 10.4191 15.5314 10.9422 15.5397C11.4653 15.5479 11.9637 15.3504 12.3279 14.9908L16.1562 11.2355C16.8845 10.5161 17.2845 9.53123 17.2682 8.4975C17.252 7.46376 16.8208 6.46583 16.0696 5.72324C15.3184 4.98066 14.3086 4.55425 13.2624 4.53782C12.2162 4.52138 11.2193 4.91627 10.4911 5.63562L6.66277 9.39093C5.57035 10.4699 4.97032 11.9473 4.99467 13.4979C5.01903 15.0485 5.66578 16.5454 6.79264 17.6592C7.9195 18.7731 9.43417 19.4127 11.0034 19.4374C12.5727 19.462 14.068 18.8697 15.1604 17.7907L18.9887 14.0354"></path></svg>
636
- </div>
675
+ {file_icon}
637
676
  </div>
638
677
  <div class="cdx-attaches__file-info">
639
678
  <div class="cdx-attaches__title" data-placeholder="File title" data-empty="false">
640
- {node.get("body", "")}
679
+ {node.get("body", "")}
641
680
  </div>
681
+ {file_size}
642
682
  </div>
643
- <a class="cdx-attaches__download-button" href="{node.get('file', '')}" target="_blank" rel="nofollow noindex noreferrer">
683
+ <a class="cdx-attaches__download-button" href="{node.get('file', '')}" target="_blank" rel="nofollow noindex noreferrer" title="{node.get('name', '')}">
644
684
  <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>
645
685
  </a>
646
686
  </div>
@@ -690,6 +730,41 @@ class AlignmentBlock(EditorJSBlock):
690
730
  return f"<{tag} style='text-align: {alignment}'>{body}</{tag}>"
691
731
 
692
732
 
733
+ @block("embed")
734
+ class EmbedBlock(EditorJSBlock):
735
+
736
+ @classmethod
737
+ def to_markdown(cls, data: EditorChildData) -> str:
738
+ service = data.get("service", "")
739
+ source = data.get("source", "")
740
+ embed = data.get("embed", "")
741
+ caption = data.get("caption", "")
742
+
743
+ return f"<editorjs type='embed' service='{service}' source='{source}' embed='{embed}' caption='{caption}'/>\n\n"
744
+
745
+ @classmethod
746
+ def to_json(cls, node: MDChildNode) -> list[dict]:
747
+ return [{"type": "embed", "data": node}]
748
+
749
+ @classmethod
750
+ def to_text(cls, node: MDChildNode) -> str:
751
+ source = node.get("source", "")
752
+ embed = node.get("embed", "")
753
+ caption = node.get("caption", "")
754
+ return f"""
755
+ <div class="cdx-block embed-tool">
756
+ <preloader class="embed-tool__preloader">
757
+ <div class="embed-tool__url">{source}</div>
758
+ </preloader>
759
+ <iframe style="width:100%;" height="320" frameborder="0" allowfullscreen="" src="{embed}" class="embed-tool__content"></iframe>
760
+ <div class="cdx-input embed-tool__caption" contenteditable="true" data-placeholder="Enter a caption" data-empty="false">{caption}</div>
761
+ </div>
762
+ """
763
+
764
+
765
+ ### end blocks
766
+
767
+
693
768
  class AttributeParser(HTMLParser):
694
769
  def __init__(self):
695
770
  super().__init__()
@@ -29,6 +29,7 @@ dependencies = [
29
29
  # "bleach",
30
30
  "mdast",
31
31
  "markdown2",
32
+ "humanize",
32
33
  ]
33
34
 
34
35
  [project.optional-dependencies]
@@ -112,6 +112,17 @@ def test_attachment():
112
112
  print(e.to_json())
113
113
  print(e.to_html())
114
114
 
115
+ attachment_two = r"""[{"id":"RJGyL0ZWOL","type":"attaches","data":{"file":{"url":"https://py4web.leiden.dockers.local/img/upload/8.deb?hash=778760cf05483147b2ff0fa0ddeab2b22d9343e8","name":"gemistdownloader_3.0.0.5-1.deb","extension":"deb","size":1613660},"title":"gemistdownloader_3.0.0.5-1"}}]"""
116
+
117
+ e = EditorJS.from_json(attachment_two)
118
+ print(e.to_markdown())
119
+ print(e.to_html())
120
+ j = json.loads(e.to_json())
121
+ print(j)
122
+
123
+ assert j["blocks"][0]["data"]["file"]["size"]
124
+ assert j["blocks"][0]["data"]["file"]["extension"]
125
+
115
126
 
116
127
  def test_raw_html():
117
128
  # e = EditorJS.from_markdown(textwrap.dedent("""
@@ -226,3 +237,12 @@ def test_alignment():
226
237
 
227
238
  print(e.to_json())
228
239
 
240
+
241
+ def test_embed():
242
+ json_blocks = r"""{"time":1732710342696,"blocks":[{"id":"AzmqC3FWx3","type":"embed","data":{"service":"youtube","source":"https://www.youtube.com/watch?v=LDU_Txk06tM","embed":"https://www.youtube.com/embed/LDU_Txk06tM","width":580,"height":320,"caption":"krab"}}],"version":"2.30.6"}"""
243
+
244
+ e = EditorJS.from_json(json_blocks)
245
+
246
+ print(e.to_markdown())
247
+ print(e.to_html())
248
+ print(e.to_json())
@@ -1 +0,0 @@
1
- __version__ = "2.2.2"
File without changes
File without changes