tinyssg 1.1.0__py3-none-any.whl → 1.2.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.
tinyssg/__init__.py CHANGED
@@ -7,6 +7,7 @@ import re
7
7
  import shutil
8
8
  import subprocess
9
9
  import sys
10
+ import textwrap
10
11
  import time
11
12
  import webbrowser
12
13
  from http.server import HTTPServer, SimpleHTTPRequestHandler
@@ -40,6 +41,12 @@ class TinySSGPage:
40
41
  """
41
42
  raise TinySSGException(f"The Page class corresponding to {self.__class__.__name__} does not appear to be implemented correctly.")
42
43
 
44
+ def indent(self, src: str, indent: int = 0) -> str:
45
+ """
46
+ Indentation process
47
+ """
48
+ return TinySSGUtility.set_indent(src, indent)
49
+
43
50
 
44
51
  class TinySSGException(Exception):
45
52
  """
@@ -62,6 +69,95 @@ class TinySSGUtility:
62
69
  result = re.sub(start_delimiter + re.escape(key) + end_delimiter, str(value), result)
63
70
  return result
64
71
 
72
+ @classmethod
73
+ def set_indent(cls, src: str, indent: int = 0) -> str:
74
+ """
75
+ Set the indent level of the text
76
+ """
77
+ return textwrap.indent(textwrap.dedent(src).strip(), (' ' * indent)) + '\n'
78
+
79
+ @classmethod
80
+ def merge_dict(cls, base: dict, add: dict, overwrite: bool = True, extend: bool = True, reverse: bool = False) -> dict:
81
+ """
82
+ Merge dictionaries
83
+ """
84
+ if not isinstance(base, dict) or not isinstance(add, dict):
85
+ raise ValueError('Both base and add must be dictionary type.')
86
+
87
+ result = base.copy()
88
+
89
+ for key, value in add.items():
90
+ TinySSGUtility.merge_dict_value(result, key, value, overwrite, extend, reverse)
91
+
92
+ return result
93
+
94
+ @classmethod
95
+ def extend_list(cls, base: any, add: any) -> list:
96
+ """
97
+ List Expansion
98
+ """
99
+ if base is None:
100
+ return add if isinstance(add, list) else [add]
101
+
102
+ result = base.copy() if isinstance(base, list) else [base]
103
+
104
+ if isinstance(add, list):
105
+ result.extend(add)
106
+ else:
107
+ result.append(add)
108
+
109
+ return result
110
+
111
+ @classmethod
112
+ def merge_dict_value(cls, base: any, key: str, value: any, overwrite: bool = True, extend: bool = True, reverse: bool = False) -> None:
113
+ """
114
+ Merge dictionary values (type-based merging process)
115
+ """
116
+ if not isinstance(base, dict):
117
+ raise ValueError('Base must be dictionary type.')
118
+
119
+ if key not in base:
120
+ base[key] = value
121
+ elif isinstance(base[key], dict) and isinstance(value, dict):
122
+ base[key] = TinySSGUtility.merge_dict(base[key], value, overwrite, extend, reverse)
123
+ elif extend and (isinstance(base[key], list) or isinstance(value, list)):
124
+ if reverse:
125
+ base[key] = TinySSGUtility.extend_list(value, base[key])
126
+ else:
127
+ base[key] = TinySSGUtility.extend_list(base[key], value)
128
+ elif overwrite:
129
+ base[key] = value
130
+
131
+ @classmethod
132
+ def filter_json_serializable(cls, data):
133
+ """
134
+ Filter only JSON-able objects
135
+ """
136
+ if isinstance(data, (dict, list, str, int, float, bool, type(None))):
137
+ if isinstance(data, dict):
138
+ return {k: TinySSGUtility.filter_json_serializable(v) for k, v in data.items()}
139
+ elif isinstance(data, list):
140
+ return [TinySSGUtility.filter_json_serializable(v) for v in data]
141
+ else:
142
+ return data
143
+ return None
144
+
145
+ @classmethod
146
+ def get_serialize_json(cls, data: dict, jsonindent: any = 4) -> str:
147
+ """
148
+ Only JSON-able objects from the dictionary are converted to JSON.
149
+ """
150
+ if not isinstance(data, dict):
151
+ raise ValueError('The specified variable is not a dictionary type.')
152
+ return json.dumps(TinySSGUtility.filter_json_serializable(data), indent=jsonindent)
153
+
154
+ @classmethod
155
+ def exclude_double_underscore(cls, data: dict) -> dict:
156
+ """
157
+ Exclude keys beginning with __
158
+ """
159
+ return {k: v for k, v in data.items() if not k.startswith('__')}
160
+
65
161
  @classmethod
66
162
  def get_fullpath(cls, args: dict, pathkey: str = '') -> str:
67
163
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: tinyssg
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: A simple static site generator
5
5
  Author: Uniras
6
6
  Author-email: tkappeng@gmail.com
@@ -50,7 +50,7 @@ Configure the directory as follows.The directory name can be changed with an opt
50
50
  |-- static Place static files that are not subject to SSG (css, images, etc.)
51
51
  |-- dist This is the directory where SSG results will be output.The contents of this directory can be published as a web site by placing it on a web server.
52
52
  |-- static The static directory is copied to this directory.
