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.
@@ -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