flowmark 0.4.0__tar.gz → 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.
Files changed (36) hide show
  1. {flowmark-0.4.0 → flowmark-0.4.2}/.copier-answers.yml +1 -1
  2. {flowmark-0.4.0 → flowmark-0.4.2}/.github/workflows/ci.yml +2 -1
  3. {flowmark-0.4.0 → flowmark-0.4.2}/.github/workflows/publish.yml +1 -1
  4. {flowmark-0.4.0 → flowmark-0.4.2}/Makefile +2 -1
  5. flowmark-0.4.0/README.md → flowmark-0.4.2/PKG-INFO +49 -4
  6. flowmark-0.4.0/PKG-INFO → flowmark-0.4.2/README.md +25 -19
  7. {flowmark-0.4.0 → flowmark-0.4.2}/devtools/lint.py +7 -3
  8. flowmark-0.4.2/installation.md +27 -0
  9. {flowmark-0.4.0 → flowmark-0.4.2}/pyproject.toml +44 -7
  10. flowmark-0.4.2/src/flowmark/cleanups.py +76 -0
  11. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/cli.py +10 -0
  12. flowmark-0.4.0/src/flowmark/markdown_filling.py → flowmark-0.4.2/src/flowmark/custom_marko.py +76 -134
  13. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/line_wrappers.py +4 -0
  14. flowmark-0.4.2/src/flowmark/markdown_filling.py +133 -0
  15. flowmark-0.4.2/src/flowmark/py.typed +0 -0
  16. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/text_wrapping.py +43 -2
  17. flowmark-0.4.2/tests/test_cleanups.py +62 -0
  18. {flowmark-0.4.0 → flowmark-0.4.2}/tests/test_ref_docs.py +8 -4
  19. {flowmark-0.4.0 → flowmark-0.4.2}/tests/test_wrapping.py +93 -0
  20. {flowmark-0.4.0 → flowmark-0.4.2}/tests/testdocs/testdoc.orig.md +3 -0
  21. flowmark-0.4.2/tests/testdocs/testdoc.out.cleaned.md +943 -0
  22. {flowmark-0.4.0 → flowmark-0.4.2}/tests/testdocs/testdoc.out.plain.md +15 -14
  23. {flowmark-0.4.0 → flowmark-0.4.2}/tests/testdocs/testdoc.out.semantic.md +19 -20
  24. {flowmark-0.4.0 → flowmark-0.4.2}/.gitignore +0 -0
  25. {flowmark-0.4.0 → flowmark-0.4.2}/LICENSE +0 -0
  26. {flowmark-0.4.0 → flowmark-0.4.2}/development.md +0 -0
  27. {flowmark-0.4.0 → flowmark-0.4.2}/poetry.lock +0 -0
  28. {flowmark-0.4.0 → flowmark-0.4.2}/publishing.md +0 -0
  29. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/__init__.py +0 -0
  30. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/frontmatter.py +0 -0
  31. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/sentence_split_regex.py +0 -0
  32. {flowmark-0.4.0 → flowmark-0.4.2}/src/flowmark/text_filling.py +0 -0
  33. {flowmark-0.4.0 → flowmark-0.4.2}/tests/test_filling.py +0 -0
  34. {flowmark-0.4.0 → flowmark-0.4.2}/tests/test_frontmatter.py +0 -0
  35. {flowmark-0.4.0 → flowmark-0.4.2}/tests/test_sentences.py +0 -0
  36. {flowmark-0.4.0 → flowmark-0.4.2}/uv.lock +0 -0
@@ -1,5 +1,5 @@
1
1
  # Changes here will be overwritten by Copier. Do not edit manually.
2
- _commit: v0.2.0
2
+ _commit: v0.2.7
3
3
  _src_path: gh:jlevy/simple-modern-uv
4
4
  package_author_email: joshua@cal.berkeley.edu
5
5
  package_author_name: Joshua Levy
@@ -40,7 +40,8 @@ jobs:
40
40
  - name: Install uv (official Astral action)
41
41
  uses: astral-sh/setup-uv@v5
42
42
  with:
43
- version: "0.6.5"
43
+ # Update this as needed:
44
+ version: "0.6.14"
44
45
  enable-cache: true