53
- ````
53
+ ```
54
54
 
55
55
  ### Creating pages
56
56
 
@@ -66,19 +66,20 @@ class IndexPage(TinySSGPage):.
66
66
  'content': 'Hello, World!'
67
67
  }
68
68
 
69
- def template(self): return
70
- return '''
71
- <!DOCTYPE html>
72
- <html>
73
- <head>
74
- <meta charset="utf-8" />
75
- <title>{{ title }}</title>
76
- </head>
77
- <body>
78
- <h1>{{ title }}</h1>
79
- <p>{{ content }}</p>
80
- </body>
81
- </html>'''
69
+ def template(self):
70
+ return self.indent("""
71
+ <!DOCTYPE html>
72
+ <html>
73
+ <head>
74
+ <meta charset="utf-8" />
75
+ <title>{{ title }}</title>
76
+ </head>
77
+ <body>
78
+ <h1>{{ title }}</h1>
79
+ <p>{{ content }}</p>
80
+ </body>
81
+ </html>
82
+ """, 0)
82
83
  ```
83
84
 
84
85
  Building it will generate an HTML file with the same name as the Python file.
@@ -140,3 +141,86 @@ Options:
140
141
  --noopen, -N Do not open browser when starting development server
141
142
  --curdir CURDIR, -C CURDIR Specify current directory.
142
143
  ```
144
+
145
+ ## FAQ
146
+
147
+ ### **Q.** How can I use jinja2 as a template engine?
148
+
149
+ **A.** Override the `render` method to use jinja2 to render templates.
150
+
151
+ lib/jinja2_page.py
152
+
153
+ ```python
154
+ from tinyssg import TinySSGPage
155
+ from jinja2 import Template
156
+
157
+ class Jinja2Page(TinySSGPage):
158
+ def render(self, src: str, data: dict) -> str:
159
+ template = Template(src)
160
+ return template.render(data)
161
+ ```
162
+
163
+ pages/index.py
164
+
165
+ ```python
166
+ from tinyssg import TinySSGPage
167
+ from lib.jinja2_page import Jinja2Page
168
+
169
+ class IndexPage(Jinja2Page):
170
+ def query(self):
171
+ return {
172
+ 'title': 'Index', 'content': 'Hello, World!'
173
+ }
174
+
175
+ def template(self):
176
+ return self.indent("""
177
+ <!DOCTYPE html>
178
+ <html>
179
+ <head>
180
+ <meta charset="utf-8" />
181
+ <title>{{ title }}</title>
182
+ </head>
183
+ <body>
184
+ <h1>{{ title }}</h1>
185
+ <p>{{ content }}</p>
186
+ </body>
187
+ </html>
188
+ """, 0)
189
+ ```
190
+
191
+ ### **Q.** How do I use Markdown to write in my templates?
192
+
193
+ **A.** Override the `translate` method and use the Markdown library to convert it to HTML.
194
+
195
+ lib/markdown_page.py
196
+
197
+ ```python
198
+ from tinyssg import TinySSGPage
199
+ import markdown
200
+
201
+ class MarkdownPage(TinySSGPage):
202
+ def translate(self, basestr: str) -> str:
203
+ return markdown.markdown(basestr)
204
+ ```
205
+
206
+ pages/index.py
207
+
208
+ ```python
209
+ from tinyssg import TinySSGPage
210
+ from lib.markdown_page import MarkdownPage
211
+
212
+ class IndexPage(MarkdownPage):
213
+ def query(self):
214
+ return {
215
+ 'title': 'Index', 'content': 'Hello, World!'
216
+ }
217
+
218
+ def template(self):
219
+ return self.indent("""
220
+ # {{ title }}
221
+
222
+ {{ content }}
223
+
224
+ This is **Markdown** template.
225
+ """, 0)
226
+ ```
@@ -0,0 +1,6 @@
1
+ tinyssg/__init__.py,sha256=5dn_SPH78JJStnQCxz_7YMflRHQRFusF-hJAdGWQ8X4,30677
2
+ tinyssg/__main__.py,sha256=E8PEZ-wWYae76H_iWbY1Xu9VYGb6sfsWMN-hzqTMoBc,83
3
+ tinyssg-1.2.0.dist-info/METADATA,sha256=3nFvOkOZmcjeYVja9crVQ6fhFPhxyw4CXllMyzRYHKU,8063
4
+ tinyssg-1.2.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
5
+ tinyssg-1.2.0.dist-info/top_level.txt,sha256=8u1XtPYCatbklb6u3NbJbFUbwA8nDKZ6cY3FScGwJDQ,8
6
+ tinyssg-1.2.0.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- tinyssg/__init__.py,sha256=puqhv4_E1ZG7c9NYUBhIn8ZtWRhPWcy0JspdWKmX9hU,27214
2
- tinyssg/__main__.py,sha256=E8PEZ-wWYae76H_iWbY1Xu9VYGb6sfsWMN-hzqTMoBc,83
3
- tinyssg-1.1.0.dist-info/METADATA,sha256=i0XNcAf4B3pS3CeA0cgnIWYnixswGHPpPm8tNbwFN_0,6072
4
- tinyssg-1.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
5
- tinyssg-1.1.0.dist-info/top_level.txt,sha256=8u1XtPYCatbklb6u3NbJbFUbwA8nDKZ6cY3FScGwJDQ,8
6
- tinyssg-1.1.0.dist-info/RECORD,,