Coverage for meta_tags_parser/snippets.py: 97%

29 statements  

« prev     ^ index     » next       coverage.py v7.10.3, created at 2025-08-21 00:51 +0000

1import dataclasses 

2import types 

3import typing 

4 

5from . import structs 

6from .parse import parse_meta_tags_from_source 

7 

8 

9def _parse_dimension(dimension_text: str) -> int: 

10 cleaned_text: typing.Final[str] = dimension_text.strip() 

11 if not cleaned_text: 

12 return 0 

13 if not cleaned_text.isascii() or not cleaned_text.isdigit(): 

14 return 0 

15 return int(cleaned_text) 

16 

17 

18_SNIPPET_RULES: typing.Final[ 

19 typing.Mapping[str, typing.Callable[[structs.SocialMediaSnippet, str], structs.SocialMediaSnippet]] 

20] = types.MappingProxyType( 

21 { 

22 "title": lambda snippet_data, tag_value: dataclasses.replace(snippet_data, title=tag_value), 

23 "description": lambda snippet_data, tag_value: dataclasses.replace(snippet_data, description=tag_value), 

24 "url": lambda snippet_data, tag_value: dataclasses.replace(snippet_data, url=tag_value), 

25 "image": lambda snippet_data, tag_value: dataclasses.replace(snippet_data, image=tag_value), 

26 "image:width": lambda snippet_data, tag_value: dataclasses.replace( 

27 snippet_data, image_width=_parse_dimension(tag_value) 

28 ), 

29 "image:height": lambda snippet_data, tag_value: dataclasses.replace( 

30 snippet_data, image_height=_parse_dimension(tag_value) 

31 ), 

32 } 

33) 

34 

35 

36def _merge_snippet_tag( 

37 snippet_object: structs.SocialMediaSnippet, one_meta_tag: structs.OneMetaTag 

38) -> structs.SocialMediaSnippet: 

39 rule: typing.Final[typing.Callable[[structs.SocialMediaSnippet, str], structs.SocialMediaSnippet] | None] = ( 

40 _SNIPPET_RULES.get(one_meta_tag.name) 

41 ) 

42 if rule is None: 

43 return snippet_object 

44 return rule(snippet_object, one_meta_tag.value) 

45 

46 

47def parse_snippets_from_source(source_code: str) -> structs.SnippetGroup: 

48 parsed_group: typing.Final[structs.TagsGroup] = parse_meta_tags_from_source( 

49 source_code, (structs.WhatToParse.OPEN_GRAPH, structs.WhatToParse.TWITTER) 

50 ) 

51 result_group: structs.SnippetGroup = structs.SnippetGroup() 

52 social_name: str 

53 parsed_tags: list[structs.OneMetaTag] 

54 for social_name, parsed_tags in ( 

55 ("twitter", parsed_group.twitter), 

56 ("open_graph", parsed_group.open_graph), 

57 ): 

58 snippet_object: structs.SocialMediaSnippet = structs.SocialMediaSnippet() 

59 one_meta_tag: structs.OneMetaTag 

60 for one_meta_tag in parsed_tags: 

61 snippet_object = _merge_snippet_tag(snippet_object, one_meta_tag) 

62 if social_name == "twitter": 

63 result_group = dataclasses.replace(result_group, twitter=snippet_object) 

64 else: 

65 result_group = dataclasses.replace(result_group, open_graph=snippet_object) 

66 return result_group