Skip to content

feat: add synchronous parseMarkdown returning a parsed State#591

Merged
mikepenz merged 1 commit into
mikepenz:developfrom
mvanhorn:feat/587-synchronous-parse-markdown
Jun 22, 2026
Merged

feat: add synchronous parseMarkdown returning a parsed State#591
mikepenz merged 1 commit into
mikepenz:developfrom
mvanhorn:feat/587-synchronous-parse-markdown

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Description

Adds a public top-level parseMarkdown(content, lookupLinks, flavour, parser, referenceLinkHandler): State to MarkdownState.kt, sitting alongside the existing parseMarkdownFlow(...) and mirroring its parameter list and defaults. It parses on the calling thread and returns the final, immutable State directly (State.Success on success, or State.Error on failure).

Internally it builds the same Input and MarkdownStateImpl and calls the already-present parseBlocking(), so the change is purely additive and reuses every existing code path (input construction, parsing, link lookup).

Motivation: today the only non-composable parse API is parseMarkdownFlow(), which forces callers through mutable Flow/StateFlow machinery to obtain a result. There was no way to synchronously get a State.Success to hand to the Markdown composable. parseMarkdown lets you pre-parse content before the UI is shown and pass the already-parsed, immutable State straight into Markdown(state), with no mutable surface exposed to the caller.

val state = parseMarkdown("# Markdown")
Markdown(state)

Note: parsing happens on the calling thread; for large documents callers should invoke off the main thread.

Fixes #587

Type of change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

How Has This Been Tested?

Added ParseMarkdownTest in commonTest and ran it on the JVM target.

  • ./gradlew :multiplatform-markdown-renderer:jvmTest --tests "com.mikepenz.markdown.model.ParseMarkdownTest" passes (4/4): happy path (synchronous State.Success with parsed node and original content), empty content (returns State.Success, not State.Loading), reference-link resolution with lookupLinks = true, and the error path (returns State.Error carrying the throwable instead of throwing).
  • Updated the binary-compatibility .api / .klib.api dumps for the new function.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules

Adds a public top-level parseMarkdown(content, lookupLinks, flavour,
parser, referenceLinkHandler): State alongside parseMarkdownFlow. It
parses on the calling thread and returns the final immutable State
directly (State.Success or State.Error), without exposing any mutable
Flow/StateFlow surface. Useful to pre-parse content before the UI is
shown and pass the parsed state into the Markdown composable.

Reuses the existing Input / MarkdownStateImpl / parseBlocking path, so
it is purely additive. Adds commonTest coverage and documents the
function in the README.

Closes mikepenz#587
@mvanhorn mvanhorn mentioned this pull request Jun 22, 2026
3 tasks
@mikepenz mikepenz enabled auto-merge June 22, 2026 09:34
@mikepenz mikepenz merged commit 9344324 into mikepenz:develop Jun 22, 2026
5 checks passed
@mvanhorn

Copy link
Copy Markdown
Contributor Author

Thank you @mikepenz. A synchronous parseMarkdown that returns a parsed State is a handy addition for callers that don't want the async path.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Explicit markdown pre-rendering

2 participants