mdformat-space-control 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.
@@ -10,9 +10,10 @@ mdformat-space-control is an mdformat plugin that provides unified control over
10
10
  - **Frontmatter spacing**: Normalizes spacing after YAML frontmatter (works with mdformat-frontmatter)
11
11
  - **Consecutive blank line normalization**: Limits runs of 3+ empty lines to a maximum of 2
12
12
  - **Trailing whitespace removal**: Strips trailing whitespace outside code blocks
13
+ - **Smart dash conversion**: Converts `--` to en-dash and `---` to em-dash, with protection for HTML comments, tags, code blocks, and inline code spans
13
14
  - **Escaped link repair**: Fixes malformed multi-line links from web-clipped content
14
15
  - **Wikilink preservation**: Handles Obsidian-style `[[links]]`, `[[links|aliases]]`, `[[page#heading]]`, `[[page#^blockid]]`, and `![[embeds]]`
15
- - **Explicit line breaks**: Converts soft breaks to hard breaks (`\` + newline) in paragraphs, list items, and blockquotes
16
+ - **Soft break joining**: Joins soft breaks (plain newlines) into single lines in paragraphs, list items, and blockquotes
16
17
 
17
18
  This plugin merges functionality from mdformat-editorconfig and mdformat-tight-lists into a single plugin, solving the issue where mdformat only applies one set of list renderers when multiple plugins are installed.
18
19
 
@@ -41,11 +42,11 @@ mdformat_space_control/
41
42
  - **`plugin.py`**: Provides renderers, postprocessors, and parser extensions:
42
43
  - `_wikilink_rule`: Inline parser for Obsidian-style wikilinks
43
44
  - `_render_wikilink`: Preserves wikilinks unchanged
44
- - `_render_softbreak`: Converts soft breaks to hard breaks (backslash + newline)
45
+ - `_render_softbreak`: Joins soft breaks (plain newlines) into single lines with spaces
45
46
  - `_render_list_item`: Per-item tight/loose formatting based on paragraph count
46
47
  - `_render_bullet_list`: Configurable indent + content-based tight/loose
47
48
  - `_render_ordered_list`: Configurable indent + content-based tight/loose
48
- - `_postprocess_root`: Combined postprocessor applying frontmatter spacing, escaped link repair, consecutive blank line normalization, and trailing whitespace removal
49
+ - `_postprocess_root`: Combined postprocessor applying frontmatter spacing, smart dash conversion, escaped link repair, consecutive blank line normalization, and trailing whitespace removal
49
50
 
50
51
  ## Plugin Extension Points
51
52
 
@@ -66,6 +67,7 @@ space_control = "mdformat_space_control"
66
67
  - **`tests/test_fixtures.py`**: Parametrized fixture tests
67
68
  - **`tests/test_editorconfig.py`**: EditorConfig-specific tests using temp directories
68
69
  - **`tests/test_frontmatter.py`**: Frontmatter spacing tests (requires mdformat-frontmatter)
70
+ - **`tests/test_dash_conversion.py`**: Smart dash conversion with HTML comment/tag protection
69
71
  - **`tests/test_spacing_features.py`**: Trailing whitespace, hard breaks, escaped link repair, consecutive blank line tests
70
72
  - **`tests/test_integration.py`**: Full-stack integration tests combining multiple features
71
73
  - **`tests/test_plugin_interactions.py`**: Tests for compatibility with other mdformat plugins
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdformat_space_control
3
- Version: 0.4.0
3
+ Version: 0.4.2
4
4
  Summary: An mdformat plugin for space control: EditorConfig indentation, tight lists, frontmatter spacing, smart dash conversion, explicit line breaks, and wikilinks.
5
5
  Project-URL: Homepage, https://github.com/jdmonaco/mdformat-space-control
6
6
  Author-email: Joseph Monaco <joe@selfmotion.net>
@@ -39,9 +39,9 @@ An [mdformat](https://github.com/executablebooks/mdformat) plugin that provides
39
39
  - **Consecutive blank line normalization**: Limits runs of 3+ empty lines to a maximum of 2
40
40
  - **Trailing whitespace removal**: Strips trailing whitespace outside code blocks
41
41
  - **Escaped link repair**: Fixes malformed multi-line links from web-clipped content
42
- - **Smart dash conversion**: Converts `--` to en-dash (–) and `---` to em-dash (—), preserving code blocks and inline code
42
+ - **Smart dash conversion**: Converts `--` to en-dash (–) and `---` to em-dash (—), preserving code blocks, inline code, HTML comments, and HTML tags
43
43
  - **Wikilink preservation**: Handles Obsidian-style `[[links]]`, `[[links|aliases]]`, `[[page#heading]]`, `[[page#^blockid]]`, and `![[embeds]]`
44
- - **Explicit line breaks**: Converts soft breaks to hard breaks (`\` + newline) so source line breaks render visually in all Markdown renderers
44
+ - **Soft break joining**: Joins soft breaks (plain newlines within paragraphs) into single lines, normalizing to single-line paragraphs
45
45
 
46
46
  ## Installation
47
47
 
@@ -193,7 +193,7 @@ The result—unexpected as it was—changed everything.
193
193
  Pages 10–20 of the report.
194
194
  ```
195
195
 
196
- Dashes are preserved inside fenced code blocks and inline code spans. Thematic breaks (`---`) and frontmatter delimiters are not affected. Sequences of 4+ dashes are left unchanged.
196
+ Dashes are preserved inside fenced code blocks, inline code spans, HTML comments, and HTML tags. Thematic breaks (`---`) and frontmatter delimiters are not affected. Sequences of 4+ dashes are left unchanged.
197
197
 
198
198
  ### Wikilink Preservation
199
199
 
@@ -212,9 +212,9 @@ Wikilinks inside markdown link text are correctly handled without duplication:
212
212
  [![[image.jpg]]](http://example.com)
213
213
  ```
214
214
 
215
- ### Explicit Line Breaks
215
+ ### Soft Break Joining
216
216
 
217
- Soft breaks (plain newlines within paragraphs) are converted to hard breaks (backslash + newline). This makes source line breaks explicit so they render visually regardless of the Markdown renderer's line-break strictness setting. The conversion applies to paragraphs, list items, and blockquotes.
217
+ Soft breaks (plain newlines within paragraphs) are joined into single lines with spaces. This normalizes editor-inserted line wraps to single-line paragraphs, matching CommonMark rendering behavior where soft breaks produce spaces in HTML output. The joining applies to paragraphs, list items, and blockquotes.
218
218
 
219
219
  **Before:**
220
220
  ```markdown
@@ -224,14 +224,10 @@ a soft line break in the source.
224
224
 
225
225
  **After:**
226
226
  ```markdown
227
- This is a paragraph with\
228
- a hard line break in the output.
227
+ This is a paragraph with a soft line break in the source.
229
228
  ```
230
229
 
231
- > **Note:** Without a GFM table parser, markdown-it treats pipe tables as paragraphs
232
- > containing soft breaks, which causes backslashes to appear at the end of table rows.
233
- > Install `mdformat-gfm` to enable proper table parsing and avoid this issue
234
- > (see [Compatible Plugins](#compatible-plugins)).
230
+ Explicit hard breaks (`\` + newline) are preserved unchanged.
235
231
 
236
232
  ## Compatible Plugins
237
233
 
@@ -11,9 +11,9 @@ An [mdformat](https://github.com/executablebooks/mdformat) plugin that provides
11
11
  - **Consecutive blank line normalization**: Limits runs of 3+ empty lines to a maximum of 2
12
12
  - **Trailing whitespace removal**: Strips trailing whitespace outside code blocks
13
13
  - **Escaped link repair**: Fixes malformed multi-line links from web-clipped content
14
- - **Smart dash conversion**: Converts `--` to en-dash (–) and `---` to em-dash (—), preserving code blocks and inline code
14
+ - **Smart dash conversion**: Converts `--` to en-dash (–) and `---` to em-dash (—), preserving code blocks, inline code, HTML comments, and HTML tags
15
15
  - **Wikilink preservation**: Handles Obsidian-style `[[links]]`, `[[links|aliases]]`, `[[page#heading]]`, `[[page#^blockid]]`, and `![[embeds]]`
16
- - **Explicit line breaks**: Converts soft breaks to hard breaks (`\` + newline) so source line breaks render visually in all Markdown renderers
16
+ - **Soft break joining**: Joins soft breaks (plain newlines within paragraphs) into single lines, normalizing to single-line paragraphs
17
17
 
18
18
  ## Installation
19
19
 
@@ -165,7 +165,7 @@ The result—unexpected as it was—changed everything.
165
165
  Pages 10–20 of the report.
166
166
  ```
167
167
 
168
- Dashes are preserved inside fenced code blocks and inline code spans. Thematic breaks (`---`) and frontmatter delimiters are not affected. Sequences of 4+ dashes are left unchanged.
168
+ Dashes are preserved inside fenced code blocks, inline code spans, HTML comments, and HTML tags. Thematic breaks (`---`) and frontmatter delimiters are not affected. Sequences of 4+ dashes are left unchanged.
169
169
 
170
170
  ### Wikilink Preservation
171
171
 
@@ -184,9 +184,9 @@ Wikilinks inside markdown link text are correctly handled without duplication:
184
184
  [![[image.jpg]]](http://example.com)
185
185
  ```
186
186
 
187
- ### Explicit Line Breaks
187
+ ### Soft Break Joining
188
188
 
189
- Soft breaks (plain newlines within paragraphs) are converted to hard breaks (backslash + newline). This makes source line breaks explicit so they render visually regardless of the Markdown renderer's line-break strictness setting. The conversion applies to paragraphs, list items, and blockquotes.
189
+ Soft breaks (plain newlines within paragraphs) are joined into single lines with spaces. This normalizes editor-inserted line wraps to single-line paragraphs, matching CommonMark rendering behavior where soft breaks produce spaces in HTML output. The joining applies to paragraphs, list items, and blockquotes.
190
190
 
191
191
  **Before:**
192
192
  ```markdown
@@ -196,14 +196,10 @@ a soft line break in the source.
196
196
 
197
197
  **After:**
198
198
  ```markdown
199
- This is a paragraph with\
200
- a hard line break in the output.
199
+ This is a paragraph with a soft line break in the source.
201
200
  ```
202
201
 
203
- > **Note:** Without a GFM table parser, markdown-it treats pipe tables as paragraphs
204
- > containing soft breaks, which causes backslashes to appear at the end of table rows.
205
- > Install `mdformat-gfm` to enable proper table parsing and avoid this issue
206
- > (see [Compatible Plugins](#compatible-plugins)).
202
+ Explicit hard breaks (`\` + newline) are preserved unchanged.
207
203
 
208
204
  ## Compatible Plugins
209
205
 
@@ -1,6 +1,6 @@
1
- """An mdformat plugin for space control: EditorConfig indentation, tight lists, frontmatter spacing, smart dash conversion, explicit line breaks, and wikilinks."""
1
+ """An mdformat plugin for space control: EditorConfig indentation, tight lists, frontmatter spacing, smart dash conversion, soft break joining, and wikilinks."""
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.4.2"
4
4
 
5
5
  from .config import (
6
6
  get_current_file,
@@ -274,13 +274,14 @@ def _render_wikilink(node: RenderTreeNode, context: RenderContext) -> str:
274
274
 
275
275
 
276
276
  def _render_softbreak(node: RenderTreeNode, context: RenderContext) -> str:
277
- """Render soft breaks with terminal backslash.
277
+ """Join soft breaks into a single line.
278
278
 
279
- Converts soft breaks (plain newlines within paragraphs) to hard breaks
280
- (backslash + newline) to preserve visible line-break rendering and avoid
281
- relying on trailing whitespace.
279
+ Soft breaks (plain newlines within paragraphs) are editor-inserted
280
+ line wraps, not intentional visible breaks. Join them with a space
281
+ to normalize to single-line paragraphs. This matches CommonMark
282
+ rendering behavior where soft breaks produce spaces in HTML output.
282
283
  """
283
- return "\\" + "\n"
284
+ return " "
284
285
 
285
286
 
286
287
  # A mapping from syntax tree node type to a function that renders it.
@@ -391,7 +392,8 @@ def _convert_dash_sequences(text: str) -> str:
391
392
  """Convert markdown dash sequences to Unicode em-dash and en-dash.
392
393
 
393
394
  Converts ``---`` to em-dash (U+2014) and ``--`` to en-dash (U+2013).
394
- Preserves dashes inside fenced code blocks and inline code spans.
395
+ Preserves dashes inside fenced code blocks, inline code spans,
396
+ HTML comments, and HTML tags.
395
397
  Skips lines that are only dashes (thematic breaks, frontmatter delimiters).
396
398
 
397
399
  Em-dash is matched first (longer sequence) to prevent ``---`` from being
@@ -400,6 +402,10 @@ def _convert_dash_sequences(text: str) -> str:
400
402
  # Patterns for inline code span placeholders
401
403
  inline_code_re = re.compile(r"(`+)(.+?)\1")
402
404
 
405
+ # HTML protection patterns
406
+ html_comment_re = re.compile(r"<!--.*?-->")
407
+ html_tag_re = re.compile(r"<[^>]+>")
408
+
403
409
  # Dash conversion patterns: negative lookahead/behind prevent matching
404
410
  # 4+ dash sequences (e.g., ---- horizontal rules in some contexts)
405
411
  em_dash_re = re.compile(r"(?<!-)---(?!-)")
@@ -411,6 +417,7 @@ def _convert_dash_sequences(text: str) -> str:
411
417
  lines = text.split("\n")
412
418
  result = []
413
419
  in_code_block = False
420
+ in_html_comment = False
414
421
 
415
422
  for line in lines:
416
423
  stripped = line.lstrip()
@@ -419,23 +426,38 @@ def _convert_dash_sequences(text: str) -> str:
419
426
  result.append(line)
420
427
  elif in_code_block:
421
428
  result.append(line)
429
+ elif in_html_comment:
430
+ # Inside a multi-line HTML comment, skip dash conversion
431
+ if "-->" in line:
432
+ in_html_comment = False
433
+ result.append(line)
422
434
  elif only_dashes_re.match(line):
423
435
  result.append(line)
424
436
  else:
425
- # Protect inline code spans with placeholders
437
+ # Check for multi-line HTML comment opening (no closing on same line)
438
+ if "<!--" in line and "-->" not in line:
439
+ in_html_comment = True
440
+ result.append(line)
441
+ continue
442
+
443
+ # Protect inline code spans and HTML elements with placeholders
426
444
  placeholders = []
427
445
 
428
- def _save_code_span(m: re.Match) -> str:
446
+ def _save_placeholder(m: re.Match) -> str:
429
447
  placeholders.append(m.group(0))
430
448
  return f"\x00CODE{len(placeholders) - 1}\x00"
431
449
 
432
- protected = inline_code_re.sub(_save_code_span, line)
450
+ protected = inline_code_re.sub(_save_placeholder, line)
451
+
452
+ # Protect HTML comments first (longer matches), then tags
453
+ protected = html_comment_re.sub(_save_placeholder, protected)
454
+ protected = html_tag_re.sub(_save_placeholder, protected)
433
455
 
434
456
  # Convert em-dash first (longer match), then en-dash
435
457
  protected = em_dash_re.sub("\u2014", protected)
436
458
  protected = en_dash_re.sub("\u2013", protected)
437
459
 
438
- # Restore inline code spans
460
+ # Restore placeholders
439
461
  for i, original in enumerate(placeholders):
440
462
  protected = protected.replace(f"\x00CODE{i}\x00", original)
441
463