@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,298 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
import { toString } from "orgast-util-to-string";
|
|
3
|
+
/**
|
|
4
|
+
* Logseq dialect preset: `heading::` properties and outline nesting.
|
|
5
|
+
*/
|
|
6
|
+
export function logseq(options = {}) {
|
|
7
|
+
const nestUnderHeadings = options.nestUnderHeadings ?? true;
|
|
8
|
+
return {
|
|
9
|
+
name: "logseq",
|
|
10
|
+
applyToUniorg: uniorgAst => applyLogseqSpecificsToUniorgAst(uniorgAst, nestUnderHeadings),
|
|
11
|
+
extractFromUniorg: extractLogseqSpecificsFromUniorgAst
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function headingProperty(level) {
|
|
15
|
+
return { type: "node-property", key: "heading", value: String(level) };
|
|
16
|
+
}
|
|
17
|
+
function headingDrawer(level) {
|
|
18
|
+
return {
|
|
19
|
+
type: "property-drawer",
|
|
20
|
+
children: [headingProperty(level)],
|
|
21
|
+
contentsBegin: 0,
|
|
22
|
+
contentsEnd: 0
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
// org fixes the order below a headline: the planning line first, then a
|
|
26
|
+
// single property drawer. :heading: therefore has to let the planning
|
|
27
|
+
// line pass and join an existing drawer rather than displace either.
|
|
28
|
+
// Returns whether the property has been placed on `node`.
|
|
29
|
+
function placeHeadingProperty(node, level) {
|
|
30
|
+
if (node.type === "planning") {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
if (node.type !== "property-drawer") {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
;
|
|
37
|
+
node.children.unshift(headingProperty(level));
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
// the page name of a [[page]] link destination, or null. The core
|
|
41
|
+
// transform percent-encodes brackets in urls (an org link path cannot
|
|
42
|
+
// hold them), so the destination arrives here already encoded.
|
|
43
|
+
function pageRefUrlTarget(rawLink) {
|
|
44
|
+
const decoded = rawLink.replaceAll("%5B", "[").replaceAll("%5D", "]");
|
|
45
|
+
return /^\[\[(.+)\]\]$/.exec(decoded)?.[1] ?? null;
|
|
46
|
+
}
|
|
47
|
+
// Logseq md labeled page refs ([label]([[page]])) become org's
|
|
48
|
+
// [[page][label]] description syntax. A page name containing a space is
|
|
49
|
+
// not a valid CommonMark destination, so the ref travels as plain text;
|
|
50
|
+
// without one remark parses it as a real link instead.
|
|
51
|
+
function rewriteLabeledPageRefs(uniorgAst) {
|
|
52
|
+
visit(uniorgAst, "text", (node) => {
|
|
53
|
+
node.value = node.value.replace(/\[([^\]]+)\]\(\[\[([^\]]+)\]\]\)/g, "[[$2][$1]]");
|
|
54
|
+
});
|
|
55
|
+
visit(uniorgAst, "link", (node) => {
|
|
56
|
+
const page = pageRefUrlTarget(node.rawLink);
|
|
57
|
+
if (page === null) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
node.linkType = "fuzzy";
|
|
61
|
+
node.rawLink = page;
|
|
62
|
+
node.path = page;
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function toBlockHeadline(node, level) {
|
|
66
|
+
const blockHeadline = {
|
|
67
|
+
type: "headline",
|
|
68
|
+
level,
|
|
69
|
+
todoKeyword: null,
|
|
70
|
+
priority: null,
|
|
71
|
+
commented: false,
|
|
72
|
+
rawValue: "",
|
|
73
|
+
tags: [],
|
|
74
|
+
children: node.children
|
|
75
|
+
};
|
|
76
|
+
takeTaskMarker(blockHeadline);
|
|
77
|
+
return blockHeadline;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Applies Logseq-specific conventions to a uniorg AST: every heading gets
|
|
81
|
+
* a `:heading:` property drawer, and with `nestUnderHeadings` following
|
|
82
|
+
* paragraphs become child block headlines (in Logseq's org format every
|
|
83
|
+
* outline block is a headline).
|
|
84
|
+
* @param uniorgAst The uniorg AST to transform.
|
|
85
|
+
* @param nestUnderHeadings Nest content as child blocks. Default: `true`.
|
|
86
|
+
* @returns The Logseq-flavored uniorg AST.
|
|
87
|
+
*/
|
|
88
|
+
export function applyLogseqSpecificsToUniorgAst(uniorgAst, nestUnderHeadings = true) {
|
|
89
|
+
rewriteLabeledPageRefs(uniorgAst);
|
|
90
|
+
const children = uniorgAst.children;
|
|
91
|
+
const result = [];
|
|
92
|
+
let currentLevel = 0;
|
|
93
|
+
// level of a headline whose :heading: property still needs a home
|
|
94
|
+
let pending = null;
|
|
95
|
+
const separate = () => {
|
|
96
|
+
if (!nestUnderHeadings) {
|
|
97
|
+
result.push({ type: "text", value: "\n" });
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
// no drawer took the property: give it one of its own
|
|
101
|
+
const settle = () => {
|
|
102
|
+
if (pending === null) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
result.push(headingDrawer(pending));
|
|
106
|
+
pending = null;
|
|
107
|
+
separate();
|
|
108
|
+
};
|
|
109
|
+
for (const node of children) {
|
|
110
|
+
if (node.type === "headline") {
|
|
111
|
+
settle();
|
|
112
|
+
const headline = node;
|
|
113
|
+
currentLevel = headline.level;
|
|
114
|
+
takeTaskMarker(headline);
|
|
115
|
+
result.push(node);
|
|
116
|
+
pending = headline.level;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (pending !== null) {
|
|
120
|
+
if (placeHeadingProperty(node, pending)) {
|
|
121
|
+
pending = null;
|
|
122
|
+
result.push(node);
|
|
123
|
+
separate();
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (node.type !== "planning") {
|
|
127
|
+
settle();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
result.push(nestUnderHeadings && node.type === "paragraph"
|
|
131
|
+
? toBlockHeadline(node, currentLevel + 1)
|
|
132
|
+
: node);
|
|
133
|
+
}
|
|
134
|
+
settle();
|
|
135
|
+
uniorgAst.children = result;
|
|
136
|
+
return uniorgAst;
|
|
137
|
+
}
|
|
138
|
+
// Logseq md keeps TODO/DONE as leading text markers and priorities as
|
|
139
|
+
// [#A] text; in org they are the headline's TODO keyword and priority
|
|
140
|
+
// (other Logseq markers like DOING are not org keywords and simply
|
|
141
|
+
// stay in the title text)
|
|
142
|
+
function takeTaskMarker(headline) {
|
|
143
|
+
const first = headline.children[0];
|
|
144
|
+
if (first?.type !== "text") {
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const marker = /^(TODO|DONE) (?:\[#([A-Z])\] )?/.exec(first.value);
|
|
148
|
+
if (!marker) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
headline.todoKeyword = marker[1];
|
|
152
|
+
if (marker[2]) {
|
|
153
|
+
headline.priority = marker[2];
|
|
154
|
+
}
|
|
155
|
+
first.value = first.value.slice((marker[0] ?? "").length);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Extracts Logseq-specific conventions from a uniorg AST: headlines with
|
|
159
|
+
* a `:heading:` property become plain headings of that level, headlines
|
|
160
|
+
* without one are outline blocks and become paragraphs.
|
|
161
|
+
* @param uniorgAst The Logseq-flavored uniorg AST to transform.
|
|
162
|
+
* @returns The generic uniorg AST.
|
|
163
|
+
*/
|
|
164
|
+
function extractLogseqSpecificsFromUniorgAst(uniorgAst) {
|
|
165
|
+
extractInParent(uniorgAst);
|
|
166
|
+
repairHighlights(uniorgAst);
|
|
167
|
+
fuzzyLinksToPageRefs(uniorgAst);
|
|
168
|
+
markHiccupParagraphs(uniorgAst);
|
|
169
|
+
return uniorgAst;
|
|
170
|
+
}
|
|
171
|
+
// Logseq highlight markup (^^words^^) re-parses as a caret plus a
|
|
172
|
+
// superscript; merge the pieces back into literal text
|
|
173
|
+
function repairHighlights(uniorgAst) {
|
|
174
|
+
visit(uniorgAst, node => {
|
|
175
|
+
const children = node.children;
|
|
176
|
+
if (!children) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
for (let i = 0; i + 1 < children.length; i++) {
|
|
180
|
+
const current = children[i];
|
|
181
|
+
const next = children[i + 1];
|
|
182
|
+
if (current?.type === "text" &&
|
|
183
|
+
current.value?.endsWith("^") &&
|
|
184
|
+
next?.type === "superscript") {
|
|
185
|
+
current.value += `^${toString(next)}`;
|
|
186
|
+
children.splice(i + 1, 1);
|
|
187
|
+
i--;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
// Logseq page and block references: [[page]] stays a wikilink,
|
|
193
|
+
// [[page][label]] becomes [label]([[page]]), [[((uuid))][label]]
|
|
194
|
+
// becomes [label](((uuid))) — emitted unescaped via verbatim-inline
|
|
195
|
+
const BLOCK_REF_RE = /^\(\(.*\)\)$/;
|
|
196
|
+
function pageRefValue(label, target) {
|
|
197
|
+
if (!label) {
|
|
198
|
+
return `[[${target}]]`;
|
|
199
|
+
}
|
|
200
|
+
if (BLOCK_REF_RE.test(target)) {
|
|
201
|
+
return `[${label}](${target})`;
|
|
202
|
+
}
|
|
203
|
+
return `[${label}]([[${target}]])`;
|
|
204
|
+
}
|
|
205
|
+
function fuzzyLinksToPageRefs(uniorgAst) {
|
|
206
|
+
visit(uniorgAst, "link", (node, index, parent) => {
|
|
207
|
+
const target = node.rawLink ?? "";
|
|
208
|
+
const isBlockRef = BLOCK_REF_RE.test(target);
|
|
209
|
+
if ((node.linkType !== "fuzzy" && !isBlockRef) || !parent) {
|
|
210
|
+
return undefined;
|
|
211
|
+
}
|
|
212
|
+
const label = node.children.length ? toString(node) : "";
|
|
213
|
+
const value = pageRefValue(label, target);
|
|
214
|
+
parent.children[index] = {
|
|
215
|
+
type: "verbatim-inline",
|
|
216
|
+
value
|
|
217
|
+
};
|
|
218
|
+
return undefined;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
// hiccup blocks ([:tag …]) are Logseq markup, not links or footnotes; a
|
|
222
|
+
// verbatim-inline node keeps the brackets unescaped in Markdown output
|
|
223
|
+
function markHiccupParagraphs(uniorgAst) {
|
|
224
|
+
visit(uniorgAst, "paragraph", (node) => {
|
|
225
|
+
const text = toString(node);
|
|
226
|
+
if (text.startsWith("[:")) {
|
|
227
|
+
node.children = [
|
|
228
|
+
{ type: "verbatim-inline", value: text.replace(/\n$/, "") }
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
function extractInParent(parent) {
|
|
234
|
+
const children = parent.children;
|
|
235
|
+
for (let i = 0; i < children.length; i++) {
|
|
236
|
+
const node = children[i];
|
|
237
|
+
if (!node) {
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
if (node.type === "section") {
|
|
241
|
+
extractInParent(node);
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
if (node.type !== "headline") {
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
const headline = node;
|
|
248
|
+
if (headline.todoKeyword) {
|
|
249
|
+
// back to Logseq md's text conventions (TODO [#A] Ship it);
|
|
250
|
+
// verbatim-inline keeps the [#A] brackets unescaped
|
|
251
|
+
const priority = headline.priority ? `[#${headline.priority}] ` : "";
|
|
252
|
+
headline.children.unshift({
|
|
253
|
+
type: "verbatim-inline",
|
|
254
|
+
value: `${headline.todoKeyword} ${priority}`
|
|
255
|
+
});
|
|
256
|
+
headline.todoKeyword = null;
|
|
257
|
+
headline.priority = null;
|
|
258
|
+
}
|
|
259
|
+
// a planning line sits between the headline and its drawer
|
|
260
|
+
const drawerIndex = children[i + 1]?.type === "planning" ? i + 2 : i + 1;
|
|
261
|
+
const heading = takeHeadingProperty(children, drawerIndex);
|
|
262
|
+
if (heading !== null) {
|
|
263
|
+
headline.level = heading;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// a block headline (no :heading:) is outline structure only; its
|
|
267
|
+
// title is the block's content
|
|
268
|
+
children[i] = {
|
|
269
|
+
type: "paragraph",
|
|
270
|
+
children: headline.children,
|
|
271
|
+
contentsBegin: 0,
|
|
272
|
+
contentsEnd: 0
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// removes the heading property from a drawer at `index` (and the drawer
|
|
278
|
+
// itself if that empties it); returns the heading level or null
|
|
279
|
+
function takeHeadingProperty(children, index) {
|
|
280
|
+
const drawer = children[index];
|
|
281
|
+
if (drawer?.type !== "property-drawer") {
|
|
282
|
+
return null;
|
|
283
|
+
}
|
|
284
|
+
const properties = drawer.children;
|
|
285
|
+
const heading = properties.find(property => property.key === "heading");
|
|
286
|
+
if (!heading) {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
const remaining = properties.filter(property => property !== heading);
|
|
290
|
+
if (remaining.length) {
|
|
291
|
+
;
|
|
292
|
+
drawer.children = remaining;
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
children.splice(index, 1);
|
|
296
|
+
}
|
|
297
|
+
return parseInt(heading.value, 10) || null;
|
|
298
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { visit } from "unist-util-visit";
|
|
2
|
+
import { toString } from "orgast-util-to-string";
|
|
3
|
+
/**
|
|
4
|
+
* Obsidian dialect preset: `[[Page]]` / `[[Page|alias]]` wikilinks map
|
|
5
|
+
* to org fuzzy links (`[[Page]]` / `[[Page][alias]]`).
|
|
6
|
+
*/
|
|
7
|
+
export function obsidian() {
|
|
8
|
+
return {
|
|
9
|
+
name: "obsidian",
|
|
10
|
+
applyToUniorg: rewriteAliasedWikilinks,
|
|
11
|
+
extractFromUniorg: fuzzyLinksToWikilinks
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
// md→org: a wikilink travels as plain text; org already reads `[[Page]]`
|
|
15
|
+
// as a fuzzy link, only the `[[Page|alias]]` form needs rewriting to
|
|
16
|
+
// org's `[[Page][alias]]` description syntax
|
|
17
|
+
function rewriteAliasedWikilinks(uniorgAst) {
|
|
18
|
+
visit(uniorgAst, "text", (node) => {
|
|
19
|
+
node.value = node.value.replace(/\[\[([^\][|]+)\|([^\][]+)\]\]/g, "[[$1][$2]]");
|
|
20
|
+
});
|
|
21
|
+
return uniorgAst;
|
|
22
|
+
}
|
|
23
|
+
// org→md: fuzzy links become wikilink text; a verbatim-inline node keeps
|
|
24
|
+
// the brackets unescaped in the Markdown output
|
|
25
|
+
function fuzzyLinksToWikilinks(uniorgAst) {
|
|
26
|
+
visit(uniorgAst, "link", (node, index, parent) => {
|
|
27
|
+
if (node.linkType !== "fuzzy") {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
const description = node.children.length ? toString(node) : "";
|
|
31
|
+
parent.children[index] = {
|
|
32
|
+
type: "verbatim-inline",
|
|
33
|
+
value: description
|
|
34
|
+
? `[[${node.rawLink}|${description}]]`
|
|
35
|
+
: `[[${node.rawLink}]]`
|
|
36
|
+
};
|
|
37
|
+
return undefined;
|
|
38
|
+
});
|
|
39
|
+
return uniorgAst;
|
|
40
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Preset } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Instantiates a preset by name.
|
|
4
|
+
* @param presetName Preset name, or `undefined` for no preset.
|
|
5
|
+
* @returns The preset, or `undefined` when no name was given.
|
|
6
|
+
* @throws If the name is not a known preset.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createPreset(presetName: string | undefined): Preset | undefined;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { logseq } from "./logseq.js";
|
|
2
|
+
import { obsidian } from "./obsidian.js";
|
|
3
|
+
// the one place a dialect preset is registered; both adapters (CLI and
|
|
4
|
+
// Web UI) resolve names through here so they cannot drift apart
|
|
5
|
+
const PRESETS = {
|
|
6
|
+
logseq: () => logseq(),
|
|
7
|
+
obsidian: () => obsidian()
|
|
8
|
+
};
|
|
9
|
+
const PRESET_NAMES = Object.keys(PRESETS);
|
|
10
|
+
/**
|
|
11
|
+
* Instantiates a preset by name.
|
|
12
|
+
* @param presetName Preset name, or `undefined` for no preset.
|
|
13
|
+
* @returns The preset, or `undefined` when no name was given.
|
|
14
|
+
* @throws If the name is not a known preset.
|
|
15
|
+
*/
|
|
16
|
+
export function createPreset(presetName) {
|
|
17
|
+
if (!presetName) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const factory = PRESETS[presetName];
|
|
21
|
+
if (!factory) {
|
|
22
|
+
throw new Error(`Unknown preset '${presetName}'. Available presets: ${PRESET_NAMES.join(", ")}`);
|
|
23
|
+
}
|
|
24
|
+
return factory();
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { OrgData } from "uniorg";
|
|
2
|
+
/**
|
|
3
|
+
* A dialect preset: transforms applied on top of the dialect-agnostic core.
|
|
4
|
+
* `applyToUniorg` runs in the md→org pipeline after the generic transform;
|
|
5
|
+
* `extractFromUniorg` runs in the org→md pipeline before the generic
|
|
6
|
+
* transform, normalizing dialect conventions back to generic uniorg.
|
|
7
|
+
*/
|
|
8
|
+
export interface Preset {
|
|
9
|
+
name: string;
|
|
10
|
+
applyToUniorg?: (uniorgAst: OrgData) => OrgData;
|
|
11
|
+
extractFromUniorg?: (uniorgAst: OrgData) => OrgData;
|
|
12
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@remigius42/morg",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Bidirectional Markdown ↔ Org-mode converter with round-trip convergence",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"org-mode",
|
|
7
|
+
"markdown",
|
|
8
|
+
"converter",
|
|
9
|
+
"unified",
|
|
10
|
+
"remark",
|
|
11
|
+
"uniorg",
|
|
12
|
+
"logseq",
|
|
13
|
+
"obsidian"
|
|
14
|
+
],
|
|
15
|
+
"license": "GPL-3.0-or-later",
|
|
16
|
+
"author": "Andreas Remigius Schmidt",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/remigius42/morg.git"
|
|
20
|
+
},
|
|
21
|
+
"bugs": "https://github.com/remigius42/morg/issues",
|
|
22
|
+
"homepage": "https://github.com/remigius42/morg#readme",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"bin": {
|
|
33
|
+
"morg": "./dist/cli.js"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist"
|
|
37
|
+
],
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public",
|
|
40
|
+
"provenance": true
|
|
41
|
+
},
|
|
42
|
+
"engines": {
|
|
43
|
+
"node": ">=20"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"prepare": "husky",
|
|
47
|
+
"prepack": "npm run build",
|
|
48
|
+
"version": "node scripts/release-changelog.mjs && git add CHANGELOG.md",
|
|
49
|
+
"build": "tsc -p tsconfig.build.json",
|
|
50
|
+
"build:web": "vite build web",
|
|
51
|
+
"dev:web": "vite web",
|
|
52
|
+
"preview:web": "vite preview web --port 4173 --strictPort",
|
|
53
|
+
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
54
|
+
"lint": "npm run lint:prettier && npm run lint:cspell && npm run lint:markdown && npm run lint:eslint && npm run lint:knip && npm run typecheck",
|
|
55
|
+
"lint:knip": "knip",
|
|
56
|
+
"lint:packaging": "attw --pack . --ignore-rules cjs-resolves-to-esm",
|
|
57
|
+
"lint:prettier": "prettier --no-error-on-unmatched-pattern --ignore-unknown --list-different '**/*'",
|
|
58
|
+
"lint:cspell": "cspell --dot --no-must-find-files --no-progress '**/*'",
|
|
59
|
+
"lint:markdown": "markdownlint-cli2 '**/*.md' '!node_modules/**'",
|
|
60
|
+
"lint:eslint": "eslint --max-warnings=0 '**/*.{ts,mts,js,mjs}'",
|
|
61
|
+
"lint:fix": "npm run lint:fix:prettier && npm run lint:fix:eslint",
|
|
62
|
+
"lint:fix:prettier": "prettier --write '**/*'",
|
|
63
|
+
"lint:fix:eslint": "eslint --fix '**/*.{ts,mts,js}'",
|
|
64
|
+
"test:unit": "vitest",
|
|
65
|
+
"test:unit:ci": "vitest run --reporter default --coverage",
|
|
66
|
+
"test:coverage": "vitest run --coverage",
|
|
67
|
+
"test:e2e": "playwright test",
|
|
68
|
+
"test:e2e:chromium": "playwright test --project=chromium",
|
|
69
|
+
"test:e2e:report": "playwright show-report tests/e2e/reports/html"
|
|
70
|
+
},
|
|
71
|
+
"dependencies": {
|
|
72
|
+
"@types/mdast": "^4.0.4",
|
|
73
|
+
"orgast-util-to-string": "^1.1.0",
|
|
74
|
+
"remark-frontmatter": "^5.0.0",
|
|
75
|
+
"remark-gfm": "^4.0.1",
|
|
76
|
+
"remark-math": "^6.0.0",
|
|
77
|
+
"remark-parse": "^11.0.0",
|
|
78
|
+
"remark-stringify": "^11.0.0",
|
|
79
|
+
"smol-toml": "^1.8.0",
|
|
80
|
+
"unified": "^11.0.5",
|
|
81
|
+
"uniorg": "^1.4.0",
|
|
82
|
+
"uniorg-parse": "^3.2.2",
|
|
83
|
+
"uniorg-stringify": "^1.4.0",
|
|
84
|
+
"unist-util-visit": "^5.0.0",
|
|
85
|
+
"yaml": "^2.9.0"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
89
|
+
"@axe-core/playwright": "^4.13.0",
|
|
90
|
+
"@commitlint/cli": "^21.2.2",
|
|
91
|
+
"@commitlint/config-conventional": "^21.2.2",
|
|
92
|
+
"@eslint/js": "^10.0.1",
|
|
93
|
+
"@picocss/pico": "^2.1.1",
|
|
94
|
+
"@playwright/test": "^1.63.0",
|
|
95
|
+
"@types/node": "^24.3.0",
|
|
96
|
+
"@types/unist": "^3.0.3",
|
|
97
|
+
"@vitest/coverage-v8": "^5.0.0",
|
|
98
|
+
"cspell": "^10.2.2",
|
|
99
|
+
"eslint": "^10.10.0",
|
|
100
|
+
"happy-dom": "^20.14.3",
|
|
101
|
+
"husky": "^9.1.7",
|
|
102
|
+
"knip": "^6.35.1",
|
|
103
|
+
"lint-staged": "^17.5.1",
|
|
104
|
+
"markdownlint-cli2": "^0.23.2",
|
|
105
|
+
"prettier": "^3.6.2",
|
|
106
|
+
"tsx": "^4.23.13",
|
|
107
|
+
"typescript": "^5.9.2",
|
|
108
|
+
"typescript-eslint": "^8.42.0",
|
|
109
|
+
"vite": "^8.2.2",
|
|
110
|
+
"vitest": "^5.0.0"
|
|
111
|
+
}
|
|
112
|
+
}
|