@remigius42/morg 0.4.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/LICENSE +674 -0
- package/README.md +267 -0
- package/dist/cli/args.d.ts +15 -0
- package/dist/cli/args.js +105 -0
- package/dist/cli/configFile.d.ts +2 -0
- package/dist/cli/configFile.js +18 -0
- package/dist/cli/conversion.d.ts +11 -0
- package/dist/cli/conversion.js +50 -0
- package/dist/cli/error.d.ts +2 -0
- package/dist/cli/error.js +4 -0
- package/dist/cli/formats.d.ts +3 -0
- package/dist/cli/formats.js +46 -0
- package/dist/cli/presets.d.ts +2 -0
- package/dist/cli/presets.js +10 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +54 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.js +22 -0
- package/dist/conversionOptions.d.ts +32 -0
- package/dist/conversionOptions.js +34 -0
- package/dist/core/markdownStyle.d.ts +27 -0
- package/dist/core/markdownStyle.js +108 -0
- package/dist/core/mdastToUniorg/blocks.d.ts +20 -0
- package/dist/core/mdastToUniorg/blocks.js +211 -0
- package/dist/core/mdastToUniorg/context.d.ts +15 -0
- package/dist/core/mdastToUniorg/context.js +7 -0
- package/dist/core/mdastToUniorg/index.d.ts +13 -0
- package/dist/core/mdastToUniorg/index.js +95 -0
- package/dist/core/mdastToUniorg/lists.d.ts +4 -0
- package/dist/core/mdastToUniorg/lists.js +45 -0
- package/dist/core/mdastToUniorg/phrasing.d.ts +4 -0
- package/dist/core/mdastToUniorg/phrasing.js +176 -0
- package/dist/core/uniorgToMdast/elements.d.ts +4 -0
- package/dist/core/uniorgToMdast/elements.js +278 -0
- package/dist/core/uniorgToMdast/footnotes.d.ts +10 -0
- package/dist/core/uniorgToMdast/footnotes.js +54 -0
- package/dist/core/uniorgToMdast/index.d.ts +11 -0
- package/dist/core/uniorgToMdast/index.js +84 -0
- package/dist/core/uniorgToMdast/lists.d.ts +4 -0
- package/dist/core/uniorgToMdast/lists.js +94 -0
- package/dist/core/uniorgToMdast/objects.d.ts +4 -0
- package/dist/core/uniorgToMdast/objects.js +152 -0
- package/dist/core/uniorgToMdast/shared.d.ts +25 -0
- package/dist/core/uniorgToMdast/shared.js +55 -0
- package/dist/core/uniorgToMdast/tables.d.ts +6 -0
- package/dist/core/uniorgToMdast/tables.js +66 -0
- package/dist/fileNames.d.ts +16 -0
- package/dist/fileNames.js +34 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +8 -0
- package/dist/markdownToOrg.d.ts +8 -0
- package/dist/markdownToOrg.js +194 -0
- package/dist/normalize.d.ts +26 -0
- package/dist/normalize.js +24 -0
- package/dist/options.d.ts +102 -0
- package/dist/options.js +9 -0
- package/dist/orgToMarkdown.d.ts +8 -0
- package/dist/orgToMarkdown.js +61 -0
- package/dist/presets/logseq.d.ts +25 -0
- package/dist/presets/logseq.js +298 -0
- package/dist/presets/obsidian.d.ts +6 -0
- package/dist/presets/obsidian.js +40 -0
- package/dist/presets/registry.d.ts +8 -0
- package/dist/presets/registry.js +25 -0
- package/dist/presets/types.d.ts +12 -0
- package/dist/presets/types.js +1 -0
- package/package.json +112 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { toString as orgastToString } from "orgast-util-to-string";
|
|
2
|
+
import { htmlEnabled } from "./shared.js";
|
|
3
|
+
import { transformNodes } from "./elements.js";
|
|
4
|
+
export function transformPlainList(ctx, node) {
|
|
5
|
+
if (node.listType === "descriptive" && htmlEnabled(ctx, "descriptiveList")) {
|
|
6
|
+
return descriptiveListToHtml(node);
|
|
7
|
+
}
|
|
8
|
+
return transformUniorgList(ctx, node);
|
|
9
|
+
}
|
|
10
|
+
// a descriptive list item starts with a list-item-tag (the term)
|
|
11
|
+
function listItemTag(item) {
|
|
12
|
+
return (item.children || []).find(child => child.type === "list-item-tag");
|
|
13
|
+
}
|
|
14
|
+
// `&`, `<` and `>` in the text would otherwise produce invalid html that
|
|
15
|
+
// interpretDefinitionList cannot read back; decoded again on that side
|
|
16
|
+
function escapeHtmlText(text) {
|
|
17
|
+
return text
|
|
18
|
+
.replaceAll("&", "&")
|
|
19
|
+
.replaceAll("<", "<")
|
|
20
|
+
.replaceAll(">", ">");
|
|
21
|
+
}
|
|
22
|
+
// with useHtml a descriptive list renders as a <dl> block (a preserved
|
|
23
|
+
// md-ism on the return trip); terms and definitions are flattened to text
|
|
24
|
+
function descriptiveListToHtml(node) {
|
|
25
|
+
const lines = ["<dl>"];
|
|
26
|
+
for (const item of node.children || []) {
|
|
27
|
+
if (item.type !== "list-item") {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
const tag = listItemTag(item);
|
|
31
|
+
const definition = (item.children || []).filter(child => child !== tag);
|
|
32
|
+
lines.push(`<dt>${escapeHtmlText(tag ? orgastToString(tag).trim() : "")}</dt>`);
|
|
33
|
+
lines.push(`<dd>${escapeHtmlText(definition
|
|
34
|
+
.map(child => orgastToString(child))
|
|
35
|
+
.join("")
|
|
36
|
+
.trim())}</dd>`);
|
|
37
|
+
}
|
|
38
|
+
lines.push("</dl>");
|
|
39
|
+
return { type: "html", value: lines.join("\n") };
|
|
40
|
+
}
|
|
41
|
+
// A single blank line does not end a list in org, so one uniorg plain-list
|
|
42
|
+
// can mix ordered and unordered bullets. Markdown cannot: split the items
|
|
43
|
+
// into runs by bullet kind, one mdast list per run.
|
|
44
|
+
function transformUniorgList(ctx, node) {
|
|
45
|
+
const items = (node.children || []).filter((child) => child.type === "list-item");
|
|
46
|
+
const runs = [];
|
|
47
|
+
let previousOrdered;
|
|
48
|
+
for (const item of items) {
|
|
49
|
+
const ordered = /^\d/.test(item.bullet);
|
|
50
|
+
if (ordered === previousOrdered) {
|
|
51
|
+
runs[runs.length - 1]?.push(item);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
runs.push([item]);
|
|
55
|
+
previousOrdered = ordered;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return runs.map(run => {
|
|
59
|
+
const firstBullet = run[0]?.bullet ?? "- ";
|
|
60
|
+
const ordered = /^\d/.test(firstBullet);
|
|
61
|
+
return {
|
|
62
|
+
type: "list",
|
|
63
|
+
ordered,
|
|
64
|
+
start: ordered ? parseInt(firstBullet, 10) || 1 : null,
|
|
65
|
+
spread: false,
|
|
66
|
+
children: run.map(item => transformUniorgListItem(ctx, item))
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function transformUniorgListItem(ctx, item) {
|
|
71
|
+
// md has no descriptive lists, so keep the ` :: ` syntax literally in the
|
|
72
|
+
// item text — the return trip re-parses it as a descriptive list
|
|
73
|
+
const tag = listItemTag(item);
|
|
74
|
+
const children = transformNodes(ctx, (item.children || []).filter(child => child !== tag));
|
|
75
|
+
if (tag) {
|
|
76
|
+
const term = {
|
|
77
|
+
type: "text",
|
|
78
|
+
value: `${orgastToString(tag)} :: `
|
|
79
|
+
};
|
|
80
|
+
const first = children[0];
|
|
81
|
+
if (first?.type === "paragraph") {
|
|
82
|
+
first.children.unshift(term);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
children.unshift({ type: "paragraph", children: [term] });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
type: "listItem",
|
|
90
|
+
spread: false,
|
|
91
|
+
checked: item.checkbox === "on" ? true : item.checkbox === "off" ? false : null,
|
|
92
|
+
children
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { toString as orgastToString } from "orgast-util-to-string";
|
|
2
|
+
import { htmlEnabled, orgNodeToText, warn } from "./shared.js";
|
|
3
|
+
import { transformFootnoteReference } from "./footnotes.js";
|
|
4
|
+
const IMAGE_EXTENSION_RE = /\.(png|jpe?g|gif|svg|webp|avif|bmp|ico)$/i;
|
|
5
|
+
export function transformUniorgObjects(ctx, children) {
|
|
6
|
+
return (children || [])
|
|
7
|
+
.flatMap(child => transformUniorgObjectToMdastPhrasingContent(ctx, child))
|
|
8
|
+
.filter(Boolean);
|
|
9
|
+
}
|
|
10
|
+
function transformUniorgObjectToMdastPhrasingContent(ctx, node) {
|
|
11
|
+
switch (node.type) {
|
|
12
|
+
case "text":
|
|
13
|
+
return { type: "text", value: node.value };
|
|
14
|
+
case "bold":
|
|
15
|
+
return {
|
|
16
|
+
type: "strong",
|
|
17
|
+
children: transformUniorgObjects(ctx, node.children)
|
|
18
|
+
};
|
|
19
|
+
case "italic":
|
|
20
|
+
return {
|
|
21
|
+
type: "emphasis",
|
|
22
|
+
children: transformUniorgObjects(ctx, node.children)
|
|
23
|
+
};
|
|
24
|
+
case "strike-through":
|
|
25
|
+
return {
|
|
26
|
+
type: "delete",
|
|
27
|
+
children: transformUniorgObjects(ctx, node.children)
|
|
28
|
+
};
|
|
29
|
+
case "link":
|
|
30
|
+
return transformUniorgLink(ctx, node);
|
|
31
|
+
case "code":
|
|
32
|
+
case "verbatim":
|
|
33
|
+
return { type: "inlineCode", value: node.value };
|
|
34
|
+
case "line-break":
|
|
35
|
+
return { type: "break" };
|
|
36
|
+
case "footnote-reference":
|
|
37
|
+
return transformFootnoteReference(ctx, node);
|
|
38
|
+
case "underline":
|
|
39
|
+
case "superscript":
|
|
40
|
+
case "subscript":
|
|
41
|
+
return transformScriptMarkup(ctx, node);
|
|
42
|
+
case "latex-fragment":
|
|
43
|
+
// display-only paragraphs become math blocks (see the paragraph
|
|
44
|
+
// handler); a fragment inside running text is inline math
|
|
45
|
+
return {
|
|
46
|
+
type: "inlineMath",
|
|
47
|
+
value: node.contents.trim()
|
|
48
|
+
};
|
|
49
|
+
case "entity":
|
|
50
|
+
// org export renders entities as their character; \alpha → α
|
|
51
|
+
return { type: "text", value: node.utf8 };
|
|
52
|
+
case "timestamp":
|
|
53
|
+
// md has no timestamps; keep the raw org value as text so the
|
|
54
|
+
// return trip re-parses it natively
|
|
55
|
+
return { type: "text", value: node.rawValue };
|
|
56
|
+
case "statistics-cookie":
|
|
57
|
+
return { type: "text", value: node.value };
|
|
58
|
+
case "citation":
|
|
59
|
+
// org-cite has no md equivalent; keep the raw [cite:…] text so the
|
|
60
|
+
// return trip re-parses it natively
|
|
61
|
+
return { type: "text", value: orgNodeToText(node).trim() };
|
|
62
|
+
case "verbatim-inline":
|
|
63
|
+
// preset-emitted passthrough: rendered unescaped by a custom
|
|
64
|
+
// stringify handler (see orgToMarkdown)
|
|
65
|
+
return {
|
|
66
|
+
type: "verbatimInline",
|
|
67
|
+
value: node.value
|
|
68
|
+
};
|
|
69
|
+
case "export-snippet":
|
|
70
|
+
return transformExportSnippet(node);
|
|
71
|
+
// remaining object types have no mapping; dropped with a warning
|
|
72
|
+
default:
|
|
73
|
+
warn(ctx, `dropped org ${node.type}`);
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function transformUniorgLink(ctx, node) {
|
|
78
|
+
const descriptionText = orgastToString(node);
|
|
79
|
+
// org has no dedicated image syntax; the common convention is a
|
|
80
|
+
// link to an image file, so map those to markdown images
|
|
81
|
+
if (IMAGE_EXTENSION_RE.test(node.rawLink)) {
|
|
82
|
+
return { type: "image", url: node.rawLink, alt: descriptionText };
|
|
83
|
+
}
|
|
84
|
+
// a description equal to the url (a common Logseq pattern) is no
|
|
85
|
+
// description: text === url makes remark-stringify emit an
|
|
86
|
+
// autolink (<url>), which restores to a plain org link. Urls full
|
|
87
|
+
// of / and _ re-parse as italic/subscript inside the description
|
|
88
|
+
// (and even uniorg-stringify garbles them back), so compare with
|
|
89
|
+
// org's emphasis-marker characters stripped from both sides
|
|
90
|
+
const withoutMarkers = (value) => value.replace(/[/*_+~={}]/g, "");
|
|
91
|
+
const serializedDescription = node.children.length
|
|
92
|
+
? orgNodeToText({
|
|
93
|
+
type: "paragraph",
|
|
94
|
+
children: node.children,
|
|
95
|
+
contentsBegin: 0,
|
|
96
|
+
contentsEnd: 0
|
|
97
|
+
}).trim()
|
|
98
|
+
: "";
|
|
99
|
+
if (!node.children.length ||
|
|
100
|
+
withoutMarkers(serializedDescription) === withoutMarkers(node.rawLink)) {
|
|
101
|
+
return {
|
|
102
|
+
type: "link",
|
|
103
|
+
url: node.rawLink,
|
|
104
|
+
children: [{ type: "text", value: node.rawLink }]
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const children = transformUniorgObjects(ctx, node.children);
|
|
108
|
+
// md cannot nest links; flatten a description that contains one
|
|
109
|
+
// (org parses bare urls inside descriptions as links)
|
|
110
|
+
const flattened = children.some(child => child.type === "link" || child.type === "image")
|
|
111
|
+
? [{ type: "text", value: descriptionText }]
|
|
112
|
+
: children;
|
|
113
|
+
return { type: "link", url: node.rawLink, children: flattened };
|
|
114
|
+
}
|
|
115
|
+
function transformScriptMarkup(ctx, node) {
|
|
116
|
+
// markdown has no equivalents; with useHtml render as raw html
|
|
117
|
+
// (a preserved md-ism on the return trip), otherwise keep the raw
|
|
118
|
+
// org markup as text so the return trip re-parses it natively
|
|
119
|
+
// (convergent, like inline timestamps)
|
|
120
|
+
if (htmlEnabled(ctx, node.type)) {
|
|
121
|
+
const tagName = node.type === "underline"
|
|
122
|
+
? "u"
|
|
123
|
+
: node.type === "superscript"
|
|
124
|
+
? "sup"
|
|
125
|
+
: "sub";
|
|
126
|
+
return [
|
|
127
|
+
{ type: "html", value: `<${tagName}>` },
|
|
128
|
+
...transformUniorgObjects(ctx, node.children),
|
|
129
|
+
{ type: "html", value: `</${tagName}>` }
|
|
130
|
+
];
|
|
131
|
+
}
|
|
132
|
+
const content = orgastToString(node);
|
|
133
|
+
return {
|
|
134
|
+
type: "text",
|
|
135
|
+
value: node.type === "underline"
|
|
136
|
+
? `_${content}_`
|
|
137
|
+
: node.type === "superscript"
|
|
138
|
+
? `^{${content}}`
|
|
139
|
+
: `_{${content}}`
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function transformExportSnippet(node) {
|
|
143
|
+
if (node.backEnd !== "html") {
|
|
144
|
+
// kept as raw @@backend:…@@ text (unescaped) so the return trip
|
|
145
|
+
// re-parses the snippet natively
|
|
146
|
+
return {
|
|
147
|
+
type: "verbatimInline",
|
|
148
|
+
value: `@@${node.backEnd}:${node.value}@@`
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { type: "html", value: node.value };
|
|
152
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { PhrasingContent, RootContent } from "mdast";
|
|
2
|
+
import { type Toggle } from "../../options.js";
|
|
3
|
+
export interface UniorgToMdastOptions {
|
|
4
|
+
preserveOrgisms?: Toggle;
|
|
5
|
+
useHtml?: Toggle;
|
|
6
|
+
taskCheckboxes?: boolean;
|
|
7
|
+
orgismKeys?: Record<string, string>;
|
|
8
|
+
onWarning?: (message: string) => void;
|
|
9
|
+
}
|
|
10
|
+
export interface TransformContext {
|
|
11
|
+
options: UniorgToMdastOptions;
|
|
12
|
+
inlineFootnotes: {
|
|
13
|
+
label: string;
|
|
14
|
+
children: PhrasingContent[];
|
|
15
|
+
}[];
|
|
16
|
+
usedFootnoteLabels: Set<string>;
|
|
17
|
+
}
|
|
18
|
+
export declare function orgismEnabled(ctx: TransformContext, key: string): boolean;
|
|
19
|
+
export declare function htmlEnabled(ctx: TransformContext, key: string): boolean;
|
|
20
|
+
export declare function warn(ctx: TransformContext, message: string): void;
|
|
21
|
+
export declare function keyName(ctx: TransformContext, key: string): string;
|
|
22
|
+
export declare function keyValueParagraph(lines: string[]): RootContent;
|
|
23
|
+
export declare function orgNodeToText(node: unknown): string;
|
|
24
|
+
export declare function trimTrailingNewline(value: string): string;
|
|
25
|
+
export declare function affiliatedLines(node: unknown): string[];
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { toString as orgastToString } from "orgast-util-to-string";
|
|
2
|
+
import { unified } from "unified";
|
|
3
|
+
import { uniorgStringify } from "uniorg-stringify";
|
|
4
|
+
import { toggleEnabled } from "../../options.js";
|
|
5
|
+
export function orgismEnabled(ctx, key) {
|
|
6
|
+
return toggleEnabled(ctx.options.preserveOrgisms, key);
|
|
7
|
+
}
|
|
8
|
+
export function htmlEnabled(ctx, key) {
|
|
9
|
+
return toggleEnabled(ctx.options.useHtml, key, false);
|
|
10
|
+
}
|
|
11
|
+
export function warn(ctx, message) {
|
|
12
|
+
ctx.options.onWarning?.(message);
|
|
13
|
+
}
|
|
14
|
+
// org-ism key:: names are user-configurable (ADR 0002 point 5)
|
|
15
|
+
export function keyName(ctx, key) {
|
|
16
|
+
return ctx.options.orgismKeys?.[key] ?? key;
|
|
17
|
+
}
|
|
18
|
+
// custom mdast node stringified verbatim (see orgToMarkdown handlers) so
|
|
19
|
+
// keys like custom_id are not markdown-escaped to custom\_id
|
|
20
|
+
export function keyValueParagraph(lines) {
|
|
21
|
+
return { type: "keyValue", value: lines.join("\n") };
|
|
22
|
+
}
|
|
23
|
+
// renders a single uniorg node back to its org text (without the
|
|
24
|
+
// trailing newline), for verbatim passthrough of org-only constructs
|
|
25
|
+
export function orgNodeToText(node) {
|
|
26
|
+
const orgText = unified()
|
|
27
|
+
.use(uniorgStringify)
|
|
28
|
+
.stringify({
|
|
29
|
+
type: "org-data",
|
|
30
|
+
children: [node],
|
|
31
|
+
contentsBegin: 0,
|
|
32
|
+
contentsEnd: 0
|
|
33
|
+
});
|
|
34
|
+
return orgText.replace(/\n$/, "");
|
|
35
|
+
}
|
|
36
|
+
// uniorg block values keep the newline before the #+end_ line; mdast
|
|
37
|
+
// code values do not include it
|
|
38
|
+
export function trimTrailingNewline(value) {
|
|
39
|
+
return value.replace(/\n$/, "");
|
|
40
|
+
}
|
|
41
|
+
// affiliated keywords (#+CAPTION:, #+NAME:, #+ATTR_*) precede their
|
|
42
|
+
// element as verbatim lines so the return trip re-attaches them natively
|
|
43
|
+
export function affiliatedLines(node) {
|
|
44
|
+
const affiliated = node
|
|
45
|
+
.affiliated;
|
|
46
|
+
return Object.entries(affiliated ?? {}).flatMap(([key, value]) => {
|
|
47
|
+
const entries = Array.isArray(value) ? value : [value];
|
|
48
|
+
return entries.map(entry => {
|
|
49
|
+
const text = Array.isArray(entry)
|
|
50
|
+
? entry.map(child => orgastToString(child)).join("")
|
|
51
|
+
: String(entry);
|
|
52
|
+
return `#+${key}: ${text}`;
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RootContent } from "mdast";
|
|
2
|
+
import type { GreaterElementType } from "uniorg";
|
|
3
|
+
import { type TransformContext } from "./shared.js";
|
|
4
|
+
export declare function transformTable(ctx: TransformContext, node: Extract<GreaterElementType, {
|
|
5
|
+
type: "table";
|
|
6
|
+
}>): RootContent;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { trimTrailingNewline } from "./shared.js";
|
|
2
|
+
import { transformUniorgObjects } from "./objects.js";
|
|
3
|
+
function cellText(cell) {
|
|
4
|
+
return (cell.children || [])
|
|
5
|
+
.map(child => (child.type === "text" ? child.value : ""))
|
|
6
|
+
.join("")
|
|
7
|
+
.trim();
|
|
8
|
+
}
|
|
9
|
+
function isAlignmentCookieRow(row) {
|
|
10
|
+
const cells = row.children || [];
|
|
11
|
+
return (cells.length > 0 &&
|
|
12
|
+
cells.every(cell => {
|
|
13
|
+
const text = cellText(cell);
|
|
14
|
+
return text === "" || /^<[lrc]\d*>$/.test(text);
|
|
15
|
+
}) &&
|
|
16
|
+
cells.some(cell => cellText(cell) !== ""));
|
|
17
|
+
}
|
|
18
|
+
// org cell content keeps the aligning whitespace padding; markdown
|
|
19
|
+
// cells are re-padded by the stringifier
|
|
20
|
+
function trimCellPadding(node) {
|
|
21
|
+
if (node.type === "text") {
|
|
22
|
+
node.value = node.value.trim();
|
|
23
|
+
}
|
|
24
|
+
return node;
|
|
25
|
+
}
|
|
26
|
+
export function transformTable(ctx, node) {
|
|
27
|
+
if (node.tableType === "table.el") {
|
|
28
|
+
// table.el tables have no cell structure, only a verbatim value;
|
|
29
|
+
// a table.el-tagged fenced block carries it so the return trip
|
|
30
|
+
// can restore the table
|
|
31
|
+
return {
|
|
32
|
+
type: "code",
|
|
33
|
+
lang: "table.el",
|
|
34
|
+
value: trimTrailingNewline(node.value)
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const standardRows = (node.children || []).filter((row) => row.type === "table-row" && row.rowType === "standard");
|
|
38
|
+
// an org alignment cookie row (| <l> | <r> | <c> |) becomes GFM
|
|
39
|
+
// column alignment instead of a content row
|
|
40
|
+
const cookieRow = standardRows.find(isAlignmentCookieRow);
|
|
41
|
+
const align = cookieRow
|
|
42
|
+
? (cookieRow.children || []).map(cell => {
|
|
43
|
+
const cookie = /^<([lrc])\d*>$/.exec(cellText(cell))?.[1];
|
|
44
|
+
return cookie === "l"
|
|
45
|
+
? "left"
|
|
46
|
+
: cookie === "r"
|
|
47
|
+
? "right"
|
|
48
|
+
: cookie === "c"
|
|
49
|
+
? "center"
|
|
50
|
+
: null;
|
|
51
|
+
})
|
|
52
|
+
: null;
|
|
53
|
+
return {
|
|
54
|
+
type: "table",
|
|
55
|
+
align,
|
|
56
|
+
children: standardRows
|
|
57
|
+
.filter(row => row !== cookieRow)
|
|
58
|
+
.map(row => ({
|
|
59
|
+
type: "tableRow",
|
|
60
|
+
children: (row.children || []).map(cell => ({
|
|
61
|
+
type: "tableCell",
|
|
62
|
+
children: transformUniorgObjects(ctx, cell.children).map(trimCellPadding)
|
|
63
|
+
}))
|
|
64
|
+
}))
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits a file name into the part a derived name keeps and the extension
|
|
3
|
+
* that carries its format. A dotless name and a dotfile both have no
|
|
4
|
+
* extension — `org` is a file called org, and `.org` is a hidden file whose
|
|
5
|
+
* name happens to start with a dot.
|
|
6
|
+
*
|
|
7
|
+
* The extension comes from the last path segment, since the CLI is handed
|
|
8
|
+
* paths rather than the bare names the Web UI reads off a `File`; the stem
|
|
9
|
+
* keeps any directory, being the part a derived name builds on.
|
|
10
|
+
*/
|
|
11
|
+
export declare function splitFileName(name: string): {
|
|
12
|
+
stem: string;
|
|
13
|
+
extension: string;
|
|
14
|
+
};
|
|
15
|
+
/** The format a file name implies, or undefined if it implies none. */
|
|
16
|
+
export declare function formatFromFileName(name: string): "markdown" | "org" | undefined;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** The document formats morg reads, by file extension. */
|
|
2
|
+
const DOCUMENT_FORMATS = new Map([
|
|
3
|
+
["md", "markdown"],
|
|
4
|
+
["org", "org"]
|
|
5
|
+
]);
|
|
6
|
+
/**
|
|
7
|
+
* Splits a file name into the part a derived name keeps and the extension
|
|
8
|
+
* that carries its format. A dotless name and a dotfile both have no
|
|
9
|
+
* extension — `org` is a file called org, and `.org` is a hidden file whose
|
|
10
|
+
* name happens to start with a dot.
|
|
11
|
+
*
|
|
12
|
+
* The extension comes from the last path segment, since the CLI is handed
|
|
13
|
+
* paths rather than the bare names the Web UI reads off a `File`; the stem
|
|
14
|
+
* keeps any directory, being the part a derived name builds on.
|
|
15
|
+
*/
|
|
16
|
+
export function splitFileName(name) {
|
|
17
|
+
const base = name.slice(lastSeparator(name) + 1);
|
|
18
|
+
const dot = base.lastIndexOf(".");
|
|
19
|
+
if (dot <= 0) {
|
|
20
|
+
return { stem: name, extension: "" };
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
stem: name.slice(0, name.length - base.length + dot),
|
|
24
|
+
extension: base.slice(dot + 1).toLowerCase()
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** Index of the last path separator, or -1. Windows accepts both. */
|
|
28
|
+
function lastSeparator(name) {
|
|
29
|
+
return Math.max(name.lastIndexOf("/"), name.lastIndexOf("\\"));
|
|
30
|
+
}
|
|
31
|
+
/** The format a file name implies, or undefined if it implies none. */
|
|
32
|
+
export function formatFromFileName(name) {
|
|
33
|
+
return DOCUMENT_FORMATS.get(splitFileName(name).extension);
|
|
34
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { convertMarkdownToOrg } from "./markdownToOrg.js";
|
|
2
|
+
export { convertOrgToMarkdown } from "./orgToMarkdown.js";
|
|
3
|
+
export { normalizeMarkdown, normalizeOrg } from "./normalize.js";
|
|
4
|
+
export type { NormalizeOptions } from "./normalize.js";
|
|
5
|
+
export { parseConfig } from "./config.js";
|
|
6
|
+
export type { MorgConfig } from "./config.js";
|
|
7
|
+
export { transformMdastToUniorgAst } from "./core/mdastToUniorg/index.js";
|
|
8
|
+
export { transformUniorgAstToMdast } from "./core/uniorgToMdast/index.js";
|
|
9
|
+
export { logseq } from "./presets/logseq.js";
|
|
10
|
+
export { obsidian } from "./presets/obsidian.js";
|
|
11
|
+
export type { Preset } from "./presets/types.js";
|
|
12
|
+
export type { LogseqPresetOptions } from "./presets/logseq.js";
|
|
13
|
+
export type { Toggle, MarkdownToOrgOptions, OrgToMarkdownOptions, MarkdownStyleOptions } from "./options.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { convertMarkdownToOrg } from "./markdownToOrg.js";
|
|
2
|
+
export { convertOrgToMarkdown } from "./orgToMarkdown.js";
|
|
3
|
+
export { normalizeMarkdown, normalizeOrg } from "./normalize.js";
|
|
4
|
+
export { parseConfig } from "./config.js";
|
|
5
|
+
export { transformMdastToUniorgAst } from "./core/mdastToUniorg/index.js";
|
|
6
|
+
export { transformUniorgAstToMdast } from "./core/uniorgToMdast/index.js";
|
|
7
|
+
export { logseq } from "./presets/logseq.js";
|
|
8
|
+
export { obsidian } from "./presets/obsidian.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MarkdownToOrgOptions } from "./options.js";
|
|
2
|
+
/**
|
|
3
|
+
* Converts a Markdown string to an Org-mode string.
|
|
4
|
+
* @param markdown The Markdown string to convert.
|
|
5
|
+
* @param options Conversion options (md-ism preservation, dialect preset).
|
|
6
|
+
* @returns The converted Org-mode string.
|
|
7
|
+
*/
|
|
8
|
+
export declare function convertMarkdownToOrg(markdown: string, options?: MarkdownToOrgOptions): string;
|