Skip to content

Feature request: Make block spacing configurable via MarkdownRenderConfig #87

Description

@szguicheng

Problem

All block-level spacing in the library is currently hardcoded in BlockView.swift:

  • Inter-block spacing: VStack(alignment: .leading, spacing: 30) — the gap between paragraphs, headings, code blocks, etc.
  • Paragraph line spacing: ParagraphView(contents: contents, lineSpacing: 5) — additional line spacing within paragraph blocks

MarkdownRenderConfig already provides a clean configuration surface for fonts and colors, but has no spacing properties. For apps that want to adjust the visual density of rendered Markdown (e.g., a chat bubble needs tighter spacing than a full-width article view), there is currently no way to do this without forking.

Proposed solution

Add a blockSpacing property to MarkdownRenderConfig that controls the inter-block gap, preserving the current value of 30 as the default:

Changes to MarkdownRenderConfig

/// Vertical spacing between adjacent blocks (paragraphs, headings,
/// code blocks, lists, etc.). Defaults to 30.
public let blockSpacing: CGFloat

Add it to the init, the static let default, and provide a withBlockSpacing(value:) builder — matching the existing pattern of every other config property.

Changes to BlockView

Read blockSpacing from @Environment(\.markdownConfig) and pass it into the VStack:

VStack(alignment: .leading, spacing: config.blockSpacing) {

Out of scope (for this PR)

  • lineSpacing for paragraphs — that could be a separate discussion
  • Per block-type spacing (e.g., tighter after headings) — could follow later if there's demand

Why this fits the library

  • Follows the exact same pattern as every existing MarkdownRenderConfig property
  • No API breakage — the default is 30, identical to current behavior
  • Minimal diff (roughly 4 files touched: MarkdownRenderConfig.swift, BlockView.swift, the builders extension, and possibly DocumentView.swift)
  • Enables real use cases without adding complexity

Happy to open a PR if the direction looks good — I've already prototyped this in a fork and confirmed it works end-to-end.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions