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.
Files changed (36) hide show
  1. {bloops-0.2.0 → bloops-0.2.1}/PKG-INFO +21 -9
  2. {bloops-0.2.0 → bloops-0.2.1}/README.md +9 -8
  3. {bloops-0.2.0 → bloops-0.2.1}/docs/api.md +22 -3
  4. {bloops-0.2.0 → bloops-0.2.1}/pyproject.toml +17 -1
  5. bloops-0.2.1/src/bloops/__about__.py +5 -0
  6. bloops-0.2.1/src/bloops/__init__.py +6 -0
  7. bloops-0.2.1/src/bloops/__main__.py +6 -0
  8. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/_build_and_preview.py +8 -11
  9. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/_helper.py +0 -2
  10. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/bloopser.py +5 -3
  11. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/bracer.py +1 -4
  12. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/cli.py +0 -1
  13. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/validator.py +7 -5
  14. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/vars.py +13 -0
  15. {bloops-0.2.0 → bloops-0.2.1}/tests/test_bracer.py +1 -1
  16. {bloops-0.2.0 → bloops-0.2.1}/tests/test_validator.py +1 -1
  17. bloops-0.2.0/src/bloops/__about__.py +0 -3
  18. bloops-0.2.0/src/bloops/__main__.py +0 -4
  19. {bloops-0.2.0 → bloops-0.2.1}/.gitignore +0 -0
  20. {bloops-0.2.0 → bloops-0.2.1}/LICENSE +0 -0
  21. {bloops-0.2.0 → bloops-0.2.1}/example/content.bbcode +0 -0
  22. {bloops-0.2.0 → bloops-0.2.1}/example/index.html +0 -0
  23. /bloops-0.2.0/src/bloops/__init__.py → /bloops-0.2.1/src/bloops/py.typed +0 -0
  24. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/error_template.html +0 -0
  25. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/index.html +0 -0
  26. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/script.js +0 -0
  27. {bloops-0.2.0 → bloops-0.2.1}/src/bloops/static/style.css +0 -0
  28. /bloops-0.2.0/tests/test_asy_generatation.py → /bloops-0.2.1/tests/test_asy_generation.py +0 -0
  29. {bloops-0.2.0 → bloops-0.2.1}/tests/test_asy_tag.py +0 -0
  30. {bloops-0.2.0 → bloops-0.2.1}/tests/test_bloopser.py +0 -0
  31. {bloops-0.2.0 → bloops-0.2.1}/tests/test_img_tag.py +0 -0
  32. {bloops-0.2.0 → bloops-0.2.1}/tests/test_list_tag.py +0 -0
  33. {bloops-0.2.0 → bloops-0.2.1}/tests/test_math_boxes.py +0 -0
  34. {bloops-0.2.0 → bloops-0.2.1}/tests/test_remaining_tags.py +0 -0
  35. {bloops-0.2.0 → bloops-0.2.1}/tests/test_simple_tags.py +0 -0
  36. {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.0
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" style="width: 90%; height: auto;">
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" style="height: 28px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; margin: 6px 0;">
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" style="height: 28px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; margin: 6px 0;">
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" style="height: 28px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; margin: 6px 0;">
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
- | `-v` | `--version` | Show the version of `bloops`. |
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 | Mandatory | Description |
199
- | ------- | :-------: | ---------------------------------------- |
200
- | `color` | YES | Color code in hex (with the leading \#). |
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">&uarr; 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" style="width: 90%; height: auto;">
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" style="height: 28px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; margin: 6px 0;">
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" style="height: 28px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; margin: 6px 0;">
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" style="height: 28px; display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 4px; margin: 6px 0;">
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
- | `-v` | `--version` | Show the version of `bloops`. |
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 | Mandatory | Description |
177
- | ------- | :-------: | ---------------------------------------- |
178
- | `color` | YES | Color code in hex (with the leading \#). |
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">&uarr; 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: List of tag configurations and rule definitions.
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: List of tag configurations, matching patterns,
84
- and permitted argument lists.
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,5 @@
1
+ """Version, author and license metadata for bloops."""
2
+
3
+ __version__ = "0.2.1"
4
+ __author__ = "Bubu-Droid"
5
+ __license__ = "MIT"
@@ -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
+ """
@@ -0,0 +1,6 @@
1
+ """Run the bloops command-line interface with `python -m bloops`."""
2
+
3
+ from bloops.cli import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -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: List of tag configurations and rule definitions.
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 an opening pair for delimiter."
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: List of tag configurations, matching patterns,
36
- and permitted argument lists.
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 an opening pair for delimiter." in str(
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 an opening pair for delimiter." in str(
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)
@@ -1,3 +0,0 @@
1
- __version__ = "0.2.0"
2
- __author__ = "Bubu-Droid"
3
- __license__ = "MIT"
@@ -1,4 +0,0 @@
1
- from bloops.cli import main
2
-
3
- if __name__ == "__main__":
4
- main()
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