md2star.preprocessing.images module

Image-related Markdown transformations.

Three concerns live here:

  1. Size capping — bare ![](...) images get an aspect-ratio-aware {width=…cm} or {height=…cm} block appended so the image fits an A4 page in both dimensions. URL/data refs and unreadable files fall back to {width=100%}.

  2. In-cell resize — images embedded inside pipe-table cells are physically downscaled to a small pixel ceiling. Pandoc’s {width=100%} attribute refers to the full page width, not the cell width, so a hard resize is the only reliable way to keep cell images from overflowing.

  3. Remote download — HTTP(S) image URLs are fetched to local temp files so Pandoc can embed them in the OOXML output (it does not reliably embed network URLs).

All on-disk artifacts (downloaded images, downscaled rasters, cell-fitted copies, rendered SVGs) live in the user-level XDG cache directory provided by md2star.cache so the user’s source tree stays clean.

Author

[Warith HARCHAOUI](https://linkedin.com/in/warith-harchaoui/)

md2star.preprocessing.images.absolutize_image_paths(content, base_dir)[source]

Rewrite relative ![](path) refs to absolute paths against base_dir.

URLs (http(s)://, //, data:, file://) and paths that are already absolute pass through untouched. Fenced code blocks are skipped so example snippets are not mutated. Making the preprocessed Markdown self-contained means Pandoc resolves every image regardless of its cwd, which is what users expect when they run md2docx subdir/file.md.

Parameters:
  • content (str)

  • base_dir (str)

Return type:

str

md2star.preprocessing.images.download_remote_images(content, out_dir)[source]

Download http(s):// image references to the XDG cache directory.

Pandoc does not reliably embed remote images in DOCX/PPTX output, so we fetch each URL once (keyed by MD5 of the URL) and rewrite the Markdown to point at the local copy. Failures leave the original URL in place.

out_dir is retained for backwards compatibility but ignored — every download now lands in $XDG_CACHE_HOME/md2star/remote/ so the user’s source directory stays clean.

Parameters:
Return type:

str

md2star.preprocessing.images.fix_image_widths(content)[source]

Append an A4-fitting attribute block to every bare ![](…) image.

Each image is sized by aspect ratio (see image_size_attr()) so it never overflows an A4 page in either dimension — width and height are bounded, unlike the historical {width=100%} injection which left tall images running past the bottom margin.

Images already inside pipe-table rows are skipped — those get physically resized via resize_images_in_markdown_tables() instead. Applying a page-wide cap inside a cell would still overflow the cell.

Parameters:

content (str)

Return type:

str

md2star.preprocessing.images.html_images_to_markdown(content)[source]

Flatten HTML <img> tags (and benign wrappers) into Markdown images.

Two passes:

  1. <p|div|center|figure>…<img>…</tag> collapses to just the Markdown image (the wrapper is discarded so Pandoc doesn’t drop the whole HTML block when writing DOCX/PPTX).

  2. Any remaining bare <img> tag is converted in place.

Fenced code blocks are temporarily stashed under \x00 placeholder tokens so example snippets that show HTML are preserved verbatim — the NUL byte is effectively never present in real Markdown sources.

Parameters:

content (str)

Return type:

str

md2star.preprocessing.images.image_size_attr(src)[source]

Return a Pandoc attribute block that caps src inside an A4 page.

Reads the image’s pixel dimensions and emits the single binding constraint — {width=15cm} for wide images, {height=17cm} for tall ones — so Pandoc preserves the aspect ratio across DOCX, PDF, HTML and PPTX. Without this, a plain {width=100%} constrains only the horizontal extent and lets tall images run past the bottom margin.

Falls back to {width=100%} for URL/data refs and any image that Pillow cannot open — preserving the historical behaviour for sources we can’t physically measure.

Parameters:

src (str)

Return type:

str

md2star.preprocessing.images.process_image_assets(content, base_dir, max_px=1600)[source]

Convert SVG → PNG and downscale oversized rasters in every image ref.

Walks every Markdown ![alt](src) and HTML <img src="src"> outside fenced code blocks. For each local file:

  • .svg → render to a cached PNG (via rsvg-convert or cairosvg) and rewrite the reference to point at the PNG.

  • Other raster formats above max_px on the longest side → downscale to a cached <hash>_max<N>.<ext> via _resize_raster().

  • URLs, data: URIs, and missing files pass through unchanged.

Pandoc’s DOCX/PPTX writers don’t render SVG reliably across Office versions, and embedding a 4000-px hero image into a docx blows the file size up for no visible gain — so this pass is a defensive normalisation before Pandoc sees the document.

Parameters:
Return type:

str

md2star.preprocessing.images.resize_image_for_cell(src, base_dir, max_px=400)[source]

Physically downscale a local image so it fits inside a pipe-table cell.

URL-based and missing files are returned unchanged; Pillow is the only backend (returns the original on any failure). Output is written to the XDG cache dir (cell/<src-hash><ext>), not next to the input file.

Parameters:
Return type:

str

md2star.preprocessing.images.resize_images_in_markdown_tables(content, base_dir='.')[source]

Replace image references in pipe-table cells with paths to resized copies.

URL-based images and images that cannot be located on disk are left as-is. Grid-table rows are skipped: their cell images carry explicit {width=…} hints that Pandoc honours, so physically downscaling them here (and dropping the hint) would make a grid gallery render at uneven native sizes. Only genuine pipe-table cells are resized.

Parameters:
  • content (str)

  • base_dir (str)

Return type:

str