mkdocs2confluence 0.6.5__tar.gz → 0.6.7__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.
- {mkdocs2confluence-0.6.5/src/mkdocs2confluence.egg-info → mkdocs2confluence-0.6.7}/PKG-INFO +9 -3
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/README.md +8 -2
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/pyproject.toml +1 -1
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7/src/mkdocs2confluence.egg-info}/PKG-INFO +9 -3
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/emitter/xhtml.py +3 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/ir/__init__.py +2 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/ir/nodes.py +7 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/config.py +7 -2
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/parser/markdown.py +58 -16
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_emitter.py +5 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_ir.py +5 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_parser.py +32 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_publish_pipeline.py +1 -1
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/LICENSE +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/setup.cfg +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/SOURCES.txt +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/dependency_links.txt +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/entry_points.txt +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/requires.txt +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/top_level.txt +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/cli.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/emitter/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/ir/document.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/ir/treeutil.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/extra_css.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/nav.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/page.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/parser/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/abbrevs.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/fence.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/frontmatter.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/icons.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/includes.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/linkdefs.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preview/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preview/render.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/publisher/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/publisher/client.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/publisher/pipeline.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/__init__.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/abbrevs.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/assets.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/editlink.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/images.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/internallinks.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/mermaid.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_abbrevs.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_cli.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_editlink.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_extra_css.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_frontmatter.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_icons.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_images.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_internallinks.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_linkdefs.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_loader.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_mermaid.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_page_loader.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_preprocess.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_preview.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_publish_client.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_publish_config.py +0 -0
- {mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/tests/test_treeutil.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs2confluence
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: Publish MkDocs Material pages to Confluence Cloud — admonitions, Mermaid diagrams, tabs, page properties and more
|
|
5
5
|
Author: Anders Hybertz
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -36,7 +36,7 @@ Requires-Dist: bandit; extra == "dev"
|
|
|
36
36
|
Requires-Dist: build; extra == "dev"
|
|
37
37
|
Dynamic: license-file
|
|
38
38
|
|
|
39
|
-
# mk2conf — MkDocs to Confluence
|
|
39
|
+
# mk2conf — MkDocs / Zensical to Confluence
|
|
40
40
|
|
|
41
41
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
42
42
|
[](https://www.python.org/downloads/)
|
|
@@ -54,6 +54,8 @@ A Python CLI tool that compiles MkDocs-flavoured Markdown into native Confluence
|
|
|
54
54
|
|
|
55
55
|
It is a **compiler/transpiler**, not an HTML converter — every Markdown construct is mapped to the equivalent native Confluence macro or element, so pages look and behave like hand-authored Confluence content.
|
|
56
56
|
|
|
57
|
+
> **Zensical compatible** — [Zensical](https://zensical.org/) is the modern successor to MkDocs + Material for MkDocs, built by the same team. Since Zensical uses the same `mkdocs.yml` format and Python Markdown extensions, your Zensical project works with this tool today — no changes required.
|
|
58
|
+
|
|
57
59
|
---
|
|
58
60
|
|
|
59
61
|
## Architecture
|
|
@@ -255,12 +257,16 @@ extra_css:
|
|
|
255
257
|
| `**bold**` / `__bold__` | `<strong>` |
|
|
256
258
|
| `*italic*` | `<em>` |
|
|
257
259
|
| `~~strikethrough~~` | `<s>` |
|
|
260
|
+
| `~subscript~` | `<sub>` (pymdownx.tilde) |
|
|
261
|
+
| `^superscript^` | `<sup>` (pymdownx.caret) |
|
|
262
|
+
| `^^inserted^^` | `<u>` (pymdownx.caret insert) |
|
|
258
263
|
| `` `inline code` `` | `<code>` |
|
|
259
264
|
| `[text](url)` | `<a href="...">` |
|
|
265
|
+
| `https://bare-url` | `<a href="...">` (autolink) |
|
|
260
266
|
| `[text](file.pdf)` | `<ac:link><ri:attachment .../>` (uploaded as attachment) |
|
|
261
267
|
| `` | `<ac:image>` with `<ri:attachment>` (local) or `<ri:url>` (remote) |
|
|
262
268
|
| `{ width="400" }` | `<ac:image ac:width="400">` — also supports `height` and `align` |
|
|
263
|
-
| `<br>` / `<br/>` | `<br />` |
|
|
269
|
+
| `<br>` / `<br/>` / trailing `\` | `<br />` |
|
|
264
270
|
| `<sub>` / `<sup>` / `<u>` / `<small>` | Direct XHTML passthrough |
|
|
265
271
|
| `<mark>text</mark>` | `<span style="background-color: yellow;">` |
|
|
266
272
|
| `<kbd>text</kbd>` | `<code>` |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# mk2conf — MkDocs to Confluence
|
|
1
|
+
# mk2conf — MkDocs / Zensical to Confluence
|
|
2
2
|
|
|
3
3
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
4
4
|
[](https://www.python.org/downloads/)
|
|
@@ -16,6 +16,8 @@ A Python CLI tool that compiles MkDocs-flavoured Markdown into native Confluence
|
|
|
16
16
|
|
|
17
17
|
It is a **compiler/transpiler**, not an HTML converter — every Markdown construct is mapped to the equivalent native Confluence macro or element, so pages look and behave like hand-authored Confluence content.
|
|
18
18
|
|
|
19
|
+
> **Zensical compatible** — [Zensical](https://zensical.org/) is the modern successor to MkDocs + Material for MkDocs, built by the same team. Since Zensical uses the same `mkdocs.yml` format and Python Markdown extensions, your Zensical project works with this tool today — no changes required.
|
|
20
|
+
|
|
19
21
|
---
|
|
20
22
|
|
|
21
23
|
## Architecture
|
|
@@ -217,12 +219,16 @@ extra_css:
|
|
|
217
219
|
| `**bold**` / `__bold__` | `<strong>` |
|
|
218
220
|
| `*italic*` | `<em>` |
|
|
219
221
|
| `~~strikethrough~~` | `<s>` |
|
|
222
|
+
| `~subscript~` | `<sub>` (pymdownx.tilde) |
|
|
223
|
+
| `^superscript^` | `<sup>` (pymdownx.caret) |
|
|
224
|
+
| `^^inserted^^` | `<u>` (pymdownx.caret insert) |
|
|
220
225
|
| `` `inline code` `` | `<code>` |
|
|
221
226
|
| `[text](url)` | `<a href="...">` |
|
|
227
|
+
| `https://bare-url` | `<a href="...">` (autolink) |
|
|
222
228
|
| `[text](file.pdf)` | `<ac:link><ri:attachment .../>` (uploaded as attachment) |
|
|
223
229
|
| `` | `<ac:image>` with `<ri:attachment>` (local) or `<ri:url>` (remote) |
|
|
224
230
|
| `{ width="400" }` | `<ac:image ac:width="400">` — also supports `height` and `align` |
|
|
225
|
-
| `<br>` / `<br/>` | `<br />` |
|
|
231
|
+
| `<br>` / `<br/>` / trailing `\` | `<br />` |
|
|
226
232
|
| `<sub>` / `<sup>` / `<u>` / `<small>` | Direct XHTML passthrough |
|
|
227
233
|
| `<mark>text</mark>` | `<span style="background-color: yellow;">` |
|
|
228
234
|
| `<kbd>text</kbd>` | `<code>` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mkdocs2confluence"
|
|
3
|
-
version = "0.6.
|
|
3
|
+
version = "0.6.7"
|
|
4
4
|
description = "Publish MkDocs Material pages to Confluence Cloud — admonitions, Mermaid diagrams, tabs, page properties and more"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = { text = "GPL-3.0-or-later" }
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mkdocs2confluence
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: Publish MkDocs Material pages to Confluence Cloud — admonitions, Mermaid diagrams, tabs, page properties and more
|
|
5
5
|
Author: Anders Hybertz
|
|
6
6
|
License: GPL-3.0-or-later
|
|
@@ -36,7 +36,7 @@ Requires-Dist: bandit; extra == "dev"
|
|
|
36
36
|
Requires-Dist: build; extra == "dev"
|
|
37
37
|
Dynamic: license-file
|
|
38
38
|
|
|
39
|
-
# mk2conf — MkDocs to Confluence
|
|
39
|
+
# mk2conf — MkDocs / Zensical to Confluence
|
|
40
40
|
|
|
41
41
|
[](https://www.gnu.org/licenses/gpl-3.0)
|
|
42
42
|
[](https://www.python.org/downloads/)
|
|
@@ -54,6 +54,8 @@ A Python CLI tool that compiles MkDocs-flavoured Markdown into native Confluence
|
|
|
54
54
|
|
|
55
55
|
It is a **compiler/transpiler**, not an HTML converter — every Markdown construct is mapped to the equivalent native Confluence macro or element, so pages look and behave like hand-authored Confluence content.
|
|
56
56
|
|
|
57
|
+
> **Zensical compatible** — [Zensical](https://zensical.org/) is the modern successor to MkDocs + Material for MkDocs, built by the same team. Since Zensical uses the same `mkdocs.yml` format and Python Markdown extensions, your Zensical project works with this tool today — no changes required.
|
|
58
|
+
|
|
57
59
|
---
|
|
58
60
|
|
|
59
61
|
## Architecture
|
|
@@ -255,12 +257,16 @@ extra_css:
|
|
|
255
257
|
| `**bold**` / `__bold__` | `<strong>` |
|
|
256
258
|
| `*italic*` | `<em>` |
|
|
257
259
|
| `~~strikethrough~~` | `<s>` |
|
|
260
|
+
| `~subscript~` | `<sub>` (pymdownx.tilde) |
|
|
261
|
+
| `^superscript^` | `<sup>` (pymdownx.caret) |
|
|
262
|
+
| `^^inserted^^` | `<u>` (pymdownx.caret insert) |
|
|
258
263
|
| `` `inline code` `` | `<code>` |
|
|
259
264
|
| `[text](url)` | `<a href="...">` |
|
|
265
|
+
| `https://bare-url` | `<a href="...">` (autolink) |
|
|
260
266
|
| `[text](file.pdf)` | `<ac:link><ri:attachment .../>` (uploaded as attachment) |
|
|
261
267
|
| `` | `<ac:image>` with `<ri:attachment>` (local) or `<ri:url>` (remote) |
|
|
262
268
|
| `{ width="400" }` | `<ac:image ac:width="400">` — also supports `height` and `align` |
|
|
263
|
-
| `<br>` / `<br/>` | `<br />` |
|
|
269
|
+
| `<br>` / `<br/>` / trailing `\` | `<br />` |
|
|
264
270
|
| `<sub>` / `<sup>` / `<u>` / `<small>` | Direct XHTML passthrough |
|
|
265
271
|
| `<mark>text</mark>` | `<span style="background-color: yellow;">` |
|
|
266
272
|
| `<kbd>text</kbd>` | `<code>` |
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/emitter/xhtml.py
RENAMED
|
@@ -37,6 +37,7 @@ from mkdocs_to_confluence.ir.nodes import (
|
|
|
37
37
|
HorizontalRule,
|
|
38
38
|
ImageNode,
|
|
39
39
|
InlineHtmlNode,
|
|
40
|
+
InsertNode,
|
|
40
41
|
IRNode,
|
|
41
42
|
ItalicNode,
|
|
42
43
|
LineBreakNode,
|
|
@@ -548,6 +549,8 @@ def _emit_inline(node: IRNode) -> str:
|
|
|
548
549
|
return f"<sub>{_emit_inlines(node.children)}</sub>"
|
|
549
550
|
if isinstance(node, SuperscriptNode):
|
|
550
551
|
return f"<sup>{_emit_inlines(node.children)}</sup>"
|
|
552
|
+
if isinstance(node, InsertNode):
|
|
553
|
+
return f"<u>{_emit_inlines(node.children)}</u>"
|
|
551
554
|
if isinstance(node, CodeInlineNode):
|
|
552
555
|
style_attr = styles_to_attr(_styles.code_inline) if _styles else ""
|
|
553
556
|
return f"<code{style_attr}>{html.escape(node.code)}</code>"
|
|
@@ -32,6 +32,7 @@ from mkdocs_to_confluence.ir.nodes import (
|
|
|
32
32
|
ImageNode,
|
|
33
33
|
# Inline HTML nodes
|
|
34
34
|
InlineHtmlNode,
|
|
35
|
+
InsertNode,
|
|
35
36
|
# Traversal utility
|
|
36
37
|
IRNode,
|
|
37
38
|
ItalicNode,
|
|
@@ -79,6 +80,7 @@ __all__ = [
|
|
|
79
80
|
"ImageNode",
|
|
80
81
|
"LineBreakNode",
|
|
81
82
|
"InlineHtmlNode",
|
|
83
|
+
"InsertNode",
|
|
82
84
|
# Block
|
|
83
85
|
"Section",
|
|
84
86
|
"Paragraph",
|
|
@@ -73,6 +73,13 @@ class SubscriptNode(IRNode):
|
|
|
73
73
|
children: tuple[IRNode, ...]
|
|
74
74
|
|
|
75
75
|
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class InsertNode(IRNode):
|
|
78
|
+
"""Inserted (underlined) inline content (``^^text^^``)."""
|
|
79
|
+
|
|
80
|
+
children: tuple[IRNode, ...]
|
|
81
|
+
|
|
82
|
+
|
|
76
83
|
@dataclass(frozen=True)
|
|
77
84
|
class CodeInlineNode(IRNode):
|
|
78
85
|
"""An inline code span (`` `code` ``)."""
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/config.py
RENAMED
|
@@ -7,6 +7,7 @@ import re
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import Any
|
|
10
|
+
from urllib.parse import urlparse
|
|
10
11
|
|
|
11
12
|
import yaml
|
|
12
13
|
|
|
@@ -118,9 +119,13 @@ def _default_edit_uri(repo_url: str | None) -> str | None:
|
|
|
118
119
|
"""Return a sensible default ``edit_uri`` based on the hosting platform."""
|
|
119
120
|
if not repo_url:
|
|
120
121
|
return None
|
|
121
|
-
|
|
122
|
+
try:
|
|
123
|
+
hostname = urlparse(repo_url).hostname or ""
|
|
124
|
+
except ValueError:
|
|
125
|
+
return None
|
|
126
|
+
if hostname == "github.com" or hostname.endswith(".github.com"):
|
|
122
127
|
return "edit/main/docs/"
|
|
123
|
-
if "gitlab.com"
|
|
128
|
+
if hostname == "gitlab.com" or hostname.endswith(".gitlab.com") or "gitlab" in hostname:
|
|
124
129
|
return "-/edit/master/docs/"
|
|
125
130
|
return None
|
|
126
131
|
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/parser/markdown.py
RENAMED
|
@@ -1,24 +1,36 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
3
|
-
Supported
|
|
1
|
+
"""Markdown-to-IR parser.
|
|
2
|
+
|
|
3
|
+
Supported inline constructs
|
|
4
|
+
----------------------------
|
|
5
|
+
* ``**bold**`` / ``__bold__`` → :class:`~ir.BoldNode`
|
|
6
|
+
* ``*italic*`` → :class:`~ir.ItalicNode`
|
|
7
|
+
* ``~~strikethrough~~`` → :class:`~ir.StrikethroughNode`
|
|
8
|
+
* ``~subscript~`` → :class:`~ir.SubscriptNode`
|
|
9
|
+
* ``^superscript^`` → :class:`~ir.SuperscriptNode`
|
|
10
|
+
* ``^^insert^^`` (underline) → :class:`~ir.InsertNode`
|
|
11
|
+
* `` `code` `` → :class:`~ir.CodeInlineNode`
|
|
12
|
+
* ``[text](url)`` → :class:`~ir.LinkNode`
|
|
13
|
+
* Bare ``https://`` / ``http://`` URLs → :class:`~ir.LinkNode`
|
|
14
|
+
* ```` → :class:`~ir.ImageNode`
|
|
15
|
+
* ``<br>`` / ``<br/>`` / trailing ``\\`` → :class:`~ir.LineBreakNode`
|
|
16
|
+
* ``<mark>``, ``<kbd>``, ``<sub>``, ``<sup>``, ``<u>``, ``<s>``, ``<small>`` → :class:`~ir.InlineHtmlNode`
|
|
17
|
+
* ``++key+key++`` → :class:`~ir.InlineHtmlNode` ``kbd`` (pymdownx.keys)
|
|
18
|
+
* ``[^label]`` footnote references → :class:`~ir.FootnoteRef`
|
|
19
|
+
|
|
20
|
+
Supported block constructs
|
|
4
21
|
---------------------------
|
|
5
22
|
* ATX headings (``# H1`` … ``###### H6``) → :class:`~ir.Section`
|
|
6
23
|
* Fenced code blocks (`` ``` `` or ``~~~``) → :class:`~ir.CodeBlock`
|
|
7
24
|
with full Material attribute parsing (language, title, linenums, hl_lines)
|
|
8
25
|
* Paragraphs (consecutive non-blank lines) → :class:`~ir.Paragraph`
|
|
9
26
|
* Admonitions (``!!!``/``???``/``???+``) → :class:`~ir.Admonition`
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* Block quotes, lists, tables, horizontal rules
|
|
18
|
-
|
|
19
|
-
Inline content of headings and paragraphs is represented as a single
|
|
20
|
-
:class:`~ir.TextNode` carrying the raw text; once the inline parser is
|
|
21
|
-
implemented that node will be replaced by structured inline nodes.
|
|
27
|
+
* Content tabs (``=== "Label"``) → :class:`~ir.ContentTabs`
|
|
28
|
+
* Ordered and unordered lists, incl. task lists (``- [x]``) → :class:`~ir.BulletList` / :class:`~ir.OrderedList`
|
|
29
|
+
* Tables → :class:`~ir.Table`
|
|
30
|
+
* Definition lists → :class:`~ir.DefinitionList`
|
|
31
|
+
* Block quotes → :class:`~ir.BlockQuote`
|
|
32
|
+
* Horizontal rules → :class:`~ir.HorizontalRule`
|
|
33
|
+
* Mermaid fenced blocks → :class:`~ir.MermaidDiagram`
|
|
22
34
|
|
|
23
35
|
Architecture notes
|
|
24
36
|
------------------
|
|
@@ -57,6 +69,7 @@ from mkdocs_to_confluence.ir.nodes import (
|
|
|
57
69
|
HorizontalRule,
|
|
58
70
|
ImageNode,
|
|
59
71
|
InlineHtmlNode,
|
|
72
|
+
InsertNode,
|
|
60
73
|
IRNode,
|
|
61
74
|
ItalicNode,
|
|
62
75
|
LineBreakNode,
|
|
@@ -833,6 +846,16 @@ def _scan_inline(text: str, fn_map: dict[str, int] | None = None) -> list[IRNode
|
|
|
833
846
|
i = close_idx + 1
|
|
834
847
|
continue
|
|
835
848
|
|
|
849
|
+
# Insert (underline): ^^text^^ — checked before single ^
|
|
850
|
+
if text[i : i + 2] == "^^":
|
|
851
|
+
close_idx = text.find("^^", i + 2)
|
|
852
|
+
if close_idx != -1:
|
|
853
|
+
flush()
|
|
854
|
+
inner = _scan_inline(text[i + 2 : close_idx], _fn)
|
|
855
|
+
nodes.append(InsertNode(children=tuple(inner)))
|
|
856
|
+
i = close_idx + 2
|
|
857
|
+
continue
|
|
858
|
+
|
|
836
859
|
# Superscript: ^text^
|
|
837
860
|
if text[i] == "^":
|
|
838
861
|
close_idx = text.find("^", i + 1)
|
|
@@ -878,6 +901,16 @@ def _scan_inline(text: str, fn_map: dict[str, int] | None = None) -> list[IRNode
|
|
|
878
901
|
i = close_idx + len(close)
|
|
879
902
|
continue
|
|
880
903
|
|
|
904
|
+
# Bare URL autolink: https:// or http://
|
|
905
|
+
if text[i : i + 4] in ("http", "ftp:"):
|
|
906
|
+
url_m = re.match(r"(https?://|ftp://)[^\s<>\[\]\"']+", text[i:])
|
|
907
|
+
if url_m:
|
|
908
|
+
flush()
|
|
909
|
+
url = url_m.group(0)
|
|
910
|
+
nodes.append(LinkNode(href=url, children=(TextNode(text=url),)))
|
|
911
|
+
i += len(url)
|
|
912
|
+
continue
|
|
913
|
+
|
|
881
914
|
buf += text[i]
|
|
882
915
|
i += 1
|
|
883
916
|
|
|
@@ -1067,7 +1100,16 @@ def _append_content(
|
|
|
1067
1100
|
|
|
1068
1101
|
def _paragraph_node(token: _ParagraphToken, fn_map: dict[str, int] | None = None) -> Paragraph:
|
|
1069
1102
|
"""Convert a paragraph token into a :class:`~ir.Paragraph` node."""
|
|
1070
|
-
|
|
1103
|
+
# Trailing backslash on a line is a hard line break (CommonMark / pymdownx.escapeall).
|
|
1104
|
+
# Preserve it as <br> so the inline parser can detect it.
|
|
1105
|
+
parts: list[str] = []
|
|
1106
|
+
for line in token.lines:
|
|
1107
|
+
stripped = line.strip()
|
|
1108
|
+
if stripped.endswith("\\"):
|
|
1109
|
+
parts.append(stripped[:-1] + "<br>")
|
|
1110
|
+
else:
|
|
1111
|
+
parts.append(stripped)
|
|
1112
|
+
text = " ".join(parts)
|
|
1071
1113
|
return Paragraph(children=_parse_inline(text, fn_map=fn_map))
|
|
1072
1114
|
|
|
1073
1115
|
|
|
@@ -12,6 +12,7 @@ from mkdocs_to_confluence.ir.nodes import (
|
|
|
12
12
|
ContentTabs,
|
|
13
13
|
Expandable,
|
|
14
14
|
HorizontalRule,
|
|
15
|
+
InsertNode,
|
|
15
16
|
ItalicNode,
|
|
16
17
|
LinkNode,
|
|
17
18
|
ListItem,
|
|
@@ -267,6 +268,10 @@ class TestSubscriptSuperscriptEmitter:
|
|
|
267
268
|
out = emit((Paragraph((SuperscriptNode((TextNode("2"),)),)),))
|
|
268
269
|
assert "<sup>2</sup>" in out
|
|
269
270
|
|
|
271
|
+
def test_insert(self) -> None:
|
|
272
|
+
out = emit((Paragraph((InsertNode((TextNode("new"),)),)),))
|
|
273
|
+
assert "<u>new</u>" in out
|
|
274
|
+
|
|
270
275
|
|
|
271
276
|
class TestDefinitionListEmitter:
|
|
272
277
|
def test_basic_dl(self) -> None:
|
|
@@ -19,6 +19,7 @@ from mkdocs_to_confluence.ir import (
|
|
|
19
19
|
Expandable,
|
|
20
20
|
HorizontalRule,
|
|
21
21
|
ImageNode,
|
|
22
|
+
InsertNode,
|
|
22
23
|
IRNode,
|
|
23
24
|
ItalicNode,
|
|
24
25
|
LinkNode,
|
|
@@ -192,6 +193,10 @@ class TestInlineNodes:
|
|
|
192
193
|
node = SuperscriptNode(children=(TextNode(text="2"),))
|
|
193
194
|
assert len(node.children) == 1
|
|
194
195
|
|
|
196
|
+
def test_insert_node(self) -> None:
|
|
197
|
+
node = InsertNode(children=(TextNode(text="new"),))
|
|
198
|
+
assert len(node.children) == 1
|
|
199
|
+
|
|
195
200
|
def test_code_inline_node(self) -> None:
|
|
196
201
|
node = CodeInlineNode(code="print()")
|
|
197
202
|
assert node.code == "print()"
|
|
@@ -735,6 +735,7 @@ from mkdocs_to_confluence.ir import ( # noqa: E402
|
|
|
735
735
|
DefinitionList,
|
|
736
736
|
HorizontalRule,
|
|
737
737
|
ImageNode,
|
|
738
|
+
InsertNode,
|
|
738
739
|
ItalicNode,
|
|
739
740
|
LinkNode,
|
|
740
741
|
OrderedList,
|
|
@@ -783,6 +784,37 @@ class TestInlineParsing:
|
|
|
783
784
|
sup = next(n for n in para.children if isinstance(n, SuperscriptNode))
|
|
784
785
|
assert sup.children[0].text == "2" # type: ignore[union-attr]
|
|
785
786
|
|
|
787
|
+
def test_insert_underline(self) -> None:
|
|
788
|
+
para = first(parse("^^inserted^^\n"), Paragraph)
|
|
789
|
+
assert isinstance(para, Paragraph)
|
|
790
|
+
ins = next(n for n in para.children if isinstance(n, InsertNode))
|
|
791
|
+
assert ins.children[0].text == "inserted" # type: ignore[union-attr]
|
|
792
|
+
|
|
793
|
+
def test_insert_does_not_consume_superscript(self) -> None:
|
|
794
|
+
"""^^text^^ should produce InsertNode, not two SuperscriptNodes."""
|
|
795
|
+
para = first(parse("^^hello^^\n"), Paragraph)
|
|
796
|
+
nodes = [n for n in para.children if isinstance(n, InsertNode)]
|
|
797
|
+
sup_nodes = [n for n in para.children if isinstance(n, SuperscriptNode)]
|
|
798
|
+
assert len(nodes) == 1
|
|
799
|
+
assert len(sup_nodes) == 0
|
|
800
|
+
|
|
801
|
+
def test_bare_url_autolink(self) -> None:
|
|
802
|
+
para = first(parse("See https://example.com for details.\n"), Paragraph)
|
|
803
|
+
link = next(n for n in para.children if isinstance(n, LinkNode))
|
|
804
|
+
assert link.href == "https://example.com"
|
|
805
|
+
assert link.children[0].text == "https://example.com" # type: ignore[union-attr]
|
|
806
|
+
|
|
807
|
+
def test_bare_url_http(self) -> None:
|
|
808
|
+
para = first(parse("Visit http://example.com today.\n"), Paragraph)
|
|
809
|
+
link = next(n for n in para.children if isinstance(n, LinkNode))
|
|
810
|
+
assert link.href == "http://example.com"
|
|
811
|
+
|
|
812
|
+
def test_trailing_backslash_hard_break(self) -> None:
|
|
813
|
+
from mkdocs_to_confluence.ir import LineBreakNode
|
|
814
|
+
nodes = parse("Line one\\\nLine two\n")
|
|
815
|
+
para = first(nodes, Paragraph)
|
|
816
|
+
assert any(isinstance(n, LineBreakNode) for n in para.children)
|
|
817
|
+
|
|
786
818
|
def test_inline_code(self) -> None:
|
|
787
819
|
para = first(parse("Use `foo()` here.\n"), Paragraph)
|
|
788
820
|
assert isinstance(para, Paragraph)
|
|
@@ -332,7 +332,7 @@ def test_dry_run_prints_page_list(tmp_path: Path, capsys: pytest.CaptureFixture)
|
|
|
332
332
|
|
|
333
333
|
captured = capsys.readouterr()
|
|
334
334
|
assert "Dry run" in captured.out
|
|
335
|
-
assert "example.atlassian.net" in captured.out
|
|
335
|
+
assert "example.atlassian.net" in captured.out # codeql[py/incomplete-url-substring-sanitization]
|
|
336
336
|
|
|
337
337
|
|
|
338
338
|
def test_dry_run_no_api_calls(tmp_path: Path, capsys: pytest.CaptureFixture) -> None:
|
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/entry_points.txt
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/requires.txt
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs2confluence.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/emitter/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/__init__.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/loader/extra_css.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/parser/__init__.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/__init__.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/abbrevs.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/fence.py
RENAMED
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/icons.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/includes.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preprocess/linkdefs.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preview/__init__.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/preview/render.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/publisher/__init__.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/publisher/client.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/publisher/pipeline.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/__init__.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/abbrevs.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/assets.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/editlink.py
RENAMED
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/images.py
RENAMED
|
File without changes
|
|
File without changes
|
{mkdocs2confluence-0.6.5 → mkdocs2confluence-0.6.7}/src/mkdocs_to_confluence/transforms/mermaid.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|