pytpro 0.2.4__tar.gz → 0.2.7__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.
- {pytpro-0.2.4 → pytpro-0.2.7}/PKG-INFO +47 -39
- {pytpro-0.2.4 → pytpro-0.2.7}/README.md +41 -37
- {pytpro-0.2.4 → pytpro-0.2.7}/pytpro/__init__.py +1 -1
- pytpro-0.2.7/pytpro/markdown.py +342 -0
- {pytpro-0.2.4 → pytpro-0.2.7}/pytpro.egg-info/PKG-INFO +47 -39
- {pytpro-0.2.4 → pytpro-0.2.7}/pytpro.egg-info/SOURCES.txt +1 -0
- pytpro-0.2.7/pytpro.egg-info/requires.txt +1 -0
- pytpro-0.2.7/setup.py +51 -0
- pytpro-0.2.4/pytpro/markdown.py +0 -179
- pytpro-0.2.4/setup.py +0 -29
- {pytpro-0.2.4 → pytpro-0.2.7}/LICENSE +0 -0
- {pytpro-0.2.4 → pytpro-0.2.7}/pytpro/main.py +0 -0
- {pytpro-0.2.4 → pytpro-0.2.7}/pytpro.egg-info/dependency_links.txt +0 -0
- {pytpro-0.2.4 → pytpro-0.2.7}/pytpro.egg-info/top_level.txt +0 -0
- {pytpro-0.2.4 → pytpro-0.2.7}/setup.cfg +0 -0
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytpro
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: Lightweight Python library for math, randomness, HTML, Markdown, CSS, and JS rendering — clean and minimal.
|
|
5
5
|
Author: Ibrahim Akhlaq
|
|
6
6
|
Author-email: ibakhlaq@gmail.com
|
|
7
|
+
Keywords: python,tools,utilities,python tools,python utilities,math,random,utility,mathematics,randomness,random number,random numbers,random number generator,random number generators,random number generators python,html,css,javascript,markdown,markdown preview,markdown previewer,markdown previewer python
|
|
7
8
|
Classifier: Programming Language :: Python :: 3
|
|
8
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
9
10
|
Classifier: Operating System :: OS Independent
|
|
10
11
|
Requires-Python: >=3.6
|
|
11
12
|
Description-Content-Type: text/markdown
|
|
12
13
|
License-File: LICENSE
|
|
14
|
+
Requires-Dist: tkhtmlview
|
|
13
15
|
Dynamic: author
|
|
14
16
|
Dynamic: author-email
|
|
15
17
|
Dynamic: classifier
|
|
16
18
|
Dynamic: description
|
|
17
19
|
Dynamic: description-content-type
|
|
20
|
+
Dynamic: keywords
|
|
18
21
|
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-dist
|
|
19
23
|
Dynamic: requires-python
|
|
20
24
|
Dynamic: summary
|
|
21
25
|
|
|
@@ -23,12 +27,38 @@ Dynamic: summary
|
|
|
23
27
|
<img src="https://i.postimg.cc/BjSmyvYv/download.png" width="200" alt="pytpro logo">
|
|
24
28
|
</p>
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
<
|
|
30
|
+
<p align="center">
|
|
31
|
+
<img src="https://i.postimg.cc/s2PM4pyd/pyt.png" width="140" alt="pytpro heading">
|
|
32
|
+
</p>
|
|
28
33
|
|
|
29
34
|
**pytpro** is a lightweight Python package by Ibrahim Akhlaq that provides powerful utility functions for math, randomness, and HTML rendering. It's clean, minimal, and built to feel like magic.
|
|
30
35
|
---
|
|
36
|
+
|
|
37
|
+
# 🖥️ Example Usage
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import pytpro
|
|
41
|
+
|
|
42
|
+
pytpro.add(2, 3)
|
|
43
|
+
pytpro.square(6)
|
|
44
|
+
pytpro.pi()
|
|
45
|
+
pytpro.htmlcssjs("<h1>Hello!</h1><p>This is raw HTML.</p>")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
# 🖥️ Instructions to install:
|
|
49
|
+
|
|
50
|
+
To install locally from your project directory, open PowerShell or terminal and run:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install pytpro
|
|
54
|
+
```
|
|
55
|
+
|
|
31
56
|
# API REFERENCE
|
|
57
|
+
|
|
58
|
+
- disclaimer: Some of the output examples in the API reference cannot be rendered in PYPI, so screenshots of the actual results were provided. Keep in mind that the output may differ slightly from the actual results, as I had to resize the images in some cases.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
32
62
|
## 🚀 Features
|
|
33
63
|
### ➕ Math Functions:
|
|
34
64
|
- `add(a, b):`
|
|
@@ -179,7 +209,7 @@ py.caption("Hello World!")
|
|
|
179
209
|
```HTML
|
|
180
210
|
<p style='font-size: 0.9em; color: gray;'>Hello World!</p>
|
|
181
211
|
```
|
|
182
|
-
|
|
212
|
+
<p align="left"><img src='https://i.postimg.cc/hjRzR2D5/caption.png' width='90' alt='Hello World!'></p>
|
|
183
213
|
|
|
184
214
|
### `htmlcssjs(html_fragment)`
|
|
185
215
|
You can use the `htmlcssjs()` function to render raw HTML, CSS, and Javascript code.
|
|
@@ -190,6 +220,9 @@ py.htmlcssjs("""
|
|
|
190
220
|
<style>
|
|
191
221
|
button {
|
|
192
222
|
background-color: red;
|
|
223
|
+
border: none;
|
|
224
|
+
border-radius: 4px;
|
|
225
|
+
padding: 15px 32px;
|
|
193
226
|
color: white;
|
|
194
227
|
}
|
|
195
228
|
</style>
|
|
@@ -208,6 +241,9 @@ button {
|
|
|
208
241
|
<style>
|
|
209
242
|
button {
|
|
210
243
|
background-color: red;
|
|
244
|
+
border: none;
|
|
245
|
+
border-radius: 4px;
|
|
246
|
+
padding: 15px 32px;
|
|
211
247
|
color: white;
|
|
212
248
|
}
|
|
213
249
|
</style>
|
|
@@ -220,14 +256,9 @@ button {
|
|
|
220
256
|
}
|
|
221
257
|
</script>
|
|
222
258
|
```
|
|
223
|
-
|
|
224
|
-
button
|
|
225
|
-
|
|
226
|
-
color: white;
|
|
227
|
-
}
|
|
228
|
-
</style>
|
|
229
|
-
<button onclick='click()'>Hello World!</button>
|
|
230
|
-
<p id="output">{javascript is not supported in PYPI}</p>
|
|
259
|
+
<p>
|
|
260
|
+
<img src="https://i.postimg.cc/NfyFK8rf/pypi2.png" width="230" alt="button">
|
|
261
|
+
</p>
|
|
231
262
|
|
|
232
263
|
### Alert Boxes
|
|
233
264
|
#### `alertbox_red(text)`
|
|
@@ -302,37 +333,14 @@ This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
|
302
333
|
<h1> Hello World!</h1>
|
|
303
334
|
<p>This is a paragraph with <strong>bold</strong>, <em>italic</em>, and <code>inline code</code>.</p>
|
|
304
335
|
```
|
|
305
|
-
- <
|
|
306
|
-
|
|
307
|
-
This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
336
|
+
- <h1>Hello World!</h1>
|
|
337
|
+
<p> This is a paragraph with <strong>bold</strong>, <em>italic</em>, and <code>inline code</code>.</p>
|
|
308
338
|
|
|
309
339
|
For more information about Markdown formatting and its syntax, see the [Markdown documentation](https://www.markdownguide.org/), [cheat sheet](https://www.markdownguide.org/cheat-sheet/), [basic syntax](https://www.markdownguide.org/basic-syntax/), or [extended syntax](https://www.markdownguide.org/extended-syntax/).
|
|
310
340
|
---
|
|
311
|
-
<p style="text-align: center !important;
|
|
312
|
-
font-size: 50px;
|
|
313
|
-
color: #838383ff;
|
|
314
|
-
font-weight: bold;
|
|
315
|
-
font-family: sans-serif;
|
|
316
|
-
text-align: center ">Pytpro</p>
|
|
317
|
-
|
|
318
|
-
# 🖥️ Example Usage
|
|
319
|
-
|
|
320
|
-
```python
|
|
321
|
-
import pytpro
|
|
322
341
|
|
|
323
|
-
|
|
324
|
-
pytpro.square(6)
|
|
325
|
-
pytpro.pi()
|
|
326
|
-
pytpro.htmlcssjs("<h1>Hello!</h1><p>This is raw HTML.</p>")
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
# 🖥️ Instructions to install:
|
|
330
|
-
|
|
331
|
-
To install locally from your project directory, open PowerShell or terminal and run:
|
|
342
|
+
<h1 align="center">Pytpro</h1>
|
|
332
343
|
|
|
333
|
-
```bash
|
|
334
|
-
pip install pytpro
|
|
335
|
-
```
|
|
336
344
|
<pre>
|
|
337
345
|
_______ ___ ___ ________ _______ _________ ________
|
|
338
346
|
| ___ \\ \ / /|__ __|| ___ \ | ___ | / ______ \
|
|
@@ -2,12 +2,38 @@
|
|
|
2
2
|
<img src="https://i.postimg.cc/BjSmyvYv/download.png" width="200" alt="pytpro logo">
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
<
|
|
5
|
+
<p align="center">
|
|
6
|
+
<img src="https://i.postimg.cc/s2PM4pyd/pyt.png" width="140" alt="pytpro heading">
|
|
7
|
+
</p>
|
|
7
8
|
|
|
8
9
|
**pytpro** is a lightweight Python package by Ibrahim Akhlaq that provides powerful utility functions for math, randomness, and HTML rendering. It's clean, minimal, and built to feel like magic.
|
|
9
10
|
---
|
|
11
|
+
|
|
12
|
+
# 🖥️ Example Usage
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import pytpro
|
|
16
|
+
|
|
17
|
+
pytpro.add(2, 3)
|
|
18
|
+
pytpro.square(6)
|
|
19
|
+
pytpro.pi()
|
|
20
|
+
pytpro.htmlcssjs("<h1>Hello!</h1><p>This is raw HTML.</p>")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
# 🖥️ Instructions to install:
|
|
24
|
+
|
|
25
|
+
To install locally from your project directory, open PowerShell or terminal and run:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pip install pytpro
|
|
29
|
+
```
|
|
30
|
+
|
|
10
31
|
# API REFERENCE
|
|
32
|
+
|
|
33
|
+
- disclaimer: Some of the output examples in the API reference cannot be rendered in PYPI, so screenshots of the actual results were provided. Keep in mind that the output may differ slightly from the actual results, as I had to resize the images in some cases.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
11
37
|
## 🚀 Features
|
|
12
38
|
### ➕ Math Functions:
|
|
13
39
|
- `add(a, b):`
|
|
@@ -158,7 +184,7 @@ py.caption("Hello World!")
|
|
|
158
184
|
```HTML
|
|
159
185
|
<p style='font-size: 0.9em; color: gray;'>Hello World!</p>
|
|
160
186
|
```
|
|
161
|
-
|
|
187
|
+
<p align="left"><img src='https://i.postimg.cc/hjRzR2D5/caption.png' width='90' alt='Hello World!'></p>
|
|
162
188
|
|
|
163
189
|
### `htmlcssjs(html_fragment)`
|
|
164
190
|
You can use the `htmlcssjs()` function to render raw HTML, CSS, and Javascript code.
|
|
@@ -169,6 +195,9 @@ py.htmlcssjs("""
|
|
|
169
195
|
<style>
|
|
170
196
|
button {
|
|
171
197
|
background-color: red;
|
|
198
|
+
border: none;
|
|
199
|
+
border-radius: 4px;
|
|
200
|
+
padding: 15px 32px;
|
|
172
201
|
color: white;
|
|
173
202
|
}
|
|
174
203
|
</style>
|
|
@@ -187,6 +216,9 @@ button {
|
|
|
187
216
|
<style>
|
|
188
217
|
button {
|
|
189
218
|
background-color: red;
|
|
219
|
+
border: none;
|
|
220
|
+
border-radius: 4px;
|
|
221
|
+
padding: 15px 32px;
|
|
190
222
|
color: white;
|
|
191
223
|
}
|
|
192
224
|
</style>
|
|
@@ -199,14 +231,9 @@ button {
|
|
|
199
231
|
}
|
|
200
232
|
</script>
|
|
201
233
|
```
|
|
202
|
-
|
|
203
|
-
button
|
|
204
|
-
|
|
205
|
-
color: white;
|
|
206
|
-
}
|
|
207
|
-
</style>
|
|
208
|
-
<button onclick='click()'>Hello World!</button>
|
|
209
|
-
<p id="output">{javascript is not supported in PYPI}</p>
|
|
234
|
+
<p>
|
|
235
|
+
<img src="https://i.postimg.cc/NfyFK8rf/pypi2.png" width="230" alt="button">
|
|
236
|
+
</p>
|
|
210
237
|
|
|
211
238
|
### Alert Boxes
|
|
212
239
|
#### `alertbox_red(text)`
|
|
@@ -281,37 +308,14 @@ This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
|
281
308
|
<h1> Hello World!</h1>
|
|
282
309
|
<p>This is a paragraph with <strong>bold</strong>, <em>italic</em>, and <code>inline code</code>.</p>
|
|
283
310
|
```
|
|
284
|
-
- <
|
|
285
|
-
|
|
286
|
-
This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
311
|
+
- <h1>Hello World!</h1>
|
|
312
|
+
<p> This is a paragraph with <strong>bold</strong>, <em>italic</em>, and <code>inline code</code>.</p>
|
|
287
313
|
|
|
288
314
|
For more information about Markdown formatting and its syntax, see the [Markdown documentation](https://www.markdownguide.org/), [cheat sheet](https://www.markdownguide.org/cheat-sheet/), [basic syntax](https://www.markdownguide.org/basic-syntax/), or [extended syntax](https://www.markdownguide.org/extended-syntax/).
|
|
289
315
|
---
|
|
290
|
-
<p style="text-align: center !important;
|
|
291
|
-
font-size: 50px;
|
|
292
|
-
color: #838383ff;
|
|
293
|
-
font-weight: bold;
|
|
294
|
-
font-family: sans-serif;
|
|
295
|
-
text-align: center ">Pytpro</p>
|
|
296
|
-
|
|
297
|
-
# 🖥️ Example Usage
|
|
298
|
-
|
|
299
|
-
```python
|
|
300
|
-
import pytpro
|
|
301
316
|
|
|
302
|
-
|
|
303
|
-
pytpro.square(6)
|
|
304
|
-
pytpro.pi()
|
|
305
|
-
pytpro.htmlcssjs("<h1>Hello!</h1><p>This is raw HTML.</p>")
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
# 🖥️ Instructions to install:
|
|
309
|
-
|
|
310
|
-
To install locally from your project directory, open PowerShell or terminal and run:
|
|
317
|
+
<h1 align="center">Pytpro</h1>
|
|
311
318
|
|
|
312
|
-
```bash
|
|
313
|
-
pip install pytpro
|
|
314
|
-
```
|
|
315
319
|
<pre>
|
|
316
320
|
_______ ___ ___ ________ _______ _________ ________
|
|
317
321
|
| ___ \\ \ / /|__ __|| ___ \ | ___ | / ______ \
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from main import htmlcssjs as html
|
|
3
|
+
import html as html_lib
|
|
4
|
+
|
|
5
|
+
_css_injected = False
|
|
6
|
+
|
|
7
|
+
def markdown(md_text: str):
|
|
8
|
+
global _css_injected
|
|
9
|
+
if not _css_injected:
|
|
10
|
+
html("""
|
|
11
|
+
<style>
|
|
12
|
+
pre code, code, pre, blockquote, table, th, td {
|
|
13
|
+
border: 1px solid #ccc;
|
|
14
|
+
}
|
|
15
|
+
pre, code, pre code {
|
|
16
|
+
background-color: #efefef !important;
|
|
17
|
+
border-radius: 4px;
|
|
18
|
+
font-family: monospace;
|
|
19
|
+
font-size: 0.95em;
|
|
20
|
+
overflow-x: auto;
|
|
21
|
+
border: none !important;
|
|
22
|
+
}
|
|
23
|
+
.hljs {
|
|
24
|
+
display: block;
|
|
25
|
+
overflow-x: auto;
|
|
26
|
+
padding: 10px 16px;
|
|
27
|
+
background: #efefef;
|
|
28
|
+
color: #333;
|
|
29
|
+
border-radius: 4px;
|
|
30
|
+
margin: 16px 0;
|
|
31
|
+
}
|
|
32
|
+
pre {
|
|
33
|
+
background-color: #efefef !important;
|
|
34
|
+
margin: 0 0 17px 0;
|
|
35
|
+
}
|
|
36
|
+
code {
|
|
37
|
+
padding: 2px 6px;
|
|
38
|
+
}
|
|
39
|
+
blockquote {
|
|
40
|
+
position: relative;
|
|
41
|
+
padding: 12px 16px 12px 24px;
|
|
42
|
+
background-color: #efefef;
|
|
43
|
+
border-radius: 4px;
|
|
44
|
+
color: #333;
|
|
45
|
+
font-size: 17px;
|
|
46
|
+
margin: 16px 0;
|
|
47
|
+
}
|
|
48
|
+
blockquote::before {
|
|
49
|
+
content: '';
|
|
50
|
+
position: absolute;
|
|
51
|
+
top: 0;
|
|
52
|
+
bottom: 0;
|
|
53
|
+
left: 0;
|
|
54
|
+
width: 6px;
|
|
55
|
+
background-color: #595959;
|
|
56
|
+
border-radius: 4px;
|
|
57
|
+
}
|
|
58
|
+
ul, ol, p, blockquote, table {
|
|
59
|
+
margin-bottom: 12px;
|
|
60
|
+
}
|
|
61
|
+
table {
|
|
62
|
+
border-collapse: collapse;
|
|
63
|
+
width: 100%;
|
|
64
|
+
}
|
|
65
|
+
th, td {
|
|
66
|
+
padding: 6px 12px;
|
|
67
|
+
text-align: left;
|
|
68
|
+
}
|
|
69
|
+
</style>
|
|
70
|
+
<link rel="stylesheet"
|
|
71
|
+
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
|
|
72
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
|
73
|
+
<script>setTimeout(() => hljs.highlightAll(), 100);</script>
|
|
74
|
+
""")
|
|
75
|
+
_css_injected = True
|
|
76
|
+
|
|
77
|
+
# --- Sanitize Input ---
|
|
78
|
+
md_text = html_lib.unescape(md_text)
|
|
79
|
+
|
|
80
|
+
# Remove dangerous tags and attributes (same as before)
|
|
81
|
+
md_text = re.sub(r'<\s*script[^>]*?>.*?<\s*/\s*script\s*>', '', md_text, flags=re.DOTALL | re.IGNORECASE)
|
|
82
|
+
md_text = re.sub(r'<\s*/?\s*script[^>]*?>', '', md_text, flags=re.IGNORECASE)
|
|
83
|
+
md_text = re.sub(r'<\s*(iframe|object|embed|svg)[^>]*?>.*?<\s*/\s*\1\s*>', '', md_text, flags=re.DOTALL | re.IGNORECASE)
|
|
84
|
+
md_text = re.sub(r'<\s*/?\s*(iframe|object|embed|svg)[^>]*?>', '', md_text, flags=re.IGNORECASE)
|
|
85
|
+
md_text = re.sub(r'\son\w+\s*=\s*"[^"]*"', '', md_text, flags=re.IGNORECASE)
|
|
86
|
+
md_text = re.sub(r"\son\w+\s*=\s*'[^']*'", '', md_text, flags=re.IGNORECASE)
|
|
87
|
+
md_text = re.sub(r'(["\'])\s*javascript:[^"\']*\1', r'\1\1', md_text, flags=re.IGNORECASE)
|
|
88
|
+
md_text = re.sub(r'(["\'])\s*data:[^"\']*\1', r'\1\1', md_text, flags=re.IGNORECASE)
|
|
89
|
+
|
|
90
|
+
lines = md_text.strip('\n').split('\n')
|
|
91
|
+
|
|
92
|
+
# States
|
|
93
|
+
in_code_block = False
|
|
94
|
+
code_block = []
|
|
95
|
+
language = 'plaintext'
|
|
96
|
+
|
|
97
|
+
list_stack = [] # stack of ('ul' or 'ol', indent_level)
|
|
98
|
+
table_rows = []
|
|
99
|
+
in_table = False
|
|
100
|
+
html_out = []
|
|
101
|
+
|
|
102
|
+
def close_all_lists(min_indent=0):
|
|
103
|
+
# Close lists in stack with indent >= min_indent
|
|
104
|
+
while list_stack and list_stack[-1][1] >= min_indent:
|
|
105
|
+
tag, _ = list_stack.pop()
|
|
106
|
+
html_out.append(f'</{tag}>')
|
|
107
|
+
|
|
108
|
+
def close_table():
|
|
109
|
+
nonlocal in_table, table_rows
|
|
110
|
+
if in_table:
|
|
111
|
+
if len(table_rows) > 1:
|
|
112
|
+
header = table_rows[0]
|
|
113
|
+
align_line = table_rows[1]
|
|
114
|
+
|
|
115
|
+
aligns = []
|
|
116
|
+
# Parse alignment row
|
|
117
|
+
for cell in [c.strip() for c in align_line.split('|')]:
|
|
118
|
+
if cell.startswith(':') and cell.endswith(':'):
|
|
119
|
+
aligns.append('center')
|
|
120
|
+
elif cell.startswith(':'):
|
|
121
|
+
aligns.append('left')
|
|
122
|
+
elif cell.endswith(':'):
|
|
123
|
+
aligns.append('right')
|
|
124
|
+
else:
|
|
125
|
+
aligns.append(None)
|
|
126
|
+
|
|
127
|
+
table_rows.pop(1) # Remove align row
|
|
128
|
+
|
|
129
|
+
# Build table html
|
|
130
|
+
html_out.append('<table>')
|
|
131
|
+
html_out.append('<thead><tr>')
|
|
132
|
+
header_cells = [c.strip() for c in header.split('|')]
|
|
133
|
+
for i, cell in enumerate(header_cells):
|
|
134
|
+
align_attr = f' style="text-align:{aligns[i]}"' if i < len(aligns) and aligns[i] else ''
|
|
135
|
+
html_out.append(f'<th{align_attr}>{cell}</th>')
|
|
136
|
+
html_out.append('</tr></thead><tbody>')
|
|
137
|
+
|
|
138
|
+
for row in table_rows[1:]:
|
|
139
|
+
html_out.append('<tr>')
|
|
140
|
+
cells = [c.strip() for c in row.split('|')]
|
|
141
|
+
# Pad cells if missing
|
|
142
|
+
while len(cells) < len(header_cells):
|
|
143
|
+
cells.append('')
|
|
144
|
+
for i, cell in enumerate(cells):
|
|
145
|
+
align_attr = f' style="text-align:{aligns[i]}"' if i < len(aligns) and aligns[i] else ''
|
|
146
|
+
html_out.append(f'<td{align_attr}>{cell}</td>')
|
|
147
|
+
html_out.append('</tr>')
|
|
148
|
+
html_out.append('</tbody></table>')
|
|
149
|
+
else:
|
|
150
|
+
# Not a valid table, output rows as paragraphs
|
|
151
|
+
for row in table_rows:
|
|
152
|
+
html_out.append(f'<p>{row}</p>')
|
|
153
|
+
table_rows = []
|
|
154
|
+
in_table = False
|
|
155
|
+
|
|
156
|
+
def inline_format(text):
|
|
157
|
+
# Escape HTML
|
|
158
|
+
from html import escape
|
|
159
|
+
text = escape(text)
|
|
160
|
+
|
|
161
|
+
# Escaping markdown chars with backslash
|
|
162
|
+
text = re.sub(r'\\([\\`\*_\{\}\[\]\(\)#\+\-\.\!~>])', r'\1', text)
|
|
163
|
+
|
|
164
|
+
# Links: [text](url "optional title")
|
|
165
|
+
# Support optional title in quotes
|
|
166
|
+
def repl_link(m):
|
|
167
|
+
text, url, title = m.group(1), m.group(2), m.group(4)
|
|
168
|
+
title_attr = f' title="{escape(title)}"' if title else ''
|
|
169
|
+
url = url.strip()
|
|
170
|
+
return f'<a href="{escape(url)}"{title_attr} target="_blank" rel="noopener noreferrer">{text}</a>'
|
|
171
|
+
|
|
172
|
+
text = re.sub(r'\[([^\]]+)\]\(\s*([^\s\)]+)(\s+"([^"]+)")?\s*\)', repl_link, text)
|
|
173
|
+
|
|
174
|
+
# Images: 
|
|
175
|
+
def repl_img(m):
|
|
176
|
+
alt, url, title = m.group(1), m.group(2), m.group(4)
|
|
177
|
+
title_attr = f' title="{escape(title)}"' if title else ''
|
|
178
|
+
return f'<img src="{escape(url.strip())}" alt="{escape(alt)}"{title_attr} />'
|
|
179
|
+
|
|
180
|
+
text = re.sub(r'!\[([^\]]*)\]\(\s*([^\s\)]+)(\s+"([^"]+)")?\s*\)', repl_img, text)
|
|
181
|
+
|
|
182
|
+
# Strikethrough
|
|
183
|
+
text = re.sub(r'~~(.*?)~~', r'<del>\1</del>', text)
|
|
184
|
+
|
|
185
|
+
# Bold + Italic (***text***)
|
|
186
|
+
text = re.sub(r'\*\*\*(.+?)\*\*\*', r'<strong><em>\1</em></strong>', text)
|
|
187
|
+
|
|
188
|
+
# Bold (**text**)
|
|
189
|
+
text = re.sub(r'\*\*(.+?)\*\*', r'<strong>\1</strong>', text)
|
|
190
|
+
|
|
191
|
+
# Italic (*text*)
|
|
192
|
+
text = re.sub(r'\*(.+?)\*', r'<em>\1</em>', text)
|
|
193
|
+
|
|
194
|
+
# Inline code (`code`)
|
|
195
|
+
text = re.sub(r'`(.+?)`', r'<code>\1</code>', text)
|
|
196
|
+
|
|
197
|
+
# Convert two spaces at line end into <br>
|
|
198
|
+
text = re.sub(r' $', r'<br>', text)
|
|
199
|
+
|
|
200
|
+
return text
|
|
201
|
+
blockquote_level = 0
|
|
202
|
+
paragraph_lines = []
|
|
203
|
+
|
|
204
|
+
def flush_paragraph():
|
|
205
|
+
nonlocal paragraph_lines
|
|
206
|
+
if paragraph_lines:
|
|
207
|
+
html_out.append(f'<p>{" ".join(paragraph_lines)}</p>')
|
|
208
|
+
paragraph_lines = []
|
|
209
|
+
|
|
210
|
+
for idx, line in enumerate(lines):
|
|
211
|
+
line_rstrip = line.rstrip('\r\n')
|
|
212
|
+
|
|
213
|
+
# Code block toggle
|
|
214
|
+
if line_rstrip.startswith("```"):
|
|
215
|
+
flush_paragraph()
|
|
216
|
+
close_all_lists()
|
|
217
|
+
close_table()
|
|
218
|
+
if not in_code_block:
|
|
219
|
+
in_code_block = True
|
|
220
|
+
language = line_rstrip[3:].strip()
|
|
221
|
+
code_block = []
|
|
222
|
+
else:
|
|
223
|
+
from html import escape
|
|
224
|
+
code_html = escape('\n'.join(code_block))
|
|
225
|
+
html_out.append(f'<pre><code class="hljs language-{language}">{code_html}</code></pre>')
|
|
226
|
+
in_code_block = False
|
|
227
|
+
continue
|
|
228
|
+
# Inside your main loop, replace this blockquote handling part:
|
|
229
|
+
|
|
230
|
+
m = re.match(r'^(>+)\s+(.*)', line)
|
|
231
|
+
if m:
|
|
232
|
+
flush_paragraph()
|
|
233
|
+
close_all_lists()
|
|
234
|
+
close_table()
|
|
235
|
+
new_level = len(m.group(1))
|
|
236
|
+
content = inline_format(m.group(2).strip())
|
|
237
|
+
|
|
238
|
+
# Adjust blockquote level:
|
|
239
|
+
while blockquote_level < new_level:
|
|
240
|
+
html_out.append('<blockquote>')
|
|
241
|
+
blockquote_level += 1
|
|
242
|
+
while blockquote_level > new_level:
|
|
243
|
+
html_out.append('</blockquote>')
|
|
244
|
+
blockquote_level -= 1
|
|
245
|
+
|
|
246
|
+
html_out.append(content)
|
|
247
|
+
continue
|
|
248
|
+
else:
|
|
249
|
+
# Close all blockquotes if we leave blockquote lines
|
|
250
|
+
while blockquote_level > 0:
|
|
251
|
+
html_out.append('</blockquote>')
|
|
252
|
+
blockquote_level -= 1
|
|
253
|
+
# Tables
|
|
254
|
+
if re.match(r'^\s*\|.*\|\s*$', line):
|
|
255
|
+
flush_paragraph()
|
|
256
|
+
if not in_table:
|
|
257
|
+
close_all_lists()
|
|
258
|
+
in_table = True
|
|
259
|
+
table_rows = []
|
|
260
|
+
table_rows.append(line.strip())
|
|
261
|
+
continue
|
|
262
|
+
else:
|
|
263
|
+
if in_table:
|
|
264
|
+
flush_paragraph()
|
|
265
|
+
close_table()
|
|
266
|
+
|
|
267
|
+
# Horizontal rules
|
|
268
|
+
if re.match(r'^([\*\-_]\s?){3,}$', line.strip()):
|
|
269
|
+
flush_paragraph()
|
|
270
|
+
close_all_lists()
|
|
271
|
+
close_table()
|
|
272
|
+
html_out.append('<hr>')
|
|
273
|
+
continue
|
|
274
|
+
|
|
275
|
+
# Headings
|
|
276
|
+
m = re.match(r'^(#{1,6})\s+(.*)', line)
|
|
277
|
+
if m:
|
|
278
|
+
flush_paragraph()
|
|
279
|
+
close_all_lists()
|
|
280
|
+
close_table()
|
|
281
|
+
level = len(m.group(1))
|
|
282
|
+
content = inline_format(m.group(2).strip())
|
|
283
|
+
html_out.append(f'<h{level}>{content}</h{level}>')
|
|
284
|
+
continue
|
|
285
|
+
|
|
286
|
+
# Ordered list detection with indentation for nesting
|
|
287
|
+
m = re.match(r'^(\s*)(\d+)\.\s+(.*)', line)
|
|
288
|
+
if m:
|
|
289
|
+
flush_paragraph()
|
|
290
|
+
close_table()
|
|
291
|
+
indent = len(m.group(1).replace('\t', ' '))
|
|
292
|
+
# Close lists with indent >= current
|
|
293
|
+
close_all_lists(min_indent=indent)
|
|
294
|
+
if not list_stack or list_stack[-1][0] != 'ol' or list_stack[-1][1] < indent:
|
|
295
|
+
html_out.append('<ol>')
|
|
296
|
+
list_stack.append(('ol', indent))
|
|
297
|
+
item_text = inline_format(m.group(3).strip())
|
|
298
|
+
html_out.append(f'<li>{item_text}</li>')
|
|
299
|
+
continue
|
|
300
|
+
|
|
301
|
+
# Unordered list detection with indentation for nesting
|
|
302
|
+
m = re.match(r'^(\s*)[-*+]\s+(.*)', line)
|
|
303
|
+
if m:
|
|
304
|
+
flush_paragraph()
|
|
305
|
+
close_table()
|
|
306
|
+
indent = len(m.group(1).replace('\t', ' '))
|
|
307
|
+
close_all_lists(min_indent=indent)
|
|
308
|
+
if not list_stack or list_stack[-1][0] != 'ul' or list_stack[-1][1] < indent:
|
|
309
|
+
html_out.append('<ul>')
|
|
310
|
+
list_stack.append(('ul', indent))
|
|
311
|
+
|
|
312
|
+
item_text = inline_format(m.group(2).strip())
|
|
313
|
+
|
|
314
|
+
# Task list support
|
|
315
|
+
task_match = re.match(r'^\[( |x|X)\]\s+(.*)', item_text)
|
|
316
|
+
if task_match:
|
|
317
|
+
checked = 'checked' if task_match.group(1).lower() == 'x' else ''
|
|
318
|
+
item_text = task_match.group(2)
|
|
319
|
+
html_out.append(f'<li><input type="checkbox" disabled {checked}/> {item_text}</li>')
|
|
320
|
+
else:
|
|
321
|
+
html_out.append(f'<li>{item_text}</li>')
|
|
322
|
+
continue
|
|
323
|
+
|
|
324
|
+
# Not list, close any open lists at this indent
|
|
325
|
+
close_all_lists()
|
|
326
|
+
|
|
327
|
+
# ... inside your main loop, instead of the old paragraph handling:
|
|
328
|
+
|
|
329
|
+
if not line.strip():
|
|
330
|
+
flush_paragraph()
|
|
331
|
+
else:
|
|
332
|
+
paragraph_lines.append(inline_format(line.strip()))
|
|
333
|
+
|
|
334
|
+
# Also, before any block elements (headings, lists, blockquotes, code blocks, tables, horizontal rules),
|
|
335
|
+
# call flush_paragraph() to close any open paragraph.
|
|
336
|
+
|
|
337
|
+
# At the very end of the loop, after processing all lines, call:
|
|
338
|
+
flush_paragraph()
|
|
339
|
+
close_all_lists()
|
|
340
|
+
close_table()
|
|
341
|
+
|
|
342
|
+
html('\n'.join(html_out))
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pytpro
|
|
3
|
-
Version: 0.2.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 0.2.7
|
|
4
|
+
Summary: Lightweight Python library for math, randomness, HTML, Markdown, CSS, and JS rendering — clean and minimal.
|
|
5
5
|
Author: Ibrahim Akhlaq
|
|
6
6
|
Author-email: ibakhlaq@gmail.com
|
|
7
|
+
Keywords: python,tools,utilities,python tools,python utilities,math,random,utility,mathematics,randomness,random number,random numbers,random number generator,random number generators,random number generators python,html,css,javascript,markdown,markdown preview,markdown previewer,markdown previewer python
|
|
7
8
|
Classifier: Programming Language :: Python :: 3
|
|
8
9
|
Classifier: License :: OSI Approved :: MIT License
|
|
9
10
|
Classifier: Operating System :: OS Independent
|
|
10
11
|
Requires-Python: >=3.6
|
|
11
12
|
Description-Content-Type: text/markdown
|
|
12
13
|
License-File: LICENSE
|
|
14
|
+
Requires-Dist: tkhtmlview
|
|
13
15
|
Dynamic: author
|
|
14
16
|
Dynamic: author-email
|
|
15
17
|
Dynamic: classifier
|
|
16
18
|
Dynamic: description
|
|
17
19
|
Dynamic: description-content-type
|
|
20
|
+
Dynamic: keywords
|
|
18
21
|
Dynamic: license-file
|
|
22
|
+
Dynamic: requires-dist
|
|
19
23
|
Dynamic: requires-python
|
|
20
24
|
Dynamic: summary
|
|
21
25
|
|
|
@@ -23,12 +27,38 @@ Dynamic: summary
|
|
|
23
27
|
<img src="https://i.postimg.cc/BjSmyvYv/download.png" width="200" alt="pytpro logo">
|
|
24
28
|
</p>
|
|
25
29
|
|
|
26
|
-
|
|
27
|
-
<
|
|
30
|
+
<p align="center">
|
|
31
|
+
<img src="https://i.postimg.cc/s2PM4pyd/pyt.png" width="140" alt="pytpro heading">
|
|
32
|
+
</p>
|
|
28
33
|
|
|
29
34
|
**pytpro** is a lightweight Python package by Ibrahim Akhlaq that provides powerful utility functions for math, randomness, and HTML rendering. It's clean, minimal, and built to feel like magic.
|
|
30
35
|
---
|
|
36
|
+
|
|
37
|
+
# 🖥️ Example Usage
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
import pytpro
|
|
41
|
+
|
|
42
|
+
pytpro.add(2, 3)
|
|
43
|
+
pytpro.square(6)
|
|
44
|
+
pytpro.pi()
|
|
45
|
+
pytpro.htmlcssjs("<h1>Hello!</h1><p>This is raw HTML.</p>")
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
# 🖥️ Instructions to install:
|
|
49
|
+
|
|
50
|
+
To install locally from your project directory, open PowerShell or terminal and run:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install pytpro
|
|
54
|
+
```
|
|
55
|
+
|
|
31
56
|
# API REFERENCE
|
|
57
|
+
|
|
58
|
+
- disclaimer: Some of the output examples in the API reference cannot be rendered in PYPI, so screenshots of the actual results were provided. Keep in mind that the output may differ slightly from the actual results, as I had to resize the images in some cases.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
32
62
|
## 🚀 Features
|
|
33
63
|
### ➕ Math Functions:
|
|
34
64
|
- `add(a, b):`
|
|
@@ -179,7 +209,7 @@ py.caption("Hello World!")
|
|
|
179
209
|
```HTML
|
|
180
210
|
<p style='font-size: 0.9em; color: gray;'>Hello World!</p>
|
|
181
211
|
```
|
|
182
|
-
|
|
212
|
+
<p align="left"><img src='https://i.postimg.cc/hjRzR2D5/caption.png' width='90' alt='Hello World!'></p>
|
|
183
213
|
|
|
184
214
|
### `htmlcssjs(html_fragment)`
|
|
185
215
|
You can use the `htmlcssjs()` function to render raw HTML, CSS, and Javascript code.
|
|
@@ -190,6 +220,9 @@ py.htmlcssjs("""
|
|
|
190
220
|
<style>
|
|
191
221
|
button {
|
|
192
222
|
background-color: red;
|
|
223
|
+
border: none;
|
|
224
|
+
border-radius: 4px;
|
|
225
|
+
padding: 15px 32px;
|
|
193
226
|
color: white;
|
|
194
227
|
}
|
|
195
228
|
</style>
|
|
@@ -208,6 +241,9 @@ button {
|
|
|
208
241
|
<style>
|
|
209
242
|
button {
|
|
210
243
|
background-color: red;
|
|
244
|
+
border: none;
|
|
245
|
+
border-radius: 4px;
|
|
246
|
+
padding: 15px 32px;
|
|
211
247
|
color: white;
|
|
212
248
|
}
|
|
213
249
|
</style>
|
|
@@ -220,14 +256,9 @@ button {
|
|
|
220
256
|
}
|
|
221
257
|
</script>
|
|
222
258
|
```
|
|
223
|
-
|
|
224
|
-
button
|
|
225
|
-
|
|
226
|
-
color: white;
|
|
227
|
-
}
|
|
228
|
-
</style>
|
|
229
|
-
<button onclick='click()'>Hello World!</button>
|
|
230
|
-
<p id="output">{javascript is not supported in PYPI}</p>
|
|
259
|
+
<p>
|
|
260
|
+
<img src="https://i.postimg.cc/NfyFK8rf/pypi2.png" width="230" alt="button">
|
|
261
|
+
</p>
|
|
231
262
|
|
|
232
263
|
### Alert Boxes
|
|
233
264
|
#### `alertbox_red(text)`
|
|
@@ -302,37 +333,14 @@ This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
|
302
333
|
<h1> Hello World!</h1>
|
|
303
334
|
<p>This is a paragraph with <strong>bold</strong>, <em>italic</em>, and <code>inline code</code>.</p>
|
|
304
335
|
```
|
|
305
|
-
- <
|
|
306
|
-
|
|
307
|
-
This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
336
|
+
- <h1>Hello World!</h1>
|
|
337
|
+
<p> This is a paragraph with <strong>bold</strong>, <em>italic</em>, and <code>inline code</code>.</p>
|
|
308
338
|
|
|
309
339
|
For more information about Markdown formatting and its syntax, see the [Markdown documentation](https://www.markdownguide.org/), [cheat sheet](https://www.markdownguide.org/cheat-sheet/), [basic syntax](https://www.markdownguide.org/basic-syntax/), or [extended syntax](https://www.markdownguide.org/extended-syntax/).
|
|
310
340
|
---
|
|
311
|
-
<p style="text-align: center !important;
|
|
312
|
-
font-size: 50px;
|
|
313
|
-
color: #838383ff;
|
|
314
|
-
font-weight: bold;
|
|
315
|
-
font-family: sans-serif;
|
|
316
|
-
text-align: center ">Pytpro</p>
|
|
317
|
-
|
|
318
|
-
# 🖥️ Example Usage
|
|
319
|
-
|
|
320
|
-
```python
|
|
321
|
-
import pytpro
|
|
322
341
|
|
|
323
|
-
|
|
324
|
-
pytpro.square(6)
|
|
325
|
-
pytpro.pi()
|
|
326
|
-
pytpro.htmlcssjs("<h1>Hello!</h1><p>This is raw HTML.</p>")
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
# 🖥️ Instructions to install:
|
|
330
|
-
|
|
331
|
-
To install locally from your project directory, open PowerShell or terminal and run:
|
|
342
|
+
<h1 align="center">Pytpro</h1>
|
|
332
343
|
|
|
333
|
-
```bash
|
|
334
|
-
pip install pytpro
|
|
335
|
-
```
|
|
336
344
|
<pre>
|
|
337
345
|
_______ ___ ___ ________ _______ _________ ________
|
|
338
346
|
| ___ \\ \ / /|__ __|| ___ \ | ___ | / ______ \
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
tkhtmlview
|
pytpro-0.2.7/setup.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
if sys.version_info < (3, 6):
|
|
5
|
+
print("❌ To use this module, you need Python 3.6 or newer.")
|
|
6
|
+
sys.exit(1)
|
|
7
|
+
|
|
8
|
+
with open("README.md", encoding="utf-8") as f:
|
|
9
|
+
long_description = f.read()
|
|
10
|
+
|
|
11
|
+
setup(
|
|
12
|
+
name="pytpro",
|
|
13
|
+
version="0.2.7",
|
|
14
|
+
description="Lightweight Python library for math, randomness, HTML, Markdown, CSS, and JS rendering — clean and minimal.",
|
|
15
|
+
long_description= long_description,
|
|
16
|
+
long_description_content_type="text/markdown",
|
|
17
|
+
author="Ibrahim Akhlaq",
|
|
18
|
+
author_email="ibakhlaq@gmail.com",
|
|
19
|
+
packages=find_packages(),
|
|
20
|
+
classifiers=[
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
],
|
|
25
|
+
python_requires=">=3.6",
|
|
26
|
+
install_requires=[
|
|
27
|
+
"tkhtmlview",
|
|
28
|
+
],
|
|
29
|
+
keywords=["python",
|
|
30
|
+
"tools",
|
|
31
|
+
"utilities",
|
|
32
|
+
"python tools",
|
|
33
|
+
"python utilities",
|
|
34
|
+
"math",
|
|
35
|
+
"random",
|
|
36
|
+
"utility",
|
|
37
|
+
"mathematics",
|
|
38
|
+
"randomness",
|
|
39
|
+
"random number",
|
|
40
|
+
"random numbers",
|
|
41
|
+
"random number generator",
|
|
42
|
+
"random number generators",
|
|
43
|
+
"random number generators python",
|
|
44
|
+
"html",
|
|
45
|
+
"css",
|
|
46
|
+
"javascript",
|
|
47
|
+
"markdown",
|
|
48
|
+
"markdown preview",
|
|
49
|
+
"markdown previewer",
|
|
50
|
+
"markdown previewer python",]
|
|
51
|
+
)
|
pytpro-0.2.4/pytpro/markdown.py
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
from main import htmlcssjs as html
|
|
3
|
-
|
|
4
|
-
_css_injected = False
|
|
5
|
-
|
|
6
|
-
def markdown(md_text: str):
|
|
7
|
-
global _css_injected
|
|
8
|
-
if not _css_injected:
|
|
9
|
-
html("""
|
|
10
|
-
<style>
|
|
11
|
-
pre code, code, pre, blockquote {
|
|
12
|
-
border: 1px;
|
|
13
|
-
}
|
|
14
|
-
pre, code, pre code {
|
|
15
|
-
background-color: #efefef !important;
|
|
16
|
-
border: 0px solid rgba(128, 128, 128, 0.2);
|
|
17
|
-
border-radius: 4px;
|
|
18
|
-
font-family: monospace;
|
|
19
|
-
font-size: 0.95em;
|
|
20
|
-
overflow-x: auto;
|
|
21
|
-
}
|
|
22
|
-
.hljs {
|
|
23
|
-
display: block;
|
|
24
|
-
overflow-x: auto;
|
|
25
|
-
padding: 10px 16px;
|
|
26
|
-
background: #efefef;
|
|
27
|
-
color: #333;
|
|
28
|
-
border-radius: 4px;
|
|
29
|
-
margin: 16px 0;
|
|
30
|
-
}
|
|
31
|
-
pre code {
|
|
32
|
-
background-color: transparent !important;
|
|
33
|
-
border: none !important;
|
|
34
|
-
}
|
|
35
|
-
pre {
|
|
36
|
-
background-color: #efefef !important;
|
|
37
|
-
margin: 0;
|
|
38
|
-
margin-bottom: 17px;
|
|
39
|
-
margin-top: 17px;
|
|
40
|
-
}
|
|
41
|
-
code {
|
|
42
|
-
padding: 2px 6px;
|
|
43
|
-
}
|
|
44
|
-
blockquote {
|
|
45
|
-
position: relative;
|
|
46
|
-
padding: 12px 16px 12px 24px;
|
|
47
|
-
background-color: #efefef;
|
|
48
|
-
border-radius: 4px;
|
|
49
|
-
color: #333;
|
|
50
|
-
font-size: 17px;
|
|
51
|
-
margin: 16px 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
blockquote::before {
|
|
55
|
-
content: '';
|
|
56
|
-
position: absolute;
|
|
57
|
-
top: 0;
|
|
58
|
-
bottom: 0;
|
|
59
|
-
left: 0;
|
|
60
|
-
width: 6px;
|
|
61
|
-
background-color: #595959;
|
|
62
|
-
border-radius: 4px;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
ul, p, blockquote {
|
|
66
|
-
margin-bottom: 12px;
|
|
67
|
-
}
|
|
68
|
-
</style>
|
|
69
|
-
<link rel="stylesheet"
|
|
70
|
-
href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css">
|
|
71
|
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
|
|
72
|
-
<script>setTimeout(() => hljs.highlightAll(), 100);</script>
|
|
73
|
-
""")
|
|
74
|
-
_css_injected = True
|
|
75
|
-
|
|
76
|
-
lines = md_text.strip().split('\n')
|
|
77
|
-
in_code_block = False
|
|
78
|
-
in_list = False
|
|
79
|
-
code_block = []
|
|
80
|
-
html_out = []
|
|
81
|
-
language = ''
|
|
82
|
-
|
|
83
|
-
def close_list():
|
|
84
|
-
nonlocal in_list
|
|
85
|
-
if in_list:
|
|
86
|
-
html_out.append('</ul>')
|
|
87
|
-
in_list = False
|
|
88
|
-
|
|
89
|
-
for line in lines:
|
|
90
|
-
line = line.rstrip()
|
|
91
|
-
|
|
92
|
-
# Code block toggle
|
|
93
|
-
if line.startswith("```"):
|
|
94
|
-
if not in_code_block:
|
|
95
|
-
in_code_block = True
|
|
96
|
-
language = line[3:].strip()
|
|
97
|
-
code_block = []
|
|
98
|
-
else:
|
|
99
|
-
from html import escape
|
|
100
|
-
|
|
101
|
-
code_html = escape('\n'.join(code_block))
|
|
102
|
-
html_out.append(f'<pre><code class="hljs language-{language}">{code_html}</code></pre>')
|
|
103
|
-
|
|
104
|
-
in_code_block = False
|
|
105
|
-
continue
|
|
106
|
-
|
|
107
|
-
if in_code_block:
|
|
108
|
-
code_block.append(line)
|
|
109
|
-
continue
|
|
110
|
-
|
|
111
|
-
# Horizontal rules
|
|
112
|
-
if re.match(r'^([\*\-_]\s?){3,}$', line.strip()):
|
|
113
|
-
close_list()
|
|
114
|
-
html_out.append('<hr>')
|
|
115
|
-
continue
|
|
116
|
-
|
|
117
|
-
# Headings
|
|
118
|
-
if re.match(r'^#{1,6} ', line):
|
|
119
|
-
close_list()
|
|
120
|
-
level = len(line.split(' ')[0])
|
|
121
|
-
content = line[level+1:].strip()
|
|
122
|
-
html_out.append(f"<h{level}>{content}</h{level}>")
|
|
123
|
-
continue
|
|
124
|
-
|
|
125
|
-
# Blockquotes
|
|
126
|
-
if line.startswith('> '):
|
|
127
|
-
close_list()
|
|
128
|
-
content = line[2:].strip()
|
|
129
|
-
html_out.append(f"<blockquote>{content}</blockquote>")
|
|
130
|
-
continue
|
|
131
|
-
|
|
132
|
-
# Unordered Lists
|
|
133
|
-
if re.match(r'^[-*+] ', line):
|
|
134
|
-
if not in_list:
|
|
135
|
-
in_list = True
|
|
136
|
-
html_out.append('<ul>')
|
|
137
|
-
item = re.sub(r'^[-*+] ', '', line)
|
|
138
|
-
# Inline formatting
|
|
139
|
-
item = re.sub(r'\*\*\*(.*?)\*\*\*', r'<strong><em>\1</em></strong>', item)
|
|
140
|
-
item = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', item)
|
|
141
|
-
item = re.sub(r'\*(.*?)\*', r'<em>\1</em>', item)
|
|
142
|
-
item = re.sub(r'`(.*?)`', r'<code>\1</code>', item)
|
|
143
|
-
html_out.append(f"<li>{item}</li>")
|
|
144
|
-
continue
|
|
145
|
-
else:
|
|
146
|
-
close_list()
|
|
147
|
-
|
|
148
|
-
# Inline formatting for normal paragraphs
|
|
149
|
-
formatted = line
|
|
150
|
-
formatted = re.sub(r'\*\*\*(.*?)\*\*\*', r'<strong><em>\1</em></strong>', formatted)
|
|
151
|
-
formatted = re.sub(r'\*\*(.*?)\*\*', r'<strong>\1</strong>', formatted)
|
|
152
|
-
formatted = re.sub(r'\*(.*?)\*', r'<em>\1</em>', formatted)
|
|
153
|
-
formatted = re.sub(r'`(.*?)`', r'<code>\1</code>', formatted)
|
|
154
|
-
|
|
155
|
-
html_out.append(f"<p>{formatted}</p>")
|
|
156
|
-
|
|
157
|
-
close_list()
|
|
158
|
-
html('\n'.join(html_out))
|
|
159
|
-
|
|
160
|
-
markdown(
|
|
161
|
-
"""
|
|
162
|
-
# Heading 1
|
|
163
|
-
## Heading 2
|
|
164
|
-
### Heading 3
|
|
165
|
-
#### Heading 4
|
|
166
|
-
##### Heading 5
|
|
167
|
-
###### Heading 6
|
|
168
|
-
This is a paragraph with **bold**, *italic*, and `inline code`.
|
|
169
|
-
- List item 1
|
|
170
|
-
- List item 2
|
|
171
|
-
> Blockquote
|
|
172
|
-
```python
|
|
173
|
-
print('Hello, world!')
|
|
174
|
-
```
|
|
175
|
-
```html
|
|
176
|
-
<h1>Hello, world!</h1>
|
|
177
|
-
```
|
|
178
|
-
"""
|
|
179
|
-
)
|
pytpro-0.2.4/setup.py
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from setuptools import setup, find_packages
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
if sys.version_info < (3, 6):
|
|
5
|
-
print("❌ To use this module, you need Python 3.6 or newer.")
|
|
6
|
-
sys.exit(1)
|
|
7
|
-
|
|
8
|
-
with open("README.md", encoding="utf-8") as f:
|
|
9
|
-
long_description = f.read()
|
|
10
|
-
|
|
11
|
-
setup(
|
|
12
|
-
name="pytpro",
|
|
13
|
-
version="0.2.4",
|
|
14
|
-
description="A simple Python tools package by Ibrahim Akhlaq",
|
|
15
|
-
long_description=long_description,
|
|
16
|
-
long_description_content_type="text/markdown",
|
|
17
|
-
author="Ibrahim Akhlaq",
|
|
18
|
-
author_email="ibakhlaq@gmail.com",
|
|
19
|
-
packages=find_packages(),
|
|
20
|
-
classifiers=[
|
|
21
|
-
"Programming Language :: Python :: 3",
|
|
22
|
-
"License :: OSI Approved :: MIT License",
|
|
23
|
-
"Operating System :: OS Independent",
|
|
24
|
-
],
|
|
25
|
-
python_requires=">=3.6",
|
|
26
|
-
install_requires=[
|
|
27
|
-
"",
|
|
28
|
-
],
|
|
29
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|