AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Documentation Bc Md To Docx Converter

skill-fernandoartalf-al-copilot-skills-collection-documentation-bc-md-to-docx-converter · by fernandoartalf

>-

No reviews yet
0 installs
47 views
0.0% view→install

Install

$ agentstack add skill-fernandoartalf-al-copilot-skills-collection-documentation-bc-md-to-docx-converter

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-fernandoartalf-al-copilot-skills-collection-documentation-bc-md-to-docx-converter)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Documentation Bc Md To Docx Converter? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Markdown to DOCX Converter with Template (Python)

Overview

Converts markdown (.md) files to professionally formatted Word documents (.docx) using Python and the python-docx library. The conversion pipeline works in three stages:

  1. Parse the markdown file into named sections (metadata fields + H2 body sections)
  2. Generate a JSON file containing all extracted sections as key-value pairs
  3. Substitute {{Placeholder}} tokens in the Word template with the corresponding JSON values

The conversion is only considered complete when the custom template is applied and all placeholders are substituted. The template ensures consistent branding, styles, headers, footers, and formatting across all generated documents.

Agent Instructions

When asked to convert a markdown file to a Word document, follow this checklist in order:

  1. Validate — Confirm python-docx is installed and the source .md file exists.
  2. List templates — Run --list-templates to show available templates. If only one template exists, it is auto-selected (skip step 3).
  3. Ask user — Present the available templates and ask the user to select one.
  4. Run — Execute convert_md_to_docx.py --template .
  5. Verify — Confirm the .docx file was created and is at least 20 KB.
  6. Report — Tell the user the output file path and confirm all placeholders were substituted.

> For CLI flags, JSON schema, field maps, examples, and error handling, see the reference sections below.

Prerequisites

  • Python 3.10+ installed and available in the system PATH
  • python-docx library — install via:

``bash pip install -r .github\skills\documentation-bc-md-to-docx-converter\scripts\requirements.txt ` or directly: `bash pip install python-docx ``

  • Template files: bundled in the skill's templates/ folder (1_UserStory_Template.docx, 2_Spec_Template.docx, 3_Analysis_Template.docx, 4_Architecture_Template.docx, 5_CCN_Template.docx, 6_ReleaseNote_Template.docx)
  • The template must contain {{Placeholder}} tokens in paragraphs, tables, headers, or footers that will be replaced with values from the parsed markdown
  • (Optional) Mermaid CLI — only required when the source markdown contains ` markers (emitted by the documentation-bc-ccn-generator` skill) and you want them rendered as inline images. Install once globally:

``bash npm install -g @mermaid-js/mermaid-cli ` After installation, mmdc must be on PATH. When mmdc is missing the converter still succeeds but each diagram is inserted as its plain-text fallback with a [Diagram: ()]` label and a warning is printed.

Quick Start

Step 0: Install Python Dependencies

pip install -r .github\skills\documentation-bc-md-to-docx-converter\scripts\requirements.txt

Step 1: List Available Templates

python .github\skills\documentation-bc-md-to-docx-converter\scripts\convert_md_to_docx.py --list-templates

This will display all available templates in the templates/ folder with their index numbers.

Step 2: Run the Converter with a Selected Template

python .github\skills\documentation-bc-md-to-docx-converter\scripts\convert_md_to_docx.py "docs\releasenotesmd\Release_Note_DSD-1234_Test_Customer_123456.md" --template 1

> Note (macOS/Linux): Replace backslashes with forward slashes in paths and line-continuation characters (^).

This will:

  1. Parse the markdown into sections
  2. Create a .json file alongside the output with all section values
  3. Open the selected template, replace all {{Placeholder}} tokens, and save the .docx

How the Pipeline Works

Field Map Configuration

The converter uses a unified field map registry shared across every documentation-bc-* skill at:

.github/skills/shared/unified-field-map.json

This JSON file is the single source of truth for all documentation artefacts (USERSTORY, SPEC, ANALYSIS, ARCHITECTURE, CCN, PLAN, RELEASENOTE). Each artefact entry contains pointers to:

  • A reference markdown template under

