Coverage for pyeditorjs/parser.py: 82%

34 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-10-31 13:29 +0100

1import typing as t 

2import warnings 

3from dataclasses import dataclass 

4 

5from .blocks import BLOCKS_MAP, EditorJsBlock 

6from .exceptions import EditorJsParseError, EditorJSUnsupportedBlock 

7 

8 

9@dataclass 

10class EditorJsParser: 

11 """ 

12 An Editor.js parser. 

13 """ 

14 

15 content: dict 

16 """The JSON data of Editor.js content.""" 

17 

18 def __post_init__(self) -> None: 

19 if not isinstance(self.content, dict): 

20 raise EditorJsParseError( 

21 f"Content must be `dict`, not {type(self.content).__name__}" 

22 ) 

23 

24 @staticmethod 

25 def _get_block(data: dict, strict: bool = False) -> t.Optional[EditorJsBlock]: 

26 """ 

27 Obtains block instance from block data. 

28 """ 

29 

30 _type = data.get("type", None) 

31 

32 if _type not in BLOCKS_MAP: 

33 if strict: 

34 raise EditorJSUnsupportedBlock(_type) 

35 else: 

36 warnings.warn(f"Unsupported block: {_type}", category=RuntimeWarning) 

37 return None 

38 

39 return BLOCKS_MAP[_type](_data=data) 

40 

41 def blocks(self, strict: bool = False) -> list[EditorJsBlock]: 

42 """ 

43 Obtains a list of all available blocks from the editor's JSON data. 

44 """ 

45 

46 all_blocks: list[EditorJsBlock] = [] 

47 blocks = self.content.get("blocks", []) 

48 

49 if not isinstance(blocks, list): 

50 raise EditorJsParseError( 

51 f"Blocks is not `list`, but `{type(blocks).__name__}`" 

52 ) 

53 

54 for block_data in blocks: 

55 if block := self._get_block(data=block_data, strict=strict): 

56 all_blocks.append(block) 

57 

58 return all_blocks 

59 

60 def __iter__(self) -> t.Iterator[EditorJsBlock]: 

61 """Returns `iter(self.blocks())`""" 

62 

63 return iter(self.blocks()) 

64 

65 def html(self, sanitize: bool = False, strict: bool = False) -> str: 

66 """ 

67 Renders the editor's JSON content as HTML. 

68 

69 ### Parameters: 

70 - `sanitize` - whether to also sanitize the blocks' texts/contents. 

71 """ 

72 

73 return "\n".join( 

74 [block.html(sanitize=sanitize) for block in self.blocks(strict=strict)] 

75 )