markdocx 3.0.0__tar.gz → 4.0.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.
- {markdocx-3.0.0 → markdocx-4.0.0}/PKG-INFO +1 -1
- {markdocx-3.0.0 → markdocx-4.0.0}/pyproject.toml +1 -1
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/__init__.py +1 -1
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/diagram_renderer.py +104 -52
- {markdocx-3.0.0 → markdocx-4.0.0}/uv.lock +1 -1
- {markdocx-3.0.0 → markdocx-4.0.0}/.gitignore +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/.python-version +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/LICENSE +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/README.md +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/main.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/requirements.txt +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/rule/ai_gen_doc_rule.md +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/rule/ai_gen_doc_rule_en.md +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/cli.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/code_renderer.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/core.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/docx_builder.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/math_renderer.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/md_parser.py +0 -0
- {markdocx-3.0.0 → markdocx-4.0.0}/src/markdocx/styles.py +0 -0
|
@@ -731,42 +731,76 @@ def _render_workflow(code: str):
|
|
|
731
731
|
n = len(steps)
|
|
732
732
|
is_vertical = direction.startswith("v")
|
|
733
733
|
|
|
734
|
-
#
|
|
734
|
+
# ── Measure text to compute adaptive box sizes ──────────────
|
|
735
|
+
def _wrap_text(text, max_chars):
|
|
736
|
+
"""Wrap text into multiple lines if too long."""
|
|
737
|
+
if len(text) <= max_chars:
|
|
738
|
+
return text
|
|
739
|
+
words = text.split()
|
|
740
|
+
lines = []
|
|
741
|
+
current = ""
|
|
742
|
+
for word in words:
|
|
743
|
+
test = f"{current} {word}".strip() if current else word
|
|
744
|
+
if len(test) <= max_chars:
|
|
745
|
+
current = test
|
|
746
|
+
else:
|
|
747
|
+
if current:
|
|
748
|
+
lines.append(current)
|
|
749
|
+
current = word
|
|
750
|
+
if current:
|
|
751
|
+
lines.append(current)
|
|
752
|
+
return "\n".join(lines) if lines else text
|
|
753
|
+
|
|
754
|
+
# Find longest text to size boxes appropriately
|
|
755
|
+
max_text_len = max(len(s.get("text", "")) for s in steps)
|
|
756
|
+
|
|
735
757
|
if is_vertical:
|
|
736
|
-
|
|
737
|
-
|
|
758
|
+
# Vertical: boxes can be wide
|
|
759
|
+
max_chars_per_line = 30
|
|
760
|
+
box_w = max(3.0, min(6.0, max_text_len * 0.18 + 1.0))
|
|
761
|
+
box_h = 0.9
|
|
762
|
+
fontsize_normal = 12
|
|
763
|
+
fontsize_decision = 11
|
|
764
|
+
spacing_y = 1.8 # center-to-center vertical distance
|
|
765
|
+
|
|
766
|
+
fig_w = max(6, box_w + 3.0)
|
|
767
|
+
fig_h = max(4, n * spacing_y + 2.0)
|
|
738
768
|
else:
|
|
739
|
-
|
|
740
|
-
|
|
769
|
+
# Horizontal: limited width per box, allow wrapping
|
|
770
|
+
max_chars_per_line = 14
|
|
771
|
+
box_w = max(2.2, min(3.5, max_text_len * 0.15 + 0.8))
|
|
772
|
+
box_h = 1.0
|
|
773
|
+
fontsize_normal = 11
|
|
774
|
+
fontsize_decision = 10
|
|
775
|
+
spacing_x = box_w + 1.0 # center-to-center horizontal distance
|
|
776
|
+
|
|
777
|
+
fig_w = max(6, n * spacing_x + 2.0)
|
|
778
|
+
fig_h = max(3.5, 4.0)
|
|
741
779
|
|
|
742
780
|
fig, ax = plt.subplots(figsize=(fig_w, fig_h))
|
|
743
|
-
|
|
781
|
+
# Do NOT use set_aspect("equal") — it distorts boxes
|
|
744
782
|
ax.axis("off")
|
|
745
783
|
|
|
746
|
-
#
|
|
747
|
-
box_w = 2.0
|
|
748
|
-
box_h = 0.7
|
|
749
|
-
spacing = 1.5 # center-to-center distance
|
|
750
|
-
|
|
751
|
-
# Calculate positions
|
|
784
|
+
# ── Calculate positions ─────────────────────────────────────
|
|
752
785
|
positions = []
|
|
753
786
|
for i in range(n):
|
|
754
787
|
if is_vertical:
|
|
755
788
|
x = fig_w / 2
|
|
756
|
-
y = fig_h - 1.
|
|
789
|
+
y = fig_h - 1.5 - i * spacing_y
|
|
757
790
|
else:
|
|
758
|
-
x = 1.5 + i *
|
|
791
|
+
x = 1.5 + i * spacing_x
|
|
759
792
|
y = fig_h / 2
|
|
760
793
|
positions.append((x, y))
|
|
761
794
|
|
|
762
795
|
# Adjust axes limits
|
|
763
796
|
all_x = [p[0] for p in positions]
|
|
764
797
|
all_y = [p[1] for p in positions]
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
ax.
|
|
798
|
+
pad_x = box_w / 2 + 1.5
|
|
799
|
+
pad_y = box_h + 1.5
|
|
800
|
+
ax.set_xlim(min(all_x) - pad_x, max(all_x) + pad_x)
|
|
801
|
+
ax.set_ylim(min(all_y) - pad_y, max(all_y) + pad_y)
|
|
768
802
|
|
|
769
|
-
# Color scheme
|
|
803
|
+
# ── Color scheme ────────────────────────────────────────────
|
|
770
804
|
type_colors = {
|
|
771
805
|
"terminal": ("#34A853", "white"),
|
|
772
806
|
"start": ("#34A853", "white"),
|
|
@@ -776,17 +810,21 @@ def _render_workflow(code: str):
|
|
|
776
810
|
"io": ("#7B61FF", "white"),
|
|
777
811
|
}
|
|
778
812
|
|
|
779
|
-
# Draw steps
|
|
813
|
+
# ── Draw steps ──────────────────────────────────────────────
|
|
780
814
|
for i, step in enumerate(steps):
|
|
781
815
|
x, y = positions[i]
|
|
782
816
|
step_type = step.get("type", "process")
|
|
783
|
-
|
|
817
|
+
raw_text = step.get("text", "")
|
|
818
|
+
display_text = _wrap_text(raw_text, max_chars_per_line)
|
|
784
819
|
bg_color, text_color = type_colors.get(step_type, ("#4285F4", "white"))
|
|
785
820
|
|
|
821
|
+
# Count lines for height adjustment
|
|
822
|
+
n_lines = display_text.count("\n") + 1
|
|
823
|
+
effective_h = max(box_h, box_h + (n_lines - 1) * 0.3)
|
|
824
|
+
|
|
786
825
|
if step_type == "decision":
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
diamond_h = box_h * 1.2
|
|
826
|
+
diamond_w = box_w * 0.55
|
|
827
|
+
diamond_h = effective_h * 0.9
|
|
790
828
|
diamond = plt.Polygon([
|
|
791
829
|
(x, y + diamond_h),
|
|
792
830
|
(x + diamond_w, y),
|
|
@@ -795,68 +833,82 @@ def _render_workflow(code: str):
|
|
|
795
833
|
], closed=True, facecolor=bg_color, edgecolor="#333333",
|
|
796
834
|
linewidth=1.5, zorder=3)
|
|
797
835
|
ax.add_patch(diamond)
|
|
798
|
-
ax.text(x, y,
|
|
799
|
-
fontsize=
|
|
800
|
-
|
|
836
|
+
ax.text(x, y, display_text, ha="center", va="center",
|
|
837
|
+
fontsize=fontsize_decision, fontweight="bold",
|
|
838
|
+
color=text_color, zorder=4, linespacing=1.2)
|
|
801
839
|
|
|
802
840
|
elif step_type in ("terminal", "start", "end"):
|
|
803
|
-
# Rounded rectangle (stadium shape)
|
|
804
841
|
patch = FancyBboxPatch(
|
|
805
|
-
(x - box_w / 2, y -
|
|
842
|
+
(x - box_w / 2, y - effective_h / 2), box_w, effective_h,
|
|
806
843
|
boxstyle="round,pad=0.15", facecolor=bg_color,
|
|
807
844
|
edgecolor="#333333", linewidth=1.5, zorder=3
|
|
808
845
|
)
|
|
809
846
|
ax.add_patch(patch)
|
|
810
|
-
ax.text(x, y,
|
|
811
|
-
fontsize=
|
|
847
|
+
ax.text(x, y, display_text, ha="center", va="center",
|
|
848
|
+
fontsize=fontsize_normal, fontweight="bold",
|
|
849
|
+
color=text_color, zorder=4, linespacing=1.2)
|
|
812
850
|
|
|
813
851
|
elif step_type == "io":
|
|
814
|
-
|
|
815
|
-
skew = 0.2
|
|
852
|
+
skew = 0.25
|
|
816
853
|
pgram = plt.Polygon([
|
|
817
|
-
(x - box_w / 2 + skew, y +
|
|
818
|
-
(x + box_w / 2 + skew, y +
|
|
819
|
-
(x + box_w / 2 - skew, y -
|
|
820
|
-
(x - box_w / 2 - skew, y -
|
|
854
|
+
(x - box_w / 2 + skew, y + effective_h / 2),
|
|
855
|
+
(x + box_w / 2 + skew, y + effective_h / 2),
|
|
856
|
+
(x + box_w / 2 - skew, y - effective_h / 2),
|
|
857
|
+
(x - box_w / 2 - skew, y - effective_h / 2)
|
|
821
858
|
], closed=True, facecolor=bg_color, edgecolor="#333333",
|
|
822
859
|
linewidth=1.5, zorder=3)
|
|
823
860
|
ax.add_patch(pgram)
|
|
824
|
-
ax.text(x, y,
|
|
825
|
-
fontsize=
|
|
861
|
+
ax.text(x, y, display_text, ha="center", va="center",
|
|
862
|
+
fontsize=fontsize_normal, fontweight="bold",
|
|
863
|
+
color=text_color, zorder=4, linespacing=1.2)
|
|
826
864
|
|
|
827
865
|
else: # process
|
|
828
|
-
# Rectangle
|
|
829
866
|
patch = FancyBboxPatch(
|
|
830
|
-
(x - box_w / 2, y -
|
|
867
|
+
(x - box_w / 2, y - effective_h / 2), box_w, effective_h,
|
|
831
868
|
boxstyle="square,pad=0.1", facecolor=bg_color,
|
|
832
869
|
edgecolor="#333333", linewidth=1.5, zorder=3
|
|
833
870
|
)
|
|
834
871
|
ax.add_patch(patch)
|
|
835
|
-
ax.text(x, y,
|
|
836
|
-
fontsize=
|
|
872
|
+
ax.text(x, y, display_text, ha="center", va="center",
|
|
873
|
+
fontsize=fontsize_normal, fontweight="bold",
|
|
874
|
+
color=text_color, zorder=4, linespacing=1.2)
|
|
837
875
|
|
|
838
|
-
# Draw arrows between steps
|
|
876
|
+
# ── Draw arrows between steps ───────────────────────────────
|
|
839
877
|
for i in range(n - 1):
|
|
840
878
|
x1, y1 = positions[i]
|
|
841
879
|
x2, y2 = positions[i + 1]
|
|
842
880
|
|
|
843
|
-
|
|
881
|
+
cur_type = steps[i].get("type", "process")
|
|
882
|
+
next_type = steps[i + 1].get("type", "process")
|
|
883
|
+
|
|
884
|
+
# Recompute effective heights for arrow endpoints
|
|
885
|
+
cur_text = _wrap_text(steps[i].get("text", ""), max_chars_per_line)
|
|
886
|
+
next_text = _wrap_text(steps[i + 1].get("text", ""), max_chars_per_line)
|
|
887
|
+
cur_h = max(box_h, box_h + (cur_text.count("\n")) * 0.3)
|
|
888
|
+
next_h = max(box_h, box_h + (next_text.count("\n")) * 0.3)
|
|
844
889
|
|
|
845
890
|
if is_vertical:
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
start_y = y1 -
|
|
850
|
-
next_type = steps[i + 1].get("type", "process")
|
|
891
|
+
if cur_type == "decision":
|
|
892
|
+
start_y = y1 - cur_h * 0.9 - 0.08
|
|
893
|
+
else:
|
|
894
|
+
start_y = y1 - cur_h / 2 - 0.08
|
|
851
895
|
if next_type == "decision":
|
|
852
|
-
end_y = y2 +
|
|
896
|
+
end_y = y2 + next_h * 0.9 + 0.08
|
|
897
|
+
else:
|
|
898
|
+
end_y = y2 + next_h / 2 + 0.08
|
|
853
899
|
ax.annotate("", xy=(x2, end_y), xytext=(x1, start_y),
|
|
854
900
|
arrowprops=dict(arrowstyle="-|>", color="#555555",
|
|
855
901
|
lw=2, mutation_scale=15),
|
|
856
902
|
zorder=2)
|
|
857
903
|
else:
|
|
858
|
-
|
|
859
|
-
|
|
904
|
+
if cur_type == "decision":
|
|
905
|
+
start_x = x1 + box_w * 0.55 + 0.08
|
|
906
|
+
else:
|
|
907
|
+
start_x = x1 + box_w / 2 + 0.08
|
|
908
|
+
if next_type == "decision":
|
|
909
|
+
end_x = x2 - box_w * 0.55 - 0.08
|
|
910
|
+
else:
|
|
911
|
+
end_x = x2 - box_w / 2 - 0.08
|
|
860
912
|
ax.annotate("", xy=(end_x, y2), xytext=(start_x, y1),
|
|
861
913
|
arrowprops=dict(arrowstyle="-|>", color="#555555",
|
|
862
914
|
lw=2, mutation_scale=15),
|
|
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
|