sommark 3.3.4 → 4.0.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/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 +7 -17
- package/cli/commands/build.js +26 -6
- package/cli/commands/color.js +22 -26
- package/cli/commands/help.js +10 -10
- package/cli/commands/init.js +20 -31
- package/cli/commands/print.js +18 -16
- 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 +15 -17
- package/core/errors.js +49 -25
- package/core/formats.js +7 -3
- package/core/formatter.js +215 -0
- package/core/helpers/config-loader.js +40 -75
- 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 +238 -154
- 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/dedent.js +19 -0
- 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 +186 -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 -120
- 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,58 @@ 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 {Array<string>} [options.customProps=[]] - Allowed custom HTML attributes.
|
|
38
|
+
* @param {Array<string>} [options.importStack=[]] - Tracking for circular dependencies.
|
|
39
|
+
*/
|
|
40
|
+
constructor({ src, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], importStack = [] }) {
|
|
29
41
|
this.src = src;
|
|
30
|
-
this.
|
|
42
|
+
this.targetFormat = format;
|
|
31
43
|
this.mapperFile = mapperFile;
|
|
32
|
-
this.priority = priority;
|
|
33
44
|
this.filename = filename;
|
|
45
|
+
this.removeComments = removeComments;
|
|
46
|
+
this.placeholders = placeholders;
|
|
47
|
+
this.customProps = customProps;
|
|
48
|
+
this.importStack = importStack;
|
|
34
49
|
this.warnings = [];
|
|
35
50
|
this._prepared = false;
|
|
36
51
|
|
|
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);
|
|
52
|
+
// Create a random token to safely wrap data
|
|
53
|
+
this.moduleIdentityToken = `$_SM_MOD_${Math.random().toString(36).slice(2, 7)}_$`;
|
|
92
54
|
|
|
93
55
|
this.Mapper = Mapper;
|
|
94
|
-
this.includeDocument = includeDocument;
|
|
95
56
|
|
|
96
|
-
const mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [mdxFormat]: MDX, [jsonFormat]: Json, [textFormat]: new Mapper() };
|
|
57
|
+
const mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [mdxFormat]: MDX, [jsonFormat]: Json, [xmlFormat]: XML, [textFormat]: new Mapper() };
|
|
97
58
|
|
|
98
|
-
if (!this.mapperFile && this.
|
|
99
|
-
const DefaultMapper = mapperFiles[this.
|
|
59
|
+
if (!this.mapperFile && this.targetFormat) {
|
|
60
|
+
const DefaultMapper = mapperFiles[this.targetFormat];
|
|
100
61
|
if (DefaultMapper) {
|
|
101
62
|
this.mapperFile = DefaultMapper.clone();
|
|
102
63
|
}
|
|
@@ -104,17 +65,48 @@ class SomMark {
|
|
|
104
65
|
this.mapperFile = this.mapperFile.clone();
|
|
105
66
|
}
|
|
106
67
|
|
|
68
|
+
if (this.mapperFile) {
|
|
69
|
+
this.mapperFile.options.removeComments = this.removeComments;
|
|
70
|
+
this.mapperFile.options.moduleIdentityToken = this.moduleIdentityToken;
|
|
71
|
+
this.mapperFile.options.filename = this.filename;
|
|
72
|
+
|
|
73
|
+
// Initialize custom props whitelist
|
|
74
|
+
if (this.customProps && this.customProps.length > 0) {
|
|
75
|
+
const props = Array.isArray(this.customProps) ? this.customProps : [this.customProps];
|
|
76
|
+
props.forEach(prop => this.mapperFile.customProps.add(prop));
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
107
80
|
this._initializeMappers();
|
|
108
81
|
}
|
|
109
82
|
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Adds a new rule or changes an existing one.
|
|
86
|
+
*
|
|
87
|
+
* @param {string} id - The name of the tag.
|
|
88
|
+
* @param {Function} render - The function that formats the tag.
|
|
89
|
+
* @param {Object} [options] - Extra settings for the tag.
|
|
90
|
+
*/
|
|
110
91
|
register = (id, render, options) => {
|
|
111
92
|
this.mapperFile.register(id, render, options);
|
|
112
93
|
};
|
|
113
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Copies rules from other mappers.
|
|
97
|
+
*
|
|
98
|
+
* @param {...Mapper} mappers - The mappers to copy from.
|
|
99
|
+
*/
|
|
114
100
|
inherit = (...mappers) => {
|
|
115
101
|
this.mapperFile.inherit(...mappers);
|
|
116
102
|
};
|
|
117
103
|
|
|
104
|
+
/**
|
|
105
|
+
* Gets a rule by its name.
|
|
106
|
+
*
|
|
107
|
+
* @param {string} id - The tag name.
|
|
108
|
+
* @returns {Object|null}
|
|
109
|
+
*/
|
|
118
110
|
get = id => {
|
|
119
111
|
return this.mapperFile.get(id);
|
|
120
112
|
};
|
|
@@ -128,18 +120,12 @@ class SomMark {
|
|
|
128
120
|
};
|
|
129
121
|
|
|
130
122
|
_initializeMappers() {
|
|
131
|
-
|
|
132
|
-
const pluginMapper = this.pluginManager.getFormatMapper(this.format);
|
|
133
|
-
if (pluginMapper) {
|
|
134
|
-
this.mapperFile = pluginMapper.clone();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (!this.format) {
|
|
123
|
+
if (!this.targetFormat) {
|
|
138
124
|
runtimeError(["{line}<$red:Undefined Format$>: <$yellow:Format argument is not defined.$>{line}"]);
|
|
139
125
|
}
|
|
140
126
|
|
|
141
|
-
if (!this.mapperFile && this.
|
|
142
|
-
runtimeError([`{line}<$red:Unknown Format$>: <$yellow:Mapper for format '${this.
|
|
127
|
+
if (!this.mapperFile && this.targetFormat) {
|
|
128
|
+
runtimeError([`{line}<$red:Unknown Format$>: <$yellow:Mapper for format '${this.targetFormat}' not found.$>{line}`]);
|
|
143
129
|
}
|
|
144
130
|
}
|
|
145
131
|
|
|
@@ -147,149 +133,149 @@ class SomMark {
|
|
|
147
133
|
this.warnings.push(message);
|
|
148
134
|
}
|
|
149
135
|
|
|
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
|
-
|
|
136
|
+
|
|
193
137
|
_ensurePrepared() {
|
|
194
138
|
if (this._prepared) return;
|
|
195
139
|
|
|
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
140
|
// Final check
|
|
205
141
|
if (!this.mapperFile) {
|
|
206
142
|
runtimeError([
|
|
207
|
-
`{line}<$red:Unknown Format$>: <$yellow:No mapper found for format:$> <$green:'${this.
|
|
208
|
-
`{N}<$yellow:Make sure you have registered
|
|
143
|
+
`{line}<$red:Unknown Format$>: <$yellow:No mapper found for format:$> <$green:'${this.targetFormat}'$>`,
|
|
144
|
+
`{N}<$yellow:Make sure you have registered format mapper correctly.$>{line}`
|
|
209
145
|
]);
|
|
210
146
|
}
|
|
211
147
|
|
|
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
148
|
this._prepared = true;
|
|
240
149
|
}
|
|
241
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Breaks the code into small pieces called tokens.
|
|
153
|
+
*
|
|
154
|
+
* @param {string} [src=this.src] - The code to break apart.
|
|
155
|
+
* @returns {Promise<Array<Object>>} - The list of tokens.
|
|
156
|
+
*/
|
|
242
157
|
async lex(src = this.src) {
|
|
243
158
|
this._ensurePrepared();
|
|
244
159
|
if (src !== this.src) this.src = src;
|
|
245
|
-
|
|
246
|
-
let tokens = lexer(processedSrc, this.filename);
|
|
247
|
-
tokens = await this.pluginManager.runAfterLex(tokens);
|
|
160
|
+
let tokens = lexer(this.src, this.filename);
|
|
248
161
|
return tokens;
|
|
249
162
|
}
|
|
250
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Organizes the code into a tree structure.
|
|
166
|
+
* Also handles modules and checks for errors.
|
|
167
|
+
*
|
|
168
|
+
* @param {string} [src=this.src] - Optional source override.
|
|
169
|
+
* @returns {Promise<Array<Object>>} - The final code tree.
|
|
170
|
+
*/
|
|
251
171
|
async parse(src = this.src) {
|
|
252
172
|
const tokens = await this.lex(src);
|
|
253
|
-
let ast = parser(tokens, this.filename);
|
|
254
|
-
|
|
255
|
-
|
|
173
|
+
let ast = parser(tokens, this.filename, this.placeholders);
|
|
174
|
+
|
|
175
|
+
ast = await resolveModules(ast, {
|
|
176
|
+
mapperFile: this.mapperFile,
|
|
256
177
|
filename: this.filename,
|
|
257
|
-
format: this.
|
|
258
|
-
instance: this
|
|
178
|
+
format: this.targetFormat,
|
|
179
|
+
instance: this,
|
|
180
|
+
importStack: this.importStack
|
|
259
181
|
});
|
|
182
|
+
|
|
183
|
+
if (this.mapperFile) {
|
|
184
|
+
validateAST(ast, this.mapperFile, this);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return ast;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
parseSync(src = this.src) {
|
|
191
|
+
this._ensurePrepared();
|
|
192
|
+
if (src !== this.src) this.src = src;
|
|
193
|
+
const tokens = lexer(this.src, this.filename);
|
|
194
|
+
let ast = parser(tokens, this.filename, this.placeholders);
|
|
195
|
+
|
|
196
|
+
if (this.mapperFile) {
|
|
197
|
+
validateAST(ast, this.mapperFile, this);
|
|
198
|
+
}
|
|
199
|
+
|
|
260
200
|
return ast;
|
|
261
201
|
}
|
|
262
202
|
|
|
203
|
+
/**
|
|
204
|
+
* Turns the SomMark code into the final format.
|
|
205
|
+
*
|
|
206
|
+
* @param {string} [src=this.src] - Optional source override.
|
|
207
|
+
* @returns {Promise<string>} - The finished code.
|
|
208
|
+
*/
|
|
263
209
|
async transpile(src = this.src) {
|
|
264
210
|
if (src !== this.src) this.src = src;
|
|
265
211
|
this._ensurePrepared();
|
|
266
212
|
|
|
267
213
|
const ast = await this.parse(src);
|
|
214
|
+
let result = await transpiler({ ast, format: this.targetFormat, mapperFile: this.mapperFile });
|
|
215
|
+
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
268
218
|
|
|
269
|
-
let result = await transpiler({ ast, format: this.format, mapperFile: this.mapperFile, includeDocument: this.includeDocument });
|
|
270
219
|
|
|
271
|
-
|
|
272
|
-
|
|
220
|
+
async format(options = {}) {
|
|
221
|
+
const tokens = await this.lex();
|
|
222
|
+
const ast = parser(tokens, this.filename);
|
|
223
|
+
return formatAST(ast, options);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
formatSync(options = {}) {
|
|
227
|
+
const tokens = lexer(this.src, this.filename);
|
|
228
|
+
const ast = parser(tokens, this.filename);
|
|
229
|
+
return formatAST(ast, options);
|
|
273
230
|
}
|
|
274
231
|
}
|
|
275
232
|
|
|
276
|
-
|
|
277
|
-
|
|
233
|
+
/**
|
|
234
|
+
* A quick way to break code into tokens.
|
|
235
|
+
* Uses HTML settings by default.
|
|
236
|
+
*
|
|
237
|
+
* @param {string} src - The raw SomMark source.
|
|
238
|
+
* @param {string} [filename="anonymous"] - Filename for error context.
|
|
239
|
+
* @returns {Promise<Array<Object>>} - The list of tokens.
|
|
240
|
+
*/
|
|
241
|
+
const lex = async (src, filename = "anonymous") => {
|
|
242
|
+
return await new SomMark({ src, filename, format: htmlFormat }).lex();
|
|
278
243
|
};
|
|
279
244
|
|
|
280
|
-
|
|
245
|
+
/**
|
|
246
|
+
* A quick way to organize code into a tree.
|
|
247
|
+
* Uses HTML settings by default.
|
|
248
|
+
*
|
|
249
|
+
* @param {string} src - The raw SomMark source.
|
|
250
|
+
* @param {string} [filename="anonymous"] - Filename for error context.
|
|
251
|
+
* @returns {Promise<Array<Object>>} - The final code tree.
|
|
252
|
+
*/
|
|
253
|
+
async function parse(src, filename = "anonymous") {
|
|
281
254
|
if (!src) {
|
|
282
255
|
runtimeError([`{line}<$red:Missing Source:$> <$yellow:The 'src' argument is required for parsing.$>{line}`]);
|
|
283
256
|
}
|
|
284
|
-
return await new SomMark({ src, filename,
|
|
257
|
+
return await new SomMark({ src, filename, format: htmlFormat }).parse();
|
|
285
258
|
}
|
|
286
259
|
|
|
260
|
+
/**
|
|
261
|
+
* The easiest way to process SomMark code.
|
|
262
|
+
*
|
|
263
|
+
* @param {Object} options - Transpilation options.
|
|
264
|
+
* @param {string} options.src - Raw source code.
|
|
265
|
+
* @param {string} [options.format="html"] - Target format.
|
|
266
|
+
* @param {string} [options.filename="anonymous"] - Filename for context.
|
|
267
|
+
* @param {Mapper|null} [options.mapperFile=null] - Custom rules for formatting.
|
|
268
|
+
* @param {boolean} [options.removeComments=true] - Strip comments.
|
|
269
|
+
* @param {Object} [options.placeholders={}] - Global placeholders.
|
|
270
|
+
* @param {Array<string>} [options.customProps=[]] - Custom attribute whitelist.
|
|
271
|
+
* @returns {Promise<string>} - Transpiled output.
|
|
272
|
+
*/
|
|
287
273
|
async function transpile(options = {}) {
|
|
288
|
-
const { src, format = htmlFormat, filename = "anonymous", mapperFile = null,
|
|
274
|
+
const { src, format = htmlFormat, filename = "anonymous", mapperFile = null, removeComments = true, placeholders = {}, customProps = [] } = options;
|
|
289
275
|
if (typeof options !== "object" || options === null) {
|
|
290
276
|
runtimeError([`{line}<$red:Invalid Options:$> <$yellow:The options argument must be a non-null object.$>{line}`]);
|
|
291
277
|
}
|
|
292
|
-
const knownProps = ["src", "format", "filename", "mapperFile", "
|
|
278
|
+
const knownProps = ["src", "format", "filename", "mapperFile", "removeComments", "placeholders", "customProps"];
|
|
293
279
|
Object.keys(options).forEach(key => {
|
|
294
280
|
if (!knownProps.includes(key)) {
|
|
295
281
|
runtimeError([
|
|
@@ -301,13 +287,29 @@ async function transpile(options = {}) {
|
|
|
301
287
|
runtimeError([`{line}<$red:Missing Source:$> <$yellow:The 'src' argument is required for transpilation.$>{line}`]);
|
|
302
288
|
}
|
|
303
289
|
|
|
304
|
-
const sm = new SomMark({ src, format, filename, mapperFile,
|
|
290
|
+
const sm = new SomMark({ src, format, filename, mapperFile, removeComments, placeholders, customProps });
|
|
305
291
|
return await sm.transpile();
|
|
306
292
|
}
|
|
307
293
|
|
|
294
|
+
/**
|
|
295
|
+
* A quick, synchronous way to get tokens.
|
|
296
|
+
*
|
|
297
|
+
* @param {string} src - Raw source code.
|
|
298
|
+
* @returns {Array<Object>} - The list of tokens.
|
|
299
|
+
*/
|
|
308
300
|
const lexSync = src => lexer(src);
|
|
309
301
|
|
|
310
|
-
|
|
302
|
+
/**
|
|
303
|
+
* A quick, synchronous way to get the code tree.
|
|
304
|
+
*
|
|
305
|
+
* @param {string} src - Raw source code.
|
|
306
|
+
* @param {Object} [options={}] - Parsing options.
|
|
307
|
+
* @returns {Array<Object>} - The code tree.
|
|
308
|
+
*/
|
|
309
|
+
const parseSync = (src, options = {}) => {
|
|
310
|
+
const { format = htmlFormat, filename = "anonymous", mapperFile = null, removeComments = true, placeholders = {}, customProps = [] } = options;
|
|
311
|
+
return new SomMark({ src, format, filename, mapperFile, removeComments, placeholders, customProps }).parseSync();
|
|
312
|
+
};
|
|
311
313
|
|
|
312
314
|
import { findAndLoadConfig } from "./core/helpers/config-loader.js";
|
|
313
315
|
|
|
@@ -316,23 +318,19 @@ export {
|
|
|
316
318
|
MARKDOWN,
|
|
317
319
|
MDX,
|
|
318
320
|
Json,
|
|
321
|
+
XML,
|
|
319
322
|
Mapper,
|
|
320
|
-
TagBuilder,
|
|
321
|
-
MarkdownBuilder,
|
|
322
323
|
FORMATS,
|
|
323
324
|
lex,
|
|
324
325
|
parse,
|
|
325
326
|
transpile,
|
|
326
327
|
lexSync,
|
|
327
328
|
parseSync,
|
|
329
|
+
formatAST,
|
|
328
330
|
TOKEN_TYPES,
|
|
329
331
|
labels,
|
|
330
332
|
enableColor,
|
|
331
|
-
htmlTable,
|
|
332
|
-
list,
|
|
333
|
-
parseList,
|
|
334
333
|
safeArg,
|
|
335
|
-
todo,
|
|
336
334
|
findAndLoadConfig
|
|
337
335
|
};
|
|
338
336
|
export default SomMark;
|