.github/skills/documentation-bc-*-generator/references/*-template.md

  • A schema describing frontmatterFields, metadataFields, sections,

plus labelLocales / displayHeadingLocales for multi-language output

  • A canonical Word template (templateHint → filename in templates/)
  • Detection metadata (idPattern, filePattern, headingPattern,

headingKey, extraMetadataKeys)

Detection order for parse_markdown():

  1. Frontmatter template: value matched to a registered template filename.
  2. Frontmatter id: matched against the artefact's idPattern.
  3. Filename matched against the artefact's filePattern.

Language resolution: the converter selects the locale used to fill {{Label_}} and {{Label_Section_}} placeholders in this order: --language CLI flag → frontmatter language: field → "en".

To add new fields, sections, or languages: edit the artefact's schema entry in unified-field-map.json and add the matching {{Placeholder}} in the Word template. No code changes required.

Stage 1: Parse Markdown → Sections Dict

The script reads the markdown and extracts fields based on the resolved artefact schema:

| Source | JSON Key | Driven By | |--------|----------|----------| | YAML frontmatter fields | frontmatterFields[].key (via yamlKey) | unified-field-map.json | | H1 heading capture group | headingKey | unified-field-map.json (headingPattern) | | Metadata table rows \| **Label** \| Value \| | metadataFields[].key / extraMetadataKeys entries | unified-field-map.json | | ## Heading sections via ` anchors | from the anchor (PascalCase) | Reference template anchors + sections[] | | Label / LabelSection localised labels | resolvelabel() using labelLocales[lang] | unified-field-map.json + --language` |

Any ## Heading without a section-key anchor is still captured using a PascalCase key derived from the heading text.

Stage 2: Write JSON File

A JSON file is created next to the output .docx with the same base name:

{
  "CustomerName": "Test Customer 123456",
  "CCNNr": "DSD-1234",
  "Version": "1.0.0.0",
  "ChangeRequestDetails": "Implementation of the BC Dataverse...",
  "TestingSteps": "1. Open the **CDS Countries** list page..."
}

If any ... marker block was found inside an H2 section body, the body text keeps a {{DIAGRAM:}} token where the marker was and a top-level _diagrams entry is added to the JSON:

{
  "ArchitectureSolutionFromARCHNNN": "... prose ... {{DIAGRAM:component-view}} ... more prose ...",
  "_diagrams": {
    "component-view": {
      "type": "flowchart",
      "name": "component-view",
      "mermaid": "flowchart TD\n  A --> B\n  ...",
      "fallback": ""
    }
  }
}

The _diagrams key is reserved — never use it as a placeholder name. The JSON file is the single source of truth: editing mermaid source there and re-running the substitution stage is enough to update the diagram in the docx (no markdown changes needed).

Stage 3: Substitute Placeholders in Template

The script opens the .dotx/.docx template and searches for {{Key}} placeholders in:

  • Body paragraphs (all runs are joined, substituted, then rewritten)
  • Body tables (every cell in every row, including nested tables — in cells with rich formatting, all runs are joined into a single run using the first run's formatting before substitution; rich formatting within the placeholder span is not preserved)
  • Headers and footers (all section headers/footers including first-page and even-page variants)

Each {{Key}} token is replaced with the value from the JSON sections dict. If a key is not found in the JSON, the placeholder is left unchanged.

After {{Key}} substitution, any {{DIAGRAM:}} tokens that landed inside the resulting text are processed in a second pass per-paragraph:

  1. The corresponding entry is looked up in _diagrams.
  2. Its mermaid source is written to a temp file and rendered to PNG via mmdc -i .mmd -o .png -b white --quiet.
  3. The token is replaced in place with an inline picture run sized to 6.0 inches wide (Inches(6)); surrounding text on the same line is preserved.
  4. Rendered PNGs are cached per-run keyed by the mermaid source, so repeating a diagram costs nothing extra.
  5. If mmdc is not installed, the mermaid source is empty, rendering fails, or mmdc times out (30-second limit), the token is replaced with a [Diagram: ()] label followed by the diagram's fallback text and a warning is printed ([WARNING] Mermaid render timed out for on timeout). The conversion does not fail.
Bare `mermaid ` fences

In addition to the explicit ` marker pair, any **bare** triple-backtick ``mermaid ` fence found inside an H2 section body is auto-promoted to a synthetic diagram entry. The fence is extracted, given a generated name (auto-mermaid-1, auto-mermaid-2, …), its first non-empty source line is used to derive the diagram type (flowchart, erDiagram, sequenceDiagram, …), and a {{DIAGRAM:auto-mermaid-N}} token is left in the body. From there it follows the exact same render-or-fallback path as a marker-delimited diagram. This lets generator skills emit plain Mermaid code blocks without forcing markers, while preserving deterministic JSON keys.

Inline `` images

Inline markdown images of the form ` found in any H2 section body are extracted into sections["_images"] and replaced with a {{IMAGE:}}` token. During substitution the token is rendered as an inline picture sized to 6.0 inches wide. Path resolution order:

  1. Relative to the markdown file's parent directory.
  2. Relative to the repo root (the workspace folder containing the converter).

If neither resolution succeeds, the original ` markdown is left in place untouched and a [WARNING] Image not found, leaving as text line is printed. URLs (http://, https://) and data: URIs are not downloaded and are also left as text. Like diagrams, the images` key is reserved — never use it as a placeholder name.

Placeholder Format

Use double curly braces with the exact PascalCase key: {{CustomerName}}, {{CCNNr}}, {{ChangeRequestDetails}}, etc. Keys map directly to the JSON output from Stage 2. Unmatched placeholders are left unchanged.

Markdown-aware section body rendering

When a placeholder's substituted value contains block-level markdown (detected by the presence of fenced code blocks, GFM pipe tables, ordered/unordered list items, ATX headings, or a blank-line separator), the converter does not flatten the text into a single paragraph. Instead it tokenises the value into a small block model and emits the corresponding native Word constructs as siblings inserted before the placeholder paragraph; the original placeholder paragraph is then removed so no empty residual paragraph remains.

Supported subset:

  • Inline: **bold**, *italic* / _italic_, ` code (rendered with Consolas font), [label](url) (rendered as a blue-underlined run using color #0563C1`; no real hyperlink relationship is attached — visual fidelity only).
  • Paragraphs: split on blank lines; inline markdown applied per paragraph.
  • Headings: ####### produce a paragraph carrying the resolved value (no heading style is applied — styling continues to follow the template's placeholder paragraph formatting).
  • Lists: unordered (-, *, +) and ordered (1., 2., …) lists. Each item becomes its own paragraph, prefixed literally with "• " or "N. ". Literal prefixes are used (instead of List Bullet / List Number Word styles) so output is consistent regardless of which styles the template defines.
  • Tables: GFM pipe tables (header row + --- | --- separator) are emitted as raw ` XML built via OxmlElement, with tblW=auto` and single 4px borders on all six edges. The header row's cell runs are set to bold. Cells render their inline markdown.
  • Fenced code: ``` `lang `` blocks render one paragraph per source line, each in Consolas`. The language hint is currently informational only (no syntax highlighting).

Mechanics:

  • Insertion uses lxml paragraph._element.addprevious(new_elem) followed by parent.remove(p_elem). This is parent-agnostic and works whether the placeholder paragraph lives in the document body, a table cell (including nested tables), a header, a footer, or a text-box content region.
  • Every rendered paragraph clones the template paragraph's ` and every new run inherits the template run's font/size/color via copyrunformat`. This keeps localised typography intact.
  • {{DIAGRAM:}} and {{IMAGE:}} tokens are preserved through tokenisation and rendered at the inline level via the same _embed_diagram / _embed_image path used by Stage 3, so mermaid charts and inline images embedded in a section body appear as native pictures in the resulting docx (not as raw tokens or markdown source).
  • If a value does not look like block markdown, the legacy single-paragraph path (apply_formatted_text_to_paragraph) is used unchanged, preserving prior behaviour for short scalar values like {{CustomerName}} or {{Version}}.

Stage 4: TOC / Field Auto-Update

After saving the .docx, the converter patches word/settings.xml inside the ZIP archive to inject `. This instructs Word (and LibreOffice) to refresh all document fields — including the Table of Contents — the first time the file is opened. No external dependencies (Word COM, LibreOffice macro) are required; the patch uses only Python's zipfile and xml.etree.ElementTree` modules.

The patch is applied automatically on every conversion. If it fails for any reason, a [WARNING] is printed but the .docx is still usable — the user simply needs to manually update the TOC (Right-click TOC → Update Field).

Markdown Structure Requirements

The markdown must follow this structure for proper conversion:

# Release Note – [Customer Name]

| Field | Value |
|-------|-------|
| **CCN Nr.** | DSD-XXXX |
| **Issue Nr.** | IXXXX |
| **Version** | X.X.X.X |
| **Date** | DD/MM/YYYY |
| **Title** | Description |
| **Released By** | Author |

---

## Change Request Details

Content here...

---

## Testing Setup

Content here...

---

## Testing Steps

Content here...

Core Workflow

The conversion follows these steps:

Step 1: Validate Inputs

  • Verify python-docx is installed; if not, instruct the user to pip install python-docx and do not proceed.
  • Confirm the source markdown file exists.
  • Run --list-templates; auto-select if only one template exists, otherwise ask the user to choose.

Step 2: Parse Markdown and Generate JSON

  • Parse the markdown file extracting frontmatter fields, H1 heading, metadata table fields, and H2 section bodies (located via `` anchors).
  • Resolve the artefact type via the unified field map. The converter raises a ValueError if no artefact type can be determined (the markdown must carry a template: frontmatter entry, a matching id:, or a filename pattern declared in the registry).
  • Emit {{Label_}} / {{Label_Section_}} placeholders for the resolved language (--language → frontmatter language:"en").
  • If a required metadata field is missing, the converter aborts with an error listing the missing fields. Optional missing fields use their default value or leave the {{Placeholder}} unchanged.
  • Write the sections dict to a .json file alongside the output.

Step 3: Substitute Placeholders in Template

  • Open the template with python-docx
  • Walk all paragraphs, tables, headers, and footers
  • Replace every {{Key}} placeholder with the corresponding value from the JSON
  • Save the result as .docx

Step 4: Verify Output

  • Confirm the .docx file was created
  • Confirm the output .docx file size is at l

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.