45
46
  python-version: ${{ matrix.python-version }}
46
47
 
@@ -21,7 +21,7 @@ jobs:
21
21
  - name: Install uv (official Astral action)
22
22
  uses: astral-sh/setup-uv@v5
23
23
  with:
24
- version: "0.6.5"
24
+ version: "0.6.14"
25
25
  enable-cache: true
26
26
  python-version: "3.12"
27
27
 
@@ -1,5 +1,6 @@
1
1
  # Makefile for easy development workflows.
2
- # GitHub Actions call uv directly.
2
+ # See development.md for docs.
3
+ # Note GitHub Actions call uv directly, not this Makefile.
3
4
 
4
5
  .DEFAULT_GOAL := default
5
6
 
@@ -1,3 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: flowmark
3
+ Version: 0.4.2
4
+ Summary: Better line wrapping and formatting for plaintext and Markdown
5
+ Project-URL: Repository, https://github.com/jlevy/flowmark
6
+ Author-email: Joshua Levy <joshua@cal.berkeley.edu>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: OS Independent
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: <4.0,>=3.10
19
+ Requires-Dist: marko>=2.1.2
20
+ Requires-Dist: regex>=2024.11.6
21
+ Requires-Dist: strif>=2.0.0
22
+ Requires-Dist: typing-extensions>=4.12.2
23
+ Description-Content-Type: text/markdown
24
+
1
25
  # flowmark
2
26
 
3
27
  Flowmark is a new Python implementation of **text and Markdown line wrapping and
@@ -129,8 +153,7 @@ experience.
129
153
  Flowmark can be used as a library or as a CLI.
130
154
 
131
155
  ```
132
- $ flowmark --help
133
- usage: flowmark [-h] [-o OUTPUT] [-w WIDTH] [-p] [-s] [-i] [--nobackup] [file]
156
+ usage: flowmark [-h] [-o OUTPUT] [-w WIDTH] [-p] [-s] [-i] [--nobackup] [--auto] [--version] [file]
134
157
 
135
158
  Flowmark: Better line wrapping and formatting for plaintext and Markdown
136
159
 
@@ -142,9 +165,11 @@ options:
142
165
  -o, --output OUTPUT Output file (use '-' for stdout)
143
166
  -w, --width WIDTH Line width to wrap to
144
167
  -p, --plaintext Process as plaintext (no Markdown parsing)
145
- -s, --semantic Enable sentence-based line breaks (only applies to Markdown mode)
168
+ -s, --semantic Enable semantic (sentence-based) line breaks (only applies to Markdown mode)
146
169
  -i, --inplace Edit the file in place (ignores --output)
147
170
  --nobackup Do not make a backup of the original file when using --inplace
171
+ --auto Same as `--inplace --nobackup --semantic`, as a convenience for auto-formatting files
172
+ --version Show version information and exit
148
173
 
149
174
  Flowmark provides enhanced text wrapping capabilities with special handling for
150
175
  Markdown content. It can:
@@ -173,12 +198,32 @@ Command-line usage examples:
173
198
  # Process plaintext instead of Markdown
174
199
  flowmark --plaintext text.txt
175
200
 
176
- # Use sentences to guide line breaks (good for many purposes git history and diffs)
201
+ # Use semantic line breaks (based on sentences, which is helpful to reduce
202
+ # irrelevant line wrap diffs in git history)
177
203
  flowmark --semantic README.md
178
204
 
179
205
  For more details, see: https://github.com/jlevy/flowmark
180
206
  ```
181
207
 
