sommark 4.0.3 → 4.2.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.
Files changed (43) hide show
  1. package/README.md +304 -73
  2. package/cli/cli.mjs +1 -1
  3. package/cli/commands/build.js +3 -1
  4. package/cli/commands/help.js +2 -0
  5. package/cli/commands/init.js +25 -6
  6. package/cli/constants.js +2 -1
  7. package/cli/helpers/transpile.js +5 -2
  8. package/constants/html_props.js +1 -0
  9. package/core/evaluator.js +1061 -0
  10. package/core/formats.js +15 -7
  11. package/core/helpers/config-loader.js +16 -8
  12. package/core/helpers/lib.js +72 -0
  13. package/core/helpers/preprocessor.js +202 -0
  14. package/core/helpers/runtimeOutput.js +28 -0
  15. package/core/helpers/url.js +12 -0
  16. package/core/labels.js +9 -2
  17. package/core/lexer.js +228 -61
  18. package/core/modules.js +338 -60
  19. package/core/parser.js +275 -55
  20. package/core/tokenTypes.js +11 -0
  21. package/core/transpiler.js +352 -66
  22. package/core/validator.js +70 -7
  23. package/formatter/tag.js +31 -7
  24. package/grammar.ebnf +21 -10
  25. package/helpers/fetch-fs.js +37 -0
  26. package/helpers/safeDataParser.js +3 -3
  27. package/helpers/spinner.js +97 -0
  28. package/helpers/utils.js +46 -0
  29. package/helpers/virtual-fs.js +29 -0
  30. package/index.browser.js +87 -0
  31. package/index.js +23 -332
  32. package/index.shared.js +443 -0
  33. package/mappers/languages/html.js +50 -9
  34. package/mappers/languages/json.js +81 -38
  35. package/mappers/languages/jsonc.js +82 -0
  36. package/mappers/languages/markdown.js +88 -48
  37. package/mappers/languages/mdx.js +50 -15
  38. package/mappers/languages/text.js +67 -0
  39. package/mappers/languages/xml.js +6 -6
  40. package/mappers/mapper.js +36 -4
  41. package/mappers/shared/index.js +12 -13
  42. package/package.json +11 -2
  43. package/core/formatter.js +0 -215
