docmarq 0.1.0__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.
- docmarq-0.1.0/PKG-INFO +104 -0
- docmarq-0.1.0/docmarq/__init__.py +54 -0
- docmarq-0.1.0/docmarq/constants.py +77 -0
- docmarq-0.1.0/docmarq/core.py +936 -0
- docmarq-0.1.0/docmarq/fonts.py +19 -0
- docmarq-0.1.0/docmarq/inline.py +98 -0
- docmarq-0.1.0/docmarq/layout.py +42 -0
- docmarq-0.1.0/docmarq/md/__init__.py +33 -0
- docmarq-0.1.0/docmarq/md/image_utils.py +241 -0
- docmarq-0.1.0/docmarq/md/mermaid.py +140 -0
- docmarq-0.1.0/docmarq/md/presets.py +119 -0
- docmarq-0.1.0/docmarq/md/render.py +219 -0
- docmarq-0.1.0/docmarq/md/renderer.py +1210 -0
- docmarq-0.1.0/docmarq/md/slug.py +59 -0
- docmarq-0.1.0/docmarq/md/style.py +124 -0
- docmarq-0.1.0/docmarq/md/tokens.py +69 -0
- docmarq-0.1.0/docmarq/structure.py +36 -0
- docmarq-0.1.0/docmarq/styles.py +111 -0
- docmarq-0.1.0/docmarq/tables.py +135 -0
- docmarq-0.1.0/docmarq/tests/__init__.py +0 -0
- docmarq-0.1.0/docmarq/tests/conftest.py +25 -0
- docmarq-0.1.0/docmarq/tests/test_md_smoke.py +87 -0
- docmarq-0.1.0/docmarq/tests/test_smoke.py +82 -0
- docmarq-0.1.0/docmarq/tests/test_units.py +116 -0
- docmarq-0.1.0/docmarq/utils.py +174 -0
- docmarq-0.1.0/docmarq.egg-info/PKG-INFO +104 -0
- docmarq-0.1.0/docmarq.egg-info/SOURCES.txt +31 -0
- docmarq-0.1.0/docmarq.egg-info/dependency_links.txt +1 -0
- docmarq-0.1.0/docmarq.egg-info/requires.txt +11 -0
- docmarq-0.1.0/docmarq.egg-info/top_level.txt +1 -0
- docmarq-0.1.0/pyproject.toml +24 -0
- docmarq-0.1.0/readme.md +84 -0
- docmarq-0.1.0/setup.cfg +4 -0
docmarq-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docmarq
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DOCX generation library with fluent API
|
|
5
|
+
Author: Xaeian
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Repository, https://github.com/Xaeian/docmarq
|
|
8
|
+
Keywords: docx,word,ooxml,document,generation
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
Requires-Dist: python-docx
|
|
12
|
+
Provides-Extra: md
|
|
13
|
+
Requires-Dist: PyYAML; extra == "md"
|
|
14
|
+
Requires-Dist: markdown-it-py; extra == "md"
|
|
15
|
+
Requires-Dist: mdit-py-plugins; extra == "md"
|
|
16
|
+
Provides-Extra: all
|
|
17
|
+
Requires-Dist: PyYAML; extra == "all"
|
|
18
|
+
Requires-Dist: markdown-it-py; extra == "all"
|
|
19
|
+
Requires-Dist: mdit-py-plugins; extra == "all"
|
|
20
|
+
|
|
21
|
+
# DocMarQ
|
|
22
|
+
|
|
23
|
+
DOCX generation with a fluent API. Core is lean _(just `python-docx`)_. Optional `[md]` extra adds markdown-to-DOCX rendering with banner headers, mermaid, GitHub callouts and more. Sibling library to [`pdfmarq`](https://github.com/Xaeian/PDFMarQ) with the same API shape and `.docx` output.
|
|
24
|
+
|
|
25
|
+
## Philosophy
|
|
26
|
+
|
|
27
|
+
DocMarQ wraps `python-docx` _(OOXML zip plumbing, content types, relationships)_ into a fluent paragraph/run API. You describe document flow; Word handles layout, pagination, and reflow on open.
|
|
28
|
+
|
|
29
|
+
- **Fluent paragraph/run model**: `doc.para("First.")` opens a paragraph, `doc.text(" with bold", bold=True)` appends a styled run. Close with `enter()` or let the next block auto-open one.
|
|
30
|
+
- **One way per feature**: `doc.table()`, `doc.image()`, `doc.bullet()`, `doc.link()`, no overloaded call signatures
|
|
31
|
+
- **Markdown is optional**: core → 1 dep _(`python-docx`)_, `[md]` adds `markdown-it-py`, `mdit-py-plugins`, `PyYAML`
|
|
32
|
+
- **Cross-library parity**: API shape mirrors [`pdfmarq`](https://github.com/Xaeian/PDFMarQ), including `TableStyle`, `Styles`, `parse_color`, `rgb255`, page sizes, and `lang_style()` for i18n. The same markdown source can target both PDF and DOCX.
|
|
33
|
+
- **Word-native output**: opens cleanly in Word, LibreOffice, Google Docs. Templates `.dotx` / `.docx` are respected, so themes and styles carry over.
|
|
34
|
+
|
|
35
|
+
Trade-offs:
|
|
36
|
+
- No cursor or coordinate control. Word owns layout. Great for content-driven documents, not for pixel-perfect grids _(use `pdfmarq` if you need that)_.
|
|
37
|
+
- No math support. Word's equation editor is OOXML-native and out of scope for v0.2.0. For math-heavy docs use `pdfmarq` with matplotlib.
|
|
38
|
+
- Syntax highlighting in code blocks is not rendered yet. The `language` argument is accepted but ignored.
|
|
39
|
+
- The dep tree is small but `python-docx` is the only path to OOXML. If it can't express something _(e.g. complex equation OMML)_, neither can DocMarQ. Drop to `doc.doc` for raw `python-docx` access.
|
|
40
|
+
|
|
41
|
+
## Install
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
pip install docmarq # core: python-docx
|
|
45
|
+
pip install docmarq[md] # + markdown rendering stack
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
```py
|
|
51
|
+
from docmarq import DOCX
|
|
52
|
+
# Fluent core API
|
|
53
|
+
with DOCX("report.docx") as doc:
|
|
54
|
+
doc.font("Calibri", 20, "Bold").para("Quarterly Report")
|
|
55
|
+
doc.font(size=11, mode="Regular")
|
|
56
|
+
doc.para("Revenue up 23% year-over-year.")
|
|
57
|
+
doc.table(
|
|
58
|
+
[["Q1", "120k"], ["Q2", "148k"], ["Q3", "172k"]],
|
|
59
|
+
header=["Quarter", "Revenue"],
|
|
60
|
+
aligns=["C", "R"],
|
|
61
|
+
)
|
|
62
|
+
doc.image("chart.png", width=180, height=80)
|
|
63
|
+
doc.link("google.com", url="https://google.com")
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```py
|
|
67
|
+
from docmarq.md import md_to_docx, MarkdownStyle
|
|
68
|
+
# Markdown to DOCX
|
|
69
|
+
style = MarkdownStyle(
|
|
70
|
+
body_family="Calibri",
|
|
71
|
+
mono_family="Consolas",
|
|
72
|
+
line_height=1.4,
|
|
73
|
+
)
|
|
74
|
+
md_to_docx(open("doc.md").read(), "doc.docx", style=style)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
See [`example.py`](example.py) for an end-to-end CLI script: language preset, Word-native fonts, `link_root` for cross-document references, and `base_dir` for relative images.
|
|
78
|
+
|
|
79
|
+
## Markdown features
|
|
80
|
+
|
|
81
|
+
- GitHub-flavored markdown _(tables, fenced code, lists, strikethrough)_
|
|
82
|
+
- YAML frontmatter rendered as a page-1 banner _(logo, status badge, version, sign block)_
|
|
83
|
+
- Built-in language presets _(en|pl|de|fr|es|it|cs|sk)_ via `lang_style()`: covers banner labels, callouts, date format
|
|
84
|
+
- Skip-duplicate-title: drops `# X` when it matches frontmatter `title`
|
|
85
|
+
- Auto-slugged headings with clickable `[text](#anchor)` internal links _(unicode-aware)_
|
|
86
|
+
- Local-path links configurable via `link_root` + `link_base` _(or per-doc YAML `base:`)_
|
|
87
|
+
- Mermaid diagrams via `mermaid-cli` _(local)_ or `mermaid.ink` _(network fallback)_, with a shared cache with `pdfmarq`
|
|
88
|
+
- Footnotes, emoji shortcodes `:rocket:`, nested lists, blockquotes, GitHub callouts _(`> [!NOTE]`, `> [!WARNING]`, …)_
|
|
89
|
+
- Images with size caps for block and inline use _(`` works inline at x-height)_
|
|
90
|
+
- Headerless single-row tables for label/value cards
|
|
91
|
+
- Setext-heading-with-image recovery: `\n---` renders as block image + `<hr>` instead of a thumbnail-sized setext h2
|
|
92
|
+
|
|
93
|
+
Not supported _(use `pdfmarq` if you need them)_: math formulas, syntax highlighting in code blocks, deferred page numbering _(Word does its own page numbers via field codes, see `doc.footer(page_number=True)`)_.
|
|
94
|
+
|
|
95
|
+
## Modules
|
|
96
|
+
|
|
97
|
+
| Module | Description | Docs |
|
|
98
|
+
| ------------ | --------------------------------------------------- | -------------------------------------------- |
|
|
99
|
+
| `docmarq` | Core DOCX API _(fluent paragraph/run model)_ | [docmarq/readme.md](docmarq/readme.md) |
|
|
100
|
+
| `docmarq.md` | Markdown-to-DOCX renderer _(optional `[md]` extra)_ | [docmarq/md/readme.md](docmarq/md/readme.md) |
|
|
101
|
+
|
|
102
|
+
## See also
|
|
103
|
+
|
|
104
|
+
Need PDF instead of `.docx`? Check [**PDFMarQ**](https://github.com/Xaeian/PDFMarQ), the sibling library with the same API shape and PDF output. It adds math formulas, syntax highlighting, and pre-measured page breaks. Otherwise feature parity _(banner, callouts, mermaid, lang presets)_.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# docmarq/__init__.py
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
DOCX generation with fluent API. Built on `python-docx`.
|
|
5
|
+
|
|
6
|
+
Mirror of `pdfmarq` philosophy: thin fluent layer over a heavy backend.
|
|
7
|
+
We use `python-docx` for OOXML zip plumbing, content types, and
|
|
8
|
+
relationships - everything user-facing is our own API.
|
|
9
|
+
|
|
10
|
+
Example:
|
|
11
|
+
>>> from docmarq import DOCX, Align
|
|
12
|
+
>>> with DOCX("out.docx") as doc:
|
|
13
|
+
... doc.heading("Tytuł", level=1)
|
|
14
|
+
... doc.para("Pierwszy akapit.")
|
|
15
|
+
... doc.text("Drugi z ").text("bold", bold=True).text(" tekstem.")
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
#----------------------------------------------------------------------- Metadata for auto-toml
|
|
19
|
+
|
|
20
|
+
__version__ = "0.1.0"
|
|
21
|
+
__repo__ = "Xaeian/docmarq"
|
|
22
|
+
__python__ = ">=3.10"
|
|
23
|
+
__description__ = "DOCX generation library with fluent API"
|
|
24
|
+
__author__ = "Xaeian"
|
|
25
|
+
__keywords__ = ["docx", "word", "ooxml", "document", "generation"]
|
|
26
|
+
__dependencies__ = ["python-docx"]
|
|
27
|
+
# pip-name → import-name mapping. `python-docx` is the pip package but
|
|
28
|
+
# the import is `import docx`; the hint surfaces in dependency diagnostics
|
|
29
|
+
# so users debugging `No module named 'docx'` see the right install command.
|
|
30
|
+
__import_names__ = {"python-docx": "docx"}
|
|
31
|
+
|
|
32
|
+
#----------------------------------------------------------------------------------- Public API
|
|
33
|
+
|
|
34
|
+
from .constants import (
|
|
35
|
+
Unit, PageSize, Align, Colors, Defaults,
|
|
36
|
+
A4, A3, A5, LETTER, LEGAL, EMU_PER_MM, EMU_PER_PT,
|
|
37
|
+
)
|
|
38
|
+
from .styles import Style, TableStyle, Styles
|
|
39
|
+
from .layout import PageGeometry
|
|
40
|
+
from .structure import Metadata, Bookmark
|
|
41
|
+
from .utils import to_mm, mm_to_emu, pt_to_emu, parse_color, parse_margin, color_hex, rgb255
|
|
42
|
+
from .inline import RichSegment
|
|
43
|
+
from .core import DOCX
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
"DOCX",
|
|
47
|
+
"Unit", "PageSize", "Align", "Colors", "Defaults",
|
|
48
|
+
"A4", "A3", "A5", "LETTER", "LEGAL", "EMU_PER_MM", "EMU_PER_PT",
|
|
49
|
+
"Style", "TableStyle", "Styles",
|
|
50
|
+
"PageGeometry",
|
|
51
|
+
"Metadata", "Bookmark",
|
|
52
|
+
"to_mm", "mm_to_emu", "pt_to_emu", "parse_color", "parse_margin", "color_hex", "rgb255",
|
|
53
|
+
"RichSegment",
|
|
54
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# docmarq/constants.py
|
|
2
|
+
|
|
3
|
+
"""Constants for DOCX library - units, page sizes, alignment, defaults."""
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
# OOXML uses EMU (English Metric Units): 1 inch = 914400 EMU = 25.4 mm
|
|
7
|
+
EMU_PER_MM = 36000
|
|
8
|
+
EMU_PER_PT = 12700 # 1 pt = 1/72 inch
|
|
9
|
+
|
|
10
|
+
#---------------------------------------------------------------------------------------- Units
|
|
11
|
+
|
|
12
|
+
class Unit:
|
|
13
|
+
"""Unit conversion factors to millimeters."""
|
|
14
|
+
MM = 1.0
|
|
15
|
+
CM = 10.0
|
|
16
|
+
INCH = 25.4
|
|
17
|
+
PT = 25.4 / 72
|
|
18
|
+
PX = 25.4 / 96
|
|
19
|
+
|
|
20
|
+
#------------------------------------------------------------------------------------- PageSize
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class PageSize:
|
|
24
|
+
"""Common page sizes in mm."""
|
|
25
|
+
width: float
|
|
26
|
+
height: float
|
|
27
|
+
def landscape(self) -> "PageSize":
|
|
28
|
+
"""Return a copy with width/height swapped (landscape orientation)."""
|
|
29
|
+
return PageSize(self.height, self.width)
|
|
30
|
+
|
|
31
|
+
A4 = PageSize(210, 297)
|
|
32
|
+
A3 = PageSize(297, 420)
|
|
33
|
+
A5 = PageSize(148, 210)
|
|
34
|
+
LETTER = PageSize(215.9, 279.4)
|
|
35
|
+
LEGAL = PageSize(215.9, 355.6)
|
|
36
|
+
|
|
37
|
+
#---------------------------------------------------------------------------------------- Align
|
|
38
|
+
|
|
39
|
+
class Align:
|
|
40
|
+
"""Text/element alignment constants. Match pdfmarq values for cross-lib reuse."""
|
|
41
|
+
LEFT = "L"
|
|
42
|
+
RIGHT = "R"
|
|
43
|
+
CENTER = "C"
|
|
44
|
+
JUSTIFY = "J"
|
|
45
|
+
|
|
46
|
+
#--------------------------------------------------------------------------------------- Colors
|
|
47
|
+
|
|
48
|
+
class Colors:
|
|
49
|
+
"""Predefined colors as (r, g, b) tuples (0-1 range)."""
|
|
50
|
+
BLACK = (0, 0, 0)
|
|
51
|
+
WHITE = (1, 1, 1)
|
|
52
|
+
RED = (1, 0, 0)
|
|
53
|
+
GREEN = (0, 1, 0)
|
|
54
|
+
BLUE = (0, 0, 1)
|
|
55
|
+
GREY = (0.5, 0.5, 0.5)
|
|
56
|
+
LIGHT_GREY = (0.8, 0.8, 0.8)
|
|
57
|
+
DARK_GREY = (0.3, 0.3, 0.3)
|
|
58
|
+
|
|
59
|
+
#------------------------------------------------------------------------------------- Defaults
|
|
60
|
+
|
|
61
|
+
class Defaults:
|
|
62
|
+
"""Default values for DOCX generation."""
|
|
63
|
+
PAGE_WIDTH = 210
|
|
64
|
+
PAGE_HEIGHT = 297
|
|
65
|
+
MARGIN = 20
|
|
66
|
+
FONT_FAMILY = "Calibri"
|
|
67
|
+
FONT_SIZE = 11
|
|
68
|
+
FONT_MODE = "Regular"
|
|
69
|
+
LINE_HEIGHT = 1.15
|
|
70
|
+
UNIT = "mm"
|
|
71
|
+
# Heading palette - GitHub-light, mirrors `pdfmarq.MarkdownStyle`
|
|
72
|
+
HEAD_COLOR = (0.09, 0.11, 0.13) # near-black #1f2328
|
|
73
|
+
RULE_COLOR = (0.82, 0.84, 0.87) # light grey #d0d7de (h1/h2 underline)
|
|
74
|
+
# h1..h6 sizes in pt. Matches `pdfmarq.MarkdownStyle.h{1-6}_size` so
|
|
75
|
+
# the same markdown source renders at the same scale in both libs.
|
|
76
|
+
HEAD_SIZES = (20, 16, 13, 11, 11, 11)
|
|
77
|
+
HEAD_UNDERLINE_LEVELS = (1, 2) # which heading levels get bottom border
|