md2mrkdwn 0.4.2__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.
- md2mrkdwn-0.4.2/.gitignore +77 -0
- md2mrkdwn-0.4.2/LICENSE +21 -0
- md2mrkdwn-0.4.2/PKG-INFO +419 -0
- md2mrkdwn-0.4.2/README.md +395 -0
- md2mrkdwn-0.4.2/pyproject.toml +77 -0
- md2mrkdwn-0.4.2/src/md2mrkdwn/__init__.py +23 -0
- md2mrkdwn-0.4.2/src/md2mrkdwn/converter.py +615 -0
- md2mrkdwn-0.4.2/src/md2mrkdwn/patterns.py +41 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
.idea
|
|
6
|
+
media
|
|
7
|
+
|
|
8
|
+
# C extensions
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# Distribution / packaging
|
|
12
|
+
.Python
|
|
13
|
+
env/
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
configs/local_settings.py
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.coverage
|
|
43
|
+
.coverage.*
|
|
44
|
+
.cache
|
|
45
|
+
nosetests.xml
|
|
46
|
+
coverage.xml
|
|
47
|
+
*,cover
|
|
48
|
+
.hypothesis/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.pot
|
|
52
|
+
|
|
53
|
+
# Django stuff:
|
|
54
|
+
*.log
|
|
55
|
+
|
|
56
|
+
# Sphinx documentation
|
|
57
|
+
docs/_build/
|
|
58
|
+
|
|
59
|
+
# PyBuilder
|
|
60
|
+
target/
|
|
61
|
+
|
|
62
|
+
#Ipython Notebook
|
|
63
|
+
.ipynb_checkpoints
|
|
64
|
+
venv/*
|
|
65
|
+
env/*
|
|
66
|
+
.venv/*
|
|
67
|
+
.env/*
|
|
68
|
+
|
|
69
|
+
# Idea modules
|
|
70
|
+
*.iml
|
|
71
|
+
|
|
72
|
+
.ruff_cache
|
|
73
|
+
.pytest_cache
|
|
74
|
+
.mypy_cache
|
|
75
|
+
|
|
76
|
+
.claude/
|
|
77
|
+
CLAUDE.md
|
md2mrkdwn-0.4.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Dave Allie
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
md2mrkdwn-0.4.2/PKG-INFO
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: md2mrkdwn
|
|
3
|
+
Version: 0.4.2
|
|
4
|
+
Summary: Convert Markdown to Slack mrkdwn format
|
|
5
|
+
Project-URL: Homepage, https://github.com/bigbag/md2mrkdwn
|
|
6
|
+
Project-URL: Repository, https://github.com/bigbag/md2mrkdwn
|
|
7
|
+
Project-URL: Issues, https://github.com/bigbag/md2mrkdwn/issues
|
|
8
|
+
Author-email: Pavel Liashkov <pavel.liashkov@protonamil.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: converter,formatting,markdown,mrkdwn,slack
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Communications :: Chat
|
|
21
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# md2mrkdwn
|
|
26
|
+
|
|
27
|
+
[](https://github.com/bigbag/md2mrkdwn/actions?query=workflow%3ACI)
|
|
28
|
+
[](https://pypi.python.org/pypi/md2mrkdwn)
|
|
29
|
+
[](https://pypistats.org/packages/md2mrkdwn)
|
|
30
|
+
[](https://github.com/bigbag/md2mrkdwn)
|
|
31
|
+
[](https://github.com/bigbag/md2mrkdwn/blob/master/LICENSE)
|
|
32
|
+
|
|
33
|
+
Pure Python library for converting Markdown to Slack's mrkdwn format. Zero dependencies, comprehensive formatting support, and proper handling of edge cases.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- **Zero dependencies** - Pure Python implementation with no external packages required
|
|
38
|
+
- **Comprehensive formatting** - Supports bold, italic, strikethrough, links, images, lists, and more
|
|
39
|
+
- **Configurable** - Customize symbols, formats, and enable/disable specific conversions
|
|
40
|
+
- **Code block handling** - Preserves content inside code blocks without conversion
|
|
41
|
+
- **Table support** - Wraps markdown tables in code blocks for Slack display
|
|
42
|
+
- **Task lists** - Converts checkbox syntax to Unicode symbols (☐/☑)
|
|
43
|
+
- **Edge case handling** - Properly handles nested formatting and special characters
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from md2mrkdwn import convert
|
|
49
|
+
|
|
50
|
+
markdown = "**Hello** *World*! Check out [Slack](https://slack.com)"
|
|
51
|
+
mrkdwn = convert(markdown)
|
|
52
|
+
print(mrkdwn)
|
|
53
|
+
# Output: *Hello* _World_! Check out <https://slack.com|Slack>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
# Install with pip
|
|
60
|
+
pip install md2mrkdwn
|
|
61
|
+
|
|
62
|
+
# Or install with uv
|
|
63
|
+
uv add md2mrkdwn
|
|
64
|
+
|
|
65
|
+
# Or install with pipx (for CLI tools that use this library)
|
|
66
|
+
pipx install md2mrkdwn
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Usage
|
|
70
|
+
|
|
71
|
+
### Simple Function
|
|
72
|
+
|
|
73
|
+
The `convert()` function provides a simple interface for one-off conversions:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
from md2mrkdwn import convert
|
|
77
|
+
|
|
78
|
+
markdown = """
|
|
79
|
+
# Hello World
|
|
80
|
+
|
|
81
|
+
This is **bold** and *italic* text.
|
|
82
|
+
|
|
83
|
+
- Item 1
|
|
84
|
+
- Item 2
|
|
85
|
+
|
|
86
|
+
Check out [this link](https://example.com)!
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
mrkdwn = convert(markdown)
|
|
90
|
+
print(mrkdwn)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Output:
|
|
94
|
+
```
|
|
95
|
+
*Hello World*
|
|
96
|
+
|
|
97
|
+
This is *bold* and _italic_ text.
|
|
98
|
+
|
|
99
|
+
• Item 1
|
|
100
|
+
• Item 2
|
|
101
|
+
|
|
102
|
+
Check out <https://example.com|this link>!
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Class-based Usage
|
|
106
|
+
|
|
107
|
+
For multiple conversions, use the `MrkdwnConverter` class:
|
|
108
|
+
|
|
109
|
+
```python
|
|
110
|
+
from md2mrkdwn import MrkdwnConverter
|
|
111
|
+
|
|
112
|
+
converter = MrkdwnConverter()
|
|
113
|
+
|
|
114
|
+
# Convert multiple texts
|
|
115
|
+
text1 = converter.convert("**bold** and *italic*")
|
|
116
|
+
text2 = converter.convert("# Header\n\n- List item")
|
|
117
|
+
|
|
118
|
+
print(text1) # *bold* and _italic_
|
|
119
|
+
print(text2) # *Header*\n\n• List item
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Custom Configuration
|
|
123
|
+
|
|
124
|
+
Use `MrkdwnConfig` to customize conversion behavior:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from md2mrkdwn import convert, MrkdwnConfig, MrkdwnConverter
|
|
128
|
+
|
|
129
|
+
# Custom bullet character
|
|
130
|
+
config = MrkdwnConfig(bullet_char="-")
|
|
131
|
+
print(convert("- Item 1\n- Item 2", config=config))
|
|
132
|
+
# Output: - Item 1
|
|
133
|
+
# - Item 2
|
|
134
|
+
|
|
135
|
+
# Custom checkbox symbols
|
|
136
|
+
config = MrkdwnConfig(checkbox_checked="✓", checkbox_unchecked="○")
|
|
137
|
+
print(convert("- [x] Done\n- [ ] Todo", config=config))
|
|
138
|
+
# Output: • ✓ Done
|
|
139
|
+
# • ○ Todo
|
|
140
|
+
|
|
141
|
+
# Plain headers (no bold)
|
|
142
|
+
config = MrkdwnConfig(header_style="plain")
|
|
143
|
+
print(convert("# Title", config=config))
|
|
144
|
+
# Output: Title
|
|
145
|
+
|
|
146
|
+
# URL-only links (no link text)
|
|
147
|
+
config = MrkdwnConfig(link_format="url_only")
|
|
148
|
+
print(convert("[Click here](https://example.com)", config=config))
|
|
149
|
+
# Output: <https://example.com>
|
|
150
|
+
|
|
151
|
+
# Disable specific conversions
|
|
152
|
+
config = MrkdwnConfig(convert_bold=False, convert_italic=False)
|
|
153
|
+
print(convert("**bold** and *italic*", config=config))
|
|
154
|
+
# Output: **bold** and *italic*
|
|
155
|
+
|
|
156
|
+
# Reusable converter with config
|
|
157
|
+
converter = MrkdwnConverter(MrkdwnConfig(
|
|
158
|
+
bullet_char="→",
|
|
159
|
+
horizontal_rule_char="=",
|
|
160
|
+
horizontal_rule_length=20
|
|
161
|
+
))
|
|
162
|
+
print(converter.convert("- Item\n\n---"))
|
|
163
|
+
# Output: → Item
|
|
164
|
+
#
|
|
165
|
+
# ====================
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Configuration Options
|
|
169
|
+
|
|
170
|
+
| Option | Type | Default | Description |
|
|
171
|
+
|----------------------------|-------------|------------------------|-------------------------------------------|
|
|
172
|
+
| `bullet_char` | str | `•` | Character for unordered list items |
|
|
173
|
+
| `checkbox_checked` | str | `☑` | Symbol for checked task items |
|
|
174
|
+
| `checkbox_unchecked` | str | `☐` | Symbol for unchecked task items |
|
|
175
|
+
| `horizontal_rule_char` | str | `─` | Character for horizontal rules |
|
|
176
|
+
| `horizontal_rule_length` | int | `10` | Length of horizontal rules |
|
|
177
|
+
| `header_style` | HeaderStyle | `HeaderStyle.BOLD` | `BOLD`, `PLAIN`, or `PREFIX` |
|
|
178
|
+
| `link_format` | LinkFormat | `LinkFormat.SLACK` | `SLACK`, `URL_ONLY`, or `TEXT_ONLY` |
|
|
179
|
+
| `table_mode` | TableMode | `TableMode.CODE_BLOCK` | `CODE_BLOCK` or `PRESERVE` |
|
|
180
|
+
| `table_link_format` | LinkFormat | `LinkFormat.URL_ONLY` | Link format inside tables |
|
|
181
|
+
| `strip_table_emoji` | bool | `True` | Strip emoji shortcodes from tables |
|
|
182
|
+
| `convert_table_links` | bool | `True` | Enable/disable link conversion in tables |
|
|
183
|
+
| `convert_bold` | bool | `True` | Enable/disable bold conversion |
|
|
184
|
+
| `convert_italic` | bool | `True` | Enable/disable italic conversion |
|
|
185
|
+
| `convert_strikethrough` | bool | `True` | Enable/disable strikethrough conversion |
|
|
186
|
+
| `convert_links` | bool | `True` | Enable/disable link conversion |
|
|
187
|
+
| `convert_images` | bool | `True` | Enable/disable image conversion |
|
|
188
|
+
| `convert_lists` | bool | `True` | Enable/disable list conversion |
|
|
189
|
+
| `convert_task_lists` | bool | `True` | Enable/disable task list conversion |
|
|
190
|
+
| `convert_headers` | bool | `True` | Enable/disable header conversion |
|
|
191
|
+
| `convert_horizontal_rules` | bool | `True` | Enable/disable horizontal rule conversion |
|
|
192
|
+
| `convert_tables` | bool | `True` | Enable/disable table wrapping |
|
|
193
|
+
|
|
194
|
+
### Handling Tables
|
|
195
|
+
|
|
196
|
+
Markdown tables are automatically wrapped in code blocks since Slack doesn't support native table rendering:
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
from md2mrkdwn import convert
|
|
200
|
+
|
|
201
|
+
markdown = """
|
|
202
|
+
| Name | Age |
|
|
203
|
+
|------|-----|
|
|
204
|
+
| Alice | 30 |
|
|
205
|
+
| Bob | 25 |
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
print(convert(markdown))
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Output:
|
|
212
|
+
```
|
|
213
|
+
```
|
|
214
|
+
| Name | Age |
|
|
215
|
+
|------|-----|
|
|
216
|
+
| Alice | 30 |
|
|
217
|
+
| Bob | 25 |
|
|
218
|
+
```
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
#### Links in Tables
|
|
222
|
+
|
|
223
|
+
Links inside tables are converted to URL-only format by default (different from the global `link_format` setting):
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
from md2mrkdwn import convert, MrkdwnConfig, LinkFormat
|
|
227
|
+
|
|
228
|
+
markdown = """
|
|
229
|
+
| App | Link |
|
|
230
|
+
|-----|------|
|
|
231
|
+
| Example | [Visit](https://example.com) |
|
|
232
|
+
"""
|
|
233
|
+
|
|
234
|
+
# Default: URL only
|
|
235
|
+
print(convert(markdown))
|
|
236
|
+
# | App | Link |
|
|
237
|
+
# | Example | https://example.com |
|
|
238
|
+
|
|
239
|
+
# Slack format
|
|
240
|
+
config = MrkdwnConfig(table_link_format=LinkFormat.SLACK)
|
|
241
|
+
print(convert(markdown, config))
|
|
242
|
+
# | Example | <https://example.com|Visit> |
|
|
243
|
+
|
|
244
|
+
# Text only (link text, no URL)
|
|
245
|
+
config = MrkdwnConfig(table_link_format=LinkFormat.TEXT_ONLY)
|
|
246
|
+
print(convert(markdown, config))
|
|
247
|
+
# | Example | Visit |
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Conversion Reference
|
|
251
|
+
|
|
252
|
+
| Markdown | mrkdwn | Notes |
|
|
253
|
+
|----------------------------|--------------------|------------------------------|
|
|
254
|
+
| `**bold**` or `__bold__` | `*bold*` | Slack uses single asterisk |
|
|
255
|
+
| `*italic*` or `_italic_` | `_italic_` | Slack uses underscores |
|
|
256
|
+
| `***bold+italic***` | `*_text_*` | Combined formatting |
|
|
257
|
+
| `~~strikethrough~~` | `~text~` | Single tilde |
|
|
258
|
+
| `[text](url)` | `<url\|text>` | Slack link format |
|
|
259
|
+
| `` | `<url>` | Images become plain URLs |
|
|
260
|
+
| `# Header` (all levels) | `*Header*` | Bold (Slack has no headers) |
|
|
261
|
+
| `- item` / `* item` | `• item` | Bullet character (U+2022) |
|
|
262
|
+
| `1. item` | `1. item` | Preserved as-is |
|
|
263
|
+
| `- [ ] task` | `• ☐ task` | Unchecked checkbox (U+2610) |
|
|
264
|
+
| `- [x] task` | `• ☑ task` | Checked checkbox (U+2611) |
|
|
265
|
+
| `> quote` | `> quote` | Same syntax |
|
|
266
|
+
| `` `code` `` | `` `code` `` | Same syntax |
|
|
267
|
+
| ``` code block ``` | ``` code block ``` | Same syntax |
|
|
268
|
+
| `---` / `***` | `──────────` | Horizontal rule (U+2500) |
|
|
269
|
+
| Tables | Wrapped in ``` | Slack has no native tables |
|
|
270
|
+
|
|
271
|
+
## How It Works
|
|
272
|
+
|
|
273
|
+
### Conversion Pipeline
|
|
274
|
+
|
|
275
|
+
md2mrkdwn processes text through a multi-stage pipeline:
|
|
276
|
+
|
|
277
|
+
1. **Table extraction** - Tables are detected, validated, and replaced with placeholders
|
|
278
|
+
2. **Code block tracking** - Lines inside code blocks are skipped during conversion
|
|
279
|
+
3. **Pattern application** - Regex patterns convert formatting using placeholder protection
|
|
280
|
+
4. **Placeholder restoration** - Tables and temporary markers are replaced with final output
|
|
281
|
+
|
|
282
|
+
### Pattern Interference Prevention
|
|
283
|
+
|
|
284
|
+
A key challenge in markdown conversion is preventing patterns from interfering with each other. For example, converting `**bold**` to `*bold*` could then be matched by the italic pattern.
|
|
285
|
+
|
|
286
|
+
md2mrkdwn solves this using placeholder substitution:
|
|
287
|
+
1. Bold text is temporarily marked with null-byte placeholders
|
|
288
|
+
2. Italic patterns run without matching the placeholders
|
|
289
|
+
3. Placeholders are replaced with final mrkdwn characters
|
|
290
|
+
|
|
291
|
+
### Table Handling
|
|
292
|
+
|
|
293
|
+
Tables are detected using these criteria:
|
|
294
|
+
- Lines matching `|...|` pattern
|
|
295
|
+
- Second row contains separator cells (dashes with optional alignment colons)
|
|
296
|
+
- Header and separator have matching column counts
|
|
297
|
+
|
|
298
|
+
Valid tables are wrapped in triple-backtick code blocks for monospace display in Slack.
|
|
299
|
+
|
|
300
|
+
Column alignment accounts for Unicode character display width. Emoji like ⭐ render as 2 columns wide in monospace fonts but have a character length of 1. The converter pads columns based on display width to maintain proper alignment.
|
|
301
|
+
|
|
302
|
+
### Code Block Protection
|
|
303
|
+
|
|
304
|
+
Content inside code blocks (both fenced and inline) is protected from conversion:
|
|
305
|
+
- Fenced blocks: State machine tracks opening/closing ``` markers
|
|
306
|
+
- Inline code: Segments are extracted before conversion and restored after
|
|
307
|
+
|
|
308
|
+
## Development
|
|
309
|
+
|
|
310
|
+
### Setup
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
git clone https://github.com/bigbag/md2mrkdwn.git
|
|
314
|
+
cd md2mrkdwn
|
|
315
|
+
make install
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Commands
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
make install # Install all dependencies
|
|
322
|
+
make test # Run tests with coverage
|
|
323
|
+
make lint # Run linters (ruff + mypy)
|
|
324
|
+
make format # Format code with ruff
|
|
325
|
+
make clean # Clean cache and build files
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Running Tests
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
# Run all tests with coverage
|
|
332
|
+
uv run pytest --cov=md2mrkdwn --cov-report=term-missing
|
|
333
|
+
|
|
334
|
+
# Run specific test class
|
|
335
|
+
uv run pytest tests/test_converter.py::TestBasicFormatting -v
|
|
336
|
+
|
|
337
|
+
# Run with verbose output
|
|
338
|
+
uv run pytest -v
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Project Structure
|
|
342
|
+
|
|
343
|
+
```
|
|
344
|
+
md2mrkdwn/
|
|
345
|
+
├── src/
|
|
346
|
+
│ └── md2mrkdwn/
|
|
347
|
+
│ ├── __init__.py # Package exports
|
|
348
|
+
│ └── converter.py # MrkdwnConverter, MrkdwnConfig classes
|
|
349
|
+
├── tests/
|
|
350
|
+
│ ├── conftest.py # Pytest fixtures
|
|
351
|
+
│ ├── test_converter.py # Converter tests
|
|
352
|
+
│ └── test_config.py # Configuration tests
|
|
353
|
+
├── pyproject.toml # Project configuration
|
|
354
|
+
├── Makefile # Development commands
|
|
355
|
+
└── README.md
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## API Reference
|
|
359
|
+
|
|
360
|
+
### `convert(markdown: str, config: MrkdwnConfig | None = None) -> str`
|
|
361
|
+
|
|
362
|
+
Convert Markdown text to Slack mrkdwn format.
|
|
363
|
+
|
|
364
|
+
**Parameters:**
|
|
365
|
+
- `markdown` - Input text in Markdown format
|
|
366
|
+
- `config` - Optional configuration (uses defaults if not provided)
|
|
367
|
+
|
|
368
|
+
**Returns:**
|
|
369
|
+
- Text converted to Slack mrkdwn format
|
|
370
|
+
|
|
371
|
+
### `MrkdwnConverter`
|
|
372
|
+
|
|
373
|
+
Class for converting Markdown to mrkdwn.
|
|
374
|
+
|
|
375
|
+
**Constructor:**
|
|
376
|
+
- `MrkdwnConverter(config: MrkdwnConfig | None = None)`
|
|
377
|
+
|
|
378
|
+
**Methods:**
|
|
379
|
+
- `convert(markdown: str) -> str` - Convert Markdown text to mrkdwn
|
|
380
|
+
|
|
381
|
+
**Example:**
|
|
382
|
+
```python
|
|
383
|
+
converter = MrkdwnConverter()
|
|
384
|
+
result = converter.convert("**Hello** *World*")
|
|
385
|
+
|
|
386
|
+
# With custom config
|
|
387
|
+
config = MrkdwnConfig(bullet_char="-")
|
|
388
|
+
converter = MrkdwnConverter(config)
|
|
389
|
+
result = converter.convert("- Item")
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
### `MrkdwnConfig`
|
|
393
|
+
|
|
394
|
+
Immutable configuration dataclass for customizing conversion behavior.
|
|
395
|
+
|
|
396
|
+
**Example:**
|
|
397
|
+
```python
|
|
398
|
+
from md2mrkdwn import MrkdwnConfig, DEFAULT_CONFIG
|
|
399
|
+
|
|
400
|
+
# Create custom config
|
|
401
|
+
config = MrkdwnConfig(
|
|
402
|
+
bullet_char="→",
|
|
403
|
+
header_style="plain",
|
|
404
|
+
convert_bold=False
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
# Use the default config singleton
|
|
408
|
+
print(DEFAULT_CONFIG.bullet_char) # •
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
|
|
412
|
+
## See Also
|
|
413
|
+
|
|
414
|
+
- [Slack mrkdwn specification](https://api.slack.com/reference/surfaces/formatting) - Official Slack formatting documentation
|
|
415
|
+
- [markdown_to_mrkdwn](https://github.com/fla9ua/markdown_to_mrkdwn) - Related project for markdown to mrkdwn conversion
|
|
416
|
+
|
|
417
|
+
## License
|
|
418
|
+
|
|
419
|
+
MIT License - see [LICENSE](LICENSE) file.
|