bloops 0.2.0__tar.gz → 0.2.1__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.
- {bloops-0.2.0 → bloops-0.2.1}/PKG-INFO +21 -9
- {bloops-0.2.0 → bloops-0.2.1}/README.md +9 -8
- {bloops-0.2.0 → bloops-0.2.1}/docs/api.md +22 -3
- {bloops-0.2.0 → bloops-0.2.1}/pyproject.toml +17 -1
- bloops-0.2.1/src/bloops/__about__.py +5 -0
- bloops-0.2.1/src/bloops/__init__.py +6 -0
- bloops-0.2.1/src/bloops/__main__.py +6 -0
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/_build_and_preview.py +8 -11
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/_helper.py +0 -2
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/bloopser.py +5 -3
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/bracer.py +1 -4
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/cli.py +0 -1
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/validator.py +7 -5
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/vars.py +13 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_bracer.py +1 -1
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_validator.py +1 -1
- bloops-0.2.0/src/bloops/__about__.py +0 -3
- bloops-0.2.0/src/bloops/__main__.py +0 -4
- {bloops-0.2.0 → bloops-0.2.1}/.gitignore +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/LICENSE +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/example/content.bbcode +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/example/index.html +0 -0
- /bloops-0.2.0/src/bloops/__init__.py → /bloops-0.2.1/src/bloops/py.typed +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/error_template.html +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/index.html +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/script.js +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/style.css +0 -0
- /bloops-0.2.0/tests/test_asy_generatation.py → /bloops-0.2.1/tests/test_asy_generation.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_asy_tag.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_bloopser.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_img_tag.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_list_tag.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_math_boxes.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_remaining_tags.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_simple_tags.py +0 -0
- {bloops-0.2.0 → bloops-0.2.1}/tests/test_transpile.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: bloops
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: An AoPS-like BBCode to HTML transpiler, with live-preview and support for Asymptote geometry diagrams.
|
|
5
5
|
Project-URL: Documentation, https://github.com/Bubu-Droid/bloops/blob/main/docs/api.md
|
|
6
6
|
Project-URL: Issues, https://github.com/Bubu-Droid/bloops/issues
|
|
@@ -9,19 +9,30 @@ Author-email: Bubu-Droid <bubu@bubudroid.me>
|
|
|
9
9
|
License-Expression: MIT
|
|
10
10
|
License-File: LICENSE
|
|
11
11
|
Keywords: aops,asymptote,bbcode,converter,diagrams,geometry,html,latex,live-preview,markup,math,tex,transpiler
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Education
|
|
16
|
+
Classifier: Natural Language :: English
|
|
12
17
|
Classifier: Operating System :: OS Independent
|
|
13
18
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
16
21
|
Classifier: Programming Language :: Python :: 3.14
|
|
17
22
|
Classifier: Programming Language :: Python :: 3.15
|
|
23
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
24
|
+
Classifier: Topic :: Education
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
26
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
27
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
28
|
+
Classifier: Typing :: Typed
|
|
18
29
|
Requires-Python: >=3.12
|
|
19
30
|
Requires-Dist: livereload>=2.7.1
|
|
20
31
|
Requires-Dist: watchdog>=6
|
|
21
32
|
Description-Content-Type: text/markdown
|
|
22
33
|
|
|
23
34
|
<div align="center">
|
|
24
|
-
<img src="https://raw.githubusercontent.com/Bubu-Droid/bloops/main/assets/banner.png"
|
|
35
|
+
<img src="https://raw.githubusercontent.com/Bubu-Droid/bloops/main/assets/banner.png" width="90%">
|
|
25
36
|
</div>
|
|
26
37
|
|
|
27
38
|
<hr>
|
|
@@ -30,7 +41,7 @@ Bloops is an AoPS-like **BBCode to HTML transpiler**
|
|
|
30
41
|
written in Python, with **live-preview**
|
|
31
42
|
and support for **Asymptote geometry diagrams**.
|
|
32
43
|
|
|
33
|
-
<div align="center"
|
|
44
|
+
<div align="center">
|
|
34
45
|
<a href="https://github.com/Bubu-Droid/bloops/releases/latest">
|
|
35
46
|
<img alt="PyPI Version" src="https://img.shields.io/pypi/v/bloops?label=PyPI&style=for-the-badge&logo=pypi&logoColor=c0caf5&labelColor=1a1b26&color=7aa2f7&v=1" />
|
|
36
47
|
</a>
|
|
@@ -42,7 +53,7 @@ and support for **Asymptote geometry diagrams**.
|
|
|
42
53
|
</a>
|
|
43
54
|
</div>
|
|
44
55
|
|
|
45
|
-
<div align="center"
|
|
56
|
+
<div align="center">
|
|
46
57
|
<a href="https://pypi.org/project/bloops/">
|
|
47
58
|
<img alt="PyPI Python Version" src="https://img.shields.io/pypi/pyversions/bloops?style=for-the-badge&logo=python&logoColor=c0caf5&labelColor=1a1b26&color=7aa2f7&v=1" />
|
|
48
59
|
</a>
|
|
@@ -54,7 +65,7 @@ and support for **Asymptote geometry diagrams**.
|
|
|
54
65
|
</a>
|
|
55
66
|
</div>
|
|
56
67
|
|
|
57
|
-
<div align="center"
|
|
68
|
+
<div align="center">
|
|
58
69
|
<a href="https://github.com/Bubu-Droid/bloops/blob/main/LICENSE">
|
|
59
70
|
<img alt="License" src="https://img.shields.io/github/license/Bubu-Droid/bloops?label=License&style=for-the-badge&labelColor=1a1b26&color=7dcfff" />
|
|
60
71
|
</a>
|
|
@@ -127,7 +138,7 @@ Install `bloops` from PyPI. Here is the
|
|
|
127
138
|
| Flag | Long Flag | Description |
|
|
128
139
|
| ---- | -------------- | ------------------------------------------------------------------------- |
|
|
129
140
|
| `-h` | `--help` | Show help message for usage of `bloops`. |
|
|
130
|
-
| `-
|
|
141
|
+
| `-V` | `--version` | Show the version of `bloops`. |
|
|
131
142
|
| `-c` | `--build-cont` | Watch `content.bbcode` for changes and continuously rebuild `index.html`. |
|
|
132
143
|
| `-p` | `--preview` | Launch a local web live-server to preview `index.html`. |
|
|
133
144
|
| `-i` | `--input` | (**Required**) Input directory containing `content.bbcode`. |
|
|
@@ -195,9 +206,9 @@ Here are reference tables for each BBCode tag bloops uses:
|
|
|
195
206
|
|
|
196
207
|
<details><summary>[color]</summary>
|
|
197
208
|
|
|
198
|
-
| Option
|
|
199
|
-
|
|
|
200
|
-
| `
|
|
209
|
+
| Option | Mandatory | Description |
|
|
210
|
+
| ------ | :-------: | ---------------------------------------- |
|
|
211
|
+
| `hex` | YES | Color code in hex (with the leading \#). |
|
|
201
212
|
|
|
202
213
|
</details>
|
|
203
214
|
|
|
@@ -391,6 +402,7 @@ how to implement it.
|
|
|
391
402
|
(I'll be very glad if someone suggests me a solution for this;
|
|
392
403
|
I've thought about it myself, but couldn't really come up with
|
|
393
404
|
anything.)
|
|
405
|
+
- [ ] Switch lists to sets to optimize speed.
|
|
394
406
|
|
|
395
407
|
<p align="right"><a href="#index">↑ Back to top</a></p>
|
|
396
408
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/Bubu-Droid/bloops/main/assets/banner.png"
|
|
2
|
+
<img src="https://raw.githubusercontent.com/Bubu-Droid/bloops/main/assets/banner.png" width="90%">
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
<hr>
|
|
@@ -8,7 +8,7 @@ Bloops is an AoPS-like **BBCode to HTML transpiler**
|
|
|
8
8
|
written in Python, with **live-preview**
|
|
9
9
|
and support for **Asymptote geometry diagrams**.
|
|
10
10
|
|
|
11
|
-
<div align="center"
|
|
11
|
+
<div align="center">
|
|
12
12
|
<a href="https://github.com/Bubu-Droid/bloops/releases/latest">
|
|
13
13
|
<img alt="PyPI Version" src="https://img.shields.io/pypi/v/bloops?label=PyPI&style=for-the-badge&logo=pypi&logoColor=c0caf5&labelColor=1a1b26&color=7aa2f7&v=1" />
|
|
14
14
|
</a>
|
|
@@ -20,7 +20,7 @@ and support for **Asymptote geometry diagrams**.
|
|
|
20
20
|
</a>
|
|
21
21
|
</div>
|
|
22
22
|
|
|
23
|
-
<div align="center"
|
|
23
|
+
<div align="center">
|
|
24
24
|
<a href="https://pypi.org/project/bloops/">
|
|
25
25
|
<img alt="PyPI Python Version" src="https://img.shields.io/pypi/pyversions/bloops?style=for-the-badge&logo=python&logoColor=c0caf5&labelColor=1a1b26&color=7aa2f7&v=1" />
|
|
26
26
|
</a>
|
|
@@ -32,7 +32,7 @@ and support for **Asymptote geometry diagrams**.
|
|
|
32
32
|
</a>
|
|
33
33
|
</div>
|
|
34
34
|
|
|
35
|
-
<div align="center"
|
|
35
|
+
<div align="center">
|
|
36
36
|
<a href="https://github.com/Bubu-Droid/bloops/blob/main/LICENSE">
|
|
37
37
|
<img alt="License" src="https://img.shields.io/github/license/Bubu-Droid/bloops?label=License&style=for-the-badge&labelColor=1a1b26&color=7dcfff" />
|
|
38
38
|
</a>
|
|
@@ -105,7 +105,7 @@ Install `bloops` from PyPI. Here is the
|
|
|
105
105
|
| Flag | Long Flag | Description |
|
|
106
106
|
| ---- | -------------- | ------------------------------------------------------------------------- |
|
|
107
107
|
| `-h` | `--help` | Show help message for usage of `bloops`. |
|
|
108
|
-
| `-
|
|
108
|
+
| `-V` | `--version` | Show the version of `bloops`. |
|
|
109
109
|
| `-c` | `--build-cont` | Watch `content.bbcode` for changes and continuously rebuild `index.html`. |
|
|
110
110
|
| `-p` | `--preview` | Launch a local web live-server to preview `index.html`. |
|
|
111
111
|
| `-i` | `--input` | (**Required**) Input directory containing `content.bbcode`. |
|
|
@@ -173,9 +173,9 @@ Here are reference tables for each BBCode tag bloops uses:
|
|
|
173
173
|
|
|
174
174
|
<details><summary>[color]</summary>
|
|
175
175
|
|
|
176
|
-
| Option
|
|
177
|
-
|
|
|
178
|
-
| `
|
|
176
|
+
| Option | Mandatory | Description |
|
|
177
|
+
| ------ | :-------: | ---------------------------------------- |
|
|
178
|
+
| `hex` | YES | Color code in hex (with the leading \#). |
|
|
179
179
|
|
|
180
180
|
</details>
|
|
181
181
|
|
|
@@ -369,6 +369,7 @@ how to implement it.
|
|
|
369
369
|
(I'll be very glad if someone suggests me a solution for this;
|
|
370
370
|
I've thought about it myself, but couldn't really come up with
|
|
371
371
|
anything.)
|
|
372
|
+
- [ ] Switch lists to sets to optimize speed.
|
|
372
373
|
|
|
373
374
|
<p align="right"><a href="#index">↑ Back to top</a></p>
|
|
374
375
|
|
|
@@ -14,11 +14,15 @@ with MathJax and Syntax Highlighting support.
|
|
|
14
14
|
|
|
15
15
|
Args:
|
|
16
16
|
text: Raw BBCode text content.
|
|
17
|
-
bbcode_tags:
|
|
17
|
+
bbcode_tags: Mapping of tag names to their opening pattern,
|
|
18
|
+
closing pattern and permitted arguments. See `BBCODE_TAGS`.
|
|
18
19
|
|
|
19
20
|
Returns:
|
|
20
21
|
A fully formatted HTML document string.
|
|
21
22
|
|
|
23
|
+
Raises:
|
|
24
|
+
SyntaxError: If a tag has no matching closing tag.
|
|
25
|
+
|
|
22
26
|
## `bracer.py`
|
|
23
27
|
|
|
24
28
|
### `gobble_inside_delim` (Function)
|
|
@@ -68,6 +72,16 @@ Raises:
|
|
|
68
72
|
matching closing tag cannot be found.
|
|
69
73
|
RuntimeError: If parser enters an unexpected state.
|
|
70
74
|
|
|
75
|
+
## `cli.py`
|
|
76
|
+
|
|
77
|
+
### `main` (Function)
|
|
78
|
+
|
|
79
|
+
Parse command-line arguments and run the build and preview process.
|
|
80
|
+
|
|
81
|
+
Reads input/output paths and continuous build or live preview flags
|
|
82
|
+
from CLI arguments, setting default fallback paths when necessary,
|
|
83
|
+
and invokes the build and preview pipeline.
|
|
84
|
+
|
|
71
85
|
## `validator.py`
|
|
72
86
|
|
|
73
87
|
### `validate_bbcode` (Function)
|
|
@@ -80,13 +94,14 @@ dictionary mapping each diagram label to its character index.
|
|
|
80
94
|
|
|
81
95
|
Args:
|
|
82
96
|
text: Raw BBCode input string.
|
|
83
|
-
bbcode_tags:
|
|
84
|
-
and permitted
|
|
97
|
+
bbcode_tags: Mapping of tag names to their opening pattern,
|
|
98
|
+
closing pattern and permitted arguments. See `BBCODE_TAGS`.
|
|
85
99
|
|
|
86
100
|
Returns:
|
|
87
101
|
A dictionary mapping diagram labels to their starting index.
|
|
88
102
|
|
|
89
103
|
Raises:
|
|
104
|
+
SyntaxError: If a tag has no matching closing tag.
|
|
90
105
|
ValueError: If an invalid argument is supplied or duplicate
|
|
91
106
|
diagram labels are encountered.
|
|
92
107
|
|
|
@@ -104,6 +119,10 @@ Args:
|
|
|
104
119
|
text: Entire input text containing BBCode and Asymptote code.
|
|
105
120
|
in_dir: Source directory containing the build cache folder.
|
|
106
121
|
out_dir: Target directory where compiled SVG images are stored.
|
|
122
|
+
bbcode_tags: Mapping of tag names to their opening pattern,
|
|
123
|
+
closing pattern and permitted arguments. See `BBCODE_TAGS`.
|
|
107
124
|
|
|
108
125
|
Raises:
|
|
126
|
+
FileNotFoundError: If `build/cache.json` does not exist in
|
|
127
|
+
`in_dir`, or the `asy` executable is not installed.
|
|
109
128
|
ValueError: If Asymptote compilation fails.
|
|
@@ -26,12 +26,23 @@ license-files = [ "LICEN[CS]E*" ]
|
|
|
26
26
|
authors = [ { name = "Bubu-Droid", email = "bubu@bubudroid.me" } ]
|
|
27
27
|
requires-python = ">=3.12"
|
|
28
28
|
classifiers = [
|
|
29
|
+
"Development Status :: 3 - Alpha",
|
|
30
|
+
"Environment :: Console",
|
|
31
|
+
"Intended Audience :: Developers",
|
|
32
|
+
"Intended Audience :: Education",
|
|
33
|
+
"Natural Language :: English",
|
|
29
34
|
"Operating System :: OS Independent",
|
|
30
35
|
"Programming Language :: Python :: 3 :: Only",
|
|
31
36
|
"Programming Language :: Python :: 3.12",
|
|
32
37
|
"Programming Language :: Python :: 3.13",
|
|
33
38
|
"Programming Language :: Python :: 3.14",
|
|
34
39
|
"Programming Language :: Python :: 3.15",
|
|
40
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
|
41
|
+
"Topic :: Education",
|
|
42
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
43
|
+
"Topic :: Text Processing :: Markup",
|
|
44
|
+
"Topic :: Text Processing :: Markup :: HTML",
|
|
45
|
+
"Typing :: Typed",
|
|
35
46
|
]
|
|
36
47
|
dynamic = [ "version" ]
|
|
37
48
|
dependencies = [
|
|
@@ -56,9 +67,14 @@ build.targets.sdist.include = [ "/src", "/tests", "/docs", "/example" ]
|
|
|
56
67
|
|
|
57
68
|
[tool.ruff]
|
|
58
69
|
line-length = 80
|
|
59
|
-
lint.extend-select = [ "ANN" ]
|
|
70
|
+
lint.extend-select = [ "ANN", "D", "DOC" ]
|
|
71
|
+
lint.per-file-ignores.".github/**" = [ "D", "DOC" ]
|
|
72
|
+
lint.per-file-ignores."tests/**" = [ "D", "DOC" ]
|
|
60
73
|
lint.unfixable = [ "F401" ]
|
|
61
74
|
|
|
75
|
+
[tool.ruff.lint.pydocstyle]
|
|
76
|
+
convention = "google"
|
|
77
|
+
|
|
62
78
|
[tool.basedpyright]
|
|
63
79
|
executionEnvironments = [
|
|
64
80
|
{ root = "tests", reportPrivateUsage = false },
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""An AoPS-like BBCode to HTML transpiler with Asymptote diagram support.
|
|
2
|
+
|
|
3
|
+
Use `bloops.validator.validate_bbcode` and
|
|
4
|
+
`bloops.validator.compile_asy_diagrams` to check a document and render its
|
|
5
|
+
diagrams, then `bloops.bloopser.convert_bbcode_to_html` to produce the HTML.
|
|
6
|
+
"""
|
|
@@ -53,7 +53,6 @@ class _Handler(PatternMatchingEventHandler):
|
|
|
53
53
|
out_dir: Path to the directory for compiled static output.
|
|
54
54
|
file_content: Initial text content of the BBCode file.
|
|
55
55
|
"""
|
|
56
|
-
|
|
57
56
|
super().__init__(
|
|
58
57
|
patterns=["content.bbcode"],
|
|
59
58
|
ignore_directories=True,
|
|
@@ -77,7 +76,6 @@ class _Handler(PatternMatchingEventHandler):
|
|
|
77
76
|
Args:
|
|
78
77
|
event: File system event describing the modification.
|
|
79
78
|
"""
|
|
80
|
-
|
|
81
79
|
new_content = self.input_file.read_text(encoding="utf-8").strip()
|
|
82
80
|
if self.file_content == new_content:
|
|
83
81
|
return
|
|
@@ -97,7 +95,6 @@ class _Handler(PatternMatchingEventHandler):
|
|
|
97
95
|
Exception: Re-raises any syntax or compilation exception encountered
|
|
98
96
|
during execution.
|
|
99
97
|
"""
|
|
100
|
-
|
|
101
98
|
try:
|
|
102
99
|
print(
|
|
103
100
|
"Verifying syntax and generating newly added / changed asymptote diagrams (if any)..."
|
|
@@ -147,16 +144,8 @@ def main(
|
|
|
147
144
|
FileNotFoundError: If the input directory or source file is missing.
|
|
148
145
|
NotADirectoryError: If specified paths are not valid directories.
|
|
149
146
|
"""
|
|
150
|
-
|
|
151
147
|
input_file = in_dir / "content.bbcode"
|
|
152
148
|
output_file = in_dir / "index.html"
|
|
153
|
-
style_file = in_dir / "static" / "style.css"
|
|
154
|
-
style_file.parent.mkdir(parents=True, exist_ok=True)
|
|
155
|
-
script_file = in_dir / "static" / "script.js"
|
|
156
|
-
script_file.parent.mkdir(parents=True, exist_ok=True)
|
|
157
|
-
build_dir = in_dir / "build/"
|
|
158
|
-
build_dir.mkdir(parents=True, exist_ok=True)
|
|
159
|
-
asy_cache_file = build_dir / "cache.json"
|
|
160
149
|
|
|
161
150
|
if not in_dir.exists():
|
|
162
151
|
raise FileNotFoundError("Input directory not found.")
|
|
@@ -168,6 +157,14 @@ def main(
|
|
|
168
157
|
out_dir.mkdir(parents=True, exist_ok=True)
|
|
169
158
|
if not out_dir.is_dir():
|
|
170
159
|
raise NotADirectoryError(f"{out_dir} is not a directory.")
|
|
160
|
+
|
|
161
|
+
style_file = in_dir / "static" / "style.css"
|
|
162
|
+
script_file = in_dir / "static" / "script.js"
|
|
163
|
+
style_file.parent.mkdir(exist_ok=True)
|
|
164
|
+
build_dir = in_dir / "build/"
|
|
165
|
+
build_dir.mkdir(exist_ok=True)
|
|
166
|
+
asy_cache_file = build_dir / "cache.json"
|
|
167
|
+
|
|
171
168
|
file_content = input_file.read_text(encoding="utf-8").strip()
|
|
172
169
|
if not style_file.exists():
|
|
173
170
|
_ = style_file.write_text(STYLESHEET, encoding="utf-8")
|
|
@@ -13,7 +13,6 @@ def get_error_line(text: str, index: int) -> tuple[int, str]:
|
|
|
13
13
|
Returns:
|
|
14
14
|
A tuple containing the 1-based line number and line text string.
|
|
15
15
|
"""
|
|
16
|
-
|
|
17
16
|
line_num = text.count("\n", 0, index)
|
|
18
17
|
|
|
19
18
|
return (line_num + 1, text.splitlines()[line_num])
|
|
@@ -38,7 +37,6 @@ def get_tag_and_args(
|
|
|
38
37
|
Raises:
|
|
39
38
|
SyntaxError: If no valid match is found at the given index.
|
|
40
39
|
"""
|
|
41
|
-
|
|
42
40
|
match = open_delim.match(text, open_delim_start_index)
|
|
43
41
|
if not match:
|
|
44
42
|
error_line = get_error_line(text, open_delim_start_index)
|
|
@@ -25,12 +25,15 @@ def convert_bbcode_to_html(
|
|
|
25
25
|
|
|
26
26
|
Args:
|
|
27
27
|
text: Raw BBCode text content.
|
|
28
|
-
bbcode_tags:
|
|
28
|
+
bbcode_tags: Mapping of tag names to their opening pattern,
|
|
29
|
+
closing pattern and permitted arguments. See `BBCODE_TAGS`.
|
|
29
30
|
|
|
30
31
|
Returns:
|
|
31
32
|
A fully formatted HTML document string.
|
|
32
|
-
"""
|
|
33
33
|
|
|
34
|
+
Raises:
|
|
35
|
+
SyntaxError: If a tag has no matching closing tag.
|
|
36
|
+
"""
|
|
34
37
|
for tag_tuple in bbcode_tags.values():
|
|
35
38
|
open_delim = tag_tuple[0]
|
|
36
39
|
close_delim = tag_tuple[1]
|
|
@@ -70,7 +73,6 @@ def _convert_tag_to_html(
|
|
|
70
73
|
Returns:
|
|
71
74
|
The rendered HTML replacement string for the BBCode element.
|
|
72
75
|
"""
|
|
73
|
-
|
|
74
76
|
tag_and_args = get_tag_and_args(text, open_delim_start_index, open_delim)
|
|
75
77
|
tag, args = tag_and_args
|
|
76
78
|
|
|
@@ -22,7 +22,6 @@ def gobble_inside_delim(
|
|
|
22
22
|
Returns:
|
|
23
23
|
The inner text string enclosed by the matching delimiters.
|
|
24
24
|
"""
|
|
25
|
-
|
|
26
25
|
close_delim_end_index = get_close_delim_end_index(
|
|
27
26
|
text, open_delim_start_index, open_delim, close_delim
|
|
28
27
|
)
|
|
@@ -53,7 +52,6 @@ def gobble_around_delim(
|
|
|
53
52
|
Returns:
|
|
54
53
|
Substring spanning from opening tag start to closing tag end.
|
|
55
54
|
"""
|
|
56
|
-
|
|
57
55
|
close_delim_end_index = get_close_delim_end_index(
|
|
58
56
|
text, open_delim_start_index, open_delim, close_delim
|
|
59
57
|
)
|
|
@@ -86,7 +84,6 @@ def get_close_delim_end_index(
|
|
|
86
84
|
matching closing tag cannot be found.
|
|
87
85
|
RuntimeError: If parser enters an unexpected state.
|
|
88
86
|
"""
|
|
89
|
-
|
|
90
87
|
open_delim_counter = 1
|
|
91
88
|
close_delim_counter = 0
|
|
92
89
|
|
|
@@ -109,7 +106,7 @@ def get_close_delim_end_index(
|
|
|
109
106
|
if not close_delim_match:
|
|
110
107
|
error_line = get_error_line(text, index - 1)
|
|
111
108
|
raise SyntaxError(
|
|
112
|
-
"Failed to find
|
|
109
|
+
"Failed to find a closing pair for delimiter."
|
|
113
110
|
+ "\n\n"
|
|
114
111
|
+ f"{error_line[0]}: {error_line[1]}"
|
|
115
112
|
)
|
|
@@ -19,7 +19,6 @@ def main() -> None:
|
|
|
19
19
|
from CLI arguments, setting default fallback paths when necessary,
|
|
20
20
|
and invokes the build and preview pipeline.
|
|
21
21
|
"""
|
|
22
|
-
|
|
23
22
|
parser = argparse.ArgumentParser(
|
|
24
23
|
prog="bloops",
|
|
25
24
|
description="An AoPS-like BBCode to HTML transpiler written in Python,\
|
|
@@ -32,17 +32,17 @@ def validate_bbcode(
|
|
|
32
32
|
|
|
33
33
|
Args:
|
|
34
34
|
text: Raw BBCode input string.
|
|
35
|
-
bbcode_tags:
|
|
36
|
-
and permitted
|
|
35
|
+
bbcode_tags: Mapping of tag names to their opening pattern,
|
|
36
|
+
closing pattern and permitted arguments. See `BBCODE_TAGS`.
|
|
37
37
|
|
|
38
38
|
Returns:
|
|
39
39
|
A dictionary mapping diagram labels to their starting index.
|
|
40
40
|
|
|
41
41
|
Raises:
|
|
42
|
+
SyntaxError: If a tag has no matching closing tag.
|
|
42
43
|
ValueError: If an invalid argument is supplied or duplicate
|
|
43
44
|
diagram labels are encountered.
|
|
44
45
|
"""
|
|
45
|
-
|
|
46
46
|
label_dict: dict[str, int] = {}
|
|
47
47
|
for tag, tag_tuple in bbcode_tags.items():
|
|
48
48
|
open_delim = tag_tuple[0]
|
|
@@ -92,11 +92,14 @@ def compile_asy_diagrams(
|
|
|
92
92
|
text: Entire input text containing BBCode and Asymptote code.
|
|
93
93
|
in_dir: Source directory containing the build cache folder.
|
|
94
94
|
out_dir: Target directory where compiled SVG images are stored.
|
|
95
|
+
bbcode_tags: Mapping of tag names to their opening pattern,
|
|
96
|
+
closing pattern and permitted arguments. See `BBCODE_TAGS`.
|
|
95
97
|
|
|
96
98
|
Raises:
|
|
99
|
+
FileNotFoundError: If `build/cache.json` does not exist in
|
|
100
|
+
`in_dir`, or the `asy` executable is not installed.
|
|
97
101
|
ValueError: If Asymptote compilation fails.
|
|
98
102
|
"""
|
|
99
|
-
|
|
100
103
|
build_dir = in_dir / "build/"
|
|
101
104
|
asy_cache_file = build_dir / "cache.json"
|
|
102
105
|
|
|
@@ -168,7 +171,6 @@ def _validate_args(
|
|
|
168
171
|
ValueError: If unknown attributes or missing required parameters
|
|
169
172
|
are encountered, or if attribute values are invalid.
|
|
170
173
|
"""
|
|
171
|
-
|
|
172
174
|
tag_and_args = get_tag_and_args(text, open_delim_start_index, open_delim)
|
|
173
175
|
tag, args = tag_and_args
|
|
174
176
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"""Definitions of the BBCode tags supported by bloops."""
|
|
2
|
+
|
|
1
3
|
import re
|
|
2
4
|
|
|
3
5
|
BBCODE_TAGS: dict[str, tuple[re.Pattern[str], re.Pattern[str], list[str]]] = {
|
|
@@ -107,3 +109,14 @@ BBCODE_TAGS: dict[str, tuple[re.Pattern[str], re.Pattern[str], list[str]]] = {
|
|
|
107
109
|
"h5": (re.compile(r"\[(h5)\]"), re.compile(r"\[/h5\]"), []),
|
|
108
110
|
"h6": (re.compile(r"\[(h6)\]"), re.compile(r"\[/h6\]"), []),
|
|
109
111
|
}
|
|
112
|
+
"""Mapping of each tag name to `(open_pattern, close_pattern, valid_args)`.
|
|
113
|
+
|
|
114
|
+
- `open_pattern` matches the opening tag. Group 1 captures the tag name
|
|
115
|
+
and, for tags that take arguments, group 2 captures the raw argument
|
|
116
|
+
string.
|
|
117
|
+
- `close_pattern` matches the closing tag.
|
|
118
|
+
- `valid_args` lists the argument names the tag accepts, and is empty
|
|
119
|
+
for tags without arguments.
|
|
120
|
+
|
|
121
|
+
Tags are processed in the order they appear here.
|
|
122
|
+
"""
|
|
@@ -35,7 +35,7 @@ asdf [/asy]"""
|
|
|
35
35
|
text, 11, BBCODE_TAGS["asy"][0], BBCODE_TAGS["asy"][1]
|
|
36
36
|
)
|
|
37
37
|
assert context.type is SyntaxError
|
|
38
|
-
assert "Failed to find
|
|
38
|
+
assert "Failed to find a closing pair for delimiter." in str(
|
|
39
39
|
context.value
|
|
40
40
|
)
|
|
41
41
|
assert "4:" in str(context.value)
|
|
@@ -200,7 +200,7 @@ lorem [asy src=/home/bubu/meow.png label=hello]some random stuff
|
|
|
200
200
|
pathlib.Path("./build/"),
|
|
201
201
|
)
|
|
202
202
|
assert context.type is SyntaxError
|
|
203
|
-
assert "Failed to find
|
|
203
|
+
assert "Failed to find a closing pair for delimiter." in str(
|
|
204
204
|
context.value
|
|
205
205
|
)
|
|
206
206
|
assert "39:" in str(context.value)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|