Skip to content

Releases: remigius42/morg

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 07 Oct 13:17

Added

  • GFM alerts ↔ org special blocks: > [!NOTE] ↔ #+begin_note, a
    title on the marker line ↔ the block's parameters
    (> [!TIP] Stretch first ↔ #+begin_tip Stretch first). A query
    block, and a type Obsidian's callouts read otherwise (a.b), stay
    org text; Logseq md keeps writing special blocks as org does.
  • Obsidian md writes an alert as a callout, its type lower case
    (> [!note]), and keeps a callout's fold as the block's parameters'
    leading token (> [!tip]- T ↔ #+begin_tip - T).
  • The docs are on the site: docs/ and CONTEXT.md render as pages under
    /docs/, listed on a generated index linked from every page's nav
    (ADR 0009); a link between docs stays on the site, and code is
    highlighted in binarypoetry.ch's colors. The text keeps VitePress's
    reading width, about 90 characters a line, and on a wide screen a
    page's sections are listed beside it, the one being read marked,
    and on a wider one every doc.
  • The Web UI lists the licenses of the third-party packages it is
    built from, runtime and development, on a licenses page
    (licenses.html), with each package's license text (ADR 0008),
    linked from the footer of the landing and converter pages.
  • An image's size has a Spelling, images (ADR 0007): "html"
    writes an image link sized by #+ATTR_HTML: :width/:height as
    <img src alt width height> and reads that <img> back; under
    "markdown", the default, the attribute line stays verbatim.
  • Obsidian md reads an image's size (![alt|300](image.png),
    |300x200) as its #+ATTR_HTML: :width/:height line and writes
    it back, for an image alone in its paragraph outside a list;
    translating Obsidian md to or from Vanilla md turns one into the
    other. An embed's size (![[image.png|300]]) stays as written.
  • Logseq's image size ([[image.png]]{:width 300}, in Logseq md
    ![alt](image.png){:width 300}, :height too) is the image's
    #+ATTR_HTML: line in Vanilla org and back, for an image line below
    a block's title that is a paragraph of its own. A block's title is
    a headline, which org cannot size, so a title image keeps its size.

