@remigius42/morg 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -30
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.js +22 -60
- package/dist/cli/error.js +1 -1
- package/dist/cli/flags.d.ts +27 -0
- package/dist/cli/flags.js +127 -0
- package/dist/cli/formats.js +18 -4
- package/dist/cli/help.d.ts +1 -0
- package/dist/cli/help.js +28 -0
- package/dist/cli.js +24 -1
- package/dist/conversionOptions.d.ts +2 -2
- package/dist/conversionOptions.js +2 -2
- package/dist/core/bracedScripts.d.ts +12 -0
- package/dist/core/bracedScripts.js +159 -0
- package/dist/core/footnoteReferences.d.ts +10 -0
- package/dist/core/footnoteReferences.js +24 -0
- package/dist/core/lineSyntax.d.ts +12 -0
- package/dist/core/lineSyntax.js +206 -0
- package/dist/core/markupBoundary.d.ts +12 -0
- package/dist/core/markupBoundary.js +195 -0
- package/dist/core/mdastToUniorg/blocks.js +1 -1
- package/dist/core/mdastToUniorg/index.js +10 -2
- package/dist/core/mdastToUniorg/lists.d.ts +1 -1
- package/dist/core/mdastToUniorg/lists.js +21 -2
- package/dist/core/mdastToUniorg/phrasing.js +145 -12
- package/dist/core/orgPath.d.ts +9 -0
- package/dist/core/orgPath.js +24 -0
- package/dist/core/render.d.ts +33 -0
- package/dist/core/render.js +101 -0
- package/dist/core/tablePipes.d.ts +8 -0
- package/dist/core/tablePipes.js +14 -0
- package/dist/core/underscoreBullets.d.ts +10 -0
- package/dist/core/underscoreBullets.js +32 -0
- package/dist/core/uniorgToMdast/elements.js +1 -1
- package/dist/core/uniorgToMdast/lists.js +12 -1
- package/dist/core/uniorgToMdast/objects.js +38 -6
- package/dist/core/uniorgToMdast/tables.js +12 -6
- package/dist/fileNames.d.ts +1 -1
- package/dist/fileNames.js +1 -1
- package/dist/markdownToOrg.js +19 -1
- package/dist/normalize.d.ts +2 -2
- package/dist/normalize.js +1 -1
- package/dist/options.d.ts +3 -3
- package/dist/orgToMarkdown.js +29 -5
- package/dist/presets/logseq.js +1 -1
- package/package.json +4 -1
package/dist/markdownToOrg.js
CHANGED
|
@@ -7,6 +7,11 @@ import { uniorgStringify } from "uniorg-stringify";
|
|
|
7
7
|
import { visit } from "unist-util-visit";
|
|
8
8
|
import { transformMdastToUniorgAst } from "./core/mdastToUniorg/index.js";
|
|
9
9
|
import { detectMarkdownStyle, STYLE_KEYWORD } from "./core/markdownStyle.js";
|
|
10
|
+
import { escapeOrgMarkup } from "./core/markupBoundary.js";
|
|
11
|
+
import { escapeLineSyntax } from "./core/lineSyntax.js";
|
|
12
|
+
import { escapeFootnoteReferences } from "./core/footnoteReferences.js";
|
|
13
|
+
import { escapeTablePipes } from "./core/tablePipes.js";
|
|
14
|
+
import { requireBracedScripts } from "./core/bracedScripts.js";
|
|
10
15
|
/**
|
|
11
16
|
* Converts a Markdown string to an Org-mode string.
|
|
12
17
|
* @param markdown The Markdown string to convert.
|
|
@@ -40,7 +45,7 @@ export function convertMarkdownToOrg(markdown, options = {}) {
|
|
|
40
45
|
canonical
|
|
41
46
|
]));
|
|
42
47
|
restoreOrgisms(uniorgAst, canonicalKeys);
|
|
43
|
-
// Phase 2c: formatting-as-structure
|
|
48
|
+
// Phase 2c: formatting-as-structure. Adjacent lists need two blank
|
|
44
49
|
// lines between them, or org's parser merges them into one list.
|
|
45
50
|
separateAdjacentLists(uniorgAst);
|
|
46
51
|
// Phase 2d: record the source's own style markers, so the return trip
|
|
@@ -52,6 +57,19 @@ export function convertMarkdownToOrg(markdown, options = {}) {
|
|
|
52
57
|
if (options.preset?.applyToUniorg) {
|
|
53
58
|
uniorgAst = options.preset.applyToUniorg(uniorgAst);
|
|
54
59
|
}
|
|
60
|
+
// Phase 3b: literal footnote references, paragraph lines org would
|
|
61
|
+
// read as line syntax, literal markers org would read as markup, and
|
|
62
|
+
// markup touching a word character, need a zero-width space escape;
|
|
63
|
+
// a pipe in a table cell an entity
|
|
64
|
+
escapeTablePipes(uniorgAst);
|
|
65
|
+
escapeFootnoteReferences(uniorgAst);
|
|
66
|
+
escapeLineSyntax(uniorgAst);
|
|
67
|
+
escapeOrgMarkup(uniorgAst);
|
|
68
|
+
// Phase 3c: md text has no sub/superscripts; keep org from reading
|
|
69
|
+
// bare underscores and carets as such. Checked on the text as
|
|
70
|
+
// rendered: after the preset, whose text rewrites (wikilink aliases)
|
|
71
|
+
// org parses too, and after the escapes, next to which org reads them
|
|
72
|
+
requireBracedScripts(uniorgAst);
|
|
55
73
|
// Phase 4: Render uniorg-ast to Org-mode string
|
|
56
74
|
const processor = unified().use(uniorgStringify);
|
|
57
75
|
const orgContent = processor.stringify(uniorgAst);
|
package/dist/normalize.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MarkdownToOrgOptions, OrgToMarkdownOptions } from "./options.js";
|
|
2
2
|
/**
|
|
3
3
|
* The full option set of both directions: normalization uses the same
|
|
4
|
-
* configuration as conversion
|
|
4
|
+
* configuration as conversion, because Convergence is per-config (ADR
|
|
5
5
|
* 0002), so a file must be normalized with the exact config (preset,
|
|
6
6
|
* style, key names, toggles) it will be converted with.
|
|
7
7
|
*/
|
|
@@ -9,7 +9,7 @@ export type NormalizeOptions = MarkdownToOrgOptions & OrgToMarkdownOptions;
|
|
|
9
9
|
/**
|
|
10
10
|
* Normalizes a Markdown string to morg's canonical form: one full round
|
|
11
11
|
* trip (`md → org → md`), whose output is a fixed point (see ADR 0001).
|
|
12
|
-
* This canonicalizes, it does not just re-style
|
|
12
|
+
* This canonicalizes, it does not just re-style: org-isms and md-isms
|
|
13
13
|
* are rewritten the same way a conversion would rewrite them.
|
|
14
14
|
* @param markdown The Markdown string to normalize.
|
|
15
15
|
* @param options Warning callback and dialect preset.
|
package/dist/normalize.js
CHANGED
|
@@ -3,7 +3,7 @@ import { convertOrgToMarkdown } from "./orgToMarkdown.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Normalizes a Markdown string to morg's canonical form: one full round
|
|
5
5
|
* trip (`md → org → md`), whose output is a fixed point (see ADR 0001).
|
|
6
|
-
* This canonicalizes, it does not just re-style
|
|
6
|
+
* This canonicalizes, it does not just re-style: org-isms and md-isms
|
|
7
7
|
* are rewritten the same way a conversion would rewrite them.
|
|
8
8
|
* @param markdown The Markdown string to normalize.
|
|
9
9
|
* @param options Warning callback and dialect preset.
|
package/dist/options.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export interface MarkdownToOrgOptions {
|
|
|
33
33
|
/**
|
|
34
34
|
* Custom names for org-ism `key::` lines, canonical → custom (e.g.
|
|
35
35
|
* `{ todo: "state" }`). Must match the mapping the file was written
|
|
36
|
-
* with
|
|
36
|
+
* with, since Convergence is per-config (ADR 0002).
|
|
37
37
|
*/
|
|
38
38
|
orgismKeys?: Record<string, string>;
|
|
39
39
|
/** Called for each construct dropped without an equivalent. */
|
|
@@ -46,7 +46,7 @@ export interface MarkdownToOrgOptions {
|
|
|
46
46
|
* Canonical form is parameterized by these (see ADR 0001): round trips
|
|
47
47
|
* must use the same style, and files formatted under one style are not
|
|
48
48
|
* a fixed point under another. Defaults: `-` bullet, `*` emphasis /
|
|
49
|
-
* `*` strong (i.e. `**bold**`), backtick fences, `-` rule
|
|
49
|
+
* `*` strong (i.e. `**bold**`), backtick fences, `-` rule: prettier's
|
|
50
50
|
* choices except emphasis (`emphasis: "_"` aligns with prettier).
|
|
51
51
|
*/
|
|
52
52
|
export interface MarkdownStyleOptions {
|
|
@@ -78,7 +78,7 @@ export interface OrgToMarkdownOptions {
|
|
|
78
78
|
* Render Org constructs without a Markdown equivalent as raw HTML
|
|
79
79
|
* (`<u>`, `<sup>`, `<sub>`, `<dl>`) instead of keeping their org markup
|
|
80
80
|
* verbatim. HTML round-trips as a preserved md-ism (export blocks and
|
|
81
|
-
* snippets), not back to native org markup
|
|
81
|
+
* snippets), not back to native org markup, a one-way door unless
|
|
82
82
|
* the return trip enables its inverse, `interpretHtml`.
|
|
83
83
|
* Default: `false`.
|
|
84
84
|
*/
|
package/dist/orgToMarkdown.js
CHANGED
|
@@ -1,11 +1,24 @@
|
|
|
1
1
|
import { unified } from "unified";
|
|
2
|
-
import uniorgParse from "uniorg-parse";
|
|
3
2
|
import remarkStringify from "remark-stringify";
|
|
4
3
|
import remarkGfm from "remark-gfm";
|
|
5
4
|
import remarkFrontmatter from "remark-frontmatter";
|
|
6
5
|
import remarkMath from "remark-math";
|
|
7
6
|
import { transformUniorgAstToMdast } from "./core/uniorgToMdast/index.js";
|
|
8
7
|
import { takeRecordedStyle } from "./core/markdownStyle.js";
|
|
8
|
+
import { unescapeOrgMarkup } from "./core/markupBoundary.js";
|
|
9
|
+
import { unescapeLineSyntax } from "./core/lineSyntax.js";
|
|
10
|
+
import { unescapeFootnoteReferences } from "./core/footnoteReferences.js";
|
|
11
|
+
import { parseOrg } from "./core/bracedScripts.js";
|
|
12
|
+
import { dropUnderscoreBulletGuards, guardUnderscoreBullets } from "./core/underscoreBullets.js";
|
|
13
|
+
// a list item's paragraph after its nested list needs a blank line, or
|
|
14
|
+
// md reads it as a lazy continuation of the nested list's last item
|
|
15
|
+
function separateTextAfterNestedList(left, right, parent) {
|
|
16
|
+
return parent.type === "listItem" &&
|
|
17
|
+
left.type === "list" &&
|
|
18
|
+
right.type === "paragraph"
|
|
19
|
+
? 1
|
|
20
|
+
: undefined;
|
|
21
|
+
}
|
|
9
22
|
/**
|
|
10
23
|
* Converts an Org-mode string to a Markdown string.
|
|
11
24
|
* @param org The Org-mode string to convert.
|
|
@@ -14,10 +27,17 @@ import { takeRecordedStyle } from "./core/markdownStyle.js";
|
|
|
14
27
|
*/
|
|
15
28
|
export function convertOrgToMarkdown(org, options = {}) {
|
|
16
29
|
// Phase 1: Parse Org-mode to uniorg-ast
|
|
17
|
-
|
|
18
|
-
//
|
|
30
|
+
// md text has no scripts, so ^:{} is implied there and consumed here
|
|
31
|
+
// (see markdownToOrg); uniorg misreads `_.` lines (see underscoreBullets)
|
|
32
|
+
let uniorgAst = parseOrg(guardUnderscoreBullets(org));
|
|
33
|
+
dropUnderscoreBulletGuards(uniorgAst);
|
|
34
|
+
// Phase 1b: a recorded style is morg's own (ADR 0004), so consume it so
|
|
19
35
|
// it does not travel on as frontmatter; explicit options still win
|
|
20
36
|
const recordedStyle = takeRecordedStyle(uniorgAst);
|
|
37
|
+
// Phase 1c: markdown needs no zero-width space escapes (inverse of md→org)
|
|
38
|
+
unescapeOrgMarkup(uniorgAst);
|
|
39
|
+
unescapeLineSyntax(uniorgAst);
|
|
40
|
+
unescapeFootnoteReferences(uniorgAst);
|
|
21
41
|
// Phase 2: Extract dialect preset conventions, if any
|
|
22
42
|
if (options.preset?.extractFromUniorg) {
|
|
23
43
|
uniorgAst = options.preset.extractFromUniorg(uniorgAst);
|
|
@@ -46,11 +66,15 @@ export function convertOrgToMarkdown(org, options = {}) {
|
|
|
46
66
|
rule: "-",
|
|
47
67
|
...recordedStyle,
|
|
48
68
|
...options.markdownStyle,
|
|
69
|
+
join: [separateTextAfterNestedList],
|
|
49
70
|
handlers: {
|
|
50
71
|
// key:: value blocks and preset inline passthroughs (e.g.
|
|
51
|
-
// wikilinks) are emitted verbatim, unescaped
|
|
72
|
+
// wikilinks) are emitted verbatim, unescaped; only a pipe inside
|
|
73
|
+
// a table cell is escaped, or it would split the cell
|
|
52
74
|
keyValue: (node) => node.value,
|
|
53
|
-
verbatimInline: (node) =>
|
|
75
|
+
verbatimInline: (node, _parent, state) => state.stack.includes("tableCell")
|
|
76
|
+
? node.value.replaceAll("|", "\\|")
|
|
77
|
+
: node.value
|
|
54
78
|
}
|
|
55
79
|
})
|
|
56
80
|
.use(remarkGfm)
|
package/dist/presets/logseq.js
CHANGED
|
@@ -191,7 +191,7 @@ function repairHighlights(uniorgAst) {
|
|
|
191
191
|
}
|
|
192
192
|
// Logseq page and block references: [[page]] stays a wikilink,
|
|
193
193
|
// [[page][label]] becomes [label]([[page]]), [[((uuid))][label]]
|
|
194
|
-
// becomes [label](((uuid)))
|
|
194
|
+
// becomes [label](((uuid))), emitted unescaped via verbatim-inline
|
|
195
195
|
const BLOCK_REF_RE = /^\(\(.*\)\)$/;
|
|
196
196
|
function pageRefValue(label, target) {
|
|
197
197
|
if (!label) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remigius42/morg",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Bidirectional Markdown ↔ Org-mode converter with round-trip convergence",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"org-mode",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
"prepare": "husky",
|
|
47
47
|
"prepack": "npm run build",
|
|
48
48
|
"version": "node scripts/release-changelog.mjs && git add CHANGELOG.md",
|
|
49
|
+
"postversion": "printf '\\nNext:\\n git push origin v%s\\n wait for the Release run to pass\\n git push\\n' \"$npm_package_version\"",
|
|
49
50
|
"build": "tsc -p tsconfig.build.json",
|
|
50
51
|
"build:web": "vite build web",
|
|
51
52
|
"dev:web": "vite web",
|
|
@@ -61,6 +62,8 @@
|
|
|
61
62
|
"lint:fix": "npm run lint:fix:prettier && npm run lint:fix:eslint",
|
|
62
63
|
"lint:fix:prettier": "prettier --write '**/*'",
|
|
63
64
|
"lint:fix:eslint": "eslint --fix '**/*.{ts,mts,js}'",
|
|
65
|
+
"perf": "npm run build && node scripts/perf/perf.mjs",
|
|
66
|
+
"perf:record": "node scripts/perf/perf.mjs --record",
|
|
64
67
|
"test:unit": "vitest",
|
|
65
68
|
"test:unit:ci": "vitest run --reporter default --coverage",
|
|
66
69
|
"test:coverage": "vitest run --coverage",
|