Configuration

Options can live in a morg.toml (auto-discovered in the working directory, or passed via --config path). Precedence: CLI flags > config file > defaults. Sections mirror the library options objects; unknown top-level keys are rejected so typos fail loudly.

Boolean CLI flags take an optional value: --silent is shorthand for --silent true, and --silent false turns off a config that sets it, which is what makes the precedence above hold in both directions.

Presets resolve per side: --input-preset, then --preset, then inputPreset, then preset, else Vanilla (likewise for the output). So a config can name the vault's dialect and a flag override one side: with preset = "logseq", --output-preset vanilla reads Logseq org and writes Vanilla Markdown. preset next to a different side preset in the same place (both flags, or both keys) is an error. preset leaves a side Vanilla whose format it has no dialect for (Obsidian writes no org); a side preset without one is an error. With one format on both sides, one preset normalizes and two translate.

The Web UI accepts the same TOML in its Config panel.

Full reference

preset = "logseq"     # dialect preset: "vanilla" | "logseq" | "obsidian"
# or one per side (ADR 0006): the dialect the input is read in and the
# one the output is written in; next to preset only if they agree
# inputPreset = "logseq"
# outputPreset = "vanilla"
silent = false        # suppress dropped-construct warnings (CLI -s)

# custom names for org-ism key:: lines (canonical = custom);
# convergence is per-config: convert with the mapping a file
# was written with (ADR 0002)
[orgismKeys]
todo = "state"
scheduled = "when"

# Options are named by format and side (ADR 0007): an input section is
# about reading that format, an output section about writing it

# a construct's Spelling for both sides of Markdown; see "Spelling"
[markdown]
definitionList = "markdown"  # "markdown" | "html"
images = "markdown"
underline = "markdown"
superscript = "markdown"
subscript = "markdown"

# reading Markdown: also read a construct's HTML spelling as the
# construct (its own spelling is always read)
[markdown.input.interpretHtml]
definitionList = false

[markdown.output]
definitionList = "markdown"  # the Spelling to write, over [markdown]
taskCheckboxes = false       # lossy: bare TODO/DONE headlines → - [ ] / - [x]

# preserve org-only constructs in Markdown; false or a per-construct
# table
[markdown.output.preserveOrgisms]
drawers = true

# Markdown output style (canonical form is per-config, ADR 0001):
# round trips must use the same style
[markdown.output.style]
bullet = "-"        # "-" | "*" | "+"
emphasis = "*"      # "*" | "_"
strong = "*"        # "*" | "_" (doubled in output)
fence = "`"         # "`" | "~"
rule = "-"          # "-" | "*" | "_"
ruleRepetition = 3  # marker count for thematic breaks (min 3)

[org.output]
# record the source's own markdown style as a #+MORG_MARKDOWN_STYLE:
# keyword, so the return trip restores it instead of canonicalizing
# it; a marker the document uses inconsistently is skipped and warns
# (ADR 0004)
recordMarkdownStyle = false

# preserve markdown-only constructs in org; false or a per-construct
# table (ADR 0002)
[org.output.preserveMdisms]
html = false

Spelling

An org construct Markdown cannot write losslessly in its own syntax, but HTML can, has two spellings (ADR 0007): "markdown", the default, writes it in Markdown's syntax, or as verbatim org text org re-parses where Markdown has none; "html" writes <dl>, <img>, <u>, <sup> or <sub>.

Construct "markdown" "html"
definitionList term / : def <dl>
images ![alt](src), the #+ATTR_HTML: line <img src alt width>
underline _x_ (org text) <u>
superscript ^{x} (org text) <sup>
subscript _{x} (org text) <sub>

images concerns an image link alone in its paragraph that one #+ATTR_HTML: line sizes with :width and :height and nothing else; another image keeps its attribute lines verbatim either way.

A construct in [markdown] sets both sides: "html" reads its bare HTML (no attributes; an <img> with src, alt, width and height only) back as the construct and writes it, so the round trip converges with the HTML in Markdown and the construct in org. [markdown.input.interpretHtml] and [markdown.output] override one side each. Different sides migrate: reading HTML and writing "markdown" turns a document's HTML into the construct once and for all; writing "html" without reading it is a one-way door, the HTML coming back as a preserved export block. HTML morg cannot read as the construct, attributes included, is preserved per preserveMdisms.

--html sets every construct to "html" on both sides, and --html false to "markdown", over the config.

Formatter compatibility snippets

morg's canonical Markdown can be aligned with common Markdown formatters so that formatting morg output produces no diff.

prettier

# prettier compatibility: morg's canonical form already matches
# prettier's defaults except the emphasis marker
[markdown.output.style]
emphasis = "_"

Verified by test (tests/formatterCompat.spec.ts): morg output under this config is a prettier fixed point. Known residual differences, inherent rather than style knobs:

mdformat

# mdformat compatibility: defaults align except thematic breaks,
# which mdformat writes as 70 underscores
[markdown.output.style]
rule = "_"
ruleRepetition = 70

Best-effort (mdformat is a Python tool and not exercised in morg's test suite): bullet -, */** emphasis and backtick fences align with morg's defaults, and both tools alternate bullet markers between consecutive lists. mdformat's 1.-only ordered-list numbering and its escaping choices may still normalize morg output.