sommark 2.2.0 → 2.3.1
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/CHANGELOG.md +25 -0
- package/README.md +43 -14
- package/cli/commands/build.js +2 -1
- package/cli/commands/help.js +32 -31
- package/cli/constants.js +6 -5
- package/core/lexer.js +5 -3
- package/core/transpiler.js +10 -8
- package/formatter/mark.js +24 -39
- package/formatter/tag.js +6 -6
- package/mappers/mapper.js +49 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v2.3.1 (2026-03-02)
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
* Fixed MDX format issue
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## v2.3.0 (2026-02-23)
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
* Added missing JSON support in the CLI.
|
|
14
|
+
* Added two new methods: makeFrontmatter and raw_js_imports.
|
|
15
|
+
* Added new documentation.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
* Fixed MDX format output error caused by extra whitespaces.
|
|
20
|
+
* Fixed colon issue in atblock body.
|
|
21
|
+
|
|
22
|
+
### Improved
|
|
23
|
+
|
|
24
|
+
* Improved several internal methods.
|
|
25
|
+
* Updated and enhanced tests.
|
|
26
|
+
|
|
27
|
+
|
|
3
28
|
## v2.2.0 (2026-02-23)
|
|
4
29
|
## Features
|
|
5
30
|
- Added JSON support
|
package/README.md
CHANGED
|
@@ -5,15 +5,37 @@ SomMark is a declarative, extensible markup language for structured content that
|
|
|
5
5
|
</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
+
<!--License-->
|
|
9
|
+
<a href="https://www.npmjs.com/package/sommark" target="_blank">
|
|
8
10
|
<img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" />
|
|
11
|
+
</a>
|
|
12
|
+
|
|
13
|
+
<!--Npm Version-->
|
|
14
|
+
<a href="https://www.npmjs.com/package/sommark" target="_blank">
|
|
9
15
|
<img src="https://img.shields.io/npm/v/sommark?style=flat-square" />
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<img src="https://img.shields.io/badge/
|
|
14
|
-
|
|
16
|
+
</a>
|
|
17
|
+
|
|
18
|
+
<!--Language Type-->
|
|
19
|
+
<img src="https://img.shields.io/badge/type-markup%20language-white?style=flat-square" />
|
|
20
|
+
|
|
21
|
+
<!--SomMark Playground-->
|
|
22
|
+
<a href="https://adam-elmi.github.io/SomMark-Playground" target="_blank">
|
|
23
|
+
<img
|
|
24
|
+
src="https://img.shields.io/badge/SomMark-Playground-blue?style=flat-square"
|
|
25
|
+
alt="SomMark Playground Badge" />
|
|
26
|
+
</a>
|
|
15
27
|
</p>
|
|
16
28
|
|
|
29
|
+
|
|
30
|
+
----
|
|
31
|
+
|
|
32
|
+
## Try SomMark Playground
|
|
33
|
+
|
|
34
|
+
Test SomMark features live here:
|
|
35
|
+
[https://adam-elmi.github.io/SomMark-Playground/](https://adam-elmi.github.io/SomMark-Playground/)
|
|
36
|
+
|
|
37
|
+
----
|
|
38
|
+
|
|
17
39
|
# SomMark v2
|
|
18
40
|
|
|
19
41
|
> [!WARNING]
|
|
@@ -21,7 +43,6 @@ SomMark is a declarative, extensible markup language for structured content that
|
|
|
21
43
|
|
|
22
44
|
**SomMark** lets you write structured content that can be converted to HTML, Markdown, JSON, or other formats. Unlike standard Markdown, it uses explicit syntax for blocks and elements, making content easier to process, customize, and transform.
|
|
23
45
|
|
|
24
|
-
|
|
25
46
|
# Installation
|
|
26
47
|
|
|
27
48
|
To install the Command Line Interface (CLI) globally:
|
|
@@ -58,20 +79,28 @@ Hello World
|
|
|
58
79
|
`;
|
|
59
80
|
|
|
60
81
|
const smark = new SomMark({
|
|
61
|
-
|
|
62
|
-
|
|
82
|
+
src: source,
|
|
83
|
+
format: "html"
|
|
63
84
|
});
|
|
64
85
|
|
|
65
86
|
console.log(await smark.transpile());
|
|
66
87
|
```
|
|
67
88
|
|
|
89
|
+
## Supported Languages
|
|
90
|
+
|
|
91
|
+
* HTML
|
|
92
|
+
* Markdown
|
|
93
|
+
* MDX (Only ready components)
|
|
94
|
+
* JSON
|
|
95
|
+
|
|
96
|
+
|
|
68
97
|
# Documentation
|
|
69
98
|
|
|
70
99
|
Detailed guides and API references are available in the `docs/` directory:
|
|
71
100
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
101
|
+
- **[Syntax Guide](docs/03.syntax.md)**: Master SomMark syntax (Blocks, Inline, At-Blocks).
|
|
102
|
+
- **[Core API](docs/09.core.md)**: Programmatic usage of the library (`transpile`, `lex`, `parse`).
|
|
103
|
+
- **[Mapper API](docs/13.mapper.md)**: Guide for creating custom mappers and rules.
|
|
104
|
+
- **[CLI Reference](docs/11.cli.md)**: Command line options and configurations.
|
|
105
|
+
- **[API Quick Reference](docs/api)**: Fast lookup for all classes and functions.
|
|
106
|
+
- **[Configuration Reference](docs/12.config.md)**: Guide for creating custom configurations.
|
package/cli/commands/build.js
CHANGED
|
@@ -4,6 +4,7 @@ import { cliError, formatMessage } from "../../core/errors.js";
|
|
|
4
4
|
import HTML from "../../mappers/languages/html.js";
|
|
5
5
|
import MARKDOWN from "../../mappers/languages/markdown.js";
|
|
6
6
|
import MDX from "../../mappers/languages/mdx.js";
|
|
7
|
+
import Json from "../../mappers/languages/json.js";
|
|
7
8
|
import { extensions } from "../constants.js";
|
|
8
9
|
import { isExist, readContent, createFile } from "../helpers/file.js";
|
|
9
10
|
import { loadConfig } from "../helpers/config.js";
|
|
@@ -56,7 +57,7 @@ export async function runBuild(format_option, sourcePath, outputFlag, outputFile
|
|
|
56
57
|
let mappingFile = config.mappingFile;
|
|
57
58
|
|
|
58
59
|
if (!mappingFile) {
|
|
59
|
-
mappingFile = format === "html" ? HTML : format === "markdown" ? MARKDOWN : format === "mdx" ? MDX : null;
|
|
60
|
+
mappingFile = format === "html" ? HTML : format === "markdown" ? MARKDOWN : format === "mdx" ? MDX : format === "json" ? Json : null;
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
// CLI Overrides
|
package/cli/commands/help.js
CHANGED
|
@@ -6,40 +6,41 @@ import { options } from "../constants.js";
|
|
|
6
6
|
// ========================================================================== //
|
|
7
7
|
|
|
8
8
|
export function getHelp(unknown_option = true) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
const msg = [
|
|
10
|
+
`${unknown_option && process.argv[2] ? `<$red:Unrecognized option$> <$blue: '${process.argv[2]}'$>` : ""}`,
|
|
11
|
+
"{N}<$yellow:Usage:$> <$blue:sommark [option]$>",
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
"{N}{N}<$yellow:Global Options:$>",
|
|
14
|
+
"{N} <$green:-h, --help$> <$cyan: Show help message$>",
|
|
15
|
+
"{N} <$green:-v, --version$> <$cyan: Show version information$>",
|
|
16
|
+
"{N} <$green:init$> <$cyan: Initialize global SomMark configuration directory$>",
|
|
17
|
+
"{N} <$green:show config$> <$cyan: Display the absolute paths to the active SomMark configuration files$>",
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
"{N}{N}<$yellow:Transpilation Options:$>",
|
|
20
|
+
"{N}<$yellow:Usage:$> <$blue:sommark [option] [targetFile] [option] [outputFile] [outputDir]$>",
|
|
21
|
+
"{N} <$green:--html$> <$cyan: Transpile to HTML$>",
|
|
22
|
+
"{N} <$green:--markdown$> <$cyan: Transpile to Markdown$>",
|
|
23
|
+
"{N} <$green:--mdx$> <$cyan: Transpile to MDX$>",
|
|
24
|
+
"{N} <$green:--json$> <$cyan: Transpile to json$>",
|
|
25
|
+
"{N} <$green:--text$> <$cyan: Transpile to plain text$>",
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
"{N}{N}<$yellow:Output Options:$>",
|
|
28
|
+
"{N} <$green:-p, --print$> <$cyan: Print output to console (stdout)$>",
|
|
29
|
+
"{N} <$green:-o$> <$cyan: Specify output filename (and optionally directory)$>",
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
"{N}{N}<$yellow:Examples:$>",
|
|
32
|
+
"{N} <$magenta:1. Basic usage:$> <$blue:sommark --html input.smark$>",
|
|
33
|
+
"{N} <$magenta:2. Print to console:$> <$blue:sommark --html -p input.smark$>",
|
|
34
|
+
"{N} <$magenta:3. Custom output:$> <$blue:sommark --html input.smark -o myOutput ./dist/$>"
|
|
35
|
+
].join("");
|
|
36
|
+
const help_msg = formatMessage(msg);
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
if (!options.includes(process.argv[2]) && unknown_option) {
|
|
39
|
+
console.log(help_msg);
|
|
40
|
+
process.exit(0);
|
|
41
|
+
} else if (process.argv[2] === "-h" || process.argv[2] === "--help") {
|
|
42
|
+
console.log(help_msg);
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
return help_msg;
|
|
45
46
|
}
|
package/cli/constants.js
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
// CLI Constants //
|
|
3
3
|
// ========================================================================== //
|
|
4
4
|
|
|
5
|
-
export const options = ["-v", "--version", "-h", "--help", "--html", "--markdown", "--mdx", "--text", "--print", "-p"];
|
|
5
|
+
export const options = ["-v", "--version", "-h", "--help", "--html", "--markdown", "--mdx", "json", "--text", "--print", "-p"];
|
|
6
6
|
|
|
7
7
|
export const extensions = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
text: "txt",
|
|
9
|
+
html: "html",
|
|
10
|
+
markdown: "md",
|
|
11
|
+
mdx: "mdx",
|
|
12
|
+
json: "json"
|
|
12
13
|
};
|
package/core/lexer.js
CHANGED
|
@@ -289,7 +289,6 @@ function lexer(src) {
|
|
|
289
289
|
i += temp_str.length - 1;
|
|
290
290
|
// Update Metadata
|
|
291
291
|
updateMetadata(temp_str);
|
|
292
|
-
scope_state = true;
|
|
293
292
|
addToken(TOKEN_TYPES.OPEN_AT, temp_str);
|
|
294
293
|
// is next token end keyword?
|
|
295
294
|
const endKey = concatChar(src, i + 1, ["_"]);
|
|
@@ -330,7 +329,8 @@ function lexer(src) {
|
|
|
330
329
|
previous_value === at_value ||
|
|
331
330
|
previous_value === BLOCKCOLON ||
|
|
332
331
|
previous_value === ATBLOCKCOLON ||
|
|
333
|
-
previous_value === INLINECOLON)
|
|
332
|
+
previous_value === INLINECOLON) &&
|
|
333
|
+
!scope_state
|
|
334
334
|
) {
|
|
335
335
|
// Update Metadata
|
|
336
336
|
updateMetadata(current_char);
|
|
@@ -391,6 +391,7 @@ function lexer(src) {
|
|
|
391
391
|
// Update Metadata
|
|
392
392
|
updateMetadata(current_char);
|
|
393
393
|
addToken(TOKEN_TYPES.SEMICOLON, current_char);
|
|
394
|
+
scope_state = true;
|
|
394
395
|
previous_value = current_char;
|
|
395
396
|
}
|
|
396
397
|
// ========================================================================== //
|
|
@@ -574,10 +575,11 @@ function lexer(src) {
|
|
|
574
575
|
// Token: Text //
|
|
575
576
|
// ========================================================================== //
|
|
576
577
|
else {
|
|
578
|
+
if (previous_value === "_@+") scope_state = true;
|
|
577
579
|
context = concatText(src, i, scope_state, [
|
|
578
580
|
[":", previous_value === inline_id_2],
|
|
579
581
|
[",", previous_value === block_value || previous_value === at_value || previous_value === inline_value],
|
|
580
|
-
[":", previous_value === "_@+" || previous_value === at_value],
|
|
582
|
+
[":", (previous_value === "_@+" && !scope_state) || previous_value === at_value],
|
|
581
583
|
[";", previous_value === at_value],
|
|
582
584
|
[")", previous_value === inline_value]
|
|
583
585
|
]);
|
package/core/transpiler.js
CHANGED
|
@@ -119,10 +119,11 @@ async function generateOutput(ast, i, format, mapper_file) {
|
|
|
119
119
|
const block_formats = [htmlFormat, mdxFormat, jsonFormat];
|
|
120
120
|
if (target) {
|
|
121
121
|
validateRules(target, node.args, "", node.type);
|
|
122
|
+
const placeholder = format === mdxFormat && node.body.length > 0 ? "\n<%smark>\n" : "<%smark>";
|
|
122
123
|
result += block_formats.includes(format)
|
|
123
|
-
? `${target.render({ args: node.args, content:
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
? `${format === mdxFormat ? "\n" : ""}${target.render({ args: node.args, content: placeholder, ast: expose_for_fmts.includes(format) ? ast[i] : null }) + (format === mdxFormat ? "\n" : "")}`
|
|
125
|
+
: target.render({ args: node.args, content: "" }) + (format === mdxFormat ? "\n" : "");
|
|
126
|
+
// Body nodes
|
|
126
127
|
for (let j = 0; j < node.body.length; j++) {
|
|
127
128
|
const body_node = node.body[j];
|
|
128
129
|
switch (body_node.type) {
|
|
@@ -141,10 +142,11 @@ async function generateOutput(ast, i, format, mapper_file) {
|
|
|
141
142
|
target = matchedValue(mapper_file.outputs, body_node.id);
|
|
142
143
|
if (target) {
|
|
143
144
|
validateRules(target, body_node.args, body_node.value, body_node.type);
|
|
144
|
-
context +=
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
context +=
|
|
146
|
+
target.render({
|
|
147
|
+
args: body_node.args.length > 0 ? body_node.args : [],
|
|
148
|
+
content: format === htmlFormat || format === mdxFormat ? escapeHTML(body_node.value) : body_node.value
|
|
149
|
+
}) + (format === mdxFormat ? "\n" : "");
|
|
148
150
|
}
|
|
149
151
|
break;
|
|
150
152
|
// ========================================================================== //
|
|
@@ -159,7 +161,7 @@ async function generateOutput(ast, i, format, mapper_file) {
|
|
|
159
161
|
if (shouldEscape) {
|
|
160
162
|
body_node.content = escapeHTML(body_node.content);
|
|
161
163
|
}
|
|
162
|
-
context += target.render({ args: body_node.args, content: body_node.content });
|
|
164
|
+
context += target.render({ args: body_node.args, content: body_node.content }) + (format === mdxFormat ? "\n" : "");
|
|
163
165
|
}
|
|
164
166
|
break;
|
|
165
167
|
// ========================================================================== //
|
package/formatter/mark.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class MarkdownBuilder {
|
|
2
|
-
constructor() {
|
|
2
|
+
constructor() {}
|
|
3
3
|
// ========================================================================== //
|
|
4
4
|
// Headings //
|
|
5
5
|
// ========================================================================== //
|
|
@@ -64,29 +64,23 @@ class MarkdownBuilder {
|
|
|
64
64
|
// ========================================================================== //
|
|
65
65
|
// Code Block //
|
|
66
66
|
// ========================================================================== //
|
|
67
|
-
codeBlock(code, language) {
|
|
68
|
-
if (!code)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
for (const code_block of code) {
|
|
74
|
-
blocks.push(code_block);
|
|
75
|
-
}
|
|
76
|
-
if (!language) {
|
|
77
|
-
return "\n```" + "\n" + blocks.join("\n") + "\n```\n";
|
|
78
|
-
}
|
|
79
|
-
return "\n```" + language + "\n" + blocks.join("\n") + "\n```\n";
|
|
80
|
-
} else if (typeof code === "string") {
|
|
81
|
-
if (!language) {
|
|
82
|
-
return "\n```" + "\n" + code + "\n```\n";
|
|
83
|
-
}
|
|
84
|
-
return "\n```" + language + "\n" + code + "\n```\n";
|
|
85
|
-
}
|
|
86
|
-
if (!code && !language) {
|
|
67
|
+
codeBlock(code, language = "") {
|
|
68
|
+
if (!code) return "";
|
|
69
|
+
|
|
70
|
+
const normalizeContent = c => {
|
|
71
|
+
if (Array.isArray(c)) return c.join("\n");
|
|
72
|
+
if (typeof c === "string") return c;
|
|
87
73
|
return "";
|
|
88
|
-
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const content = normalizeContent(code);
|
|
77
|
+
|
|
78
|
+
if (!content) return "";
|
|
79
|
+
|
|
80
|
+
const lang = language ? language : "";
|
|
81
|
+
return `\n\`\`\`${lang}\n${content}\`\`\`\n`;
|
|
89
82
|
}
|
|
83
|
+
|
|
90
84
|
// ========================================================================== //
|
|
91
85
|
// Horizontal rule //
|
|
92
86
|
// ========================================================================== //
|
|
@@ -97,22 +91,13 @@ class MarkdownBuilder {
|
|
|
97
91
|
// Escape //
|
|
98
92
|
// ========================================================================== //
|
|
99
93
|
escape(text) {
|
|
100
|
-
|
|
101
|
-
if (!text) {
|
|
102
|
-
return "";
|
|
103
|
-
}
|
|
94
|
+
if (!text) return "";
|
|
104
95
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (special_char.includes(char)) {
|
|
109
|
-
return `\\${char}`;
|
|
110
|
-
}
|
|
111
|
-
return char;
|
|
112
|
-
})
|
|
113
|
-
.join("");
|
|
114
|
-
return text;
|
|
96
|
+
const special = /[\\*_{}\[\]()#+\-.!>|]/g;
|
|
97
|
+
|
|
98
|
+
return text.replace(special, "\\$&");
|
|
115
99
|
}
|
|
100
|
+
|
|
116
101
|
// ========================================================================== //
|
|
117
102
|
// Table //
|
|
118
103
|
// ========================================================================== //
|
|
@@ -133,15 +118,15 @@ class MarkdownBuilder {
|
|
|
133
118
|
}
|
|
134
119
|
rows = rows.map(row => {
|
|
135
120
|
let columns;
|
|
136
|
-
if (typeof row ===
|
|
137
|
-
columns = row.split(
|
|
121
|
+
if (typeof row === "string") {
|
|
122
|
+
columns = row.split(",").map(c => c.trim());
|
|
138
123
|
} else if (Array.isArray(row)) {
|
|
139
124
|
columns = row.map(c => String(c).trim());
|
|
140
125
|
} else {
|
|
141
126
|
return "";
|
|
142
127
|
}
|
|
143
128
|
|
|
144
|
-
if (columns.length > 0 && columns[0].startsWith(
|
|
129
|
+
if (columns.length > 0 && columns[0].startsWith("-")) {
|
|
145
130
|
columns[0] = `- ${columns[0].substring(1).trim()}`;
|
|
146
131
|
}
|
|
147
132
|
|
package/formatter/tag.js
CHANGED
|
@@ -38,16 +38,16 @@ class TagBuilder {
|
|
|
38
38
|
props(propsList) {
|
|
39
39
|
const list = Array.isArray(propsList) ? propsList : [propsList];
|
|
40
40
|
if (list.length > 0) {
|
|
41
|
-
|
|
41
|
+
for (const propEntry of list) {
|
|
42
42
|
if (typeof propEntry !== "object" || propEntry === null) {
|
|
43
|
-
throw new TypeError("prop expects an object with property {
|
|
43
|
+
throw new TypeError("prop expects an object with property { __type__ }");
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
if (!Object.prototype.hasOwnProperty.call(propEntry, "
|
|
47
|
-
throw new TypeError("prop expects an object with property {
|
|
46
|
+
if (!Object.prototype.hasOwnProperty.call(propEntry, "__type__")) {
|
|
47
|
+
throw new TypeError("prop expects an object with property { __type__ }");
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
const {
|
|
50
|
+
const { __type__, ...rest } = propEntry;
|
|
51
51
|
const entries = Object.entries(rest);
|
|
52
52
|
|
|
53
53
|
if (entries.length === 0) {
|
|
@@ -56,7 +56,7 @@ class TagBuilder {
|
|
|
56
56
|
|
|
57
57
|
const [key, value] = entries[0];
|
|
58
58
|
|
|
59
|
-
switch (
|
|
59
|
+
switch (__type__) {
|
|
60
60
|
case "string":
|
|
61
61
|
this.#attr.push(`${key}="${escapeHTML(String(value))}"`);
|
|
62
62
|
break;
|
package/mappers/mapper.js
CHANGED
|
@@ -27,7 +27,7 @@ class Mapper {
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
this.#customHeaderContent = "";
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
this.highlightCode = null;
|
|
32
32
|
this.escapeHTML = escapeHTML;
|
|
33
33
|
this.styles = [];
|
|
@@ -358,5 +358,53 @@ class Mapper {
|
|
|
358
358
|
|
|
359
359
|
return fallBack;
|
|
360
360
|
};
|
|
361
|
+
makeFrontmatter = entries => {
|
|
362
|
+
if (!entries || typeof entries !== "object") {
|
|
363
|
+
console.warn(`From function: ${this.makeFrontmatter.name}: invalid entries, returning empty string.`);
|
|
364
|
+
return "";
|
|
365
|
+
}
|
|
366
|
+
const keys = Object.keys(entries);
|
|
367
|
+
if (keys.length === 0) {
|
|
368
|
+
console.warn(`From function: ${this.makeFrontmatter.name}: invalid entries, returning empty string.`);
|
|
369
|
+
return "";
|
|
370
|
+
}
|
|
371
|
+
const body = keys
|
|
372
|
+
.map(key => {
|
|
373
|
+
const value = entries[key];
|
|
374
|
+
if (Array.isArray(value)) {
|
|
375
|
+
const list = value.map(item => ` - ${JSON.stringify(item)}`).join("\n");
|
|
376
|
+
return `${key}:\n${list}`;
|
|
377
|
+
}
|
|
378
|
+
return `${key}: ${JSON.stringify(value)}`;
|
|
379
|
+
})
|
|
380
|
+
.join("\n");
|
|
381
|
+
return `---\n${body}\n---\n`;
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
raw_js_imports = imports => {
|
|
385
|
+
if (!Array.isArray(imports)) {
|
|
386
|
+
console.warn("raw_js_imports: imports must be an array");
|
|
387
|
+
return "";
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (imports.length === 0) {
|
|
391
|
+
console.warn("raw_js_imports: imports array is empty");
|
|
392
|
+
return "";
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return imports
|
|
396
|
+
.map((imp, index) => {
|
|
397
|
+
if (!imp?.name || !imp?.path) {
|
|
398
|
+
console.warn(`raw_js_imports: invalid import entry at index ${index}`);
|
|
399
|
+
return "";
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const path = JSON.stringify(imp.path);
|
|
403
|
+
const newline = index === imports.length - 1 ? "\n\n" : "\n";
|
|
404
|
+
|
|
405
|
+
return `import ${imp.name} from ${path};${newline}`;
|
|
406
|
+
})
|
|
407
|
+
.join("");
|
|
408
|
+
};
|
|
361
409
|
}
|
|
362
410
|
export default Mapper;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sommark",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.1",
|
|
4
4
|
"description": "SomMark is a structural markup language for writing structured documents and converting them into HTML or Markdown or MDX(only ready components).",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|