sommark 3.3.3 → 4.0.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 +98 -82
- package/assets/logo.json +28 -0
- package/assets/smark.logo.png +0 -0
- package/assets/smark.logo.svg +21 -0
- package/cli/cli.mjs +8 -16
- package/cli/commands/build.js +24 -4
- package/cli/commands/color.js +22 -26
- package/cli/commands/help.js +10 -10
- package/cli/commands/init.js +19 -42
- package/cli/commands/print.js +20 -12
- package/cli/commands/show.js +4 -0
- package/cli/commands/version.js +6 -0
- package/cli/constants.js +9 -5
- package/cli/helpers/config.js +11 -0
- package/cli/helpers/file.js +17 -6
- package/cli/helpers/transpile.js +7 -8
- package/core/errors.js +49 -25
- package/core/formats.js +7 -3
- package/core/formatter.js +215 -0
- package/core/helpers/config-loader.js +37 -56
- package/core/labels.js +21 -9
- package/core/lexer.js +491 -212
- package/core/modules.js +164 -0
- package/core/parser.js +516 -389
- package/core/tokenTypes.js +36 -1
- package/core/transpiler.js +237 -151
- package/core/validator.js +79 -0
- package/formatter/mark.js +203 -43
- package/formatter/tag.js +202 -32
- package/grammar.ebnf +57 -50
- package/helpers/colorize.js +26 -13
- package/helpers/escapeHTML.js +13 -6
- package/helpers/kebabize.js +6 -0
- package/helpers/peek.js +9 -0
- package/helpers/removeChar.js +26 -13
- package/helpers/safeDataParser.js +114 -0
- package/helpers/utils.js +140 -158
- package/index.js +198 -188
- package/mappers/languages/html.js +105 -213
- package/mappers/languages/json.js +122 -171
- package/mappers/languages/markdown.js +355 -108
- package/mappers/languages/mdx.js +76 -114
- package/mappers/languages/xml.js +114 -0
- package/mappers/mapper.js +152 -123
- package/mappers/shared/index.js +22 -0
- package/package.json +26 -6
- package/SOMMARK-SPEC.md +0 -481
- package/cli/commands/list.js +0 -124
- package/constants/html_tags.js +0 -146
- package/core/pluginManager.js +0 -149
- package/core/plugins/comment-remover.js +0 -47
- package/core/plugins/module-system.js +0 -176
- package/core/plugins/raw-content-plugin.js +0 -78
- package/core/plugins/rules-validation-plugin.js +0 -231
- package/core/plugins/sommark-format.js +0 -244
- package/coverage_test.js +0 -21
- package/debug.js +0 -15
- package/helpers/camelize.js +0 -2
- package/helpers/defaultTheme.js +0 -3
- package/test_format_fix.js +0 -42
- package/v3-todo.smark +0 -73
package/index.js
CHANGED
|
@@ -6,97 +6,59 @@ import HTML from "./mappers/languages/html.js";
|
|
|
6
6
|
import MARKDOWN from "./mappers/languages/markdown.js";
|
|
7
7
|
import MDX from "./mappers/languages/mdx.js";
|
|
8
8
|
import Json from "./mappers/languages/json.js";
|
|
9
|
-
import
|
|
10
|
-
import MarkdownBuilder from "./formatter/mark.js";
|
|
9
|
+
import XML from "./mappers/languages/xml.js";
|
|
11
10
|
import { runtimeError } from "./core/errors.js";
|
|
12
|
-
import FORMATS, { textFormat, htmlFormat, markdownFormat, mdxFormat, jsonFormat } from "./core/formats.js";
|
|
11
|
+
import FORMATS, { textFormat, htmlFormat, markdownFormat, mdxFormat, jsonFormat, xmlFormat } from "./core/formats.js";
|
|
13
12
|
import TOKEN_TYPES from "./core/tokenTypes.js";
|
|
14
13
|
import * as labels from "./core/labels.js";
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import CommentRemover from "./core/plugins/comment-remover.js";
|
|
19
|
-
import RulesValidationPlugin from "./core/plugins/rules-validation-plugin.js";
|
|
20
|
-
import SomMarkFormat from "./core/plugins/sommark-format.js";
|
|
14
|
+
import { resolveModules } from "./core/modules.js";
|
|
15
|
+
import { formatAST } from "./core/formatter.js";
|
|
16
|
+
import { validateAST } from "./core/validator.js";
|
|
21
17
|
import { enableColor } from "./helpers/colorize.js";
|
|
22
|
-
import {
|
|
18
|
+
import { safeArg } from "./helpers/utils.js";
|
|
23
19
|
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The SomMark Core Engine.
|
|
23
|
+
* Processes SomMark code and turns it into different formats.
|
|
24
|
+
*/
|
|
27
25
|
class SomMark {
|
|
28
|
-
|
|
26
|
+
static Mapper = Mapper;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new SomMark engine.
|
|
29
|
+
*
|
|
30
|
+
* @param {Object} options - Settings for the engine.
|
|
31
|
+
* @param {string} options.src - The SomMark code to process.
|
|
32
|
+
* @param {string} options.format - The final format you want (like 'html' or 'markdown').
|
|
33
|
+
* @param {Mapper|null} [options.mapperFile=null] - Custom rules for formatting.
|
|
34
|
+
* @param {string} [options.filename="anonymous"] - The name of the file, used for errors and settings.
|
|
35
|
+
* @param {boolean} [options.removeComments=true] - If true, comments will be removed from the final code.
|
|
36
|
+
* @param {Object} [options.placeholders={}] - Values to use for {placeholders}.
|
|
37
|
+
* @param {Object} [options.placeholder={}] - Alias for placeholders (backward compatibility).
|
|
38
|
+
* @param {Array<string>} [options.customProps=[]] - Allowed custom HTML attributes.
|
|
39
|
+
* @param {Array<string>} [options.importStack=[]] - Tracking for circular dependencies.
|
|
40
|
+
*/
|
|
41
|
+
constructor({ src, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholder = {}, placeholders = {}, customProps = [], importStack = [] }) {
|
|
29
42
|
this.src = src;
|
|
30
|
-
this.
|
|
43
|
+
this.targetFormat = format;
|
|
31
44
|
this.mapperFile = mapperFile;
|
|
32
|
-
this.priority = priority;
|
|
33
45
|
this.filename = filename;
|
|
46
|
+
this.removeComments = removeComments;
|
|
47
|
+
this.placeholders = { ...placeholder, ...placeholders };
|
|
48
|
+
this.customProps = customProps;
|
|
49
|
+
this.importStack = importStack;
|
|
34
50
|
this.warnings = [];
|
|
35
51
|
this._prepared = false;
|
|
36
52
|
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
let activeBuiltIns = BUILT_IN_PLUGINS.filter(p =>
|
|
40
|
-
!inactiveByDefault.includes(p.name) && !excludePlugins.includes(p.name)
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
// 2. Process 'plugins' array:
|
|
44
|
-
// - If string, look up in BUILT_IN_PLUGINS
|
|
45
|
-
// - If object with { name, options }, it's a built-in override
|
|
46
|
-
// - If object with { plugin, options }, it's an external override
|
|
47
|
-
// - If object without name/plugin but with other keys, it's a direct plugin object
|
|
48
|
-
let processedPlugins = [];
|
|
49
|
-
let manuallyActivatedNames = [];
|
|
50
|
-
|
|
51
|
-
plugins.forEach(p => {
|
|
52
|
-
if (typeof p === "string") {
|
|
53
|
-
const builtIn = BUILT_IN_PLUGINS.find(bp => bp.name === p);
|
|
54
|
-
if (builtIn) {
|
|
55
|
-
processedPlugins.push({ ...builtIn }); // Clone to avoid mutation
|
|
56
|
-
manuallyActivatedNames.push(p);
|
|
57
|
-
}
|
|
58
|
-
} else if (typeof p === "object" && p !== null) {
|
|
59
|
-
if (p.name && p.options && !p.type) {
|
|
60
|
-
// Built-in Override: { name: "raw-content", options: { ... } }
|
|
61
|
-
const builtIn = BUILT_IN_PLUGINS.find(bp => bp.name === p.name);
|
|
62
|
-
if (builtIn) {
|
|
63
|
-
processedPlugins.push({
|
|
64
|
-
...builtIn,
|
|
65
|
-
options: { ...builtIn.options, ...p.options }
|
|
66
|
-
});
|
|
67
|
-
manuallyActivatedNames.push(p.name);
|
|
68
|
-
}
|
|
69
|
-
} else if (p.plugin && p.options) {
|
|
70
|
-
// External Override: { plugin: myPlugin, options: { ... } }
|
|
71
|
-
processedPlugins.push({
|
|
72
|
-
...p.plugin,
|
|
73
|
-
options: { ...p.plugin.options, ...p.options }
|
|
74
|
-
});
|
|
75
|
-
} else {
|
|
76
|
-
// Direct Plugin Object
|
|
77
|
-
processedPlugins.push(p);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// 3. Merge: Default active built-ins (minus ones manually re-added) + Processed Plugins
|
|
83
|
-
const finalPlugins = [
|
|
84
|
-
...activeBuiltIns
|
|
85
|
-
.filter(p => !manuallyActivatedNames.includes(p.name))
|
|
86
|
-
.map(p => ({ ...p })), // Clone defaults for isolation
|
|
87
|
-
...processedPlugins
|
|
88
|
-
];
|
|
89
|
-
|
|
90
|
-
this.plugins = finalPlugins;
|
|
91
|
-
this.pluginManager = new PluginManager(this.plugins, this.priority);
|
|
53
|
+
// Create a random token to safely wrap data
|
|
54
|
+
this.moduleIdentityToken = `$_SM_MOD_${Math.random().toString(36).slice(2, 7)}_$`;
|
|
92
55
|
|
|
93
56
|
this.Mapper = Mapper;
|
|
94
|
-
this.includeDocument = includeDocument;
|
|
95
57
|
|
|
96
|
-
const mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [mdxFormat]: MDX, [jsonFormat]: Json, [textFormat]: new Mapper() };
|
|
58
|
+
const mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [mdxFormat]: MDX, [jsonFormat]: Json, [xmlFormat]: XML, [textFormat]: new Mapper() };
|
|
97
59
|
|
|
98
|
-
if (!this.mapperFile && this.
|
|
99
|
-
const DefaultMapper = mapperFiles[this.
|
|
60
|
+
if (!this.mapperFile && this.targetFormat) {
|
|
61
|
+
const DefaultMapper = mapperFiles[this.targetFormat];
|
|
100
62
|
if (DefaultMapper) {
|
|
101
63
|
this.mapperFile = DefaultMapper.clone();
|
|
102
64
|
}
|
|
@@ -104,17 +66,58 @@ class SomMark {
|
|
|
104
66
|
this.mapperFile = this.mapperFile.clone();
|
|
105
67
|
}
|
|
106
68
|
|
|
69
|
+
if (this.mapperFile) {
|
|
70
|
+
this.mapperFile.options.removeComments = this.removeComments;
|
|
71
|
+
this.mapperFile.options.moduleIdentityToken = this.moduleIdentityToken;
|
|
72
|
+
this.mapperFile.options.filename = this.filename;
|
|
73
|
+
|
|
74
|
+
// Initialize custom props whitelist
|
|
75
|
+
if (this.customProps && this.customProps.length > 0) {
|
|
76
|
+
const props = Array.isArray(this.customProps) ? this.customProps : [this.customProps];
|
|
77
|
+
props.forEach(prop => this.mapperFile.customProps.add(prop));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
107
81
|
this._initializeMappers();
|
|
108
82
|
}
|
|
109
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Backward compatibility alias for placeholders.
|
|
86
|
+
*/
|
|
87
|
+
get placeholder() {
|
|
88
|
+
return this.placeholders;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
set placeholder(val) {
|
|
92
|
+
this.placeholders = val;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Adds a new rule or changes an existing one.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} id - The name of the tag.
|
|
99
|
+
* @param {Function} render - The function that formats the tag.
|
|
100
|
+
* @param {Object} [options] - Extra settings for the tag.
|
|
101
|
+
*/
|
|
110
102
|
register = (id, render, options) => {
|
|
111
103
|
this.mapperFile.register(id, render, options);
|
|
112
104
|
};
|
|
113
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Copies rules from other mappers.
|
|
108
|
+
*
|
|
109
|
+
* @param {...Mapper} mappers - The mappers to copy from.
|
|
110
|
+
*/
|
|
114
111
|
inherit = (...mappers) => {
|
|
115
112
|
this.mapperFile.inherit(...mappers);
|
|
116
113
|
};
|
|
117
114
|
|
|
115
|
+
/**
|
|
116
|
+
* Gets a rule by its name.
|
|
117
|
+
*
|
|
118
|
+
* @param {string} id - The tag name.
|
|
119
|
+
* @returns {Object|null}
|
|
120
|
+
*/
|
|
118
121
|
get = id => {
|
|
119
122
|
return this.mapperFile.get(id);
|
|
120
123
|
};
|
|
@@ -128,18 +131,12 @@ class SomMark {
|
|
|
128
131
|
};
|
|
129
132
|
|
|
130
133
|
_initializeMappers() {
|
|
131
|
-
|
|
132
|
-
const pluginMapper = this.pluginManager.getFormatMapper(this.format);
|
|
133
|
-
if (pluginMapper) {
|
|
134
|
-
this.mapperFile = pluginMapper.clone();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!this.format) {
|
|
134
|
+
if (!this.targetFormat) {
|
|
138
135
|
runtimeError(["{line}<$red:Undefined Format$>: <$yellow:Format argument is not defined.$>{line}"]);
|
|
139
136
|
}
|
|
140
137
|
|
|
141
|
-
if (!this.mapperFile && this.
|
|
142
|
-
runtimeError([`{line}<$red:Unknown Format$>: <$yellow:Mapper for format '${this.
|
|
138
|
+
if (!this.mapperFile && this.targetFormat) {
|
|
139
|
+
runtimeError([`{line}<$red:Unknown Format$>: <$yellow:Mapper for format '${this.targetFormat}' not found.$>{line}`]);
|
|
143
140
|
}
|
|
144
141
|
}
|
|
145
142
|
|
|
@@ -147,149 +144,150 @@ class SomMark {
|
|
|
147
144
|
this.warnings.push(message);
|
|
148
145
|
}
|
|
149
146
|
|
|
150
|
-
|
|
151
|
-
let processed = await this.pluginManager.runPreprocessor(src, "top-level", this);
|
|
152
|
-
|
|
153
|
-
// Helper for async regex replacement
|
|
154
|
-
const asyncReplace = async (str, regex, scope) => {
|
|
155
|
-
if (typeof str !== "string") return str;
|
|
156
|
-
const matches = [...str.matchAll(regex)];
|
|
157
|
-
if (matches.length === 0) return str;
|
|
158
|
-
|
|
159
|
-
// Process all matches in parallel for efficiency
|
|
160
|
-
const replacements = await Promise.all(
|
|
161
|
-
matches.map(async match => {
|
|
162
|
-
// match[2] is the group for content inside quotes/brackets/whatever depending on the regex
|
|
163
|
-
let contentToProcess;
|
|
164
|
-
if (scope === "arguments") contentToProcess = match[2];
|
|
165
|
-
if (scope === "content") contentToProcess = match[2];
|
|
166
|
-
|
|
167
|
-
if (contentToProcess !== undefined) {
|
|
168
|
-
const processedContent = await this.pluginManager.runPreprocessor(contentToProcess, scope, this);
|
|
169
|
-
// Reconstruct the match with processed content
|
|
170
|
-
if (scope === "arguments") return match[0].replace(match[2], processedContent);
|
|
171
|
-
if (scope === "content") return match[0].replace(match[2], processedContent);
|
|
172
|
-
}
|
|
173
|
-
return match[0];
|
|
174
|
-
})
|
|
175
|
-
);
|
|
176
|
-
|
|
177
|
-
// Reconstruct string by replacing matches in order
|
|
178
|
-
let i = 0;
|
|
179
|
-
return str.replace(regex, () => replacements[i++]);
|
|
180
|
-
};
|
|
181
|
-
|
|
182
|
-
// 1. Process Arguments Scope [...]
|
|
183
|
-
const argRegex = /\[\s*([a-zA-Z0-9\-_$]+)\s*(?:=\s*((?:[^"\\\]]|\\[\s\S]|"[^"]*")*))?\s*\]/g;
|
|
184
|
-
processed = await asyncReplace(processed, argRegex, "arguments");
|
|
185
|
-
|
|
186
|
-
// 2. Process Content Scope
|
|
187
|
-
const contentRegex = /(\]\s*)([\s\S]*?)(\s*\[\s*end\s*\])/g;
|
|
188
|
-
processed = await asyncReplace(processed, contentRegex, "content");
|
|
189
|
-
|
|
190
|
-
return processed;
|
|
191
|
-
}
|
|
192
|
-
|
|
147
|
+
|
|
193
148
|
_ensurePrepared() {
|
|
194
149
|
if (this._prepared) return;
|
|
195
150
|
|
|
196
|
-
// 1. Resolve Dynamic Formats from Plugins if built-in failed
|
|
197
|
-
if (!this.mapperFile) {
|
|
198
|
-
const PluginMapper = this.pluginManager.getFormatMapper(this.format);
|
|
199
|
-
if (PluginMapper) {
|
|
200
|
-
this.mapperFile = PluginMapper.clone ? PluginMapper.clone() : PluginMapper;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
151
|
// Final check
|
|
205
152
|
if (!this.mapperFile) {
|
|
206
153
|
runtimeError([
|
|
207
|
-
`{line}<$red:Unknown Format$>: <$yellow:No mapper found for format:$> <$green:'${this.
|
|
208
|
-
`{N}<$yellow:Make sure you have registered
|
|
154
|
+
`{line}<$red:Unknown Format$>: <$yellow:No mapper found for format:$> <$green:'${this.targetFormat}'$>`,
|
|
155
|
+
`{N}<$yellow:Make sure you have registered format mapper correctly.$>{line}`
|
|
209
156
|
]);
|
|
210
157
|
}
|
|
211
158
|
|
|
212
|
-
// Run active registration hooks from plugins
|
|
213
|
-
this.pluginManager.runRegisterHooks(this);
|
|
214
|
-
|
|
215
|
-
// 2. Extend Mapper with static plugins definitions
|
|
216
|
-
const extensions = this.pluginManager.getMapperExtensions();
|
|
217
|
-
if (extensions.outputs.length > 0) {
|
|
218
|
-
for (const out of extensions.outputs) {
|
|
219
|
-
// Support both object {id, render, options} and array [id, render, options]
|
|
220
|
-
if (Array.isArray(out)) {
|
|
221
|
-
const [id, render, options = {}] = out;
|
|
222
|
-
this.register(id, render, options);
|
|
223
|
-
} else if (typeof out === "object" && out !== null) {
|
|
224
|
-
const renderFn = out.register || out.render;
|
|
225
|
-
if (typeof renderFn === "function") {
|
|
226
|
-
this.register(out.id, renderFn, out.options || {});
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Add recognized arguments if provided by plugins
|
|
233
|
-
if (extensions.rules && extensions.rules.recognizedArguments) {
|
|
234
|
-
if (Array.isArray(extensions.rules.recognizedArguments)) {
|
|
235
|
-
extensions.rules.recognizedArguments.forEach(arg => this.mapperFile.extraProps.add(arg));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
159
|
this._prepared = true;
|
|
240
160
|
}
|
|
241
161
|
|
|
162
|
+
/**
|
|
163
|
+
* Breaks the code into small pieces called tokens.
|
|
164
|
+
*
|
|
165
|
+
* @param {string} [src=this.src] - The code to break apart.
|
|
166
|
+
* @returns {Promise<Array<Object>>} - The list of tokens.
|
|
167
|
+
*/
|
|
242
168
|
async lex(src = this.src) {
|
|
243
169
|
this._ensurePrepared();
|
|
244
170
|
if (src !== this.src) this.src = src;
|
|
245
|
-
|
|
246
|
-
let tokens = lexer(processedSrc, this.filename);
|
|
247
|
-
tokens = await this.pluginManager.runAfterLex(tokens);
|
|
171
|
+
let tokens = lexer(this.src, this.filename);
|
|
248
172
|
return tokens;
|
|
249
173
|
}
|
|
250
174
|
|
|
175
|
+
/**
|
|
176
|
+
* Organizes the code into a tree structure.
|
|
177
|
+
* Also handles modules and checks for errors.
|
|
178
|
+
*
|
|
179
|
+
* @param {string} [src=this.src] - Optional source override.
|
|
180
|
+
* @returns {Promise<Array<Object>>} - The final code tree.
|
|
181
|
+
*/
|
|
251
182
|
async parse(src = this.src) {
|
|
252
183
|
const tokens = await this.lex(src);
|
|
253
|
-
let ast = parser(tokens, this.filename);
|
|
254
|
-
|
|
255
|
-
|
|
184
|
+
let ast = parser(tokens, this.filename, this.placeholders);
|
|
185
|
+
|
|
186
|
+
ast = await resolveModules(ast, {
|
|
187
|
+
mapperFile: this.mapperFile,
|
|
256
188
|
filename: this.filename,
|
|
257
|
-
format: this.
|
|
258
|
-
instance: this
|
|
189
|
+
format: this.targetFormat,
|
|
190
|
+
instance: this,
|
|
191
|
+
importStack: this.importStack
|
|
259
192
|
});
|
|
193
|
+
|
|
194
|
+
if (this.mapperFile) {
|
|
195
|
+
validateAST(ast, this.mapperFile, this);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return ast;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
parseSync(src = this.src) {
|
|
202
|
+
this._ensurePrepared();
|
|
203
|
+
if (src !== this.src) this.src = src;
|
|
204
|
+
const tokens = lexer(this.src, this.filename);
|
|
205
|
+
let ast = parser(tokens, this.filename, this.placeholders);
|
|
206
|
+
|
|
207
|
+
if (this.mapperFile) {
|
|
208
|
+
validateAST(ast, this.mapperFile, this);
|
|
209
|
+
}
|
|
210
|
+
|
|
260
211
|
return ast;
|
|
261
212
|
}
|
|
262
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Turns the SomMark code into the final format.
|
|
216
|
+
*
|
|
217
|
+
* @param {string} [src=this.src] - Optional source override.
|
|
218
|
+
* @returns {Promise<string>} - The finished code.
|
|
219
|
+
*/
|
|
263
220
|
async transpile(src = this.src) {
|
|
264
221
|
if (src !== this.src) this.src = src;
|
|
265
222
|
this._ensurePrepared();
|
|
266
223
|
|
|
267
224
|
const ast = await this.parse(src);
|
|
225
|
+
let result = await transpiler({ ast, format: this.targetFormat, mapperFile: this.mapperFile });
|
|
226
|
+
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
268
229
|
|
|
269
|
-
let result = await transpiler({ ast, format: this.format, mapperFile: this.mapperFile, includeDocument: this.includeDocument });
|
|
270
230
|
|
|
271
|
-
|
|
272
|
-
|
|
231
|
+
async format(options = {}) {
|
|
232
|
+
const tokens = await this.lex();
|
|
233
|
+
const ast = parser(tokens, this.filename);
|
|
234
|
+
return formatAST(ast, options);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
formatSync(options = {}) {
|
|
238
|
+
const tokens = lexer(this.src, this.filename);
|
|
239
|
+
const ast = parser(tokens, this.filename);
|
|
240
|
+
return formatAST(ast, options);
|
|
273
241
|
}
|
|
274
242
|
}
|
|
275
243
|
|
|
276
|
-
|
|
277
|
-
|
|
244
|
+
/**
|
|
245
|
+
* A quick way to break code into tokens.
|
|
246
|
+
* Uses HTML settings by default.
|
|
247
|
+
*
|
|
248
|
+
* @param {string} src - The raw SomMark source.
|
|
249
|
+
* @param {string} [filename="anonymous"] - Filename for error context.
|
|
250
|
+
* @returns {Promise<Array<Object>>} - The list of tokens.
|
|
251
|
+
*/
|
|
252
|
+
const lex = async (src, filename = "anonymous") => {
|
|
253
|
+
return await new SomMark({ src, filename, format: htmlFormat }).lex();
|
|
278
254
|
};
|
|
279
255
|
|
|
280
|
-
|
|
256
|
+
/**
|
|
257
|
+
* A quick way to organize code into a tree.
|
|
258
|
+
* Uses HTML settings by default.
|
|
259
|
+
*
|
|
260
|
+
* @param {string} src - The raw SomMark source.
|
|
261
|
+
* @param {string} [filename="anonymous"] - Filename for error context.
|
|
262
|
+
* @returns {Promise<Array<Object>>} - The final code tree.
|
|
263
|
+
*/
|
|
264
|
+
async function parse(src, filename = "anonymous") {
|
|
281
265
|
if (!src) {
|
|
282
266
|
runtimeError([`{line}<$red:Missing Source:$> <$yellow:The 'src' argument is required for parsing.$>{line}`]);
|
|
283
267
|
}
|
|
284
|
-
return await new SomMark({ src, filename,
|
|
268
|
+
return await new SomMark({ src, filename, format: htmlFormat }).parse();
|
|
285
269
|
}
|
|
286
270
|
|
|
271
|
+
/**
|
|
272
|
+
* The easiest way to process SomMark code.
|
|
273
|
+
*
|
|
274
|
+
* @param {Object} options - Transpilation options.
|
|
275
|
+
* @param {string} options.src - Raw source code.
|
|
276
|
+
* @param {string} [options.format="html"] - Target format.
|
|
277
|
+
* @param {string} [options.filename="anonymous"] - Filename for context.
|
|
278
|
+
* @param {Mapper|null} [options.mapperFile=null] - Custom rules for formatting.
|
|
279
|
+
* @param {boolean} [options.removeComments=true] - Strip comments.
|
|
280
|
+
* @param {Object} [options.placeholders={}] - Global placeholders.
|
|
281
|
+
* @param {Object} [options.placeholder={}] - Alias for placeholders.
|
|
282
|
+
* @param {Array<string>} [options.customProps=[]] - Custom attribute whitelist.
|
|
283
|
+
* @returns {Promise<string>} - Transpiled output.
|
|
284
|
+
*/
|
|
287
285
|
async function transpile(options = {}) {
|
|
288
|
-
const { src, format = htmlFormat, filename = "anonymous", mapperFile = null,
|
|
286
|
+
const { src, format = htmlFormat, filename = "anonymous", mapperFile = null, removeComments = true, placeholder = {}, placeholders = {}, customProps = [] } = options;
|
|
289
287
|
if (typeof options !== "object" || options === null) {
|
|
290
288
|
runtimeError([`{line}<$red:Invalid Options:$> <$yellow:The options argument must be a non-null object.$>{line}`]);
|
|
291
289
|
}
|
|
292
|
-
const knownProps = ["src", "format", "filename", "mapperFile", "
|
|
290
|
+
const knownProps = ["src", "format", "filename", "mapperFile", "removeComments", "placeholder", "placeholders", "customProps"];
|
|
293
291
|
Object.keys(options).forEach(key => {
|
|
294
292
|
if (!knownProps.includes(key)) {
|
|
295
293
|
runtimeError([
|
|
@@ -301,13 +299,29 @@ async function transpile(options = {}) {
|
|
|
301
299
|
runtimeError([`{line}<$red:Missing Source:$> <$yellow:The 'src' argument is required for transpilation.$>{line}`]);
|
|
302
300
|
}
|
|
303
301
|
|
|
304
|
-
const sm = new SomMark({ src, format, filename, mapperFile,
|
|
302
|
+
const sm = new SomMark({ src, format, filename, mapperFile, removeComments, placeholder, placeholders, customProps });
|
|
305
303
|
return await sm.transpile();
|
|
306
304
|
}
|
|
307
305
|
|
|
306
|
+
/**
|
|
307
|
+
* A quick, synchronous way to get tokens.
|
|
308
|
+
*
|
|
309
|
+
* @param {string} src - Raw source code.
|
|
310
|
+
* @returns {Array<Object>} - The list of tokens.
|
|
311
|
+
*/
|
|
308
312
|
const lexSync = src => lexer(src);
|
|
309
313
|
|
|
310
|
-
|
|
314
|
+
/**
|
|
315
|
+
* A quick, synchronous way to get the code tree.
|
|
316
|
+
*
|
|
317
|
+
* @param {string} src - Raw source code.
|
|
318
|
+
* @param {Object} [options={}] - Parsing options.
|
|
319
|
+
* @returns {Array<Object>} - The code tree.
|
|
320
|
+
*/
|
|
321
|
+
const parseSync = (src, options = {}) => {
|
|
322
|
+
const { format = htmlFormat, filename = "anonymous", mapperFile = null, removeComments = true, placeholder = {}, placeholders = {}, customProps = [] } = options;
|
|
323
|
+
return new SomMark({ src, format, filename, mapperFile, removeComments, placeholder, placeholders, customProps }).parseSync();
|
|
324
|
+
};
|
|
311
325
|
|
|
312
326
|
import { findAndLoadConfig } from "./core/helpers/config-loader.js";
|
|
313
327
|
|
|
@@ -316,23 +330,19 @@ export {
|
|
|
316
330
|
MARKDOWN,
|
|
317
331
|
MDX,
|
|
318
332
|
Json,
|
|
333
|
+
XML,
|
|
319
334
|
Mapper,
|
|
320
|
-
TagBuilder,
|
|
321
|
-
MarkdownBuilder,
|
|
322
335
|
FORMATS,
|
|
323
336
|
lex,
|
|
324
337
|
parse,
|
|
325
338
|
transpile,
|
|
326
339
|
lexSync,
|
|
327
340
|
parseSync,
|
|
341
|
+
formatAST,
|
|
328
342
|
TOKEN_TYPES,
|
|
329
343
|
labels,
|
|
330
344
|
enableColor,
|
|
331
|
-
htmlTable,
|
|
332
|
-
list,
|
|
333
|
-
parseList,
|
|
334
345
|
safeArg,
|
|
335
|
-
todo,
|
|
336
346
|
findAndLoadConfig
|
|
337
347
|
};
|
|
338
348
|
export default SomMark;
|