208
+ ## Other Notes
209
+
210
+ - This enables
211
+ [GitHub-flavored Markdown support](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)
212
+ using
213
+ [Marko's extension](https://github.com/frostming/marko/blob/master/marko/ext/footnote.py).
214
+
215
+ - GFM-style tables are supported and also auto-formatted.
216
+
217
+ - GFM-style footnotes are supported.
218
+ But note these aren't actually in the GFM spec, but we follow
219
+ [micromark's conventions](https://github.com/frostming/marko/blob/master/marko/ext/footnote.py).
220
+
221
+ ## Project Docs
222
+
223
+ For how to install uv and Python, see [installation.md](installation.md).
224
+
225
+ For development workflows, see [development.md](development.md).
226
+
182
227
  For instructions on publishing to PyPI, see [publishing.md](publishing.md).
183
228
 
184
229
  * * *
@@ -1,18 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: flowmark
3
- Version: 0.4.0
4
- Summary: Better line wrapping and formatting for plaintext and Markdown
5
- Project-URL: Repository, https://github.com/jlevy/flowmark
6
- Author-email: Joshua Levy <joshua@cal.berkeley.edu>
7
- License-Expression: MIT
8
- License-File: LICENSE
9
- Requires-Python: <4.0,>=3.10
10
- Requires-Dist: marko>=2.1.2
11
- Requires-Dist: regex>=2024.11.6
12
- Requires-Dist: strif>=2.0.0
13
- Requires-Dist: typing-extensions>=4.12.2
14
- Description-Content-Type: text/markdown
15
-
16
1
  # flowmark
17
2
 
18
3
  Flowmark is a new Python implementation of **text and Markdown line wrapping and
@@ -144,8 +129,7 @@ experience.
144
129
  Flowmark can be used as a library or as a CLI.
145
130
 
146
131
  ```
147
- $ flowmark --help
148
- usage: flowmark [-h] [-o OUTPUT] [-w WIDTH] [-p] [-s] [-i] [--nobackup] [file]
132
+ usage: flowmark [-h] [-o OUTPUT] [-w WIDTH] [-p] [-s] [-i] [--nobackup] [--auto] [--version] [file]
149
133
 
150
134
  Flowmark: Better line wrapping and formatting for plaintext and Markdown
151
135
 
@@ -157,9 +141,11 @@ options:
157
141
  -o, --output OUTPUT Output file (use '-' for stdout)
158
142
  -w, --width WIDTH Line width to wrap to
159
143
  -p, --plaintext Process as plaintext (no Markdown parsing)
160
- -s, --semantic Enable sentence-based line breaks (only applies to Markdown mode)
144
+ -s, --semantic Enable semantic (sentence-based) line breaks (only applies to Markdown mode)
161
145
  -i, --inplace Edit the file in place (ignores --output)
162
146
  --nobackup Do not make a backup of the original file when using --inplace
147
+ --auto Same as `--inplace --nobackup --semantic`, as a convenience for auto-formatting files
148
+ --version Show version information and exit
163
149
 
164
150
  Flowmark provides enhanced text wrapping capabilities with special handling for
165
151
  Markdown content. It can:
@@ -188,12 +174,32 @@ Command-line usage examples:
188
174
  # Process plaintext instead of Markdown
189
175
  flowmark --plaintext text.txt
190
176
 
191
- # Use sentences to guide line breaks (good for many purposes git history and diffs)
177
+ # Use semantic line breaks (based on sentences, which is helpful to reduce
178
+ # irrelevant line wrap diffs in git history)
192
179
  flowmark --semantic README.md
193
180
 
194
181
  For more details, see: https://github.com/jlevy/flowmark
195
182
  ```
196
183
 
184
+ ## Other Notes
185
+
186
+ - This enables
187
+ [GitHub-flavored Markdown support](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax)
188
+ using
189
+ [Marko's extension](https://github.com/frostming/marko/blob/master/marko/ext/footnote.py).
190
+
191
+ - GFM-style tables are supported and also auto-formatted.
192
+
193
+ - GFM-style footnotes are supported.
194
+ But note these aren't actually in the GFM spec, but we follow
195
+ [micromark's conventions](https://github.com/frostming/marko/blob/master/marko/ext/footnote.py).
196
+
197
+ ## Project Docs
198
+
199
+ For how to install uv and Python, see [installation.md](installation.md).
200
+
201
+ For development workflows, see [development.md](development.md).
202
+
197
203
  For instructions on publishing to PyPI, see [publishing.md](publishing.md).
198
204
 
199
205
  * * *
@@ -1,6 +1,7 @@
1
1
  import subprocess
2
2
 
3
3
  from funlog import log_calls
4
+ from rich import get_console, reconfigure
4
5
  from rich import print as rprint
5
6
 
6
7
  # Update as needed.
@@ -8,6 +9,9 @@ SRC_PATHS = ["src", "tests", "devtools"]
8
9
  DOC_PATHS = ["README.md"]
9
10
 
10
11
 
12
+ reconfigure(emoji=not get_console().options.legacy_windows) # No emojis on legacy windows.
13
+
14
+
11
15
  def main():
12
16
  rprint()
13
17
 
@@ -20,9 +24,9 @@ def main():
20
24
  rprint()
21
25
 
22
26
  if errcount != 0:
23
- rprint(f"[bold red]✗ Lint failed with {errcount} errors.[/bold red]")
27
+ rprint(f"[bold red]:x: Lint failed with {errcount} errors.[/bold red]")
24
28
  else:
25
- rprint("[bold green]✔️ Lint passed![/bold green]")
29
+ rprint("[bold green]:white_check_mark: Lint passed![/bold green]")
26
30
  rprint()
27
31
 
28
32
  return errcount
@@ -31,7 +35,7 @@ def main():
31
35
  @log_calls(level="warning", show_timing_only=True)
32
36
  def run(cmd: list[str]) -> int:
33
37
  rprint()
34
- rprint(f"[bold green]❯ {' '.join(cmd)}[/bold green]")
38
+ rprint(f"[bold green]:arrow_forward: {' '.join(cmd)}[/bold green]")
35
39
  errcount = 0
36
40
  try:
37
41
  subprocess.run(cmd, text=True, check=True)
@@ -0,0 +1,27 @@
1
+ ## Installing uv and Python
2
+
3
+ This project is set up to use [**uv**](https://docs.astral.sh/uv/), the new package
4
+ manager for Python. `uv` replaces traditional use of `pyenv`, `pipx`, `poetry`, `pip`,
5
+ etc. This is a quick cheat sheet on that:
6
+
7
+ On macOS or Linux, if you don't have `uv` installed, a quick way to install it:
8
+
9
+ ```shell
10
+ curl -LsSf https://astral.sh/uv/install.sh | sh
11
+ ```
12
+
13
+ For macOS, you prefer [brew](https://brew.sh/) you can install or upgrade uv with:
14
+
15
+ ```shell
16
+ brew update
17
+ brew install uv
18
+ ```
19
+
20
+ See [uv's docs](https://docs.astral.sh/uv/getting-started/installation/) for more
21
+ installation methods and platforms.
22
+
23
+ Now you can use uv to install a current Python environment:
24
+
25
+ ```shell
26
+ uv python install 3.13 # Or pick another version.
27
+ ```
@@ -3,6 +3,7 @@
3
3
  [project.urls]
4
4
  Repository = "https://github.com/jlevy/flowmark"
5
5
  # Homepage = "https://..."
6
+ # Documentation = "https://..."
6
7
 
7
8
  [project]
8
9
  name = "flowmark"
@@ -15,6 +16,24 @@ license = "MIT"
15
16
  requires-python = ">=3.10,<4.0"
16
17
  dynamic = ["version"]
17
18
 
19
+ # https://pypi.org/classifiers/
20
+ # Adjust as needed:
21
+ classifiers = [
22
+ # Adjust as needed:
23
+ "Development Status :: 4 - Beta",
24
+ # "Development Status :: 5 - Production/Stable",
25
+ "Intended Audience :: Developers",
26
+ "Operating System :: OS Independent",
27
+ "Programming Language :: Python",
28
+ "Programming Language :: Python :: 3",
29
+ "Programming Language :: Python :: 3.11",
30
+ "Programming Language :: Python :: 3.12",
31
+ "Programming Language :: Python :: 3.13",
32
+ "Typing :: Typed",
33
+ # Include this to avoid accidentally publishing to PyPI:
34
+ # "Private :: Do Not Upload",
35
+ ]
36
+
18
37
  dependencies = [
19
38
  "marko>=2.1.2",
20
39
  "regex>=2024.11.6",
@@ -22,6 +41,7 @@ dependencies = [
22
41
  "typing-extensions>=4.12.2",
23
42
  ]
24
43
 
44
+
25
45
  [dependency-groups]
26
46
  dev = [
27
47
  "pytest>=8.3.5",
@@ -38,6 +58,7 @@ dev = [
38
58
  flowmark = "flowmark.cli:main"
39
59
 
40
60
 
61
+
41
62
  # ---- Build system ----
42
63
 
43
64
  # Dynamic versioning from:
@@ -58,6 +79,11 @@ vcs = "git"
58
79
  style = "pep440"
59
80
  bump = "true"
60
81
 
82
+ [tool.hatch.build.targets.wheel]
83
+ # The source location for the package.
84
+ packages = ["src/flowmark"]
85
+
86
+
61
87
  # ---- Settings ----
62
88
 
63
89
  [tool.ruff]
@@ -65,8 +91,8 @@ bump = "true"
65
91
  line-length = 100
66
92
 
67
93
  [tool.ruff.lint]
68
- # See: https://docs.astral.sh/ruff/rules/
69
94
  select = [
95
+ # See: https://docs.astral.sh/ruff/rules/
70
96
  # Basic list from: https://docs.astral.sh/ruff/linter/#rule-selection
71
97
  "E", # https://docs.astral.sh/ruff/rules/#error-e
72
98
  "F", # https://docs.astral.sh/ruff/rules/#pyflakes-f
@@ -81,6 +107,7 @@ select = [
81
107
 
82
108
  ]
83
109
  ignore = [
110
+ # Disable some rules that are overly pedantic. Add/remove as desired:
84
111
  "E501", # https://docs.astral.sh/ruff/rules/line-too-long/
85
112
  "E402", # https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file/
86
113
  "E731", # https://docs.astral.sh/ruff/rules/lambda-assignment/
@@ -101,28 +128,38 @@ ignore = [
101
128
  "ISC002", # https://docs.astral.sh/ruff/rules/multi-line-implicit-string-concatenation/
102
129
  ]
103
130
 
131
+ [tool.basedpyright]
104
132
  # BasedPyright currently seems like the best type checker option, much faster
105
133
  # than mypy and with a good extension for VSCode/Cursor.
106
134
  # https://marketplace.visualstudio.com/items?itemName=detachhead.basedpyright
107
135
  # https://docs.basedpyright.com/latest/configuration/config-files/#sample-pyprojecttoml-file
108
- [tool.basedpyright]
109
136
  include = ["src", "tests", "devtools"]
110
- # Make ignoring easier:
137
+
138
+ # By default BasedPyright is very strict, so you almost certainly want to disable
139
+ # some of the rules.
140
+ # First, these turn off warnings about (yes) how you ignore warnings:
111
141
  reportIgnoreCommentWithoutRule = false
112
142
  reportUnnecessaryTypeIgnoreComment = false
113
- # Typically noisy warnings, comment/uncomment as desired:
143
+ # A few typically noisy warnings are next.
144
+ # How many you enable is up to you. The first few are off by default, but you can
145
+ # comment/uncomment these as desired:
114
146
  reportMissingTypeStubs = false
115
147
  reportUnusedCallResult = false
148
+ reportAny = false
149
+ reportExplicitAny = false
150
+ reportImplicitStringConcatenation = false
151
+ # reportUnreachable = false
152
+ # reportUnusedParameter = false
153
+ # reportPrivateImportUsage = false
154
+ # reportPrivateLocalImportUsage = false
116
155
  # reportMissingImports = false
117
156
  # reportUnnecessaryIsInstance = false
118
157
  # reportUnreachable = false
119
- reportAny = false
120
- reportExplicitAny = false
121
- reportUnusedParameter = false
122
158
  # reportUnknownVariableType = false
123
159
  # reportUnknownArgumentType = false
124
160
 
125
161
  [tool.codespell]
162
+ # Add here as needed:
126
163
  # ignore-words-list = "foo,bar"
127
164
  skip = "tests/testdocs/*.md"
128
165
 
@@ -0,0 +1,76 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable
4
+
5
+ from marko import block, inline
6
+ from marko.block import Document
7
+ from marko.element import Element
8
+
9
+ ContainerElement = (
10
+ block.Document,
11
+ block.Quote,
12
+ block.List,
13
+ block.ListItem,
14
+ block.Paragraph, # Paragraphs contain inline elements
15
+ block.Heading, # Already handled, but include for completeness if structure changes
16
+ inline.Emphasis,
17
+ inline.StrongEmphasis,
18
+ inline.Link,
19
+ )
20
+
21
+
22
+ def transform_tree(element: Element, transformer: Callable[[Element], None]) -> None:
23
+ """
24
+ Recursively traverse the element tree and apply a transformer function to each node.
25
+ """
26
+ transformer(element)
27
+
28
+ # Recursively process children for known container types
29
+ if isinstance(element, ContainerElement):
30
+ # Now we know element has a .children attribute that's a Sequence[Element] or str
31
+ # We only care about processing Element children
32
+ if isinstance(element.children, list):
33
+ # Create a copy for safe iteration if modification occurs
34
+ current_children = list(element.children)
35
+ for child in current_children:
36
+ transform_tree(child, transformer)
37
+
38
+
39
+ def _unbold_heading_transformer(element: Element) -> None:
40
+ """
41
+ Transformer function to unbold headings where the entire text is bold.
42
+ """
43
+ if isinstance(element, block.Heading):
44
+ # Check if the heading consists *only* of a single StrongEmphasis element
45
+ if len(element.children) == 1 and isinstance(element.children[0], inline.StrongEmphasis):
46
+ # Replace the heading's children with the children of the StrongEmphasis element
47
+ strong_emphasis_node = element.children[0]
48
+ # Type checker struggles here, but StrongEmphasis children should be Elements.
49
+ element.children = strong_emphasis_node.children # pyright: ignore
50
+
51
+ # Handle the case where the heading is bold and italic (StrongEmphasis inside Emphasis or vice versa)
52
+ # ***text*** -> *text*
53
+ elif len(element.children) == 1 and isinstance(element.children[0], inline.Emphasis):
54
+ emphasis_node = element.children[0]
55
+ if len(emphasis_node.children) == 1 and isinstance(
56
+ emphasis_node.children[0], inline.StrongEmphasis
57
+ ):
58
+ strong_node = emphasis_node.children[0]
59
+ emphasis_node.children = strong_node.children
60
+
61
+
62
+ def unbold_headings(doc: Document) -> None:
63
+ """
64
+ Find headings where the entire text is bold and remove the bold.
65
+
66
+ Modifies the Marko document tree in place using a general transformer.
67
+ Example: `## **My Heading**` -> `## My Heading`
68
+ """
69
+ transform_tree(doc, _unbold_heading_transformer)
70
+
71
+
72
+ def doc_cleanups(doc: Document):
73
+ """
74
+ Apply (ideally quite safe) cleanups to the document.
75
+ """
76
+ unbold_headings(doc)
@@ -55,6 +55,7 @@ class Options:
55
55
  width: int
56
56
  plaintext: bool
57
57
  semantic: bool
58
+ cleanups: bool
58
59
  inplace: bool
59
60
  nobackup: bool
60
61
  version: bool
@@ -98,6 +99,13 @@ def _parse_args(args: list[str] | None = None) -> Options:
98
99
  default=False,
99
100
  help="Enable semantic (sentence-based) line breaks (only applies to Markdown mode)",
100
101
  )
102
+ parser.add_argument(
103
+ "-c",
104
+ "--cleanups",
105
+ action="store_true",
106
+ default=False,
107
+ help="Enable (safe) cleanups for common issues (only applies to Markdown mode)",
108
+ )
101
109
  parser.add_argument(
102
110
  "-i", "--inplace", action="store_true", help="Edit the file in place (ignores --output)"
103
111
  )
@@ -129,6 +137,7 @@ def _parse_args(args: list[str] | None = None) -> Options:
129
137
  width=opts.width,
130
138
  plaintext=opts.plaintext,
131
139
  semantic=opts.semantic,
140
+ cleanups=opts.cleanups,
132
141
  inplace=opts.inplace,
133
142
  nobackup=opts.nobackup,
134
143
  version=opts.version,
@@ -177,6 +186,7 @@ def main(args: list[str] | None = None) -> int:
177
186
  text,
178
187
  width=options.width,
179
188
  semantic=options.semantic,
189
+ cleanups=options.cleanups,
180
190
  dedent_input=True,
181
191
  )
182
192