package/README.md CHANGED
@@ -1,134 +1,365 @@
1
- # SomMark v4 <img src="assets/smark.logo.png" width="80" align="right">
1
+ # SomMark <img src="assets/smark.logo.png" width="80" align="right">
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/sommark.svg)](https://www.npmjs.com/package/sommark)
4
+ [![Browser Support](https://img.shields.io/badge/browser-supported-brightgreen)](https://www.npmjs.com/package/sommark)
5
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://nodejs.org)
4
6
  [![license](https://img.shields.io/npm/l/sommark.svg)](https://github.com/Adam-Elmi/SomMark/blob/master/LICENSE)
5
7
 
6
8
  SomMark is a high-performance markup language designed for structured content. It acts as an extensible source language that can be transformed into multiple formats like HTML, JSON, MDX, XML, and Markdown.
7
9
 
8
10
  SomMark uses explicit structural boundaries to ensure your document remains stable and predictable. It enables infinite nesting and provides total control over your contents.
9
11
 
12
+ > **v4.2.0 — Browser Support**: SomMark now compiles templates directly in the browser with no Node.js dependencies. Use the `sommark/browser` entry point with any bundler (Vite, Webpack, Rollup, esbuild). See [Browser API docs](docs/api/Browser/) for `resolveBaseDir` and `renderCompiledHTML`.
13
+
14
+ ---
15
+
16
+ ## Install
17
+
18
+ #### 1. Global (Command Line)
19
+ Install SomMark globally to use the `sommark` command.
20
+ ```bash
21
+ npm install -g sommark
22
+ ```
23
+
24
+ To verify it is working, check the version:
25
+ ```bash
26
+ sommark --version
27
+ ```
28
+
29
+ #### 2. Local (Project API)
30
+ Add SomMark to your project as a dependency:
31
+ ```bash
32
+ npm install sommark
33
+ ```
34
+
10
35
  ---
11
36
 
12
- ## Simple Showcase
37
+ ## Features
13
38
 
14
- SomMark uses blocks for structure. A block starts with `[identifier]` and must end with `[end]`.
39
+ ### Blocks
40
+
41
+ Blocks are the primary containers in SomMark, used to group, style, and organize structural content. A block starts with `[identifier]` and closes with a matching `[end]` or self-closing `!` if the block does not have any content, for example `[br!]` or `[img = src: "logo.png" !]`.
15
42
 
16
- ### HTML
17
43
  ```ini
18
- [h1]Welcome to SomMark[end]
44
+ [div = class: "container"]
45
+ [h1]Welcome to SomMark[end]
46
+ [p]Structured content, zero guesswork.[end]
47
+ [hr = class: "divider" !]
48
+ [end]
49
+ ```
50
+ [Read more about blocks](./docs/syntax/block.md)
19
51
 
20
- [div = class: "main"]
21
- This is content inside a container block.
22
- [p]
23
- Blocks are the most important part of SomMark.
24
- (This is a span-like inline statement)->(css: "color: green")
25
- [end]
52
+ ### Self-Closing Blocks
53
+
54
+ Blocks that carry no body content close instantly with `!`.
55
+
56
+ ```ini
57
+ [br!]
58
+ [hr = class: "divider" !]
59
+ [img = src: "logo.png", alt: "SomMark Logo" !]
60
+ ```
61
+ [Read more about self-closing blocks](./docs/syntax/self-closing.md)
62
+
63
+ ### Inline Elements
64
+
65
+ Apply styling or formatting to specific spans of text within a block using `(inline text)->(identifier = args)` or `(inline text)->(identifier: args)`. Internal newlines and duplicate spaces are automatically collapsed into a single space.
66
+
67
+ ```ini
68
+ [p]
69
+ This is (important text)->(bold).
70
+ Visit the (SomMark Website)->(link = "https://sommark.org", target: "_blank").
26
71
  [end]
27
72
  ```
73
+ [Read more about inline elements](./docs/syntax/inline.md)
74
+
75
+ ### Props (Properties)
76
+
77
+ Pass metadata (called **Props**, similar to component properties in React/Vue) to Blocks, Inline Elements, and At-Blocks. SomMark supports positional, named, and mixed props with multiple value types (JS data, placeholders, and variables).
78
+
79
+ > [!NOTE]
80
+ > In the current major version, SomMark passes these properties under the **`args`** key to custom JavaScript `render` functions for backward compatibility. This will be renamed to `props` in the next major version.
81
+
82
+ * **Blocks**: Passed after `=` (e.g., `[div = "container"][end]`).
83
+ * **Inline Elements**: Passed after `=` or `:` inside the identifier parenthesis (e.g., `(text)->(link = "url")`).
84
+ * **At-Blocks**: Passed after `:` and terminated with `;` (e.g., `@_code: lang: "js";`).
85
+
86
+ **Blocks** — props come after `=`, separated by commas. Positional args have no key; named args use `key: value`.
87
+ ```ini
88
+ [div = "container", class: "flex"][end]
89
+ # ↑ positional ↑ named
90
+ ```
28
91
 
29
- ### JSON
30
- SomMark can represent complex data structures through its specialized mappers.
92
+ **Inline Elements** — same prop syntax, after `=` or `:` inside the identifier.
31
93
  ```ini
32
- [object]
33
- [string = key: "name"]Adam Elmi[end]
34
- [number = key: "age"]25[end]
35
- [array = key: "skills"]
36
- [string]JavaScript[end]
37
- [string]SomMark[end]
38
- [end]
94
+ (Visit Website)->(link = "https://sommark.org", target: "_blank")
95
+ # ↑ positional url ↑ named prop
96
+ ```
97
+
98
+ **At-Blocks** — props follow `:` on the opening line and are terminated with `;`. The body is captured as raw text.
99
+ ```ini
100
+ @_code: lang: "js", active: js{true}, user: v{userId};
101
+ # ↑ string ↑ native JS value ↑ local variable
102
+ console.log("Hello World");
103
+ @_end_@
104
+ ```
105
+
106
+ **Static logic as a prop value** — any prop value can be a compile-time expression.
107
+ ```ini
108
+ [Date = year: static ${ new Date().getFullYear() }$][end]
109
+ ```
110
+
111
+ ### At-Blocks -- Raw Content
112
+
113
+ At-blocks capture raw text. Brackets, tags, and comments inside them are treated as literal characters and never parsed.
114
+
115
+ ```ini
116
+ @_code_@: lang: "javascript";
117
+ const items = [1, 2, 3];
118
+ // This [div] won't be parsed
119
+ @_end_@
120
+ ```
121
+
122
+ ### Comments
123
+
124
+ Single-line and multi-line. Completely removed from the compiled output.
125
+
126
+ ```ini
127
+ # This is a single-line comment
128
+
129
+ ###
130
+ This is a multi-line comment.
131
+ Nothing here reaches the output.
132
+ ###
133
+ ```
134
+
135
+ ### Static Logic -- Compile-Time JavaScript
136
+
137
+ Run JavaScript during compilation inside a sandboxed QuickJS VM. The result replaces the block inline.
138
+
139
+ ```ini
140
+ [footer]
141
+ Copyright static ${ new Date().getFullYear() }$
39
142
  [end]
40
143
  ```
41
144
 
42
- ### XML
43
- SomMark produces clean, structured XML ideal for configuration and data manifests.
145
+ Use it in props too:
146
+
44
147
  ```ini
45
- [xml = version: "1.0"][end]
46
- [project = name: "SomMark-App"]
47
- [metadata]
48
- [author]Adam Elmi[end]
49
- [version]4.0.0[end]
50
- [end]
51
- [settings]
52
- [database = type: "postgres"]
53
- [host]localhost[end]
54
- [port]5432[end]
55
- [end]
56
- [end]
148
+ [Date = year: static ${ new Date().getFullYear() }$][end]
149
+ ```
150
+
151
+ ### Runtime Logic -- Client-Side JavaScript
152
+
153
+ Preserve JavaScript in the compiled output. It runs in the browser, not during compilation.
154
+
155
+ ```ini
156
+ [button]
157
+ runtime ${
158
+ self.addEventListener("click", () => alert("Hello from SomMark"))
159
+ }$
160
+ Click Me
57
161
  [end]
58
162
  ```
59
163
 
60
- ### MDX
61
- Use the JavaScript data layer to pass native data to your components.
164
+ ### For-Each Loop
165
+
166
+ Iterate over arrays and render blocks for each item. Access the current item and its index.
167
+
62
168
  ```ini
63
- [h1]MDX Portfolio[end]
169
+ [for-each = static ${ [{name: "Adam"}, {name: "Hawa"}, {name: "Ilham"}] }$, as: "user"]
170
+ [li]static ${ user.name }$ -- position static ${ user_index }$[end]
171
+ [end]
172
+ ```
173
+
174
+ ### Modules and Components
175
+
176
+ Split your project into reusable `.smark` files. Import them, pass props, and inject body content through slots.
64
177
 
65
- [Gallery =
66
- images: js{["nature.jpg", "tech.jpg"]},
67
- active: js{true}
68
- ]
69
- This block uses native JS arrays and booleans.
178
+ **`components/Card.smark`**
179
+ ```ini
180
+ [div = class: "card"]
181
+ [h2]v{title}[end]
182
+ [div = class: "card-body"]
183
+ [slot][end]
184
+ [end]
70
185
  [end]
71
186
  ```
72
187
 
73
- ### Markdown
74
- Use placeholders to inject dynamic text into your templates.
188
+ **`page.smark`**
75
189
  ```ini
76
- [h1]Hello p{username}[end]
190
+ [import = Card: "./components/Card.smark"][end]
77
191
 
78
- [quote]
79
- You are reading documentation on p{siteName}.
80
- SomMark is an extensible language.
192
+ [Card = title: "Featured Product"]
193
+ This content fills the slot inside the card.
81
194
  [end]
195
+ ```
196
+
197
+ You can also inject a module without passing body content:
82
198
 
83
- [hr][end]
199
+ ```ini
200
+ [import = Card: "./components/Card.smark"][end]
201
+ [$use-module = Card][end]
84
202
  ```
85
203
 
86
204
  ---
87
205
 
88
- ## How It Works
89
-
90
- SomMark is an extensible language that processes content through a four-stage pipeline:
206
+ ## Output Formats
91
207
 
92
- 1. **Lexing**: The engine scans the source and converts it into a stream of tokens.
93
- 2. **Parsing**: Tokens are organized into a hierarchical tree called an **AST** (Abstract Syntax Tree).
94
- 3. **Mapping**: This is the translation layer. You define how identifiers (like `[h1]`) look in the target language.
95
- 4. **Transpilation**: The engine walks the AST and uses the Mapper to generate the final string output.
208
+ Write once, compile to any of these:
96
209
 
97
- The **Module System** enables a "Declare-then-Inject" pattern, allowing you to import mappers and create scalable projects with full recursive support.
210
+ | Format | CLI Flag | Extension |
211
+ |----------|--------------|-----------|
212
+ | HTML | `--html` | `.html` |
213
+ | Markdown | `--markdown` | `.md` |
214
+ | MDX | `--mdx` | `.mdx` |
215
+ | JSON | `--json` | `.json` |
216
+ | JSONC | `--jsonc` | `.jsonc` |
217
+ | XML | `--xml` | `.xml` |
218
+ | Text | `--text` | `.txt` |
98
219
 
99
220
  ---
100
221
 
101
- ## Installation
102
-
103
- Install the SomMark CLI globally:
222
+ ## CLI
104
223
 
105
- ```bash
106
- npm install -g sommark
224
+ ```
225
+ sommark init Create a smark.config.js file
226
+ sommark --html <file> Compile to HTML
227
+ sommark --markdown <file> Compile to Markdown
228
+ sommark --html <file> -o <name> <dir> Set output filename and directory
229
+ sommark --html --print <file> Print compiled output to terminal
230
+ sommark --lex <file> Show the token stream
231
+ sommark --parse <file> Show the syntax tree
232
+ sommark show config [file] Show the resolved configuration
233
+ sommark -v Show version
234
+ sommark -h Show help
107
235
  ```
108
236
 
109
237
  ---
110
238
 
111
- ## Usage in Node.js
239
+ ## Programmatic Usage
112
240
 
113
- ```javascript
241
+ **Node.js**
242
+ ```js
114
243
  import SomMark from "sommark";
115
244
 
116
- const sm = new SomMark({
117
- src: "[h1]Hello World[end]",
118
- format: "html"
245
+ const engine = new SomMark({
246
+ src: '[h1]Hello World[end]',
247
+ format: "html",
119
248
  });
120
249
 
121
- const output = await sm.transpile();
250
+ const output = await engine.transpile();
122
251
  // <h1>Hello World</h1>
123
252
  ```
124
253
 
254
+ **Browser** (v4.2.0+)
255
+ ```js
256
+ import SomMark, { resolveBaseDir, renderCompiledHTML } from "sommark/browser";
257
+
258
+ const src = await fetch("./main.smark").then(r => r.text());
259
+
260
+ const engine = new SomMark({
261
+ src,
262
+ format: "html",
263
+ baseDir: resolveBaseDir("./templates/"), // resolves imports via fetch
264
+ });
265
+
266
+ renderCompiledHTML(document.getElementById("output"), await engine.transpile());
267
+ ```
268
+
269
+ ---
270
+
271
+ ## Configuration
272
+
273
+ Run `sommark init` to generate a `smark.config.js` with all available settings:
274
+
275
+ ```js
276
+ export default {
277
+ format: "html",
278
+ removeComments: true,
279
+ generateRuntimeOutput: false,
280
+ hideRuntimeOutput: false,
281
+ customProps: [],
282
+ placeholders: {},
283
+ importAliases: { "@": "./" },
284
+ fallbackTarget: "style",
285
+ outputValidator: null,
286
+ baseDir: null,
287
+ showSpinner: true,
288
+ security: {
289
+ allowRaw: true,
290
+ maxDepth: 5,
291
+ timeout: 5000,
292
+ allowFetch: true,
293
+ allowHttp: false,
294
+ allowedOrigins: [],
295
+ allowedExtensions: [],
296
+ sanitize: null,
297
+ },
298
+ outputDir: "./",
299
+ outputFile: "output",
300
+ };
301
+ ```
302
+
303
+ ---
304
+
305
+ ## Security
306
+
307
+ All embedded JavaScript runs inside a **QuickJS sandbox** with strict restrictions:
308
+
309
+ | Setting | Default | What it does |
310
+ |---------------------|---------|----------------------------------------------|
311
+ | `allowRaw` | `true` | Allow raw code in static blocks |
312
+ | `maxDepth` | `5` | Maximum import nesting depth |
313
+ | `timeout` | `5000` | Script execution time limit (ms) |
314
+ | `allowFetch` | `true` | Allow network requests from scripts |
315
+ | `allowHttp` | `false` | Block insecure HTTP (HTTPS only by default) |
316
+ | `allowedOrigins` | `null` | Restrict fetch to specific domains |
317
+ | `allowedExtensions` | `null` | Restrict which file types can be imported |
318
+ | `sanitize` | `null` | Custom function to sanitize HTML output |
319
+
320
+ ---
321
+
322
+ ## Custom Output Rules
323
+
324
+ Define your own tags and rendering logic with the Mapper API:
325
+
326
+ ```js
327
+ import SomMark, { Mapper } from "sommark";
328
+
329
+ const mapper = new Mapper("custom");
330
+
331
+ mapper.register("alert", (node) => {
332
+ return `<div class="alert">${node.body}</div>`;
333
+ });
334
+
335
+ const engine = new SomMark({
336
+ src: '[alert]Check your configuration.[end]',
337
+ format: "html",
338
+ mapperFile: mapper,
339
+ });
340
+
341
+ const output = await engine.transpile();
342
+ ```
343
+
344
+ Full reference in [`docs/api/Mapper`](docs/api/Mapper).
345
+
125
346
  ---
126
347
 
127
348
  ## Documentation
128
349
 
129
- Read the full guides in the `docs/` folder:
350
+ | Topic | Location |
351
+ |------------------|-----------------------------------------------|
352
+ | Syntax Reference | [`docs/syntax/`](docs/syntax) |
353
+ | Core API | [`docs/api/Core/`](docs/api/Core) |
354
+ | Browser API | [`docs/api/Browser/`](docs/api/Browser) |
355
+ | Mapper API | [`docs/api/Mapper/`](docs/api/Mapper) |
356
+ | Sandbox API | [`docs/api/Sandbox/`](docs/api/Sandbox) |
357
+ | Output Formats | [`docs/languages/`](docs/languages) |
358
+ | CLI Guide | [`docs/cli/`](docs/cli) |
359
+ | Configuration | [`docs/cli/config.md`](docs/cli/config.md) |
360
+
361
+ ---
362
+
363
+ ## License
130
364
 
131
- * **[Syntax Guide](docs/syntax/syntax.md)**: Rules for writing Blocks, At-Blocks, and Inlines.
132
- * **[Core Logic](docs/core/core.md)**: Deep dive into the engine architecture.
133
- * **[Mapper API](docs/core/mapper.md)**: How to create your own translation layers.
134
- * **[Module System](docs/core/module-system.md)**: Managing multi-file projects.
365
+ [MIT](LICENSE) -- Adam Elmi
package/cli/cli.mjs CHANGED
@@ -70,7 +70,7 @@ async function main() {
70
70
  runColor(args[1]);
71
71
  return;
72
72
  }
73
-
73
+
74
74
 
75
75
  // 6. Lex
76
76
  if (command === "--lex") {
@@ -5,7 +5,9 @@ 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
7
  import Json from "../../mappers/languages/json.js";
8
+ import Jsonc from "../../mappers/languages/jsonc.js";
8
9
  import XML from "../../mappers/languages/xml.js";
10
+ import TEXT from "../../mappers/languages/text.js";
9
11
  import { extensions } from "../constants.js";
10
12
  import { isExist, readContent, createFile } from "../helpers/file.js";
11
13
  import { loadConfig } from "../helpers/config.js";
@@ -78,7 +80,7 @@ export async function runBuild(format_option, sourcePath, outputFlag, outputFile
78
80
  let mapperFile = config.mapperFile || config.mappingFile;
79
81
 
80
82
  if (!mapperFile) {
81
- mapperFile = format === "html" ? HTML : format === "markdown" ? MARKDOWN : format === "mdx" ? MDX : format === "json" ? Json : format === "xml" ? XML : null;
83
+ mapperFile = format === "html" ? HTML : format === "markdown" ? MARKDOWN : format === "mdx" ? MDX : format === "json" ? Json : format === "jsonc" ? Jsonc : format === "xml" ? XML : format === "text" ? TEXT : null;
82
84
  }
83
85
 
84
86
  // CLI Overrides
@@ -28,7 +28,9 @@ export function getHelp(unknown_option = true) {
28
28
  "{N} <$green:--html$> <$cyan: Transpile to HTML$>",
29
29
  "{N} <$green:--markdown$> <$cyan: Transpile to Markdown$>",
30
30
  "{N} <$green:--mdx$> <$cyan: Transpile to MDX$>",
31
+ "{N} <$green:--xml$> <$cyan: Transpile to XML$>",
31
32
  "{N} <$green:--json$> <$cyan: Transpile to JSON$>",
33
+ "{N} <$green:--jsonc$> <$cyan: Transpile to JSON with Comments (JSONC)$>",
32
34
  "{N} <$green:--text$> <$cyan: Transpile to plain text$>",
33
35
  "{N} <$green:--lex$> <$cyan: Print lexer tokens to console$>",
34
36
  "{N} <$green:--parse$> <$cyan: Print parser AST to console$>",
@@ -19,12 +19,31 @@ export async function runInit() {
19
19
  * Generated by 'smark init'
20
20
  */
21
21
  export default {
22
- format: "html", // Target output format (html, markdown, mdx, json, xml)
23
- removeComments: true, // Strip SomMark comments from the final output
24
- customProps: [], // Whitelisted HTML attributes (prevents CSS hijacking)
25
- placeholders: {}, // Global p{key} variables for content injection
26
- outputDir: "./", // Where to save the transpiled files
27
- outputFile: "output", // Default output filename
22
+ format: "html", // Target output format (html, markdown, mdx, json, xml, jsonc, text)
23
+ removeComments: true, // Strip SomMark comments from the final output
24
+ generateRuntimeOutput: false, // Generate only VM script bundles, ignoring markup layouts
25
+ hideRuntimeOutput: false, // Strip all <script> tags from final compiled HTML outputs
26
+ customProps: [], // Whitelisted HTML attributes
27
+ placeholders: {}, // Global p{key} placeholders for content injection
28
+ importAliases: { // Custom path aliases for modules (e.g. { "@": "./src/components" })
29
+ "@": "./"
30
+ },
31
+ fallbackTarget: "style", // Where unrecognized attributes go: "style", "class", or false to disable
32
+ outputValidator: null, // Custom callback function: async (transpiledOutput) => { ... }
33
+ baseDir: null, // Base directory for resolving relative module imports
34
+ showSpinner: true, // Display a dynamic spinner in the terminal during transpilation
35
+ security: { // Sandbox and security restrictions for module execution
36
+ allowRaw: true, // Permit raw code blocks in static logic blocks
37
+ maxDepth: 5, // Maximum allowed import nesting depth
38
+ timeout: 5000, // Timeout in milliseconds for scripts to execute
39
+ allowFetch: true, // Allow fetch queries inside runtime logic block execution
40
+ allowHttp: false, // Disallow http requests (highly recommended to keep false)
41
+ allowedOrigins: [], // Whitelisted HTTP origins/domains for fetch requests (e.g. ["api.github.com"])
42
+ allowedExtensions: [], // Whitelisted file extensions for local module imports (e.g. [".smark", ".json"])
43
+ sanitize: null, // Custom output HTML string sanitization function: (html) => { ... }
44
+ },
45
+ outputDir: "./", // Where to save the transpiled files
46
+ outputFile: "output", // Default output filename
28
47
  };
29
48
  `;
30
49
 
package/cli/constants.js CHANGED
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  /** @type {Array<string>} List of recognized CLI flags and commands. */
7
- export const options = ["-v", "--version", "-h", "--help", "--html", "--markdown", "--mdx", "--json", "--text", "--xml", "--print", "-p", "--lex", "--parse", "list"];
7
+ export const options = ["-v", "--version", "-h", "--help", "--html", "--markdown", "--mdx", "--json", "--jsonc", "--text", "--xml", "--print", "-p", "--lex", "--parse", "list"];
8
8
 
9
9
  /** @type {Object<string, string>} Map of output formats to their respective file extensions. */
10
10
  export const extensions = {
@@ -13,5 +13,6 @@ export const extensions = {
13
13
  markdown: "md",
14
14
  mdx: "mdx",
15
15
  json: "json",
16
+ jsonc: "jsonc",
16
17
  xml: "xml"
17
18
  };
@@ -6,11 +6,13 @@ 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 Jsonc from "../../mappers/languages/jsonc.js";
10
+ import XML from "../../mappers/languages/xml.js";
9
11
  import { isExist } from "./file.js";
10
12
  import { loadConfig } from "./config.js";
11
- import { htmlFormat, markdownFormat, mdxFormat, jsonFormat, textFormat } from "../../core/formats.js";
13
+ import { htmlFormat, markdownFormat, mdxFormat, jsonFormat, jsoncFormat, xmlFormat, textFormat } from "../../core/formats.js";
12
14
 
13
- const default_mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [mdxFormat]: MDX, [jsonFormat]: Json, [textFormat]: null };
15
+ const default_mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [mdxFormat]: MDX, [jsonFormat]: Json, [jsoncFormat]: Jsonc, [xmlFormat]: XML, [textFormat]: null };
14
16
 
15
17
  // ========================================================================== //
16
18
  // Transpile Function //
@@ -50,6 +52,7 @@ export async function transpile({ src, format, filename = null, mapperFile = "",
50
52
  format,
51
53
  filename,
52
54
  mapperFile: finalMapper,
55
+ showSpinner: finalConfig.showSpinner !== false
53
56
  });
54
57
 
55
58
  return await smark.transpile();
@@ -36,6 +36,7 @@ export const HTML_PROPS = new Set([
36
36
  "decoding",
37
37
  "crossorigin",
38
38
  "charset",
39
+ "content",
39
40
  "action",
40
41
  "method",
41
42
  "enctype",