pymdownx-mahjong 1.1.0__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pymdownx_mahjong/__init__.py +3 -2
- pymdownx_mahjong/extension.py +16 -8
- pymdownx_mahjong/inline.py +11 -3
- pymdownx_mahjong/renderer.py +22 -12
- pymdownx_mahjong/superfences.py +41 -3
- {pymdownx_mahjong-1.1.0.dist-info → pymdownx_mahjong-1.2.0.dist-info}/METADATA +3 -3
- {pymdownx_mahjong-1.1.0.dist-info → pymdownx_mahjong-1.2.0.dist-info}/RECORD +10 -10
- {pymdownx_mahjong-1.1.0.dist-info → pymdownx_mahjong-1.2.0.dist-info}/WHEEL +0 -0
- {pymdownx_mahjong-1.1.0.dist-info → pymdownx_mahjong-1.2.0.dist-info}/entry_points.txt +0 -0
- {pymdownx_mahjong-1.1.0.dist-info → pymdownx_mahjong-1.2.0.dist-info}/licenses/LICENSE +0 -0
pymdownx_mahjong/__init__.py
CHANGED
|
@@ -4,7 +4,7 @@ from .extension import MahjongExtension, makeExtension
|
|
|
4
4
|
from .inline import INLINE_TILE_PATTERN, MahjongInlineProcessor
|
|
5
5
|
from .parser import Hand, MahjongParser, Meld, Tile
|
|
6
6
|
from .renderer import MahjongRenderer
|
|
7
|
-
from .superfences import superfences_formatter, superfences_validator
|
|
7
|
+
from .superfences import configure_superfences, superfences_formatter, superfences_validator
|
|
8
8
|
|
|
9
9
|
__all__ = [
|
|
10
10
|
"MahjongExtension",
|
|
@@ -18,6 +18,7 @@ __all__ = [
|
|
|
18
18
|
"Hand",
|
|
19
19
|
"superfences_formatter",
|
|
20
20
|
"superfences_validator",
|
|
21
|
+
"configure_superfences",
|
|
21
22
|
]
|
|
22
23
|
|
|
23
|
-
__version__ = "1.
|
|
24
|
+
__version__ = "1.2.0"
|
pymdownx_mahjong/extension.py
CHANGED
|
@@ -19,6 +19,15 @@ if TYPE_CHECKING:
|
|
|
19
19
|
from markdown.blockparser import BlockParser
|
|
20
20
|
|
|
21
21
|
|
|
22
|
+
def _to_bool(value: Any) -> bool:
|
|
23
|
+
"""Convert a value to boolean, handling string 'true'/'false'."""
|
|
24
|
+
if isinstance(value, bool):
|
|
25
|
+
return value
|
|
26
|
+
if isinstance(value, str):
|
|
27
|
+
return value.lower() in ("true", "1", "yes")
|
|
28
|
+
return bool(value)
|
|
29
|
+
|
|
30
|
+
|
|
22
31
|
class MahjongBlockProcessor(BlockProcessor):
|
|
23
32
|
"""Block processor that handles ```mahjong fenced code blocks.
|
|
24
33
|
|
|
@@ -43,10 +52,9 @@ class MahjongBlockProcessor(BlockProcessor):
|
|
|
43
52
|
self.mj_parser = MahjongParser()
|
|
44
53
|
self.renderer = MahjongRenderer(
|
|
45
54
|
theme=config.get("theme", "light"),
|
|
46
|
-
|
|
47
|
-
show_labels=config.get("show_labels", True),
|
|
48
|
-
inline_svg=config.get("inline_svg", True),
|
|
55
|
+
inline_svg=_to_bool(config.get("inline_svg", True)),
|
|
49
56
|
assets_path=config.get("assets_path"),
|
|
57
|
+
closed_kan_style=config.get("closed_kan_style", "outer"),
|
|
50
58
|
)
|
|
51
59
|
|
|
52
60
|
def test(self, parent: etree.Element, block: str) -> bool:
|
|
@@ -158,13 +166,13 @@ class MahjongExtension(markdown.Extension):
|
|
|
158
166
|
**kwargs: Configuration options
|
|
159
167
|
"""
|
|
160
168
|
# Define configuration options with defaults
|
|
169
|
+
# Note: Use strings for boolean defaults for YAML compatibility
|
|
161
170
|
self.config = {
|
|
162
171
|
"theme": ["auto", "Color theme: 'light', 'dark', or 'auto'"],
|
|
163
|
-
"
|
|
164
|
-
"show_labels": [True, "Show tile names as title attributes"],
|
|
165
|
-
"inline_svg": [True, "Inline SVG content vs img tags"],
|
|
172
|
+
"inline_svg": ["true", "Inline SVG content vs img tags"],
|
|
166
173
|
"assets_path": ["", "Custom path to SVG assets"],
|
|
167
|
-
"enable_inline": [
|
|
174
|
+
"enable_inline": ["true", "Enable inline tile syntax (:1m:)"],
|
|
175
|
+
"closed_kan_style": ["outer", "Closed kan style: 'outer' or 'inner'"],
|
|
168
176
|
}
|
|
169
177
|
super().__init__(**kwargs)
|
|
170
178
|
|
|
@@ -184,7 +192,7 @@ class MahjongExtension(markdown.Extension):
|
|
|
184
192
|
|
|
185
193
|
# Register inline processor if enabled
|
|
186
194
|
# Priority 76 to run before pymdownx.emoji (which uses 75)
|
|
187
|
-
if config.get("enable_inline", True):
|
|
195
|
+
if _to_bool(config.get("enable_inline", True)):
|
|
188
196
|
inline_processor = MahjongInlineProcessor(INLINE_TILE_PATTERN, md, config)
|
|
189
197
|
md.inlinePatterns.register(inline_processor, "mahjong_inline", 76)
|
|
190
198
|
|
pymdownx_mahjong/inline.py
CHANGED
|
@@ -20,6 +20,15 @@ if TYPE_CHECKING:
|
|
|
20
20
|
INLINE_TILE_PATTERN: Final[str] = r":([0-9]+[mpsz])+:"
|
|
21
21
|
|
|
22
22
|
|
|
23
|
+
def _to_bool(value: Any) -> bool:
|
|
24
|
+
"""Convert a value to boolean, handling string 'true'/'false'."""
|
|
25
|
+
if isinstance(value, bool):
|
|
26
|
+
return value
|
|
27
|
+
if isinstance(value, str):
|
|
28
|
+
return value.lower() in ("true", "1", "yes")
|
|
29
|
+
return bool(value)
|
|
30
|
+
|
|
31
|
+
|
|
23
32
|
class MahjongInlineProcessor(InlineProcessor):
|
|
24
33
|
"""Inline processor for mahjong tile notation.
|
|
25
34
|
|
|
@@ -40,10 +49,9 @@ class MahjongInlineProcessor(InlineProcessor):
|
|
|
40
49
|
self.parser = MahjongParser()
|
|
41
50
|
self.renderer = MahjongRenderer(
|
|
42
51
|
theme=config.get("theme", "auto"),
|
|
43
|
-
|
|
44
|
-
show_labels=config.get("show_labels", True),
|
|
45
|
-
inline_svg=config.get("inline_svg", True),
|
|
52
|
+
inline_svg=_to_bool(config.get("inline_svg", True)),
|
|
46
53
|
assets_path=config.get("assets_path"),
|
|
54
|
+
css_class="mahjong-inline",
|
|
47
55
|
)
|
|
48
56
|
|
|
49
57
|
def handleMatch(self, m: re.Match, data: str) -> tuple[str | None, int | None, int | None]:
|
pymdownx_mahjong/renderer.py
CHANGED
|
@@ -50,9 +50,8 @@ class MahjongRenderer:
|
|
|
50
50
|
|
|
51
51
|
Configuration options:
|
|
52
52
|
theme: 'light', 'dark', or 'auto'
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
inline_svg: Whether to inline SVG or use img tags
|
|
53
|
+
closed_kan_style: 'outer' (default) or 'inner'
|
|
54
|
+
inline_svg: Whether to inline SVG content (vs using img tags)
|
|
56
55
|
"""
|
|
57
56
|
|
|
58
57
|
DEFAULT_TILE_WIDTH = 45
|
|
@@ -63,19 +62,21 @@ class MahjongRenderer:
|
|
|
63
62
|
def __init__(
|
|
64
63
|
self,
|
|
65
64
|
theme: str = "light",
|
|
66
|
-
css_class: str = "mahjong-hand",
|
|
67
|
-
show_labels: bool = True,
|
|
68
65
|
inline_svg: bool = True,
|
|
69
66
|
assets_path: str | Path | None = None,
|
|
67
|
+
closed_kan_style: str = "outer",
|
|
68
|
+
css_class: str = "mahjong-hand",
|
|
70
69
|
) -> None:
|
|
71
70
|
"""Initialize the renderer.
|
|
72
71
|
|
|
73
72
|
Args:
|
|
74
73
|
theme: Color theme ('light', 'dark', or 'auto')
|
|
75
|
-
css_class: CSS class for the container element
|
|
76
|
-
show_labels: Show tile names as title attributes
|
|
77
74
|
inline_svg: Inline SVG content vs img tags
|
|
78
75
|
assets_path: Custom path to SVG assets
|
|
76
|
+
closed_kan_style: Style for closed kan back tiles:
|
|
77
|
+
'outer' (default) - back tiles on edges (back, front, front, back)
|
|
78
|
+
'inner' - back tiles in middle (front, back, back, front)
|
|
79
|
+
css_class: CSS class for container (internal use)
|
|
79
80
|
"""
|
|
80
81
|
self.theme = theme
|
|
81
82
|
self.tile_width = self.DEFAULT_TILE_WIDTH
|
|
@@ -83,9 +84,9 @@ class MahjongRenderer:
|
|
|
83
84
|
self.tile_gap = self.DEFAULT_TILE_GAP
|
|
84
85
|
self.meld_gap = self.DEFAULT_MELD_GAP
|
|
85
86
|
self.css_class = css_class
|
|
86
|
-
self.show_labels = show_labels
|
|
87
87
|
self.inline_svg = inline_svg
|
|
88
88
|
self.assets_path = Path(assets_path) if assets_path else None
|
|
89
|
+
self.closed_kan_style = closed_kan_style
|
|
89
90
|
self._svg_id_counter = 0
|
|
90
91
|
|
|
91
92
|
def render(
|
|
@@ -209,7 +210,7 @@ class MahjongRenderer:
|
|
|
209
210
|
classes.append("mahjong-tile-added")
|
|
210
211
|
|
|
211
212
|
class_str = " ".join(classes)
|
|
212
|
-
title_attr = f' title="{info.display_name}"'
|
|
213
|
+
title_attr = f' title="{info.display_name}"'
|
|
213
214
|
|
|
214
215
|
if self.inline_svg:
|
|
215
216
|
svg_content = self._get_themed_svg_content(info)
|
|
@@ -271,9 +272,18 @@ class MahjongRenderer:
|
|
|
271
272
|
parts.append(self._render_tile(meld.tiles[2]))
|
|
272
273
|
else:
|
|
273
274
|
for i, tile in enumerate(meld.tiles):
|
|
274
|
-
# For closed kan, show back tiles
|
|
275
|
-
if meld.meld_type == MeldType.KAN_CLOSED
|
|
276
|
-
|
|
275
|
+
# For closed kan, show back tiles based on style setting
|
|
276
|
+
if meld.meld_type == MeldType.KAN_CLOSED:
|
|
277
|
+
if self.closed_kan_style == "inner":
|
|
278
|
+
# 'inner': back tiles in middle: front, back, back, front
|
|
279
|
+
is_back = i in (1, 2)
|
|
280
|
+
else:
|
|
281
|
+
# Default 'outer': back tiles on edges: back, front, front, back
|
|
282
|
+
is_back = i in (0, 3)
|
|
283
|
+
if is_back:
|
|
284
|
+
parts.append(self._render_back_tile())
|
|
285
|
+
else:
|
|
286
|
+
parts.append(self._render_tile(tile))
|
|
277
287
|
else:
|
|
278
288
|
parts.append(self._render_tile(tile))
|
|
279
289
|
|
pymdownx_mahjong/superfences.py
CHANGED
|
@@ -17,20 +17,32 @@ class _SuperfencesState:
|
|
|
17
17
|
"""Encapsulates global state for superfences integration.
|
|
18
18
|
|
|
19
19
|
Uses lazy initialization to create parser/renderer on first use.
|
|
20
|
+
Allows configuration via configure() method.
|
|
20
21
|
"""
|
|
21
22
|
|
|
22
23
|
def __init__(self) -> None:
|
|
23
24
|
self._renderer: MahjongRenderer | None = None
|
|
24
25
|
self._parser: MahjongParser | None = None
|
|
26
|
+
self._config: dict[str, Any] = {}
|
|
27
|
+
|
|
28
|
+
def configure(self, **kwargs: Any) -> None:
|
|
29
|
+
"""Configure the superfences state.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
**kwargs: Configuration options (theme, closed_kan_style, etc.)
|
|
33
|
+
"""
|
|
34
|
+
self._config.update(kwargs)
|
|
35
|
+
# Reset renderer to apply new config
|
|
36
|
+
self._renderer = None
|
|
25
37
|
|
|
26
38
|
@property
|
|
27
39
|
def renderer(self) -> MahjongRenderer:
|
|
28
40
|
"""Get or create the renderer instance."""
|
|
29
41
|
if self._renderer is None:
|
|
30
42
|
self._renderer = MahjongRenderer(
|
|
31
|
-
theme="auto",
|
|
32
|
-
|
|
33
|
-
|
|
43
|
+
theme=self._config.get("theme", "auto"),
|
|
44
|
+
inline_svg=self._config.get("inline_svg", True),
|
|
45
|
+
closed_kan_style=self._config.get("closed_kan_style", "outer"),
|
|
34
46
|
)
|
|
35
47
|
return self._renderer
|
|
36
48
|
|
|
@@ -46,6 +58,24 @@ class _SuperfencesState:
|
|
|
46
58
|
_state = _SuperfencesState()
|
|
47
59
|
|
|
48
60
|
|
|
61
|
+
def configure_superfences(**kwargs: Any) -> None:
|
|
62
|
+
"""Configure the superfences integration.
|
|
63
|
+
|
|
64
|
+
Call this before using superfences to set options like closed_kan_style.
|
|
65
|
+
|
|
66
|
+
Example:
|
|
67
|
+
from pymdownx_mahjong import configure_superfences
|
|
68
|
+
configure_superfences(closed_kan_style='outer')
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
**kwargs: Configuration options
|
|
72
|
+
- theme: 'light', 'dark', or 'auto'
|
|
73
|
+
- closed_kan_style: 'outer' or 'inner'
|
|
74
|
+
- inline_svg: bool
|
|
75
|
+
"""
|
|
76
|
+
_state.configure(**kwargs)
|
|
77
|
+
|
|
78
|
+
|
|
49
79
|
def superfences_validator(
|
|
50
80
|
language: str,
|
|
51
81
|
inputs: dict[str, str],
|
|
@@ -65,6 +95,14 @@ def superfences_validator(
|
|
|
65
95
|
Returns:
|
|
66
96
|
True if this is a valid mahjong fence
|
|
67
97
|
"""
|
|
98
|
+
# Try to get config from the markdown instance's extension
|
|
99
|
+
if hasattr(md, 'registeredExtensions'):
|
|
100
|
+
for ext in md.registeredExtensions:
|
|
101
|
+
if hasattr(ext, 'config') and 'closed_kan_style' in ext.config:
|
|
102
|
+
config = {key: ext.getConfig(key) for key in ext.config}
|
|
103
|
+
_state.configure(**config)
|
|
104
|
+
break
|
|
105
|
+
|
|
68
106
|
return language == "mahjong"
|
|
69
107
|
|
|
70
108
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pymdownx-mahjong
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Python Markdown extension to render and stylize Mahjong tiles.
|
|
5
5
|
Project-URL: Homepage, https://github.com/tylernguyen/pymdownx-mahjong
|
|
6
|
-
Project-URL: Documentation, https://github.
|
|
6
|
+
Project-URL: Documentation, https://tylernguyen.github.io/pymdownx-mahjong/
|
|
7
7
|
Project-URL: Repository, https://github.com/tylernguyen/pymdownx-mahjong
|
|
8
8
|
Project-URL: Issues, https://github.com/tylernguyen/pymdownx-mahjong/issues
|
|
9
9
|
Author: Tyler Nguyen
|
|
@@ -41,7 +41,7 @@ Description-Content-Type: text/markdown
|
|
|
41
41
|
|
|
42
42
|
[Python Markdown](https://python-markdown.github.io) extension to render and stylize Mahjong tiles. Designed for use with [MkDocs](https://github.com/mkdocs/mkdocs) and [Zensical](https://github.com/zensical/zensical).
|
|
43
43
|
|
|
44
|
-
## Documentation
|
|
44
|
+
## Demo and Documentation
|
|
45
45
|
|
|
46
46
|
Demo and documentation can be found at [https://tylernguyen.github.io/pymdownx-mahjong/](https://tylernguyen.github.io/pymdownx-mahjong/).
|
|
47
47
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
pymdownx_mahjong/__init__.py,sha256=
|
|
2
|
-
pymdownx_mahjong/extension.py,sha256=
|
|
3
|
-
pymdownx_mahjong/inline.py,sha256=
|
|
1
|
+
pymdownx_mahjong/__init__.py,sha256=TTW8ssjfwCA9CCZLi2_ISzBMdiiIC_0ukY2yYGMDbvc,696
|
|
2
|
+
pymdownx_mahjong/extension.py,sha256=HC-S_EUtSOyHHwJ72aDDsfyUGqxVUIwwycKpeap9YqY,6939
|
|
3
|
+
pymdownx_mahjong/inline.py,sha256=Q0_wxP4mR3DOOa3pH4d8EDmffOc9VV0eiyPIKFC5P50,2667
|
|
4
4
|
pymdownx_mahjong/parser.py,sha256=I8wDlZO6oPMhTCqC0NFmsZJOQZCCCXyc78mk3vmmwcQ,12396
|
|
5
|
-
pymdownx_mahjong/renderer.py,sha256=
|
|
6
|
-
pymdownx_mahjong/superfences.py,sha256=
|
|
5
|
+
pymdownx_mahjong/renderer.py,sha256=wl_wJSntg-7YGIfD6aVgdI0rokOpr4Qz2oFVWG49BQQ,17522
|
|
6
|
+
pymdownx_mahjong/superfences.py,sha256=7rsTfhSlYZE25uwEJTfzmEDWUSblqvX0jMGnstwh92c,4493
|
|
7
7
|
pymdownx_mahjong/tiles.py,sha256=ltA1xJeS9fVcZQyUwaIjyl1mHEZ0Kr_QUKy1jhCapDM,2583
|
|
8
8
|
pymdownx_mahjong/utils.py,sha256=aHKX4wDCGM_rvaOwFIbd9qVJHpzzUjXWMviLxdwZrdo,2637
|
|
9
9
|
pymdownx_mahjong/assets/README.md,sha256=HDNhZZlt8ffTER1fVNcTayUnFqOmB3tXoocT8iZgCz0,179
|
|
@@ -88,8 +88,8 @@ pymdownx_mahjong/assets/light/back.svg,sha256=HPAJfchslm_1uZQzpY8FUNF2s8hmbARGkh
|
|
|
88
88
|
pymdownx_mahjong/assets/light/blank.svg,sha256=uKGioQLfrCZsSbMr66iDXv4w9lKHEqGym1l098-q5DM,8499
|
|
89
89
|
pymdownx_mahjong/assets/light/front.svg,sha256=63TB5953_-10TDRd7K_kJnHoqt-6wd05MEGV2AcNsks,11906
|
|
90
90
|
pymdownx_mahjong/css/mahjong.css,sha256=OpO9RR-UPFAbPF6Q8Wuz0Ak_Pg9rOrOsMAtnP0oj5LE,9307
|
|
91
|
-
pymdownx_mahjong-1.
|
|
92
|
-
pymdownx_mahjong-1.
|
|
93
|
-
pymdownx_mahjong-1.
|
|
94
|
-
pymdownx_mahjong-1.
|
|
95
|
-
pymdownx_mahjong-1.
|
|
91
|
+
pymdownx_mahjong-1.2.0.dist-info/METADATA,sha256=S4NGo2aiURkBQXW-Z_oll-1cMjq4W8grUkzjLe1SP6Y,2222
|
|
92
|
+
pymdownx_mahjong-1.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
93
|
+
pymdownx_mahjong-1.2.0.dist-info/entry_points.txt,sha256=dEty6XpsYCWl45PeRYHiH9ORxwSZA64LQU8gWF1CuyU,72
|
|
94
|
+
pymdownx_mahjong-1.2.0.dist-info/licenses/LICENSE,sha256=Mnpx_G3eVz7AX5uTHGPaZWHJYiJYu4Y2_l01PsksHdg,19921
|
|
95
|
+
pymdownx_mahjong-1.2.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|