Changed

  • Breaking: options are named by format and side (ADR 0007). The
    config's [markdownToOrg] and [orgToMarkdown] sections are gone,
    with an error naming their replacements: [markdown],
    [markdown.input], [markdown.output] and [org.output].
    markdownStyle is [markdown.output.style], recordStyle is
    [org.output] recordMarkdownStyle (CLI --record-markdown-style),
    and the library options are renamed to match (style,
    recordMarkdownStyle).
  • Breaking: useHtml and interpretHtml give way to a Spelling
    per construct (definitionList, underline, superscript,
    subscript): "markdown" or "html", set for both sides in
    [markdown] or per side. The library's spelling and per-construct
    interpretHtml replace them; CLI --html replaces
    --interpret-html and sets both sides.
  • Breaking: org descriptive lists are written as Markdown
    definition lists (term / : definition) rather than as their
    org text (- term :: definition), and read back from them. A
    Markdown list item holding :: stays a list item, and a
    fixed-width line's : is escaped (\: text), as a line below text
    that starts with a colon now starts a definition. A descriptive list
    nested in a list item does not survive a round trip as one (a known
    limitation of the Markdown parser): it comes back as the item's text.
  • Translating Markdown honours the Markdown options, as normalizing
    does: a block holding a construct they concern is converted on its
    own, in the Spelling they name; the rest stays as written.
  • The Web UI's options are grouped by the side they act on, showing
    only those of the sides the conversion has (normalizing Org goes
    through Markdown, so its HTML options show too), and a compact table
    sets each construct's HTML reading and Spelling.
  • The Web UI's demos show a special block as a GFM alert and a link to
    a headline, and Obsidian Markdown has its own demo: wikilinks, a
    callout, an image's size and a task.
  • The Web UI's landing page keeps its text to the docs' reading width,
    about 90 characters a line, centered as the docs' text is, and lists
    what morg does in four points instead of one long paragraph; the
    detail is in the docs.
  • The Web UI and the docs draw arrows (→, ↔) outside code in
    DejaVu Sans, subset to them, centered on the lowercase letters:
    Arial's sat low and small beside them. DejaVu's license is on the
    licenses page.
  • Logseq org and Logseq md write a block's begin and end lines in
    upper case (#+BEGIN_SRC sh, #+END_QUOTE), as Logseq does; org →
    md → org changed them to Emacs's lower case (#+begin_src), a
    special block's to mixed case (#+begin_TIP). Vanilla org keeps
    lower case.

Fixed

  • Obsidian md → org reads a %%comment%% as an org comment (# …)
    alone in its paragraph, else as an html snippet
    (@@html:<!--comment-->@@), and an inline footnote ^[note] as a
    footnote, numbered on from the page's own; both were plain text,
    and the footnote came back escaped (^\[note]), no footnote in
    Obsidian. Org → md writes an inline comment as Obsidian's own
    (%%comment%%), others as an HTML comment, and a footnote. Md → org
    and Obsidian md → Vanilla md read no comment in a wikilink or a diary
    timestamp's <%%(.
  • Two quotes next to each other in a list item or a definition stay
    two: Markdown read them, written without a blank line between them,
    as one.
  • A special block's parameters (#+begin_tip Stretch first) survive
    org → md: uniorg reads and writes none, so they were dropped without
    a warning; morg reads them from the block's begin line.
  • An org descriptive list no definition list can hold (an item with a
    checkbox, or without a term) survives a round trip again: its
    - term :: definition text is written below a
    <!-- morg_descriptive_list --> comment, which reads it back as
    descriptive; it came back a plain list.
  • Spelled in HTML, such a list is written the same way: as a <dl>, it
    lost its checkboxes and gained empty terms. So is one whose
    definition holds blocks (an image, a nested list, a second
    paragraph), which a <dl> dropped.
  • Reading <sup> or <sub> as org (interpretHtml) keeps the HTML
    where a blank precedes it (x <sup>s</sup>): org reads a script
    only after a non-blank character, so it came back as the text
    ^{s}.
  • List item text after a quote or table (- a\n > b\n\n c) stays
    apart from it: org → md wrote no blank line between them, so
    Markdown read the text into the quote, gaining a > each round
    trip, or as a table row.
  • HTML in a list item (org's #+begin_export html) stays an HTML
    block in Markdown, and so does text after it: org → md kept the
    item's indentation in the HTML, which Markdown then read as text.
  • HTML in a Markdown list item keeps its own indentation in org: md →
    org lost up to the item's indentation from each line, each round
    trip.
  • Markup right after other markup (`a`*,*) comes back from org
    without a stray &#xNAN; between them.
  • Empty nested list items right below an item's text (- a\n -)
    survive org → md: Markdown read the text over a lone - as a
    heading, losing one item each round trip.
  • An org #+OPTIONS: line keeps an author's ^:{} where it is: org →
    md took it out from anywhere, md → org put it back last.
  • An indented code line org escapes with a comma (,* x after the
    indentation, in a src or export block) keeps its indentation in
    Markdown: uniorg dropped it with the comma.
  • A Markdown code block without a language, or an HTML block, whose
    line org would read as a headline or keyword (* x, #+end_example)
    gets org's comma escape in its example or export block; that line
    ended the block or became a headline. Org → md drops the comma of an
    example block's line too, which uniorg left in (in a CRLF file
    too), but keeps the escapes
    of a block in a drawer or special block, which travels as org text.
  • Adjacent Markdown tables stay apart in org: md → org wrote them
    with no blank line between them, which org reads as one table.
  • An org table keeps its #+NAME:, #+CAPTION:, #+RESULTS: (an
    empty one too) and other affiliated keywords, and its #+TBLFM:
    formulas, as lines around the Markdown table; both were lost
    without a warning (the keywords by uniorg), in a CRLF file too.
    Several #+TBLFM: lines stay apart: uniorg joined them into one.
  • Org links within a file survive a round trip: a link to a headline
    ([[*Some Heading]], or a fuzzy [[Some Heading]]) is a link to the
    heading's GitHub slug (#some-heading), a link to a <<target>> or
    a #+NAME: one to #name, and md → org links them back. They came
    back as file: links to files of that name. A Markdown anchor of a
    heading ([setup](#getting-started)) becomes a heading link, which
    Emacs follows; it was a custom ID link that found nothing.
  • An org link to a // path keeps its % as written: org → md
    percent-encoded it, md → org read the scheme-relative url as it is,
    so %25 gained a 25 each round trip.
  • Org keyword lines (#+AUTHOR: Jan <jan@x.org>, #+CALL:) go back
    to org as written: md → org read them as Markdown, so an address or
    url became a link nested once more each round trip, and escaped them
    (\n:nil in #+OPTIONS: gained a zero-width space).
  • A headline's property values that Markdown may read as syntax (a
    url, *, _) are written below a <!-- morg_properties -->
    comment, and md → org takes the lines below it back as written; it
    read them as Markdown. Unmarked key:: value lines below a heading
    are Markdown, as a person writes them (an Obsidian Dataview field),
    and convert as before.
  • An org element written verbatim to Markdown (fixed-width lines, a
    drawer, a special block) with ke...
Read more

v0.10.1

Choose a tag to compare

@github-actions github-actions released this 04 Oct 17:45

Fixed

  • Obsidian md → org keeps an embed's size (![[image.png|300]]); it
    became a link description (![[image.png][300]]).
  • Obsidian org → md writes an embed's ! unescaped; \![[image.png]]
    was a ! and a link to Obsidian.
  • Translating Markdown to or from Logseq md counts a tab in a list
    item's indentation to its tab stop. A fence indented with spaces among
    tab-indented lines drifted on each trip, and a tab-indented item's
    fence could become indented code.

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 16:37

Removed

  • Breaking: the morg normalize subcommand. One format on both
    sides is enough: with one preset it normalizes (--from org and
    --to org, or --input notes.org --output notes.org), with two it
    translates.

Added

  • translateOrg(org, { inputPreset, outputPreset }): Logseq org ↔
    Vanilla org within org, changing only the headlines the two write
    differently (an empty block's space, a first line that starts an
    element) and keeping every other line as written (ADR 0006 §4
    amended). Logseq's task markers (NOW, DOING, WAITING, …) are
    declared for Emacs in a #+TODO: line, dropped again on the way
    back; an own #+TODO: line, which Logseq ignores, warns of the
    markers Logseq shows as text. A collapsed block is folded for Emacs
    (:collapsed: true ↔ :VISIBILITY: folded). Emacs syntax Logseq
    misreads ([[*heading]] links, <<<radio>>> targets, keyword lines
    below the first headline, …) stays, with a warning.
  • translateMarkdown(md, { inputPreset, outputPreset }): Logseq
    Markdown ↔ Vanilla Markdown within Markdown, blocks ↔ list items and
    headings with their meta as before, page properties ↔ flat
    frontmatter, a block's org blocks ↔ fences, quotes and query code
    blocks; other content stays as written. Obsidian Markdown ↔ Logseq
    Markdown too, an aliased wikilink ↔ a labeled page ref, and
    Obsidian Markdown → Vanilla Markdown: a %%comment%% becomes an
    HTML comment and an inline footnote a footnote (also on the way to
    Logseq Markdown); wikilinks stay, as resolving a note's file needs
    the vault. markdownStyle (CLI --bullet, --emphasis, …) rewrites
    only the markers it names; Logseq Markdown keeps its - bullets.
  • Web UI: two dialects of one format translate (Input: Markdown
    (Logseq), Output: Markdown); a translated file is saved under its
    dialect (page.vanilla.md). Changing the input's format still moves
    the output to the other format.
  • CLI: one format on both sides with two presets translates
    (morg --input-preset logseq --input page.md --output out.md); it
    was an error.
  • Vanilla org → Logseq Markdown warns of [[*heading]] links, which
    Logseq reads as refs to pages of that name.

Changed

  • Breaking: Node.js 24 or later (engines.node was >=20, which
    nothing tested; Node 20 is end-of-life).

v0.9.2

Choose a tag to compare

@github-actions github-actions released this 04 Oct 10:48

Fixed

  • Logseq org ↔ Logseq Markdown reads a block's title as inline text: a
    title that looks like org line syntax (: a, - a, 1. a, # a)
    was converted as a fixed-width line, a list or a comment, and a
    : a title holding markup grew with each round trip. A table or a
    rule on the headline line stays one, which Logseq org → Vanilla
    Markdown now does too.

v0.9.1

Choose a tag to compare

@github-actions github-actions released this 04 Oct 00:48

Fixed

  • An empty Markdown heading becomes an org headline with a space after
    its stars, as Emacs needs to read it as one; it was written as bare
    stars, which Emacs and morg read as text.
  • Logseq Markdown → Vanilla org writes an empty block as a headline
    with a space after its stars, which Emacs reads as one, instead of
    Logseq org's bare stars.
  • Logseq Markdown → Vanilla org writes a block whose first line starts
    a src block, a table, a list or its property drawer with that line
    below an empty headline: on the stars' line, as Logseq org writes it,
    Emacs read it as the title and cut the element off (ADR 0006,
    amended).
  • A multi-line HTML comment keeps an empty first or last line as an
    empty org comment line instead of losing it, so such a
    comment comes back as it was.

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 03 Oct 20:44

Added

  • inputPreset and outputPreset conversion options: the dialect the
    input is read in and the one the output is written in, Vanilla when
    left out (ADR 0006). preset still sets both, leaving a side Vanilla
    whose format it has no dialect for; a side preset without one throws,
    as does preset together with another side preset, and normalize*
    with different presets per side.
  • --input-preset / --output-preset and inputPreset /
    outputPreset in morg.toml, and the preset name vanilla. Each
    side resolves on its own: side flag, --preset, side key, preset;
    preset next to a different side preset in one place is an error.
  • Logseq org → Vanilla Markdown (--input-preset logseq): blocks become
    a nested list, a heading block a heading whose children start a new
    list, numbered blocks an ordered list. Task markers render as Logseq
    shows them (- [ ], - [x], - [ ] LATER …); planning and
    properties become key:: value lines in the item, under the
    orgismKeys names; collapsed and drawers are dropped with a
    warning. A block's title stays inline text, as Logseq reads it, even
    where it looks like org line syntax (: a, - a). After a heading
    block, Markdown has no way back to the top level, so a later
    top-level block reads back as the heading's child. Logseq's inline
    syntax is carried as Logseq Markdown writes it, as text a return trip
    restores: page and block refs
    ([[Page]], [label]([[Page]])), macros ({{video …}}), tags,
    priorities, hiccup, highlights; a query block becomes a query code
    block.
  • Vanilla Markdown → Logseq org (--output-preset logseq), as Logseq
    reads a file it did not write: a list item is a block, its nested
    list its children; a heading is a block nesting by level, the text
    below it its content; other text after a list a block of its own.
    Task items, key:: value lines and ordered lists come back as task
    markers, planning, properties and numbered blocks. Reference links
    become inline before the page splits into blocks, and a footnote's
    definition moves to the block of its first reference. Logseq's syntax
    carried in Vanilla Markdown (page and block refs, macros, a query
    code block) is Logseq's again.
  • Logseq Markdown ↔ Vanilla org: Vanilla org is read and written as
    Logseq org, which it is, page properties as leading keywords.
  • Logseq page properties ↔ plain Vanilla Markdown frontmatter
    (title: P), as Markdown tools read metadata; a keyword that acts in
    Emacs stays in morg_keywords.
  • Web UI: an Input and an Output select, each naming a format and its
    dialect (Org, Org (Logseq), Markdown, Markdown (Logseq), Markdown
    (Obsidian)), above their text areas, replace the direction and preset
    selects. The direction follows from the two; the same on both sides
    normalizes, and says so; a dialect change within one format is not
    offered; ⇄ swaps the sides. The demo follows the input; sides
    remembered by 0.8.0 are restored.
  • Obsidian ↔ Logseq: an Obsidian wikilink and a Logseq page ref map
    onto each other ([[Page|label]] ↔ [[Page][label]]).

Changed

  • Breaking. A FragmentConverter takes a third argument, the
    preset whose syntax a Vanilla side carries. Preset.convertOrg and
    Preset.convertMarkdown get a third argument, the conversion's
    context (exported as ConversionContext): the side the preset is on
    (both, input or output), onWarning and orgismKeys.
  • Breaking. Preset holds one dialect per format, each read in
    one direction and written in the other (ADR 0006):
    markdown: { read: { mdast, org }, write } and
    org: { read, write }, typed MarkdownDialect and OrgDialect.
    applyToMdast, applyToUniorg and extractFromUniorg are gone. The
    built-in presets convert as before.

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 03 Oct 13:34

Added

  • Preset.convertOrg(org, convert) and
    Preset.convertMarkdown(markdown, convert), optional hooks that take
    a whole conversion over, for a dialect whose documents are an outline
    of fragments; convert runs the core on one fragment (recording no
    Markdown style: a fragment's style is the preset's).
  • The Web UI demo also shows a quote, a nested ordered list and a src
    block switch.
  • The Web UI offers a Logseq demo page, in Logseq org or Logseq
    Markdown, while the Logseq preset is selected; an untouched demo
    follows the preset as it follows the direction.

Changed

  • Breaking. Logseq preset: a page converts as Logseq's outline of
    blocks. Org headlines ↔ - bullets indented one tab per level, an
    empty block (bare stars) ↔ -, :heading: N ↔ - ## …, a block's
    property drawer ↔ key:: value lines; a block's content converts as
    one fragment, so a code block or table that starts on the headline
    line stays whole. Blocks used to become paragraphs below the nearest
    heading, which flattened every level below it. logseq() takes no
    options anymore (nestUnderHeadings is gone).

Fixed

  • A src block's switches and header arguments
    (#+begin_src python -n :results output) travel as the Markdown
    fence's meta (```python -n :results output) instead of being
    dropped both ways.
  • A block or drawer kept as org text in Markdown (special, verse,
    center blocks, :LOGBOOK:, …) no longer falls apart on the way back
    when its lines read as Markdown syntax: a blank line followed by an
    indented line became a code block, a # line a heading, a - line a
    list, and
    the round trip did not converge.
  • Logseq preset: a block whose content starts with its properties
    (** :PROPERTIES:, as Logseq writes a query block) keeps them as its
    key:: lines instead of growing an :END: line per round trip.
  • Logseq preset: a repeated task's :LOGBOOK: state lines take the
    bullet Logseq writes in each format, - State … in org and
    * State … in Markdown.
  • Logseq preset: an org plain link (https://…) stays a bare url in
    Markdown, as Logseq writes it, and comes back plain instead of as
    [[https://…]].
  • Logseq preset: an email address stays text, written bare in
    Markdown as Logseq does, instead of coming back as a mailto: link.
  • Logseq preset: a block that starts with a tag (#meeting) keeps it
    a tag in Markdown; it was written \#meeting, which Logseq reads as
    plain text.
  • Logseq preset: an org block written in a Markdown block
    (#+BEGIN_SRC…#+END_SRC, which Logseq reads there too) goes to org
    instead of as escaped text that changed on every round trip; the
    Markdown content of a quote block converts.

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 02 Oct 11:06

Added

  • Logseq preset: page properties map both ways. A page's first block of
    key:: value lines and flat frontmatter entries become the leading
    #+key: value lines Logseq reads as page properties of an org page,
    and come back as a key:: block, values as written. Frontmatter keys
    that act in Emacs (todo, include, setupfile, …) stay inert in
    the frontmatter block. The block used
    to become an invalid headline (* title:: …).
  • Preset.applyToMdast(mdast, markdown), an optional hook that runs
    before the generic md → org transform, with the Markdown source at
    hand.

Changed

  • Breaking output change. YAML frontmatter no longer becomes org
    keywords (tags: [a] → #+TAGS: a); it travels verbatim in a
    marked comment block, #+begin_comment morg_frontmatter, inert in
    Emacs and in export. Upper-cased keys used to collide with keywords
    that act: #+TAGS declares the tag vocabulary, #+TODO redefines
    the TODO keywords, #+INCLUDE pulls a file into exports (ADR 0005).
    transformMdastToUniorgAst returns the block as a raw text node
    instead of keyword nodes, which transformUniorgAstToMdast reads
    back; a uniorg tree parsed from org text cannot carry the block's
    marker (uniorg drops it), so pass that text as its org option, or
    convert files with convertOrgToMarkdown.
  • Breaking output change. An org file's leading keywords
    (#+TITLE, #+STARTUP, …) no longer become plain frontmatter keys;
    they travel as a morg_keywords frontmatter entry and come back as
    keywords, so #+STARTUP keeps its effect. An entry a keyword line
    cannot hold (a line break in the value, a key org does not read as a
    keyword name) stays in the frontmatter block instead.
  • Migration: files written by 0.6.0 and earlier carry their frontmatter
    as keywords and now read as org-native keywords (morg_keywords).
    That converges, but Markdown tools no longer see title. Re-convert
    them from the Markdown source, or move the keywords into a
    morg_frontmatter block by hand.

Fixed

  • A dual affiliated keyword keeps its second value through Markdown:
    #+CAPTION[short]: long used to come back as a plain #+CAPTION:
    with the short caption glued onto the long one, and
    #+RESULTS[hash]: … as two separate lines.
  • An Emacs mode line (# -*- mode: org -*-) stays on the first line
    through Markdown, where Emacs reads it, instead of landing below the
    frontmatter.
  • A file-level property drawer (org-roam's :ID:) no longer turns into
    ID:: abc text in Markdown and stays text on the way back, which
    broke org-roam links. It travels as a morg_properties frontmatter
    entry and comes back as the drawer leading the file.
  • A leading #+CAPTION:, #+NAME: or other keyword org attaches to
    the element below it (#+SOURCE: is an alias of #+NAME:) no longer
    comes back from Markdown attached to the next paragraph or keyword;
    md → org keeps it apart with a blank line.
  • A literal backslash before a letter in Markdown text no longer turns
    into LaTeX or a symbol through org: a path like C:\Users\me used to
    come back as C:$\Users$$\me$, \alpha as α.
  • A | in inline code in a Markdown table cell (`a \| b`) no
    longer splits the org table cell: it becomes the lookalike ∣
    (U+2223) in org, reported via onWarning, and \| again in
    Markdown.
  • An ordered list starting at 0. keeps its start through org → md
    instead of being renumbered from 1..
  • A hard line break inside a list item no longer comes back from org
    with the next line's indentation as literal leading whitespace
    (&#x20;).

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 26 Sep 11:15

Changed

  • Conversion is slower than in 0.5.0: md → org takes about 1.6 to 2.8
    times as long, org → md about 10 % longer. The escapes below have to
    check how org reads the output, which takes org parses of the text
    concerned; org → md guards _. lines and drops the escapes again.
    A performance check in CI now keeps it from growing unnoticed.

Fixed

Mostly found by round-tripping a real Obsidian vault, the rest by code
review and fuzzing; each of these silently changed text.

  • Markup touching a word character (`x`s, foo**bar**baz) no
    longer comes back with literal markers. Org only reads markup next to
    whitespace or punctuation, so md → org now separates the two with a
    zero-width space, the org manual's escape character, and org → md
    drops it again.
  • Literal text org would read as markup, such as the path /etc/ or an
    escaped \*b\*, stays literal instead of turning italic or bold,
    also when another inline node sits between the markers
    (\*b `x` c\*).
  • Relative links and images ([t](notes.md#Some%20Heading)) become
    org file: links ([[file:notes.md::Some Heading][t]]) and come
    back as the same Markdown links. They used to become bare org paths,
    which org reads as a heading search rather than a file, so Emacs
    would not open them and the obsidian preset turned them into
    wikilinks. A path holding a literal %5B, %5D or :: keeps it
    instead of pointing at another file, and an org file: path holding
    # or % ([[file:C# notes.md]]) comes back pointing at that file,
    not at C.
  • A heading inside a list item keeps its text as a line of the item
    and reports via onWarning, instead of silently coming back as
    literal \*\* …: org has no headline inside a list.
  • A paragraph line that starts like org line syntax, such as an
    escaped 1\., \- or \#, or a lazy continuation line, stays text
    instead of turning into a list item, headline, comment or table. This
    includes a line starting with a footnote reference ([^1] text,
    which org reads as a footnote definition), one following a nested
    list or code block inside a list item, one inside bold or a link
    text spanning two lines, one ending in a bare bullet (1.), and one
    in a logseq block below its first line. The same goes for line
    syntax spanning lines (an escaped \#+begin_src … \#+end_src) or
    depending on the heading above (SCHEDULED: <…>). A paragraph that
    is exactly one of the org constructs morg writes into Markdown
    verbatim (drawers, fixed-width lines, clocks, …) still comes back as
    org.
  • A line starting _. or _) converts in both directions: uniorg,
    morg's org parser, took it for a list bullet and failed on the whole
    document, or, when a list followed, silently dropped the line. Org
    reads it as text, and so does morg now.
  • List item text after a nested list (- a\n - b\n\n c) stays in
    the outer item instead of moving into the nested one on the next
    round trip: org → md keeps the blank line Markdown needs there.
  • A literal \[fn:1] in Markdown text stays text instead of becoming a
    footnote reference.
  • Inline code holding a ~ that ends org code early (`a~ b`)
    becomes org =a~ b= instead of breaking the rest of the line. Code
    that a = would end early too stays plain text and reports via
    onWarning.
  • #+OPTIONS: ^:nil is honored on org → md: a_b stays a_b
    instead of becoming a\_{b}, and the option stays.
  • Bold, italic or strikethrough spanning more than two lines keeps its
    markup: org markup spans at most two lines, so its line endings
    become spaces, as Markdown renders them anyway.
  • A heading inside a blockquote keeps its text as a line of the quote
    and reports via onWarning: Emacs ends a quote block at a headline.
  • A fenced code block inside a list item keeps its indentation in both
    directions. md → org used to shrink the code's own indentation by up
    to the item's (if x:\n y() lost two spaces), and org → md added
    the item's indentation to every line.
  • An escaped \| in a Markdown table cell becomes org's \vert{}
    entity instead of splitting the cell, and comes back as \|.
  • Bare underscores and carets (my_notes_2021.md, x^y, also right
    after markup or a link: **a**_b, or in an obsidian wikilink alias:
    [[a_b.md|a_b]]) are no longer read as org sub/superscripts. md → org adds ^:{} to #+OPTIONS: when the text
    needs it; org → md honors it in a top-level #+OPTIONS: and consumes
    it where the text needs it, so an author's own options: ^:{} stays.
  • Inline code spanning three or more lines converts to org; its line
    endings (LF, CRLF or CR) become spaces, which is how CommonMark
    renders them anyway.
  • Inline code with whitespace at either end, as a padding typo easily
    leaves, converts to org instead of breaking the rest of the
    paragraph: org markup may not start or end with whitespace, so the
    whitespace moves just outside the code. Whitespace-only code stays
    plain text and reports via onWarning.
  • An image with an anchor (![a](i.svg#part)) comes back as an image
    instead of a plain link.
  • A space between text and markup inside an org table cell is kept;
    only the cell's alignment padding is trimmed.
  • With the obsidian preset, an aliased wikilink in a table cell is
    written [[Page\|alias]], as Obsidian does, instead of splitting the
    cell.

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 19 Sep 12:21

Added

  • morg --help, morg -h and a bare morg print usage: the
    normalize command, every flag with its argument and a one-line
    description, and a few worked examples. morg --version prints the
    installed version. A bare invocation previously failed on formats it
    could not determine, which told a first-time reader nothing about
    what the CLI accepts; there was no way to ask at all.

    The help text is rendered from the same table the parser dispatches
    on, so it cannot document a flag that does not exist or omit one that
    does.

Changed

  • The site names the npm package and links it. The landing page says
    morg is also a CLI and a library, published as @remigius42/morg,
    and shows the npx line that runs it without an install; both pages
    carry an npm link in the nav beside GitHub. Until now the only route
    from the Web UI to the package was the repository, which documents it
    but does not hand it over.

    The nav had fit 320px exactly, so a fourth item would have put the
    whole page into a horizontal scroll: the nav lists now wrap, which
    costs a second row on the narrowest phones and leaves every wider
    viewport as it was.

Fixed

  • An unsupported format names the value it rejected, as in
    Unsupported format 'notes.md', rather than only the two it
    accepts, and a value that has a file extension is answered with the
    likely correction: --from and --to take a format name, and the
    file belongs to --input or --output. They sit beside each other
    and read alike, so a file name in the wrong one is an easy mistake that
    the old message left the reader to find unaided. Failures that come
    from the invocation now also point at morg --help.