@remigius42/morg 0.9.2 → 0.10.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.
@@ -0,0 +1,34 @@
1
+ import type { MarkdownStyleOptions } from "./options.js";
2
+ import { type PresetOptions } from "./presets/sides.js";
3
+ /**
4
+ * The presets of a translation, its warning callback and the org-ism
5
+ * key names Vanilla Markdown writes planning under.
6
+ */
7
+ export type TranslateOptions = PresetOptions & {
8
+ onWarning?: (message: string) => void;
9
+ orgismKeys?: Record<string, string>;
10
+ /** The Markdown markers to write; others stay as written. */
11
+ markdownStyle?: MarkdownStyleOptions;
12
+ };
13
+ /**
14
+ * Translates an Org string from the Input Preset's dialect into the
15
+ * Output Preset's, changing only what the two dialects write
16
+ * differently (ADR 0006): a block's content is kept as written.
17
+ * @param org The Org string to translate.
18
+ * @param options The preset of each side, which must differ.
19
+ * @returns The Org string in the output's dialect.
20
+ * @throws If both sides name the same preset (that is `normalizeOrg`),
21
+ * or a side preset has no org dialect.
22
+ */
23
+ export declare function translateOrg(org: string, options?: TranslateOptions): string;
24
+ /**
25
+ * Translates a Markdown string from the Input Preset's dialect into the
26
+ * Output Preset's, changing only what the two dialects write
27
+ * differently (ADR 0006): a block's content is kept as written.
28
+ * @param markdown The Markdown string to translate.
29
+ * @param options The preset of each side, which must differ.
30
+ * @returns The Markdown string in the output's dialect.
31
+ * @throws If both sides name the same preset (that is
32
+ * `normalizeMarkdown`).
33
+ */
34
+ export declare function translateMarkdown(markdown: string, options?: TranslateOptions): string;
@@ -0,0 +1,82 @@
1
+ import { restyleMarkdown } from "./core/restyle.js";
2
+ import { resolveSides } from "./presets/sides.js";
3
+ /**
4
+ * Translates an Org string from the Input Preset's dialect into the
5
+ * Output Preset's, changing only what the two dialects write
6
+ * differently (ADR 0006): a block's content is kept as written.
7
+ * @param org The Org string to translate.
8
+ * @param options The preset of each side, which must differ.
9
+ * @returns The Org string in the output's dialect.
10
+ * @throws If both sides name the same preset (that is `normalizeOrg`),
11
+ * or a side preset has no org dialect.
12
+ */
13
+ export function translateOrg(org, options = {}) {
14
+ const { input, output } = twoSides(options, "org", "normalizeOrg");
15
+ // Vanilla has no dialect to translate, so the other side does it
16
+ const side = input?.translateOrg ? "input" : "output";
17
+ const translate = (side === "input" ? input : output)?.translateOrg;
18
+ return translate
19
+ ? translate(org, {
20
+ side,
21
+ ...(options.onWarning && { onWarning: options.onWarning })
22
+ })
23
+ : org;
24
+ }
25
+ /**
26
+ * Translates a Markdown string from the Input Preset's dialect into the
27
+ * Output Preset's, changing only what the two dialects write
28
+ * differently (ADR 0006): a block's content is kept as written.
29
+ * @param markdown The Markdown string to translate.
30
+ * @param options The preset of each side, which must differ.
31
+ * @returns The Markdown string in the output's dialect.
32
+ * @throws If both sides name the same preset (that is
33
+ * `normalizeMarkdown`).
34
+ */
35
+ export function translateMarkdown(markdown, options = {}) {
36
+ const { input, output } = twoSides(options, "markdown", "normalizeMarkdown");
37
+ const context = hookContext(options, pageLinks({ input, output }));
38
+ // into Vanilla from the input's dialect, then from it into the
39
+ // output's; a dialect does what its side needs
40
+ const vanilla = input?.translateMarkdown?.(markdown, { ...context, side: "input" }) ??
41
+ markdown;
42
+ const translated = output?.translateMarkdown?.(vanilla, { ...context, side: "output" }) ??
43
+ vanilla;
44
+ const style = outputStyle(options, output);
45
+ return style ? restyleMarkdown(translated, style) : translated;
46
+ }
47
+ // the style to write, but for a bullet the output's outline needs
48
+ function outputStyle({ markdownStyle, onWarning }, output) {
49
+ const needed = output?.markdown?.bullet;
50
+ if (!markdownStyle?.bullet || !needed || markdownStyle.bullet === needed) {
51
+ return markdownStyle;
52
+ }
53
+ onWarning?.(`${output.name} Markdown writes its blocks with '${needed}'; bullet '${markdownStyle.bullet}' not applied`);
54
+ const style = { ...markdownStyle };
55
+ delete style.bullet;
56
+ return style;
57
+ }
58
+ // what a dialect's translation learns of the options
59
+ function hookContext({ onWarning, orgismKeys }, relink) {
60
+ return {
61
+ ...(onWarning && { onWarning }),
62
+ ...(orgismKeys && { orgismKeys }),
63
+ ...(relink && { relink })
64
+ };
65
+ }
66
+ // page links between two dialects; a Vanilla side carries the other's
67
+ function pageLinks({ input, output }) {
68
+ const read = input?.markdown?.links?.read;
69
+ const write = output?.markdown?.links?.write;
70
+ return read && write
71
+ ? (text, inTable) => write(read(text), inTable)
72
+ : undefined;
73
+ }
74
+ // a translation is between two dialects; one on both sides normalizes
75
+ function twoSides(options, format, normalize) {
76
+ const sides = resolveSides(options, format, format);
77
+ const name = sides.input?.name ?? "vanilla";
78
+ if (name === (sides.output?.name ?? "vanilla")) {
79
+ throw new Error(`translation takes two presets; for '${name}' on both sides, use ${normalize}`);
80
+ }
81
+ return sides;
82
+ }
@@ -0,0 +1,12 @@
1
+ import type { NormalizeOptions } from "./normalize.js";
2
+ import type { Format } from "./presets/sides.js";
3
+ /**
4
+ * Converts within one format: two presets translate between their
5
+ * dialects, one normalizes (ADR 0006). What both adapters do with one
6
+ * format on both sides.
7
+ * @param text The document.
8
+ * @param format Its format, on both sides.
9
+ * @param options The conversion's options, presets included.
10
+ * @returns The translated or normalized document.
11
+ */
12
+ export declare function convertWithinFormat(text: string, format: Format, options?: NormalizeOptions): string;
@@ -0,0 +1,18 @@
1
+ import { normalizeMarkdown, normalizeOrg } from "./normalize.js";
2
+ import { translateMarkdown, translateOrg } from "./translate.js";
3
+ /**
4
+ * Converts within one format: two presets translate between their
5
+ * dialects, one normalizes (ADR 0006). What both adapters do with one
6
+ * format on both sides.
7
+ * @param text The document.
8
+ * @param format Its format, on both sides.
9
+ * @param options The conversion's options, presets included.
10
+ * @returns The translated or normalized document.
11
+ */
12
+ export function convertWithinFormat(text, format, options = {}) {
13
+ const markdown = format === "markdown";
14
+ if (options.inputPreset || options.outputPreset) {
15
+ return (markdown ? translateMarkdown : translateOrg)(text, options);
16
+ }
17
+ return (markdown ? normalizeMarkdown : normalizeOrg)(text, options);
18
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remigius42/morg",
3
- "version": "0.9.2",
3
+ "version": "0.10.0",
4
4
  "description": "Bidirectional Markdown ↔ Org-mode converter with round-trip convergence",
5
5
  "keywords": [
6
6
  "org-mode",
@@ -40,7 +40,7 @@
40
40
  "provenance": true
41
41
  },
42
42
  "engines": {
43
- "node": ">=20"
43
+ "node": ">=24"
44
44
  },
45
45
  "scripts": {
46
46
  "prepare": "husky",