md2gemtext 0.0.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.
- md2gemtext-0.0.1/PKG-INFO +139 -0
- md2gemtext-0.0.1/README.md +104 -0
- md2gemtext-0.0.1/pyproject.toml +117 -0
- md2gemtext-0.0.1/pyproject.toml.orig +124 -0
- md2gemtext-0.0.1/src/md2gemtext/__init__.py +32 -0
- md2gemtext-0.0.1/src/md2gemtext/__main__.py +123 -0
- md2gemtext-0.0.1/src/md2gemtext/_converter.py +983 -0
- md2gemtext-0.0.1/src/md2gemtext/convert.py +23 -0
- md2gemtext-0.0.1/src/md2gemtext/options.py +47 -0
- md2gemtext-0.0.1/src/md2gemtext/py.typed +1 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: md2gemtext
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A simple library for converting Markdown to Gemtext
|
|
5
|
+
Keywords: converter,Gemini,Gemtext,Markdown,Hypertext,library,Markup,parser,Small Web,smolweb
|
|
6
|
+
Author: Dave Pearson
|
|
7
|
+
Author-email: Dave Pearson <davep@davep.org>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
17
|
+
Classifier: Topic :: Text Processing :: Filters
|
|
18
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
19
|
+
Classifier: Topic :: Text Processing :: Markup
|
|
20
|
+
Classifier: Topic :: Text Processing
|
|
21
|
+
Classifier: Topic :: Utilities
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Dist: html2gemtext>=0.1.0
|
|
24
|
+
Requires-Dist: linkify-it-py>=2.1.0
|
|
25
|
+
Requires-Dist: markdown-it-py>=4.2.0
|
|
26
|
+
Requires-Dist: mdit-py-plugins>=0.6.1
|
|
27
|
+
Requires-Python: >=3.12
|
|
28
|
+
Project-URL: Homepage, https://md2gemtext.davep.dev/
|
|
29
|
+
Project-URL: Repository, https://github.com/davep/md2gemtext
|
|
30
|
+
Project-URL: Documentation, https://md2gemtext.davep.dev/
|
|
31
|
+
Project-URL: Source, https://github.com/davep/md2gemtext
|
|
32
|
+
Project-URL: Issues, https://github.com/davep/md2gemtext/issues
|
|
33
|
+
Project-URL: Discussions, https://github.com/davep/md2gemtext/discussions
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# md2gemtext - A simple library for converting Markdown to Gemtext
|
|
37
|
+
|
|
38
|
+
## Introduction
|
|
39
|
+
|
|
40
|
+
`md2gemtext` is a small and simple library that provides code for
|
|
41
|
+
converting Markdown into [the hypertext markup language of the Gemini
|
|
42
|
+
project](https://geminiprotocol.net/docs/gemtext-specification.gmi).
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
`md2gemtext` is available from PyPI and can be installed with your
|
|
47
|
+
package installer of choice.
|
|
48
|
+
|
|
49
|
+
With `pip`:
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
pip install md2gemtext
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
With `uv`:
|
|
56
|
+
|
|
57
|
+
```shell
|
|
58
|
+
uv add md2gemtext
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
The library provides a main conversion function called `markdown_to_gemtext`.
|
|
64
|
+
It is passed a string of Markdown you wish to convert, and returns the converted
|
|
65
|
+
Gemtext string:
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
from md2gemtext import markdown_to_gemtext, Options
|
|
69
|
+
|
|
70
|
+
markdown = """
|
|
71
|
+
# Welcome
|
|
72
|
+
|
|
73
|
+
This is a paragraph with [a link](https://example.com) inside.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
gemtext = markdown_to_gemtext(markdown)
|
|
77
|
+
print(gemtext)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Output:
|
|
81
|
+
|
|
82
|
+
```gemtext
|
|
83
|
+
# Welcome
|
|
84
|
+
|
|
85
|
+
This is a paragraph with a link{a} inside.
|
|
86
|
+
|
|
87
|
+
=> https://example.com {a} a link
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Options
|
|
91
|
+
|
|
92
|
+
Conversion behavior can be configured using the `Options` class:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from md2gemtext import Options, markdown_to_gemtext
|
|
96
|
+
|
|
97
|
+
options = Options(
|
|
98
|
+
retain_inline_markup=False, # Strip bold, italic, code markup
|
|
99
|
+
space_after_paragraphs=True, # Add empty line after paragraphs
|
|
100
|
+
space_after_blockquotes=True, # Add empty line after blockquotes
|
|
101
|
+
space_after_lists=True, # Add empty line after runs of list items
|
|
102
|
+
hide_front_matter=True, # Hide/filter out front matter (default is False, which emits it)
|
|
103
|
+
extra_linkable_protocols=["spartan", "finger", "nex"], # Additional protocols to linkify
|
|
104
|
+
preformat_tables=True, # Emit tables as preformatted blocks with alt-text 'table'
|
|
105
|
+
html_block_handling="convert", # HTML blocks: 'convert', 'preformat', or 'striptags'
|
|
106
|
+
html_inline_handling="striptags", # Inline HTML tags: 'striptags' (default) or 'keep'
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
gemtext = markdown_to_gemtext(markdown, options=options)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Command Line Interface
|
|
113
|
+
|
|
114
|
+
`md2gemtext` includes a command-line tool which reads from files or stdin:
|
|
115
|
+
|
|
116
|
+
```shell
|
|
117
|
+
# Read from file
|
|
118
|
+
md2gemtext document.md
|
|
119
|
+
|
|
120
|
+
# Read from stdin
|
|
121
|
+
cat document.md | md2gemtext
|
|
122
|
+
|
|
123
|
+
# Strip inline markup
|
|
124
|
+
md2gemtext --strip-inline-markup document.md
|
|
125
|
+
|
|
126
|
+
# Add extra protocols to linkify
|
|
127
|
+
md2gemtext --extra-protocol spartan --extra-protocol nex document.md
|
|
128
|
+
|
|
129
|
+
# Emit tables as plain aligned text instead of preformatted blocks
|
|
130
|
+
md2gemtext --no-preformat-tables document.md
|
|
131
|
+
|
|
132
|
+
# Set HTML block handling mode ('convert', 'preformat', or 'striptags')
|
|
133
|
+
md2gemtext --html-block-handling preformat document.md
|
|
134
|
+
|
|
135
|
+
# Keep inline HTML tags rather than stripping them
|
|
136
|
+
md2gemtext --html-inline-handling keep document.md
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
[//]: # (README.md ends here)
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# md2gemtext - A simple library for converting Markdown to Gemtext
|
|
2
|
+
|
|
3
|
+
## Introduction
|
|
4
|
+
|
|
5
|
+
`md2gemtext` is a small and simple library that provides code for
|
|
6
|
+
converting Markdown into [the hypertext markup language of the Gemini
|
|
7
|
+
project](https://geminiprotocol.net/docs/gemtext-specification.gmi).
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
`md2gemtext` is available from PyPI and can be installed with your
|
|
12
|
+
package installer of choice.
|
|
13
|
+
|
|
14
|
+
With `pip`:
|
|
15
|
+
|
|
16
|
+
```shell
|
|
17
|
+
pip install md2gemtext
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
With `uv`:
|
|
21
|
+
|
|
22
|
+
```shell
|
|
23
|
+
uv add md2gemtext
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick start
|
|
27
|
+
|
|
28
|
+
The library provides a main conversion function called `markdown_to_gemtext`.
|
|
29
|
+
It is passed a string of Markdown you wish to convert, and returns the converted
|
|
30
|
+
Gemtext string:
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from md2gemtext import markdown_to_gemtext, Options
|
|
34
|
+
|
|
35
|
+
markdown = """
|
|
36
|
+
# Welcome
|
|
37
|
+
|
|
38
|
+
This is a paragraph with [a link](https://example.com) inside.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
gemtext = markdown_to_gemtext(markdown)
|
|
42
|
+
print(gemtext)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Output:
|
|
46
|
+
|
|
47
|
+
```gemtext
|
|
48
|
+
# Welcome
|
|
49
|
+
|
|
50
|
+
This is a paragraph with a link{a} inside.
|
|
51
|
+
|
|
52
|
+
=> https://example.com {a} a link
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Options
|
|
56
|
+
|
|
57
|
+
Conversion behavior can be configured using the `Options` class:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from md2gemtext import Options, markdown_to_gemtext
|
|
61
|
+
|
|
62
|
+
options = Options(
|
|
63
|
+
retain_inline_markup=False, # Strip bold, italic, code markup
|
|
64
|
+
space_after_paragraphs=True, # Add empty line after paragraphs
|
|
65
|
+
space_after_blockquotes=True, # Add empty line after blockquotes
|
|
66
|
+
space_after_lists=True, # Add empty line after runs of list items
|
|
67
|
+
hide_front_matter=True, # Hide/filter out front matter (default is False, which emits it)
|
|
68
|
+
extra_linkable_protocols=["spartan", "finger", "nex"], # Additional protocols to linkify
|
|
69
|
+
preformat_tables=True, # Emit tables as preformatted blocks with alt-text 'table'
|
|
70
|
+
html_block_handling="convert", # HTML blocks: 'convert', 'preformat', or 'striptags'
|
|
71
|
+
html_inline_handling="striptags", # Inline HTML tags: 'striptags' (default) or 'keep'
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
gemtext = markdown_to_gemtext(markdown, options=options)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Command Line Interface
|
|
78
|
+
|
|
79
|
+
`md2gemtext` includes a command-line tool which reads from files or stdin:
|
|
80
|
+
|
|
81
|
+
```shell
|
|
82
|
+
# Read from file
|
|
83
|
+
md2gemtext document.md
|
|
84
|
+
|
|
85
|
+
# Read from stdin
|
|
86
|
+
cat document.md | md2gemtext
|
|
87
|
+
|
|
88
|
+
# Strip inline markup
|
|
89
|
+
md2gemtext --strip-inline-markup document.md
|
|
90
|
+
|
|
91
|
+
# Add extra protocols to linkify
|
|
92
|
+
md2gemtext --extra-protocol spartan --extra-protocol nex document.md
|
|
93
|
+
|
|
94
|
+
# Emit tables as plain aligned text instead of preformatted blocks
|
|
95
|
+
md2gemtext --no-preformat-tables document.md
|
|
96
|
+
|
|
97
|
+
# Set HTML block handling mode ('convert', 'preformat', or 'striptags')
|
|
98
|
+
md2gemtext --html-block-handling preformat document.md
|
|
99
|
+
|
|
100
|
+
# Keep inline HTML tags rather than stripping them
|
|
101
|
+
md2gemtext --html-inline-handling keep document.md
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
[//]: # (README.md ends here)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "md2gemtext"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "A simple library for converting Markdown to Gemtext"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"html2gemtext>=0.1.0",
|
|
9
|
+
"linkify-it-py>=2.1.0",
|
|
10
|
+
"markdown-it-py>=4.2.0",
|
|
11
|
+
"mdit-py-plugins>=0.6.1",
|
|
12
|
+
]
|
|
13
|
+
license = "MIT"
|
|
14
|
+
keywords = [
|
|
15
|
+
"converter",
|
|
16
|
+
"Gemini",
|
|
17
|
+
"Gemtext",
|
|
18
|
+
"Markdown",
|
|
19
|
+
"Hypertext",
|
|
20
|
+
"library",
|
|
21
|
+
"Markup",
|
|
22
|
+
"parser",
|
|
23
|
+
"Small Web",
|
|
24
|
+
"smolweb",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Development Status :: 3 - Alpha",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3.12",
|
|
32
|
+
"Programming Language :: Python :: 3.13",
|
|
33
|
+
"Programming Language :: Python :: 3.14",
|
|
34
|
+
"Topic :: Software Development :: Libraries",
|
|
35
|
+
"Topic :: Text Processing :: Filters",
|
|
36
|
+
"Topic :: Text Processing :: Markup :: Markdown",
|
|
37
|
+
"Topic :: Text Processing :: Markup",
|
|
38
|
+
"Topic :: Text Processing",
|
|
39
|
+
"Topic :: Utilities",
|
|
40
|
+
"Typing :: Typed",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[[project.authors]]
|
|
44
|
+
name = "Dave Pearson"
|
|
45
|
+
email = "davep@davep.org"
|
|
46
|
+
|
|
47
|
+
[project.urls]
|
|
48
|
+
Homepage = "https://md2gemtext.davep.dev/"
|
|
49
|
+
Repository = "https://github.com/davep/md2gemtext"
|
|
50
|
+
Documentation = "https://md2gemtext.davep.dev/"
|
|
51
|
+
Source = "https://github.com/davep/md2gemtext"
|
|
52
|
+
Issues = "https://github.com/davep/md2gemtext/issues"
|
|
53
|
+
Discussions = "https://github.com/davep/md2gemtext/discussions"
|
|
54
|
+
|
|
55
|
+
[project.scripts]
|
|
56
|
+
md2gemtext = "md2gemtext.__main__:convert"
|
|
57
|
+
|
|
58
|
+
[build-system]
|
|
59
|
+
requires = ["uv_build>=0.12.5,<0.13.0"]
|
|
60
|
+
build-backend = "uv_build"
|
|
61
|
+
|
|
62
|
+
[[tool.uv.index]]
|
|
63
|
+
name = "testpypi"
|
|
64
|
+
url = "https://test.pypi.org/simple/"
|
|
65
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
66
|
+
explicit = true
|
|
67
|
+
|
|
68
|
+
[tool.pyright]
|
|
69
|
+
venvPath = "."
|
|
70
|
+
venv = ".venv"
|
|
71
|
+
exclude = [".venv"]
|
|
72
|
+
|
|
73
|
+
[tool.ruff.lint]
|
|
74
|
+
select = [
|
|
75
|
+
"E",
|
|
76
|
+
"F",
|
|
77
|
+
"UP",
|
|
78
|
+
"B",
|
|
79
|
+
"SIM",
|
|
80
|
+
"I",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint.pycodestyle]
|
|
84
|
+
max-line-length = 120
|
|
85
|
+
|
|
86
|
+
[tool.coverage.run]
|
|
87
|
+
omit = ["tests/*"]
|
|
88
|
+
|
|
89
|
+
[tool.coverage.report]
|
|
90
|
+
exclude_lines = [
|
|
91
|
+
"pragma: no cover",
|
|
92
|
+
"def __repr__",
|
|
93
|
+
"def _repr_props",
|
|
94
|
+
"raise AssertionError",
|
|
95
|
+
"raise NotImplementedError",
|
|
96
|
+
"if __name__ == .__main__.:",
|
|
97
|
+
"if TYPE_CHECKING:",
|
|
98
|
+
'class .*\bProtocol\):',
|
|
99
|
+
'@(abc\.)?abstractmethod',
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
[dependency-groups]
|
|
103
|
+
dev = [
|
|
104
|
+
"codespell>=2.4.2",
|
|
105
|
+
"mypy>=2.1.0",
|
|
106
|
+
"pre-commit>=4.6.0",
|
|
107
|
+
"ruff>=0.15.17",
|
|
108
|
+
]
|
|
109
|
+
docs = [
|
|
110
|
+
"mkdocs>=1.6.1,<2",
|
|
111
|
+
"mkdocs-material>=9.7.6",
|
|
112
|
+
"mkdocstrings[python]>=1.0.4",
|
|
113
|
+
]
|
|
114
|
+
test = [
|
|
115
|
+
"pytest>=9.1.0",
|
|
116
|
+
"pytest-cov>=7.1.0",
|
|
117
|
+
]
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "md2gemtext"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
description = "A simple library for converting Markdown to Gemtext"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "Dave Pearson", email = "davep@davep.org" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.12"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"html2gemtext>=0.1.0",
|
|
12
|
+
"linkify-it-py>=2.1.0",
|
|
13
|
+
"markdown-it-py>=4.2.0",
|
|
14
|
+
"mdit-py-plugins>=0.6.1",
|
|
15
|
+
]
|
|
16
|
+
license = "MIT"
|
|
17
|
+
keywords = [
|
|
18
|
+
"converter",
|
|
19
|
+
"Gemini",
|
|
20
|
+
"Gemtext",
|
|
21
|
+
"Markdown",
|
|
22
|
+
"Hypertext",
|
|
23
|
+
"library",
|
|
24
|
+
"Markup",
|
|
25
|
+
"parser",
|
|
26
|
+
"Small Web",
|
|
27
|
+
"smolweb",
|
|
28
|
+
]
|
|
29
|
+
classifiers = [
|
|
30
|
+
"Development Status :: 3 - Alpha",
|
|
31
|
+
"Operating System :: OS Independent",
|
|
32
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
+
"Programming Language :: Python :: 3",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Programming Language :: Python :: 3.13",
|
|
36
|
+
"Programming Language :: Python :: 3.14",
|
|
37
|
+
"Topic :: Software Development :: Libraries",
|
|
38
|
+
"Topic :: Text Processing :: Filters",
|
|
39
|
+
"Topic :: Text Processing :: Markup :: Markdown",
|
|
40
|
+
"Topic :: Text Processing :: Markup",
|
|
41
|
+
"Topic :: Text Processing",
|
|
42
|
+
"Topic :: Utilities",
|
|
43
|
+
"Typing :: Typed",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
[project.urls]
|
|
47
|
+
Homepage = "https://md2gemtext.davep.dev/"
|
|
48
|
+
Repository = "https://github.com/davep/md2gemtext"
|
|
49
|
+
Documentation = "https://md2gemtext.davep.dev/"
|
|
50
|
+
Source = "https://github.com/davep/md2gemtext"
|
|
51
|
+
Issues = "https://github.com/davep/md2gemtext/issues"
|
|
52
|
+
Discussions = "https://github.com/davep/md2gemtext/discussions"
|
|
53
|
+
|
|
54
|
+
[project.scripts]
|
|
55
|
+
md2gemtext = "md2gemtext.__main__:convert"
|
|
56
|
+
|
|
57
|
+
[build-system]
|
|
58
|
+
requires = ["uv_build>=0.12.5,<0.13.0"]
|
|
59
|
+
build-backend = "uv_build"
|
|
60
|
+
|
|
61
|
+
[[tool.uv.index]]
|
|
62
|
+
name = "testpypi"
|
|
63
|
+
url = "https://test.pypi.org/simple/"
|
|
64
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
65
|
+
explicit = true
|
|
66
|
+
|
|
67
|
+
[tool.pyright]
|
|
68
|
+
venvPath="."
|
|
69
|
+
venv=".venv"
|
|
70
|
+
exclude=[".venv"]
|
|
71
|
+
|
|
72
|
+
[tool.ruff.lint]
|
|
73
|
+
select = [
|
|
74
|
+
# pycodestyle
|
|
75
|
+
"E",
|
|
76
|
+
# Pyflakes
|
|
77
|
+
"F",
|
|
78
|
+
# pyupgrade
|
|
79
|
+
"UP",
|
|
80
|
+
# flake8-bugbear
|
|
81
|
+
"B",
|
|
82
|
+
# flake8-simplify
|
|
83
|
+
"SIM",
|
|
84
|
+
# isort
|
|
85
|
+
"I",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint.pycodestyle]
|
|
89
|
+
max-line-length = 120
|
|
90
|
+
|
|
91
|
+
[tool.coverage.run]
|
|
92
|
+
omit = [
|
|
93
|
+
"tests/*"
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
[tool.coverage.report]
|
|
97
|
+
exclude_lines = [
|
|
98
|
+
"pragma: no cover",
|
|
99
|
+
"def __repr__",
|
|
100
|
+
"def _repr_props",
|
|
101
|
+
"raise AssertionError",
|
|
102
|
+
"raise NotImplementedError",
|
|
103
|
+
"if __name__ == .__main__.:",
|
|
104
|
+
"if TYPE_CHECKING:",
|
|
105
|
+
"class .*\\bProtocol\\):",
|
|
106
|
+
"@(abc\\.)?abstractmethod",
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
[dependency-groups]
|
|
110
|
+
dev = [
|
|
111
|
+
"codespell>=2.4.2",
|
|
112
|
+
"mypy>=2.1.0",
|
|
113
|
+
"pre-commit>=4.6.0",
|
|
114
|
+
"ruff>=0.15.17",
|
|
115
|
+
]
|
|
116
|
+
docs = [
|
|
117
|
+
"mkdocs>=1.6.1,<2",
|
|
118
|
+
"mkdocs-material>=9.7.6",
|
|
119
|
+
"mkdocstrings[python]>=1.0.4",
|
|
120
|
+
]
|
|
121
|
+
test = [
|
|
122
|
+
"pytest>=9.1.0",
|
|
123
|
+
"pytest-cov>=7.1.0",
|
|
124
|
+
]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""A simple Markdown to Gemtext converter."""
|
|
2
|
+
|
|
3
|
+
##############################################################################
|
|
4
|
+
# Python imports.
|
|
5
|
+
from importlib.metadata import version
|
|
6
|
+
|
|
7
|
+
######################################################################
|
|
8
|
+
# Main library information.
|
|
9
|
+
__author__ = "Dave Pearson"
|
|
10
|
+
__copyright__ = "Copyright 2026, Dave Pearson"
|
|
11
|
+
__credits__ = ["Dave Pearson"]
|
|
12
|
+
__maintainer__ = "Dave Pearson"
|
|
13
|
+
__email__ = "davep@davep.org"
|
|
14
|
+
__version__: str = version("md2gemtext")
|
|
15
|
+
__licence__ = "MIT"
|
|
16
|
+
|
|
17
|
+
##############################################################################
|
|
18
|
+
# Local imports.
|
|
19
|
+
from .convert import markdown_to_gemtext
|
|
20
|
+
from .options import HTMLBlockHandling, HTMLInlineHandling, Options
|
|
21
|
+
|
|
22
|
+
##############################################################################
|
|
23
|
+
# Exports.
|
|
24
|
+
__all__ = [
|
|
25
|
+
"HTMLBlockHandling",
|
|
26
|
+
"HTMLInlineHandling",
|
|
27
|
+
"markdown_to_gemtext",
|
|
28
|
+
"Options",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### __init__.py ends here
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Command line interface for md2gemtext."""
|
|
2
|
+
|
|
3
|
+
##############################################################################
|
|
4
|
+
# Python imports.
|
|
5
|
+
import argparse
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
##############################################################################
|
|
9
|
+
# Local imports.
|
|
10
|
+
from .convert import markdown_to_gemtext
|
|
11
|
+
from .options import Options
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
##############################################################################
|
|
15
|
+
def convert() -> None:
|
|
16
|
+
"""Parse the input from stdin or files and print the parsed Gemtext."""
|
|
17
|
+
parser = argparse.ArgumentParser(
|
|
18
|
+
prog="md2gemtext",
|
|
19
|
+
description="A simple Markdown to Gemtext converter.",
|
|
20
|
+
)
|
|
21
|
+
parser.add_argument(
|
|
22
|
+
"files",
|
|
23
|
+
nargs="*",
|
|
24
|
+
default=["-"],
|
|
25
|
+
help="Markdown file(s) to convert (default: stdin).",
|
|
26
|
+
)
|
|
27
|
+
parser.add_argument(
|
|
28
|
+
"--strip-inline-markup",
|
|
29
|
+
"--no-retain-inline-markup",
|
|
30
|
+
dest="retain_inline_markup",
|
|
31
|
+
action="store_false",
|
|
32
|
+
default=True,
|
|
33
|
+
help="Strip inline Markdown markup (bold, italics, etc.).",
|
|
34
|
+
)
|
|
35
|
+
parser.add_argument(
|
|
36
|
+
"--no-space-after-paragraphs",
|
|
37
|
+
dest="space_after_paragraphs",
|
|
38
|
+
action="store_false",
|
|
39
|
+
default=True,
|
|
40
|
+
help="Do not add an empty line after paragraphs.",
|
|
41
|
+
)
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--no-space-after-blockquotes",
|
|
44
|
+
dest="space_after_blockquotes",
|
|
45
|
+
action="store_false",
|
|
46
|
+
default=True,
|
|
47
|
+
help="Do not add an empty line after blockquotes.",
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--no-space-after-lists",
|
|
51
|
+
dest="space_after_lists",
|
|
52
|
+
action="store_false",
|
|
53
|
+
default=True,
|
|
54
|
+
help="Do not add an empty line after a run of list items.",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--hide-front-matter",
|
|
58
|
+
dest="hide_front_matter",
|
|
59
|
+
action="store_true",
|
|
60
|
+
default=False,
|
|
61
|
+
help="Hide/filter out front matter from output (default: false).",
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--extra-protocol",
|
|
65
|
+
action="append",
|
|
66
|
+
default=[],
|
|
67
|
+
dest="extra_linkable_protocols",
|
|
68
|
+
help="Additional protocol to linkify (e.g. --extra-protocol spartan).",
|
|
69
|
+
)
|
|
70
|
+
parser.add_argument(
|
|
71
|
+
"--no-preformat-tables",
|
|
72
|
+
dest="preformat_tables",
|
|
73
|
+
action="store_false",
|
|
74
|
+
default=True,
|
|
75
|
+
help="Do not emit tables as preformatted blocks (emit as plain aligned text).",
|
|
76
|
+
)
|
|
77
|
+
parser.add_argument(
|
|
78
|
+
"--html-block-handling",
|
|
79
|
+
choices=["convert", "preformat", "striptags"],
|
|
80
|
+
default="convert",
|
|
81
|
+
dest="html_block_handling",
|
|
82
|
+
help="How to handle HTML blocks: 'convert', 'preformat', or 'striptags' (default: convert).",
|
|
83
|
+
)
|
|
84
|
+
parser.add_argument(
|
|
85
|
+
"--html-inline-handling",
|
|
86
|
+
choices=["keep", "striptags"],
|
|
87
|
+
default="striptags",
|
|
88
|
+
dest="html_inline_handling",
|
|
89
|
+
help="How to handle inline HTML tags: 'keep' or 'striptags' (default: striptags).",
|
|
90
|
+
)
|
|
91
|
+
args = parser.parse_args()
|
|
92
|
+
|
|
93
|
+
options = Options(
|
|
94
|
+
retain_inline_markup=args.retain_inline_markup,
|
|
95
|
+
space_after_paragraphs=args.space_after_paragraphs,
|
|
96
|
+
space_after_blockquotes=args.space_after_blockquotes,
|
|
97
|
+
space_after_lists=args.space_after_lists,
|
|
98
|
+
hide_front_matter=args.hide_front_matter,
|
|
99
|
+
extra_linkable_protocols=args.extra_linkable_protocols,
|
|
100
|
+
preformat_tables=args.preformat_tables,
|
|
101
|
+
html_block_handling=args.html_block_handling,
|
|
102
|
+
html_inline_handling=args.html_inline_handling,
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
content_list: list[str] = []
|
|
106
|
+
for file_path in args.files:
|
|
107
|
+
if file_path == "-":
|
|
108
|
+
content_list.append(sys.stdin.read())
|
|
109
|
+
else:
|
|
110
|
+
with open(file_path, encoding="utf-8") as f:
|
|
111
|
+
content_list.append(f.read())
|
|
112
|
+
|
|
113
|
+
output = markdown_to_gemtext("".join(content_list), options=options)
|
|
114
|
+
if output:
|
|
115
|
+
print(output)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
##############################################################################
|
|
119
|
+
if __name__ == "__main__":
|
|
120
|
+
convert()
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
### __main__.py ends here
|