sommark 4.5.2 → 5.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 +314 -178
- package/cli/cli.mjs +1 -1
- package/cli/commands/color.js +36 -14
- package/cli/commands/help.js +3 -0
- package/cli/commands/init.js +0 -2
- package/cli/constants.js +5 -2
- package/constants/html_props.js +66 -1
- package/constants/svg_elements.js +31 -0
- package/core/errors.js +5 -4
- package/core/evaluator.js +1 -2
- package/core/formats.js +7 -1
- package/core/helpers/config-loader.js +1 -3
- package/core/helpers/lib.js +1 -1
- package/core/labels.js +2 -15
- package/core/lexer.js +197 -313
- package/core/modules.js +13 -13
- package/core/parser.js +226 -535
- package/core/tokenTypes.js +6 -15
- package/core/transpiler.js +129 -110
- package/core/validator.js +6 -26
- package/dist/sommark.browser.js +1939 -2223
- package/dist/sommark.browser.lite.js +1937 -2220
- package/dist/sommark.lexer.js +392 -544
- package/dist/sommark.parser.js +604 -1200
- package/formatter/mark.js +34 -0
- package/formatter/tag.js +7 -33
- package/helpers/utils.js +15 -16
- package/index.js +9 -1
- package/index.shared.js +22 -12
- package/mappers/languages/csv.js +62 -0
- package/mappers/languages/html.js +21 -69
- package/mappers/languages/json.js +74 -156
- package/mappers/languages/jsonc.js +21 -63
- package/mappers/languages/markdown.js +159 -276
- package/mappers/languages/mdx.js +7 -62
- package/mappers/languages/text.js +2 -19
- package/mappers/languages/toml.js +231 -0
- package/mappers/languages/xml.js +25 -25
- package/mappers/languages/yaml.js +323 -0
- package/mappers/mapper.js +1 -22
- package/mappers/shared/index.js +3 -16
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -5,280 +5,417 @@
|
|
|
5
5
|
[](https://nodejs.org)
|
|
6
6
|
[](https://github.com/Adam-Elmi/SomMark/blob/master/LICENSE)
|
|
7
7
|
|
|
8
|
-
SomMark is a
|
|
8
|
+
**SomMark** is a template language that compiles to multiple output formats — HTML, JSON, YAML, TOML, CSV, Markdown, XML, and more.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Write your content once with a single consistent block syntax. Add loops, compile-time logic, and file imports. Compile to whatever format your project needs.
|
|
11
11
|
|
|
12
|
-
> **
|
|
12
|
+
> **v5 is the official stable release and the recommended version to start with.**
|
|
13
|
+
> SomMark has reached its main goal — a single consistent block syntax that compiles to any output format. v5 is the last major version. Future releases will be minor updates or patches.
|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
16
17
|
## Install
|
|
17
18
|
|
|
18
|
-
#### 1. Global (Command Line)
|
|
19
|
-
Install SomMark globally to use the `sommark` command.
|
|
20
19
|
```bash
|
|
20
|
+
# CLI
|
|
21
21
|
npm install -g sommark
|
|
22
|
+
|
|
23
|
+
# Use it with your project
|
|
24
|
+
npm install sommark
|
|
22
25
|
```
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Showcase
|
|
30
|
+
|
|
31
|
+
**`team.smark`** (HTML mapper)
|
|
32
|
+
|
|
33
|
+
```ini
|
|
34
|
+
[import = Card: "./components/Card.smark" !]
|
|
35
|
+
|
|
36
|
+
${
|
|
37
|
+
const team = [
|
|
38
|
+
{ name: "Adam", role: "Founder", avatar: "adam.jpg" },
|
|
39
|
+
{ name: "Hawa", role: "Engineer", avatar: "hawa.jpg" },
|
|
40
|
+
{ name: "Ilham", role: "Designer", avatar: "ilham.jpg" },
|
|
41
|
+
];
|
|
42
|
+
const year = new Date().getFullYear();
|
|
43
|
+
}$
|
|
44
|
+
|
|
45
|
+
[main = class: "team-page"]
|
|
46
|
+
[h1]Our Team[end:h1]
|
|
47
|
+
|
|
48
|
+
[section = class: "grid"]
|
|
49
|
+
[for-each = ${ team }$, as: "member"]
|
|
50
|
+
[Card = name: ${ member.name }$, role: ${ member.role }$]
|
|
51
|
+
[img = src: ${ member.avatar }$, alt: ${ member.name }$ !]
|
|
52
|
+
[end:Card]
|
|
53
|
+
[end:for-each]
|
|
54
|
+
[end:section]
|
|
55
|
+
|
|
56
|
+
[footer]© ${ year }$ SomMark[end:footer]
|
|
57
|
+
[end:main]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**`components/Card.smark`**
|
|
61
|
+
|
|
62
|
+
```ini
|
|
63
|
+
[div = class: "card"]
|
|
64
|
+
[h2]v{name}[end:h2]
|
|
65
|
+
[p]v{role}[end:p]
|
|
66
|
+
[slot!]
|
|
67
|
+
[end:div]
|
|
27
68
|
```
|
|
28
69
|
|
|
29
|
-
#### 2. Local (Project API)
|
|
30
|
-
Add SomMark to your project as a dependency:
|
|
31
70
|
```bash
|
|
32
|
-
|
|
71
|
+
sommark --html team.smark
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<main class="team-page">
|
|
76
|
+
<h1>Our Team</h1>
|
|
77
|
+
<section class="grid">
|
|
78
|
+
<div class="card">
|
|
79
|
+
<h2>Adam</h2>
|
|
80
|
+
<p>Founder</p>
|
|
81
|
+
<img src="adam.jpg" alt="Adam">
|
|
82
|
+
</div>
|
|
83
|
+
<div class="card">
|
|
84
|
+
<h2>Hawa</h2>
|
|
85
|
+
<p>Engineer</p>
|
|
86
|
+
<img src="hawa.jpg" alt="Hawa">
|
|
87
|
+
</div>
|
|
88
|
+
<div class="card">
|
|
89
|
+
<h2>Ilham</h2>
|
|
90
|
+
<p>Designer</p>
|
|
91
|
+
<img src="ilham.jpg" alt="Ilham">
|
|
92
|
+
</div>
|
|
93
|
+
</section>
|
|
94
|
+
<footer>© 2026 SomMark</footer>
|
|
95
|
+
</main>
|
|
33
96
|
```
|
|
34
97
|
|
|
35
98
|
---
|
|
36
99
|
|
|
100
|
+
## Output formats
|
|
101
|
+
|
|
102
|
+
| Format | CLI Flag |
|
|
103
|
+
| -------- | -------------- |
|
|
104
|
+
| HTML | `--html` |
|
|
105
|
+
| Markdown | `--markdown` |
|
|
106
|
+
| MDX | `--mdx` |
|
|
107
|
+
| JSON | `--json` |
|
|
108
|
+
| JSONC | `--jsonc` |
|
|
109
|
+
| YAML | `--yaml` |
|
|
110
|
+
| TOML | `--toml` |
|
|
111
|
+
| CSV | `--csv` |
|
|
112
|
+
| XML | `--xml` |
|
|
113
|
+
| Text | `--text` |
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
37
117
|
## Features
|
|
38
118
|
|
|
39
119
|
### Blocks
|
|
40
120
|
|
|
41
|
-
|
|
121
|
+
Every tag is a block. Open with `[name]`, close with `[end:name]`. A plain `[end]` also works, but `[end:name]` is recommended for readability.
|
|
42
122
|
|
|
43
123
|
```ini
|
|
44
|
-
[
|
|
45
|
-
[h1]
|
|
46
|
-
[p]Structured content, zero guesswork.[end]
|
|
47
|
-
[hr
|
|
48
|
-
[end]
|
|
124
|
+
[article = class: "post"]
|
|
125
|
+
[h1]Hello, SomMark[end:h1]
|
|
126
|
+
[p]Structured content, zero guesswork.[end:p]
|
|
127
|
+
[hr!]
|
|
128
|
+
[end:article]
|
|
49
129
|
```
|
|
50
|
-
[Read more about blocks](./docs/syntax/block.md)
|
|
51
|
-
|
|
52
|
-
### Self-Closing Blocks
|
|
53
130
|
|
|
54
|
-
|
|
131
|
+
Self-closing blocks carry no body — append `!` inside the tag:
|
|
55
132
|
|
|
56
133
|
```ini
|
|
57
134
|
[br!]
|
|
58
|
-
[
|
|
59
|
-
[
|
|
135
|
+
[img = src: "logo.png", alt: "Logo" !]
|
|
136
|
+
[input = type: "text", name: "email" !]
|
|
60
137
|
```
|
|
61
|
-
[Read more about self-closing blocks](./docs/syntax/self-closing.md)
|
|
62
138
|
|
|
63
|
-
###
|
|
139
|
+
### Compile-time JavaScript
|
|
64
140
|
|
|
65
|
-
|
|
141
|
+
`${ }$` runs JavaScript at build time inside a sandboxed QuickJS VM. The `static` keyword is optional — `${ expr }$` and `static ${ expr }$` are identical.
|
|
142
|
+
|
|
143
|
+
The example below targets the **HTML mapper**:
|
|
66
144
|
|
|
67
145
|
```ini
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
146
|
+
${
|
|
147
|
+
import pkg from "./package.json";
|
|
148
|
+
const built = new Date().toISOString();
|
|
149
|
+
}$
|
|
150
|
+
|
|
151
|
+
[footer]
|
|
152
|
+
${ pkg.name }$ v${ pkg.version }$ — built ${ built }$
|
|
153
|
+
[end:footer]
|
|
72
154
|
```
|
|
73
|
-
[Read more about inline elements](./docs/syntax/inline.md)
|
|
74
155
|
|
|
75
|
-
|
|
156
|
+
Variables declared in one `${ }$` block are available in all blocks that follow in the same file.
|
|
76
157
|
|
|
77
|
-
|
|
158
|
+
### Loops
|
|
78
159
|
|
|
79
|
-
|
|
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.
|
|
160
|
+
`[for-each]` iterates over any array. The current item is accessed via the `as:` alias. `${ i }$` gives the zero-based index.
|
|
81
161
|
|
|
82
|
-
|
|
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";`).
|
|
162
|
+
The example below targets the **HTML mapper**:
|
|
85
163
|
|
|
86
|
-
**Blocks** — props come after `=`, separated by commas. Positional args have no key; named args use `key: value`.
|
|
87
164
|
```ini
|
|
88
|
-
|
|
89
|
-
|
|
165
|
+
${
|
|
166
|
+
const links = ["Home", "Docs", "Blog", "Contact"];
|
|
167
|
+
}$
|
|
168
|
+
|
|
169
|
+
[nav]
|
|
170
|
+
[ul]
|
|
171
|
+
[for-each = ${ links }$, as: "link"]
|
|
172
|
+
[li][a = href: "#"]${ link }$[end:a][end:li]
|
|
173
|
+
[end:for-each]
|
|
174
|
+
[end:ul]
|
|
175
|
+
[end:nav]
|
|
90
176
|
```
|
|
91
177
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
#
|
|
178
|
+
```html
|
|
179
|
+
<nav>
|
|
180
|
+
<ul>
|
|
181
|
+
<li><a href="#">Home</a></li>
|
|
182
|
+
<li><a href="#">Docs</a></li>
|
|
183
|
+
<li><a href="#">Blog</a></li>
|
|
184
|
+
<li><a href="#">Contact</a></li>
|
|
185
|
+
</ul>
|
|
186
|
+
</nav>
|
|
96
187
|
```
|
|
97
188
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
@_end_@
|
|
104
|
-
```
|
|
189
|
+
### Shorthand key-value for data formats
|
|
190
|
+
|
|
191
|
+
When targeting JSON, YAML, or TOML, write key-value pairs using the tag name as the key. Type is inferred automatically — numbers stay numbers, `true`/`false` become booleans, everything else becomes a string.
|
|
192
|
+
|
|
193
|
+
The example below targets the **JSON mapper**:
|
|
105
194
|
|
|
106
|
-
**Static logic as a prop value** — any prop value can be a compile-time expression.
|
|
107
195
|
```ini
|
|
108
|
-
[
|
|
196
|
+
[Object]
|
|
197
|
+
[username = "Adam" !]
|
|
198
|
+
[age = 25 !]
|
|
199
|
+
[score = 9.8 !]
|
|
200
|
+
[isAdmin = false !]
|
|
201
|
+
[deletedAt = null !]
|
|
202
|
+
[end:Object]
|
|
109
203
|
```
|
|
110
204
|
|
|
111
|
-
|
|
205
|
+
```json
|
|
206
|
+
{
|
|
207
|
+
"username": "Adam",
|
|
208
|
+
"age": 25,
|
|
209
|
+
"score": 9.8,
|
|
210
|
+
"isAdmin": false,
|
|
211
|
+
"deletedAt": null
|
|
212
|
+
}
|
|
213
|
+
```
|
|
112
214
|
|
|
113
|
-
|
|
215
|
+
Body form also works — useful for longer values:
|
|
114
216
|
|
|
115
217
|
```ini
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
@_end_@
|
|
218
|
+
[Object]
|
|
219
|
+
[bio]Software developer based in Hargeisa.[end:bio]
|
|
220
|
+
[end:Object]
|
|
120
221
|
```
|
|
121
222
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
Single-line and multi-line. Completely removed from the compiled output.
|
|
223
|
+
Generate config from data with a loop. The example below targets the **YAML mapper**:
|
|
125
224
|
|
|
126
225
|
```ini
|
|
127
|
-
|
|
226
|
+
${
|
|
227
|
+
const services = [
|
|
228
|
+
{ name: "api", port: 8080, replicas: 3 },
|
|
229
|
+
{ name: "worker", port: 8081, replicas: 2 },
|
|
230
|
+
];
|
|
231
|
+
}$
|
|
232
|
+
|
|
233
|
+
[seq = "services"]
|
|
234
|
+
[for-each = ${ services }$, as: "s"]
|
|
235
|
+
[map-item]
|
|
236
|
+
[name = ${ s.name }$ !]
|
|
237
|
+
[port = ${ s.port }$ !]
|
|
238
|
+
[replicas = ${ s.replicas }$ !]
|
|
239
|
+
[end:map-item]
|
|
240
|
+
[end:for-each]
|
|
241
|
+
[end:seq]
|
|
242
|
+
```
|
|
128
243
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
244
|
+
```yaml
|
|
245
|
+
services:
|
|
246
|
+
- name: "api"
|
|
247
|
+
port: 8080
|
|
248
|
+
replicas: 3
|
|
249
|
+
- name: "worker"
|
|
250
|
+
port: 8081
|
|
251
|
+
replicas: 2
|
|
133
252
|
```
|
|
134
253
|
|
|
135
|
-
###
|
|
254
|
+
### Placeholders
|
|
255
|
+
|
|
256
|
+
Inject values at build time from your JavaScript config using `p{}`. Add a fallback with `|` in case a value is not set.
|
|
136
257
|
|
|
137
|
-
|
|
258
|
+
The example below targets the **HTML mapper**:
|
|
138
259
|
|
|
139
260
|
```ini
|
|
140
|
-
[
|
|
141
|
-
|
|
142
|
-
[end]
|
|
143
|
-
```
|
|
261
|
+
[div = class: "env-badge"]
|
|
262
|
+
Environment: p{NODE_ENV}
|
|
263
|
+
[end:div]
|
|
144
264
|
|
|
145
|
-
|
|
265
|
+
[footer]Built with p{engine | "SomMark"}[end:footer]
|
|
266
|
+
```
|
|
146
267
|
|
|
147
|
-
```
|
|
148
|
-
|
|
268
|
+
```js
|
|
269
|
+
new SomMark({
|
|
270
|
+
src,
|
|
271
|
+
format: "html",
|
|
272
|
+
placeholders: { NODE_ENV: "production" }
|
|
273
|
+
});
|
|
149
274
|
```
|
|
150
275
|
|
|
151
|
-
###
|
|
276
|
+
### Module system
|
|
277
|
+
|
|
278
|
+
Split templates into reusable `.smark` files. All `[import]` declarations must appear at the top of the file.
|
|
152
279
|
|
|
153
|
-
|
|
280
|
+
**Static injection** — insert a module with no props or body content:
|
|
154
281
|
|
|
155
282
|
```ini
|
|
156
|
-
[
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
[
|
|
283
|
+
[import = Nav: "./components/Nav.smark" !]
|
|
284
|
+
[import = Footer: "./components/Footer.smark" !]
|
|
285
|
+
|
|
286
|
+
[body]
|
|
287
|
+
[$use-module = Nav !]
|
|
288
|
+
[main]
|
|
289
|
+
[p]Page content.[end:p]
|
|
290
|
+
[end:main]
|
|
291
|
+
[$use-module = Footer !]
|
|
292
|
+
[end:body]
|
|
162
293
|
```
|
|
163
294
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Iterate over arrays and render blocks for each item. Access the current item and its index.
|
|
295
|
+
**Component block** — pass props and body content. Inside the component, `v{}` reads the props and `[slot]` marks where the body goes:
|
|
167
296
|
|
|
168
297
|
```ini
|
|
169
|
-
[
|
|
170
|
-
[li]static ${ user.name }$ -- position static ${ user_index }$[end]
|
|
171
|
-
[end]
|
|
172
|
-
```
|
|
298
|
+
[import = Card: "./components/Card.smark" !]
|
|
173
299
|
|
|
174
|
-
|
|
300
|
+
[Card = title: "Featured Post"]
|
|
301
|
+
This content fills the slot inside the card.
|
|
302
|
+
[end:Card]
|
|
303
|
+
```
|
|
175
304
|
|
|
176
|
-
|
|
305
|
+
`Card.smark`:
|
|
177
306
|
|
|
178
|
-
**`components/Card.smark`**
|
|
179
307
|
```ini
|
|
180
308
|
[div = class: "card"]
|
|
181
|
-
[h2]v{title}[end]
|
|
182
|
-
[div = class: "
|
|
183
|
-
[slot]
|
|
184
|
-
[end]
|
|
185
|
-
[end]
|
|
309
|
+
[h2]v{title}[end:h2]
|
|
310
|
+
[div = class: "body"]
|
|
311
|
+
[slot!]
|
|
312
|
+
[end:div]
|
|
313
|
+
[end:div]
|
|
186
314
|
```
|
|
187
315
|
|
|
188
|
-
|
|
189
|
-
```ini
|
|
190
|
-
[import = Card: "./components/Card.smark"][end]
|
|
191
|
-
|
|
192
|
-
[Card = title: "Featured Product"]
|
|
193
|
-
This content fills the slot inside the card.
|
|
194
|
-
[end]
|
|
195
|
-
```
|
|
316
|
+
### Comments
|
|
196
317
|
|
|
197
|
-
|
|
318
|
+
Completely removed at build time — never appear in the output:
|
|
198
319
|
|
|
199
320
|
```ini
|
|
200
|
-
|
|
201
|
-
|
|
321
|
+
# single-line comment
|
|
322
|
+
|
|
323
|
+
###
|
|
324
|
+
multi-line comment
|
|
325
|
+
write as much as you need
|
|
326
|
+
###
|
|
202
327
|
```
|
|
203
328
|
|
|
204
329
|
---
|
|
205
330
|
|
|
206
|
-
##
|
|
331
|
+
## CLI
|
|
207
332
|
|
|
208
|
-
|
|
333
|
+
### Global
|
|
209
334
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
| Text | `--text` | `.txt` |
|
|
335
|
+
```bash
|
|
336
|
+
sommark -h, --help # show help message
|
|
337
|
+
sommark -v, --version # show version
|
|
338
|
+
sommark init # generate smark.config.js
|
|
339
|
+
sommark show config [file] # show resolved config
|
|
340
|
+
sommark show --path-config [file] # show path to active config file
|
|
341
|
+
sommark color on|off # help on enabling terminal colors
|
|
342
|
+
```
|
|
219
343
|
|
|
220
|
-
|
|
344
|
+
### Transpile
|
|
221
345
|
|
|
222
|
-
|
|
346
|
+
```bash
|
|
347
|
+
sommark --html input.smark # compile to HTML
|
|
348
|
+
sommark --markdown input.smark # compile to Markdown
|
|
349
|
+
sommark --mdx input.smark # compile to MDX
|
|
350
|
+
sommark --xml input.smark # compile to XML
|
|
351
|
+
sommark --json input.smark # compile to JSON
|
|
352
|
+
sommark --jsonc input.smark # compile to JSONC
|
|
353
|
+
sommark --toml input.smark # compile to TOML
|
|
354
|
+
sommark --yaml input.smark # compile to YAML
|
|
355
|
+
sommark --csv input.smark # compile to CSV
|
|
356
|
+
sommark --text input.smark # compile to plain text
|
|
357
|
+
sommark --lex input.smark # print lexer token stream
|
|
358
|
+
sommark --parse input.smark # print parser AST
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Output
|
|
223
362
|
|
|
363
|
+
```bash
|
|
364
|
+
sommark --html -p input.smark # print output to console
|
|
365
|
+
sommark --html input.smark -o name ./dir/ # set output filename and directory
|
|
224
366
|
```
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
sommark
|
|
230
|
-
sommark --
|
|
231
|
-
sommark
|
|
232
|
-
sommark
|
|
233
|
-
sommark -v Show version
|
|
234
|
-
sommark -h Show help
|
|
367
|
+
|
|
368
|
+
### Browser bundle
|
|
369
|
+
|
|
370
|
+
```bash
|
|
371
|
+
sommark bundle ./dist/ # copy full bundle (JS + WASM)
|
|
372
|
+
sommark bundle ./dist/ --lite # lite bundle — no WASM
|
|
373
|
+
sommark bundle ./dist/ --only-lexer # lexer only
|
|
374
|
+
sommark bundle ./dist/ --only-parser # lexer + parser only
|
|
235
375
|
```
|
|
236
376
|
|
|
237
377
|
---
|
|
238
378
|
|
|
239
|
-
## Programmatic
|
|
379
|
+
## Programmatic API
|
|
240
380
|
|
|
241
381
|
**Node.js**
|
|
242
382
|
```js
|
|
243
383
|
import SomMark from "sommark";
|
|
244
384
|
|
|
245
|
-
const
|
|
246
|
-
src
|
|
385
|
+
const sm = new SomMark({
|
|
386
|
+
src,
|
|
247
387
|
format: "html",
|
|
388
|
+
placeholders: { title: "My App" }
|
|
248
389
|
});
|
|
249
390
|
|
|
250
|
-
const output = await
|
|
251
|
-
// <h1>Hello World</h1>
|
|
391
|
+
const output = await sm.transpile();
|
|
252
392
|
```
|
|
253
393
|
|
|
254
|
-
**Browser**
|
|
394
|
+
**Browser**
|
|
255
395
|
```js
|
|
256
396
|
import SomMark, { resolveBaseDir, renderCompiledHTML } from "sommark/browser";
|
|
257
397
|
|
|
258
398
|
const src = await fetch("./main.smark").then(r => r.text());
|
|
259
399
|
|
|
260
|
-
const
|
|
400
|
+
const sm = new SomMark({
|
|
261
401
|
src,
|
|
262
402
|
format: "html",
|
|
263
|
-
baseDir: resolveBaseDir("./templates/"),
|
|
403
|
+
baseDir: resolveBaseDir("./templates/"),
|
|
264
404
|
});
|
|
265
405
|
|
|
266
|
-
renderCompiledHTML(document.getElementById("
|
|
406
|
+
renderCompiledHTML(document.getElementById("app"), await sm.transpile());
|
|
267
407
|
```
|
|
268
408
|
|
|
269
409
|
---
|
|
270
410
|
|
|
271
411
|
## Configuration
|
|
272
412
|
|
|
273
|
-
Run `sommark init` to generate
|
|
413
|
+
Run `sommark init` to generate `smark.config.js`:
|
|
274
414
|
|
|
275
415
|
```js
|
|
276
416
|
export default {
|
|
277
417
|
format: "html",
|
|
278
418
|
removeComments: true,
|
|
279
|
-
generateRuntimeOutput: false,
|
|
280
|
-
hideRuntimeOutput: false,
|
|
281
|
-
customProps: [],
|
|
282
419
|
placeholders: {},
|
|
283
420
|
importAliases: { "@": "./" },
|
|
284
421
|
fallbackTarget: "style",
|
|
@@ -304,62 +441,61 @@ export default {
|
|
|
304
441
|
|
|
305
442
|
## Security
|
|
306
443
|
|
|
307
|
-
All
|
|
444
|
+
All `${ }$` expressions run inside a **QuickJS sandbox** — isolated from the host process:
|
|
308
445
|
|
|
309
|
-
| Setting | Default |
|
|
310
|
-
|
|
311
|
-
| `allowRaw` | `true` | Allow
|
|
312
|
-
| `maxDepth` | `5` | Maximum import nesting depth
|
|
313
|
-
| `timeout` | `5000` |
|
|
314
|
-
| `allowFetch` | `true` | Allow network requests from scripts
|
|
315
|
-
| `allowHttp` | `false` | Block
|
|
316
|
-
| `allowedOrigins` | `
|
|
317
|
-
| `allowedExtensions` | `
|
|
318
|
-
| `sanitize` | `null` | Custom function to sanitize HTML output
|
|
446
|
+
| Setting | Default | Description |
|
|
447
|
+
| ------------------- | ------- | ----------------------------------------- |
|
|
448
|
+
| `allowRaw` | `true` | Allow JavaScript in compile-time blocks |
|
|
449
|
+
| `maxDepth` | `5` | Maximum import nesting depth |
|
|
450
|
+
| `timeout` | `5000` | Max execution time per script (ms) |
|
|
451
|
+
| `allowFetch` | `true` | Allow network requests from scripts |
|
|
452
|
+
| `allowHttp` | `false` | Block plain HTTP — HTTPS only by default |
|
|
453
|
+
| `allowedOrigins` | `[]` | Restrict fetch to specific domains |
|
|
454
|
+
| `allowedExtensions` | `[]` | Restrict which file types can be imported |
|
|
455
|
+
| `sanitize` | `null` | Custom function to sanitize HTML output |
|
|
319
456
|
|
|
320
457
|
---
|
|
321
458
|
|
|
322
|
-
## Custom
|
|
459
|
+
## Custom mappers
|
|
323
460
|
|
|
324
461
|
Define your own tags and rendering logic with the Mapper API:
|
|
325
462
|
|
|
326
463
|
```js
|
|
327
464
|
import SomMark, { Mapper } from "sommark";
|
|
328
465
|
|
|
329
|
-
const mapper = new Mapper(
|
|
466
|
+
const mapper = new Mapper();
|
|
330
467
|
|
|
331
|
-
mapper.register("alert", (
|
|
332
|
-
|
|
468
|
+
mapper.register("alert", function({ content, props }) {
|
|
469
|
+
const type = props.type || "info";
|
|
470
|
+
return `<div class="alert alert-${type}">${content}</div>`;
|
|
333
471
|
});
|
|
334
472
|
|
|
335
|
-
const
|
|
336
|
-
src:
|
|
473
|
+
const sm = new SomMark({
|
|
474
|
+
src: `[alert = type: "warning"]Check your config.[end:alert]`,
|
|
337
475
|
format: "html",
|
|
338
476
|
mapperFile: mapper,
|
|
339
477
|
});
|
|
340
|
-
|
|
341
|
-
const output = await engine.transpile();
|
|
342
478
|
```
|
|
343
479
|
|
|
344
|
-
Full reference
|
|
480
|
+
Full reference: [`docs/api/Mapper`](docs/api/Mapper)
|
|
345
481
|
|
|
346
482
|
---
|
|
347
483
|
|
|
348
484
|
## Documentation
|
|
349
485
|
|
|
350
|
-
| Topic | Location
|
|
351
|
-
|
|
352
|
-
| Syntax Reference | [`docs/syntax/`](docs/syntax)
|
|
353
|
-
|
|
|
354
|
-
|
|
|
355
|
-
|
|
|
356
|
-
|
|
|
357
|
-
|
|
|
358
|
-
| CLI Guide | [`docs/cli/`](docs/cli)
|
|
359
|
-
| Configuration | [`docs/cli/config.md`](docs/cli/config.md)
|
|
486
|
+
| Topic | Location |
|
|
487
|
+
| ---------------- | ------------------------------------------ |
|
|
488
|
+
| Syntax Reference | [`docs/syntax/`](docs/syntax) |
|
|
489
|
+
| Output Formats | [`docs/languages/`](docs/languages) |
|
|
490
|
+
| Core API | [`docs/api/Core/`](docs/api/Core) |
|
|
491
|
+
| Browser API | [`docs/api/Browser/`](docs/api/Browser) |
|
|
492
|
+
| Mapper API | [`docs/api/Mapper/`](docs/api/Mapper) |
|
|
493
|
+
| Sandbox API | [`docs/api/Sandbox/`](docs/api/Sandbox) |
|
|
494
|
+
| CLI Guide | [`docs/cli/`](docs/cli) |
|
|
495
|
+
| Configuration | [`docs/cli/config.md`](docs/cli/config.md) |
|
|
360
496
|
|
|
361
497
|
---
|
|
362
498
|
|
|
363
499
|
## License
|
|
364
500
|
|
|
365
|
-
[MIT](LICENSE)
|
|
501
|
+
[MIT](LICENSE) — Adam Elmi
|