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.
@@ -1,21 +1,25 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytpro
3
- Version: 0.2.4
4
- Summary: A simple Python tools package by Ibrahim Akhlaq
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
- <h1 align="center">Pytpro</h1>
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
- - <p style='font-size: 0.9em; color: gray;'>Hello World!</p>
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
- - <style>
224
- button {
225
- background-color: red;
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
- - <p style="font-size: 30px;font-weight: 2905; ">Hello World!</p>
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
- pytpro.add(2, 3)
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
- <h1 align="center">Pytpro</h1>
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
- - <p style='font-size: 0.9em; color: gray;'>Hello World!</p>
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
- - <style>
203
- button {
204
- background-color: red;
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
- - <p style="font-size: 30px;font-weight: 2905; ">Hello World!</p>
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
- pytpro.add(2, 3)
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
  | ___ \\ \ / /|__ __|| ___ \ | ___ | / ______ \
@@ -75,7 +75,7 @@ __all__ = [
75
75
  "markdown",
76
76
  ]
77
77
 
78
- __version__ = "0.2.4"
78
+ __version__ = "0.2.7"
79
79
  __copyright__ = "Copyright (c) 2023 Ibrahim Akhlaq"
80
80
  __credits__ = ["Ibrahim Akhlaq"]
81
81
  __maintainer__ = "Ibrahim Akhlaq"
@@ -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: ![alt](url "optional title")
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
4
- Summary: A simple Python tools package by Ibrahim Akhlaq
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
- <h1 align="center">Pytpro</h1>
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
- - <p style='font-size: 0.9em; color: gray;'>Hello World!</p>
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
- - <style>
224
- button {
225
- background-color: red;
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
- - <p style="font-size: 30px;font-weight: 2905; ">Hello World!</p>
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
- pytpro.add(2, 3)
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
  | ___ \\ \ / /|__ __|| ___ \ | ___ | / ______ \
@@ -7,4 +7,5 @@ pytpro/markdown.py
7
7
  pytpro.egg-info/PKG-INFO
8
8
  pytpro.egg-info/SOURCES.txt
9
9
  pytpro.egg-info/dependency_links.txt
10
+ pytpro.egg-info/requires.txt
10
11
  pytpro.egg-info/top_level.txt
@@ -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
+ )
@@ -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