Coverage for src / rendercv / renderer / templater / footer_and_top_note.py: 100%

15 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-25 13:49 +0000

1from collections.abc import Callable 

2from datetime import date as Date 

3 

4from rendercv.schema.models.locale.locale import Locale 

5 

6from .date import build_date_placeholders, date_object_to_string 

7from .string_processor import apply_string_processors, substitute_placeholders 

8 

9 

10def render_top_note_template( 

11 top_note_template: str, 

12 *, 

13 locale: Locale, 

14 current_date: Date, 

15 name: str | None, 

16 single_date_template: str, 

17 string_processors: list[Callable[[str], str]] | None = None, 

18) -> str: 

19 """Render top note by substituting placeholders and applying string processors. 

20 

21 Why: 

22 Top notes display generation metadata like "Last Updated: Jan 2025" at 

23 document top. Template-based generation allows localization and custom 

24 formatting per user preference. 

25 

26 Example: 

27 ```py 

28 result = render_top_note_template( 

29 "LAST_UPDATED: CURRENT_DATE", 

30 locale=english_locale, 

31 current_date=date(2025, 1, 15), 

32 name="John Doe", 

33 single_date_template="MONTH_ABBREVIATION YEAR", 

34 ) 

35 # Returns: "Last Updated: Jan 2025" 

36 ``` 

37 

38 Args: 

39 top_note_template: Template with CURRENT_DATE, LAST_UPDATED, NAME placeholders. 

40 locale: Locale providing last_updated translation. 

41 current_date: Date for timestamp. 

42 name: CV owner name for placeholder substitution. 

43 single_date_template: Template for date formatting. 

44 string_processors: Optional processors for markdown parsing and formatting. 

45 

46 Returns: 

47 Rendered top note with substituted placeholders. 

48 """ 

49 if string_processors is None: 

50 string_processors = [] 

51 

52 placeholders: dict[str, str] = { 

53 "CURRENT_DATE": date_object_to_string( 

54 current_date, 

55 locale=locale, 

56 single_date_template=single_date_template, 

57 ), 

58 "LAST_UPDATED": locale.last_updated, 

59 "NAME": name or "", 

60 **build_date_placeholders(current_date, locale=locale), 

61 } 

62 return apply_string_processors( 

63 substitute_placeholders(top_note_template, placeholders), string_processors 

64 ) 

65 

66 

67def render_footer_template( 

68 footer_template: str, 

69 *, 

70 locale: Locale, 

71 current_date: Date, 

72 name: str | None, 

73 single_date_template: str, 

74 string_processors: list[Callable[[str], str]] | None = None, 

75) -> str: 

76 """Render footer by substituting placeholders and wrapping in Typst context block. 

77 

78 Why: 

79 Footers show page numbers and metadata on each page. Typst context blocks 

80 enable dynamic page number access. Template substitution handles localized 

81 dates and names before wrapping in required Typst syntax. 

82 

83 Example: 

84 ```py 

85 result = render_footer_template( 

86 "NAME - Page PAGE_NUMBER of TOTAL_PAGES", 

87 locale=english_locale, 

88 current_date=date(2025, 1, 15), 

89 name="John Doe", 

90 single_date_template="MONTH_ABBREVIATION YEAR", 

91 ) 

92 # Returns: "context { [John Doe - Page #str(here().page()) of #str(counter(page).final().first())] }" 

93 ``` 

94 

95 Args: 

96 footer_template: Template with NAME, PAGE_NUMBER, TOTAL_PAGES, CURRENT_DATE placeholders. 

97 locale: Locale for date formatting. 

98 current_date: Date for timestamp. 

99 name: CV owner name for placeholder substitution. 

100 single_date_template: Template for date formatting. 

101 string_processors: Optional processors for markdown parsing and formatting. 

102 

103 Returns: 

104 Typst context block with rendered footer content. 

105 """ 

106 if string_processors is None: 

107 string_processors = [] 

108 

109 placeholders: dict[str, str] = { 

110 "CURRENT_DATE": date_object_to_string( 

111 current_date, 

112 locale=locale, 

113 single_date_template=single_date_template, 

114 ), 

115 "NAME": name or "", 

116 "PAGE_NUMBER": "#str(here().page())", 

117 "TOTAL_PAGES": "#str(counter(page).final().first())", 

118 **build_date_placeholders(current_date, locale=locale), 

119 } 

120 return ( 

121 "context {" 

122 f" [{apply_string_processors(substitute_placeholders(footer_template, placeholders), string_processors)}] }}" 

123 )