@remigius42/morg 0.6.0 → 0.8.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 +23 -11
- package/dist/core/affiliated.d.ts +13 -0
- package/dist/core/affiliated.js +43 -0
- package/dist/core/backslashCommands.d.ts +10 -0
- package/dist/core/backslashCommands.js +43 -0
- package/dist/core/bracedScripts.d.ts +7 -0
- package/dist/core/bracedScripts.js +10 -0
- package/dist/core/frontmatterBlock.d.ts +89 -0
- package/dist/core/frontmatterBlock.js +448 -0
- package/dist/core/keyValueLines.d.ts +6 -0
- package/dist/core/keyValueLines.js +18 -0
- package/dist/core/lineSyntax.d.ts +16 -0
- package/dist/core/lineSyntax.js +25 -2
- package/dist/core/mdastToUniorg/blocks.d.ts +0 -1
- package/dist/core/mdastToUniorg/blocks.js +7 -32
- package/dist/core/mdastToUniorg/index.d.ts +6 -0
- package/dist/core/mdastToUniorg/index.js +72 -7
- package/dist/core/passthroughSource.d.ts +21 -0
- package/dist/core/passthroughSource.js +94 -0
- package/dist/core/tablePipes.d.ts +12 -3
- package/dist/core/tablePipes.js +38 -5
- package/dist/core/uniorgToMdast/elements.js +6 -1
- package/dist/core/uniorgToMdast/index.d.ts +3 -2
- package/dist/core/uniorgToMdast/index.js +100 -31
- package/dist/core/uniorgToMdast/lists.js +1 -1
- package/dist/core/uniorgToMdast/objects.js +6 -0
- package/dist/core/uniorgToMdast/shared.d.ts +5 -0
- package/dist/core/uniorgToMdast/shared.js +9 -13
- package/dist/index.d.ts +1 -2
- package/dist/markdownToOrg.js +41 -25
- package/dist/orgToMarkdown.js +18 -2
- package/dist/presets/logseq.d.ts +3 -22
- package/dist/presets/logseq.js +269 -186
- package/dist/presets/logseqOutline.d.ts +22 -0
- package/dist/presets/logseqOutline.js +251 -0
- package/dist/presets/types.d.ts +12 -1
- package/package.json +1 -1
package/dist/markdownToOrg.js
CHANGED
|
@@ -5,13 +5,17 @@ import remarkFrontmatter from "remark-frontmatter";
|
|
|
5
5
|
import remarkMath from "remark-math";
|
|
6
6
|
import { uniorgStringify } from "uniorg-stringify";
|
|
7
7
|
import { visit } from "unist-util-visit";
|
|
8
|
-
import {
|
|
8
|
+
import { transformMdastToUniorgDraft } from "./core/mdastToUniorg/index.js";
|
|
9
9
|
import { detectMarkdownStyle, STYLE_KEYWORD } from "./core/markdownStyle.js";
|
|
10
10
|
import { escapeOrgMarkup } from "./core/markupBoundary.js";
|
|
11
|
+
import { renderFileHeader } from "./core/frontmatterBlock.js";
|
|
11
12
|
import { escapeLineSyntax } from "./core/lineSyntax.js";
|
|
12
13
|
import { escapeFootnoteReferences } from "./core/footnoteReferences.js";
|
|
14
|
+
import { escapeBackslashCommands } from "./core/backslashCommands.js";
|
|
13
15
|
import { escapeTablePipes } from "./core/tablePipes.js";
|
|
14
16
|
import { requireBracedScripts } from "./core/bracedScripts.js";
|
|
17
|
+
import { keepPassthroughSource } from "./core/passthroughSource.js";
|
|
18
|
+
import { keyValueEntries } from "./core/keyValueLines.js";
|
|
15
19
|
/**
|
|
16
20
|
* Converts a Markdown string to an Org-mode string.
|
|
17
21
|
* @param markdown The Markdown string to convert.
|
|
@@ -19,15 +23,21 @@ import { requireBracedScripts } from "./core/bracedScripts.js";
|
|
|
19
23
|
* @returns The converted Org-mode string.
|
|
20
24
|
*/
|
|
21
25
|
export function convertMarkdownToOrg(markdown, options = {}) {
|
|
26
|
+
const convertMarkdown = options.preset?.convertMarkdown;
|
|
27
|
+
return convertMarkdown
|
|
28
|
+
? // a fragment's style is the preset's, not one to record
|
|
29
|
+
convertMarkdown(markdown, (fragment, preset) => convertMarkdownToOrg(fragment, {
|
|
30
|
+
...options,
|
|
31
|
+
preset,
|
|
32
|
+
recordStyle: false
|
|
33
|
+
}))
|
|
34
|
+
: convertMarkdownDocument(markdown, options);
|
|
35
|
+
}
|
|
36
|
+
function convertMarkdownDocument(markdown, options) {
|
|
22
37
|
// Phase 1: Parse Markdown to mdast
|
|
23
|
-
const mdast =
|
|
24
|
-
.use(remarkParse)
|
|
25
|
-
.use(remarkGfm)
|
|
26
|
-
.use(remarkFrontmatter)
|
|
27
|
-
.use(remarkMath)
|
|
28
|
-
.parse(markdown);
|
|
38
|
+
const mdast = parseMarkdown(markdown, options.preset);
|
|
29
39
|
// Phase 2: Generic mdast to uniorg-ast transformation
|
|
30
|
-
let uniorgAst =
|
|
40
|
+
let uniorgAst = transformMdastToUniorgDraft(mdast, {
|
|
31
41
|
...(options.preserveMdisms !== undefined && {
|
|
32
42
|
preserveMdisms: options.preserveMdisms
|
|
33
43
|
}),
|
|
@@ -60,8 +70,10 @@ export function convertMarkdownToOrg(markdown, options = {}) {
|
|
|
60
70
|
// Phase 3b: literal footnote references, paragraph lines org would
|
|
61
71
|
// read as line syntax, literal markers org would read as markup, and
|
|
62
72
|
// markup touching a word character, need a zero-width space escape;
|
|
63
|
-
// a pipe in a table cell an entity
|
|
64
|
-
|
|
73
|
+
// a pipe in a table cell an entity; a literal backslash before a
|
|
74
|
+
// letter first, the entity being none
|
|
75
|
+
escapeBackslashCommands(uniorgAst);
|
|
76
|
+
escapeTablePipes(uniorgAst, options.onWarning);
|
|
65
77
|
escapeFootnoteReferences(uniorgAst);
|
|
66
78
|
escapeLineSyntax(uniorgAst);
|
|
67
79
|
escapeOrgMarkup(uniorgAst);
|
|
@@ -70,12 +82,29 @@ export function convertMarkdownToOrg(markdown, options = {}) {
|
|
|
70
82
|
// rendered: after the preset, whose text rewrites (wikilink aliases)
|
|
71
83
|
// org parses too, and after the escapes, next to which org reads them
|
|
72
84
|
requireBracedScripts(uniorgAst);
|
|
85
|
+
// Phase 3d: the file's header (ADR 0005): mode line and file-level
|
|
86
|
+
// drawer first, keywords apart from what follows, the frontmatter as
|
|
87
|
+
// a marked comment block; raw text, past every pass that rewrites text
|
|
88
|
+
renderFileHeader(uniorgAst);
|
|
73
89
|
// Phase 4: Render uniorg-ast to Org-mode string
|
|
74
90
|
const processor = unified().use(uniorgStringify);
|
|
75
91
|
const orgContent = processor.stringify(uniorgAst);
|
|
76
92
|
return orgContent;
|
|
77
93
|
}
|
|
78
|
-
//
|
|
94
|
+
// a preset's dialect conventions that need the Markdown source apply
|
|
95
|
+
// to the parse, before the generic transform
|
|
96
|
+
function parseMarkdown(markdown, preset) {
|
|
97
|
+
const mdast = unified()
|
|
98
|
+
.use(remarkParse)
|
|
99
|
+
.use(remarkGfm)
|
|
100
|
+
.use(remarkFrontmatter)
|
|
101
|
+
.use(remarkMath)
|
|
102
|
+
.parse(markdown);
|
|
103
|
+
keepPassthroughSource(mdast, markdown);
|
|
104
|
+
preset?.applyToMdast?.(mdast, markdown);
|
|
105
|
+
return mdast;
|
|
106
|
+
}
|
|
107
|
+
// leads the document, ahead of restored keywords and the frontmatter block
|
|
79
108
|
function recordStyleKeyword(uniorgAst, style) {
|
|
80
109
|
if (!Object.keys(style).length) {
|
|
81
110
|
return;
|
|
@@ -86,7 +115,6 @@ function recordStyleKeyword(uniorgAst, style) {
|
|
|
86
115
|
value: JSON.stringify(style)
|
|
87
116
|
});
|
|
88
117
|
}
|
|
89
|
-
const KEY_VALUE_LINE_RE = /^([\w-]+):: (.*)$/;
|
|
90
118
|
function parseKeyValueParagraph(node) {
|
|
91
119
|
if (node?.type !== "paragraph" || !node.children?.length) {
|
|
92
120
|
return null;
|
|
@@ -94,19 +122,7 @@ function parseKeyValueParagraph(node) {
|
|
|
94
122
|
if (!node.children.every(child => child.type === "text")) {
|
|
95
123
|
return null;
|
|
96
124
|
}
|
|
97
|
-
|
|
98
|
-
.map(child => child.value ?? "")
|
|
99
|
-
.join("")
|
|
100
|
-
.split("\n");
|
|
101
|
-
const entries = [];
|
|
102
|
-
for (const line of lines) {
|
|
103
|
-
const match = KEY_VALUE_LINE_RE.exec(line);
|
|
104
|
-
if (!match) {
|
|
105
|
-
return null;
|
|
106
|
-
}
|
|
107
|
-
entries.push([match[1], match[2]]);
|
|
108
|
-
}
|
|
109
|
-
return entries;
|
|
125
|
+
return keyValueEntries(node.children.map(child => child.value ?? "").join(""));
|
|
110
126
|
}
|
|
111
127
|
function makeTimestamp(rawValue) {
|
|
112
128
|
return { type: "timestamp", rawValue };
|
package/dist/orgToMarkdown.js
CHANGED
|
@@ -5,9 +5,12 @@ import remarkFrontmatter from "remark-frontmatter";
|
|
|
5
5
|
import remarkMath from "remark-math";
|
|
6
6
|
import { transformUniorgAstToMdast } from "./core/uniorgToMdast/index.js";
|
|
7
7
|
import { takeRecordedStyle } from "./core/markdownStyle.js";
|
|
8
|
+
import { takeFileHeader } from "./core/frontmatterBlock.js";
|
|
8
9
|
import { unescapeOrgMarkup } from "./core/markupBoundary.js";
|
|
9
10
|
import { unescapeLineSyntax } from "./core/lineSyntax.js";
|
|
10
11
|
import { unescapeFootnoteReferences } from "./core/footnoteReferences.js";
|
|
12
|
+
import { unescapeBackslashCommands } from "./core/backslashCommands.js";
|
|
13
|
+
import { unescapeTablePipes } from "./core/tablePipes.js";
|
|
11
14
|
import { parseOrg } from "./core/bracedScripts.js";
|
|
12
15
|
import { dropUnderscoreBulletGuards, guardUnderscoreBullets } from "./core/underscoreBullets.js";
|
|
13
16
|
// a list item's paragraph after its nested list needs a blank line, or
|
|
@@ -26,18 +29,30 @@ function separateTextAfterNestedList(left, right, parent) {
|
|
|
26
29
|
* @returns The converted Markdown string.
|
|
27
30
|
*/
|
|
28
31
|
export function convertOrgToMarkdown(org, options = {}) {
|
|
32
|
+
const convertOrg = options.preset?.convertOrg;
|
|
33
|
+
return convertOrg
|
|
34
|
+
? convertOrg(org, (fragment, preset) => convertOrgToMarkdown(fragment, { ...options, preset }))
|
|
35
|
+
: convertOrgDocument(org, options);
|
|
36
|
+
}
|
|
37
|
+
function convertOrgDocument(org, options) {
|
|
29
38
|
// Phase 1: Parse Org-mode to uniorg-ast
|
|
30
39
|
// md text has no scripts, so ^:{} is implied there and consumed here
|
|
31
40
|
// (see markdownToOrg); uniorg misreads `_.` lines (see underscoreBullets)
|
|
32
|
-
|
|
41
|
+
const guarded = guardUnderscoreBullets(org);
|
|
42
|
+
let uniorgAst = parseOrg(guarded);
|
|
33
43
|
dropUnderscoreBulletGuards(uniorgAst);
|
|
34
44
|
// Phase 1b: a recorded style is morg's own (ADR 0004), so consume it so
|
|
35
45
|
// it does not travel on as frontmatter; explicit options still win
|
|
36
46
|
const recordedStyle = takeRecordedStyle(uniorgAst);
|
|
47
|
+
// frontmatter travels in a block marked as morg's (ADR 0005)
|
|
48
|
+
// and so does a file-level drawer (org-roam's :ID:)
|
|
49
|
+
const fileHeader = takeFileHeader(uniorgAst, guarded, options.onWarning);
|
|
37
50
|
// Phase 1c: markdown needs no zero-width space escapes (inverse of md→org)
|
|
38
51
|
unescapeOrgMarkup(uniorgAst);
|
|
39
52
|
unescapeLineSyntax(uniorgAst);
|
|
40
53
|
unescapeFootnoteReferences(uniorgAst);
|
|
54
|
+
unescapeBackslashCommands(uniorgAst);
|
|
55
|
+
unescapeTablePipes(uniorgAst);
|
|
41
56
|
// Phase 2: Extract dialect preset conventions, if any
|
|
42
57
|
if (options.preset?.extractFromUniorg) {
|
|
43
58
|
uniorgAst = options.preset.extractFromUniorg(uniorgAst);
|
|
@@ -54,7 +69,8 @@ export function convertOrgToMarkdown(org, options = {}) {
|
|
|
54
69
|
...(options.orgismKeys !== undefined && {
|
|
55
70
|
orgismKeys: options.orgismKeys
|
|
56
71
|
}),
|
|
57
|
-
...(options.onWarning !== undefined && { onWarning: options.onWarning })
|
|
72
|
+
...(options.onWarning !== undefined && { onWarning: options.onWarning }),
|
|
73
|
+
...fileHeader
|
|
58
74
|
});
|
|
59
75
|
// Phase 4: Render mdast to Markdown string
|
|
60
76
|
// bullet and rule "-" (not remark's default "*") are morg's canonical
|
package/dist/presets/logseq.d.ts
CHANGED
|
@@ -1,25 +1,6 @@
|
|
|
1
|
-
import type { OrgData } from "uniorg";
|
|
2
1
|
import type { Preset } from "./types.js";
|
|
3
|
-
export interface LogseqPresetOptions {
|
|
4
|
-
/**
|
|
5
|
-
* Content following a heading becomes children of that heading's block
|
|
6
|
-
* in Logseq's outline: paragraphs turn into child block headlines one
|
|
7
|
-
* level deeper; other constructs stay in the preceding block's body.
|
|
8
|
-
* Default: `true`.
|
|
9
|
-
*/
|
|
10
|
-
nestUnderHeadings?: boolean;
|
|
11
|
-
}
|
|
12
2
|
/**
|
|
13
|
-
* Logseq dialect preset:
|
|
3
|
+
* Logseq dialect preset: the outline of blocks, page properties, page
|
|
4
|
+
* and block references, highlights and hiccup.
|
|
14
5
|
*/
|
|
15
|
-
export declare function logseq(
|
|
16
|
-
/**
|
|
17
|
-
* Applies Logseq-specific conventions to a uniorg AST: every heading gets
|
|
18
|
-
* a `:heading:` property drawer, and with `nestUnderHeadings` following
|
|
19
|
-
* paragraphs become child block headlines (in Logseq's org format every
|
|
20
|
-
* outline block is a headline).
|
|
21
|
-
* @param uniorgAst The uniorg AST to transform.
|
|
22
|
-
* @param nestUnderHeadings Nest content as child blocks. Default: `true`.
|
|
23
|
-
* @returns The Logseq-flavored uniorg AST.
|
|
24
|
-
*/
|
|
25
|
-
export declare function applyLogseqSpecificsToUniorgAst(uniorgAst: OrgData, nestUnderHeadings?: boolean): OrgData;
|
|
6
|
+
export declare function logseq(): Preset;
|