sommark 2.0.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## v2.0.2 (2026-02-03)
4
+
5
+ ### Features
6
+ - **Exports**: Exposed `TOKEN_TYPES` and `labels` from core for advanced usage.
7
+
8
+ ### Refactoring
9
+ - **Config**: Removed unused `custom_html` import from `smark.config.js`.
10
+
11
+ ### Fixes
12
+ - **CLI**: Fixed typo in help message.
13
+ - **Cleanup**: Cleaned up `.npmignore`.
14
+
15
+ ## v2.0.1 (2026-02-02)
16
+
17
+ ### Refactoring
18
+ - **Highlight System**: Removed dependency on filesystem loading for themes. Bundled `atom-one-dark` theme by default.
19
+ - **Theme Registry**: Introduced `registerHighlightTheme` and `selectHighlightTheme` for easier theme management.
20
+ - **Auto-Detection**: Removed `hasCode` property. The transpiler now auto-detects code blocks for style injection if `enable_highlightTheme` is true.
21
+
22
+ ### Documentation
23
+ - **API Reference**: Complete overhaul of `docs/api` with renumbered files and new methods.
24
+ - **Syntax Guide**: Added comprehensive documentation for Block, Inline, and AtBlock syntax with examples.
25
+ - **Mappers**: Added `default_mappers.md` listing all built-in HTML, Markdown, and MDX mappings.
26
+ - **Escape Characters**: Added `escape_character.md` guide.
27
+
28
+ ### Fixes
29
+ - **Browser Compatibility**: Fixed `loadCss` to work correctly in browser environments using `fetch`.
30
+ - **Path Resolution**: Fixed path resolution issues for theme loading.
31
+
3
32
  ## v2.0.0 (2026-02-01)
4
33
 
5
34
  > [!WARNING]
package/README.md CHANGED
@@ -13,7 +13,7 @@
13
13
  <img src="https://img.shields.io/badge/mdx-supported-lightblue?style=flat-square" />
14
14
  </p>
15
15
 
16
- # SomMark v2.0.0
16
+ # SomMark v2
17
17
 
18
18
  > [!WARNING]
19
19
  > Old version is no longer supported.
@@ -151,7 +151,8 @@ Detailed guides and API references are available in the `docs/` directory:
151
151
  * **[Core API](docs/core.md)**: Programmatic usage of the library (`transpile`, `lex`, `parse`).
152
152
  * **[Mapper API](docs/mapper.md)**: Guide for creating custom mappers and rules.
153
153
  * **[CLI Reference](docs/cli.md)**: Command line options and configurations.
154
- * **[API Quick Reference](docs/api.md)**: Fast lookup for all classes and functions.
154
+ * **[API Quick Reference](docs/api)**: Fast lookup for all classes and functions.
155
+ * **[Configuration Reference](docs/config.md)**: Guide for creating custom configurations.
155
156
 
156
157
 
157
158
 
@@ -282,7 +283,15 @@ const { tag } = myMapper;
282
283
 
283
284
  myMapper.register("Code", ({ content }) => {
284
285
  return tag("pre").body(content);
285
- });
286
+ }, {
287
+ escape: false,
288
+ rules: {
289
+ args: {
290
+ min: 1,
291
+ required: ["id"]
292
+ }
293
+ }
294
+ }); // options
286
295
  ```
287
296
 
288
297
  # License
@@ -8,14 +8,14 @@ import { options } from "../constants.js";
8
8
  export function getHelp(unknown_option = true) {
9
9
  const msg = [
10
10
  `${unknown_option && process.argv[2] ? `<$red:Unrecognized option$> <$blue: '${process.argv[2]}'$>` : ""}`,
11
- "{N}<$yellow:Usage:$> <$blue:smark [option]$>",
11
+ "{N}<$yellow:Usage:$> <$blue:sommark [option]$>",
12
12
 
13
13
  "{N}{N}<$yellow:Global Options:$>",
14
14
  "{N} <$green:-h, --help$> <$cyan: Show help message$>",
15
15
  "{N} <$green:-v, --version$> <$cyan: Show version information$>",
16
16
 
17
17
  "{N}{N}<$yellow:Transpilation Options:$>",
18
- "{N}<$yellow:Usage:$> <$blue:smark [option] [targetFile] [option] [outputFile] [outputDir]$>",
18
+ "{N}<$yellow:Usage:$> <$blue:sommark [option] [targetFile] [option] [outputFile] [outputDir]$>",
19
19
  "{N} <$green:--html$> <$cyan: Transpile to HTML$>",
20
20
  "{N} <$green:--markdown$> <$cyan: Transpile to Markdown$>",
21
21
  "{N} <$green:--mdx$> <$cyan: Transpile to MDX$>",
@@ -26,9 +26,9 @@ export function getHelp(unknown_option = true) {
26
26
  "{N} <$green:-o$> <$cyan: Specify output filename (and optionally directory)$>",
27
27
 
28
28
  "{N}{N}<$yellow:Examples:$>",
29
- "{N} <$magenta:1. Basic usage:$> <$blue:smark --html input.smark$>",
30
- "{N} <$magenta:2. Print to console:$> <$blue:smark --html -p input.smark$>",
31
- "{N} <$magenta:3. Custom output:$> <$blue:smark --html input.smark -o myOutput ./dist/$>"
29
+ "{N} <$magenta:1. Basic usage:$> <$blue:sommark --html input.smark$>",
30
+ "{N} <$magenta:2. Print to console:$> <$blue:sommark --html -p input.smark$>",
31
+ "{N} <$magenta:3. Custom output:$> <$blue:sommark --html input.smark -o myOutput ./dist/$>"
32
32
  ].join("");
33
33
  const help_msg = formatMessage(msg);
34
34
 
package/core/formats.js CHANGED
@@ -6,3 +6,4 @@ const formats = {
6
6
  };
7
7
 
8
8
  export const {textFormat, htmlFormat, markdownFormat, mdxFormat} = formats;
9
+ export default formats;
@@ -199,7 +199,6 @@ async function generateOutput(ast, i, format, mapper_file) {
199
199
 
200
200
  async function transpiler({ ast, format, mapperFile, includeDocument = true }) {
201
201
  let output = "";
202
- mapperFile ? (mapperFile.hasCode = false) : null;
203
202
  for (let i = 0; i < ast.length; i++) {
204
203
  if (ast[i].type === BLOCK) {
205
204
  output += await generateOutput(ast, i, format, mapperFile);
@@ -214,25 +213,17 @@ async function transpiler({ ast, format, mapperFile, includeDocument = true }) {
214
213
  if (includeDocument && format === htmlFormat) {
215
214
  let finalHeader = mapperFile.header;
216
215
 
217
- if (mapperFile.hasCode && mapperFile.enable_highlight_link_Style && mapperFile.getHighlightTheme) {
218
- const linkTag = `<link rel="stylesheet" href="node_modules/highlight.js/styles/${mapperFile.getHighlightTheme(mapperFile.highlightTheme)}.css">`;
219
- if (linkTag && !finalHeader.includes(linkTag)) {
220
- finalHeader += linkTag + "\n";
221
- }
222
- }
223
-
224
- if (
225
- (mapperFile.hasCode || (mapperFile.styles && mapperFile.styles.length > 0)) &&
226
- mapperFile.loadStyles
227
- ) {
228
- const styles = await mapperFile.loadStyles();
229
- if (styles && styles.trim()) {
230
- const styleTag = `<style>\n${styles}\n</style>`;
216
+ // Inject Style Tag if code blocks exist
217
+ if (mapperFile.enable_highlightTheme && (output.includes("<pre") || output.includes("<code")) && mapperFile.getStyle) {
218
+ const styleContent = mapperFile.getStyle();
219
+ if (styleContent) {
220
+ const styleTag = `<style>\n${styleContent}\n</style>`;
231
221
  if (!finalHeader.includes(styleTag)) {
232
222
  finalHeader += styleTag + "\n";
233
223
  }
234
224
  }
235
225
  }
226
+
236
227
  const document = `<!DOCTYPE html>\n<html>\n${finalHeader}\n<body>\n${output}\n</body>\n</html>\n`;
237
228
  return document;
238
229
  }
package/debug.js CHANGED
@@ -1,10 +1,9 @@
1
1
  import fs from "node:fs/promises";
2
2
  import SomMark from "./index.js";
3
- import custom_html from "./custom.smark.js";
4
3
 
5
4
  const buffer = await fs.readFile("./example.smark");
6
5
  const file_content = buffer.toString();
7
- let smark = new SomMark({ src: file_content, format: "html", includeDocument: false });
6
+ let smark = new SomMark({ src: file_content, format: "html", includeDocument: true });
8
7
 
9
8
  // console.log(JSON.stringify(smark.parse(), null, 2));
10
9
  // console.log(smark.lex());
@@ -0,0 +1,3 @@
1
+ const atomOneDark = `pre code.hljs{display:block;overflow-x:auto;padding:1em}code.hljs{padding:3px 5px}.hljs{color:#abb2bf;background:#282c34}.hljs-comment,.hljs-quote{color:#5c6370;font-style:italic}.hljs-doctag,.hljs-formula,.hljs-keyword{color:#c678dd}.hljs-deletion,.hljs-name,.hljs-section,.hljs-selector-tag,.hljs-subst{color:#e06c75}.hljs-literal{color:#56b6c2}.hljs-addition,.hljs-attribute,.hljs-meta .hljs-string,.hljs-regexp,.hljs-string{color:#98c379}.hljs-attr,.hljs-number,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-pseudo,.hljs-template-variable,.hljs-type,.hljs-variable{color:#d19a66}.hljs-bullet,.hljs-link,.hljs-meta,.hljs-selector-id,.hljs-symbol,.hljs-title{color:#61aeee}.hljs-built_in,.hljs-class .hljs-title,.hljs-title.class_{color:#e6c07b}.hljs-emphasis{font-style:italic}.hljs-strong{font-weight:700}.hljs-link{text-decoration:underline}`;
2
+
3
+ export default atomOneDark;
package/index.js CHANGED
@@ -8,8 +8,9 @@ import MDX from "./mappers/languages/mdx.js";
8
8
  import TagBuilder from "./formatter/tag.js";
9
9
  import MarkdownBuilder from "./formatter/mark.js";
10
10
  import { runtimeError } from "./core/errors.js";
11
- import { textFormat, htmlFormat, markdownFormat, mdxFormat } from "./core/formats.js";
12
-
11
+ import FORMATS, { textFormat, htmlFormat, markdownFormat, mdxFormat } from "./core/formats.js";
12
+ import TOKEN_TYPES from "./core/tokenTypes.js";
13
+ import * as labels from "./core/labels.js";
13
14
  class SomMark {
14
15
  constructor({ src, format, mapperFile = null, includeDocument = true }) {
15
16
  this.src = src;
@@ -91,5 +92,18 @@ async function transpile(options = {}) {
91
92
  return await transpiler({ ast, format, mapperFile, includeDocument });
92
93
  }
93
94
 
94
- export { HTML, MARKDOWN, MDX, Mapper, TagBuilder, MarkdownBuilder, lex, parse, transpile };
95
+ export {
96
+ HTML,
97
+ MARKDOWN,
98
+ MDX,
99
+ Mapper,
100
+ TagBuilder,
101
+ MarkdownBuilder,
102
+ FORMATS,
103
+ lex,
104
+ parse,
105
+ transpile,
106
+ TOKEN_TYPES,
107
+ labels
108
+ };
95
109
  export default SomMark;
package/lib/highlight.js CHANGED
@@ -6,178 +6,6 @@ function highlightCode(code, language = "plaintext") {
6
6
  }
7
7
  return hljs.highlight(code, { language }).value;
8
8
  }
9
- const HighlightThemes = [
10
- "gradient-dark",
11
- "qtcreator-light",
12
- "sunburst",
13
- "intellij-light",
14
- "rose-pine-moon.min",
15
- "default.min",
16
- "stackoverflow-light",
17
- "rose-pine-moon",
18
- "stackoverflow-light.min",
19
- "magula.min",
20
- "qtcreator-light.min",
21
- "srcery.min",
22
- "nord",
23
- "purebasic",
24
- "atom-one-dark-reasonable.min",
25
- "a11y-light",
26
- "monokai-sublime.min",
27
- "cybertopia-dimmer.min",
28
- "arduino-light.min",
29
- "routeros",
30
- "shades-of-purple.min",
31
- "lioshi",
32
- "isbl-editor-dark",
33
- "monokai-sublime",
34
- "docco",
35
- "xcode",
36
- "lioshi.min",
37
- "foundation",
38
- "github-dark-dimmed",
39
- "far.min",
40
- "night-owl.min",
41
- "routeros.min",
42
- "atom-one-light",
43
- "1c-light.min",
44
- "kimbie-light",
45
- "ascetic.min",
46
- "tokyo-night-dark.min",
47
- "nnfx-dark",
48
- "school-book.min",
49
- "agate",
50
- "lightfair.min",
51
- "mono-blue.min",
52
- "an-old-hope.min",
53
- "a11y-dark.min",
54
- "panda-syntax-dark",
55
- "mono-blue",
56
- "obsidian.min",
57
- "gradient-light",
58
- "tomorrow-night-bright",
59
- "qtcreator-dark",
60
- "gml.min",
61
- "grayscale.min",
62
- "panda-syntax-light",
63
- "atom-one-dark-reasonable",
64
- "xt256", "monokai",
65
- "sunburst.min",
66
- "gradient-light.min",
67
- "arta",
68
- "felipec.min",
69
- "srcery",
70
- "stackoverflow-dark.min",
71
- "codepen-embed.min",
72
- "docco.min",
73
- "shades-of-purple",
74
- "github.min",
75
- "cybertopia-icecap",
76
- "felipec",
77
- "paraiso-dark.min",
78
- "arta.min",
79
- "gml",
80
- "vs2015.min",
81
- "a11y-dark",
82
- "github-dark-dimmed.min",
83
- "tokyo-night-dark",
84
- "vs2015",
85
- "rose-pine-dawn",
86
- "ir-black.min",
87
- "googlecode.min",
88
- "cybertopia-saturated.min",
89
- "color-brewer.min",
90
- "night-owl",
91
- "rose-pine",
92
- "tomorrow-night-bright.min",
93
- "a11y-light.min",
94
- "brown-paper.min",
95
- "panda-syntax-dark.min",
96
- "dark.min",
97
- "school-book",
98
- "obsidian",
99
- "stackoverflow-dark",
100
- "1c-light",
101
- "nord.min",
102
- "kimbie-dark",
103
- "brown-paper",
104
- "nnfx-light.min",
105
- "rainbow",
106
- "cybertopia-icecap.min",
107
- "gradient-dark.min",
108
- "isbl-editor-light",
109
- "paraiso-light.min",
110
- "cybertopia-cherry",
111
- "foundation.min",
112
- "purebasic.min",
113
- "xt256.min",
114
- "pojoaque.min",
115
- "lightfair",
116
- "nnfx-dark.min",
117
- "isbl-editor-light.min",
118
- "tomorrow-night-blue",
119
- "rainbow.min",
120
- "ir-black",
121
- "androidstudio",
122
- "github",
123
- "googlecode",
124
- "paraiso-dark",
125
- "codepen-embed",
126
- "vs",
127
- "cybertopia-dimmer",
128
- "devibeans",
129
- "tokyo-night-light",
130
- "isbl-editor-dark.min",
131
- "idea",
132
- "github-dark",
133
- "hybrid.min",
134
- "idea.min",
135
- "dark",
136
- "atom-one-light.min",
137
- "an-old-hope",
138
- "atom-one-dark.min",
139
- "agate.min",
140
- "github-dark.min",
141
- "qtcreator-dark.min",
142
- "devibeans.min",
143
- "magula",
144
- "rose-pine-dawn.min",
145
- "ascetic",
146
- "vs.min",
147
- "far",
148
- "rose-pine.min",
149
- "hybrid",
150
- "nnfx-light",
151
- "atom-one-dark",
152
- "paraiso-light",
153
- "intellij-light.min",
154
- "grayscale",
155
- "xcode.min",
156
- "arduino-light",
157
- "panda-syntax-light.min",
158
- "tomorrow-night-blue.min",
159
- "tokyo-night-light.min",
160
- "kimbie-light.min",
161
- "cybertopia-cherry.min",
162
- "androidstudio.min",
163
- "default",
164
- "color-brewer",
165
- "monokai.min",
166
- "pojoaque",
167
- "kimbie-dark.min",
168
- "cybertopia-saturated"];
169
-
170
- let highlightTheme = "atom-one-dark.min";
171
- function getHighlightTheme(theme = highlightTheme) {
172
- if (!HighlightThemes.includes(theme)) {
173
- theme = "atom-one-dark.min";
174
- }
175
- return theme;
176
- }
177
-
178
9
  export {
179
10
  highlightCode,
180
- getHighlightTheme,
181
- highlightTheme,
182
- HighlightThemes,
183
11
  };
package/mappers/mapper.js CHANGED
@@ -1,9 +1,8 @@
1
1
  import TagBuilder from "../formatter/tag.js";
2
2
  import MarkdownBuilder from "../formatter/mark.js";
3
- import { highlightCode, getHighlightTheme, highlightTheme, HighlightThemes } from "../lib/highlight.js";
3
+ import { highlightCode } from "../lib/highlight.js";
4
4
  import escapeHTML from "../helpers/escapeHTML.js";
5
- import loadHighlightStyle from "../helpers/loadHighlightStyle.js";
6
- import loadCss from "../helpers/loadCss.js";
5
+ import atomOneDark from "../helpers/defaultTheme.js";
7
6
 
8
7
  class Mapper {
9
8
  #customHeaderContent;
@@ -12,7 +11,7 @@ class Mapper {
12
11
  // ========================================================================== //
13
12
  constructor() {
14
13
  this.outputs = [];
15
- this.hasCode = false;
14
+ this.enable_highlightTheme = true;
16
15
  this.md = new MarkdownBuilder();
17
16
 
18
17
  this.pageProps = {
@@ -29,38 +28,40 @@ class Mapper {
29
28
  this.#customHeaderContent = "";
30
29
 
31
30
  this.highlightCode = highlightCode;
32
- this.getHighlightTheme = getHighlightTheme;
33
- this.highlightTheme = highlightTheme;
34
31
  this.escapeHTML = escapeHTML;
35
- this.enable_highlight_style_tag = true;
36
- this.enable_highlight_link_Style = false;
37
- this.enable_table_styles = true;
38
32
  this.styles = [];
39
33
  this.env = "node";
40
- this.loadStyles = async () => {
41
- let styles = "";
42
- if (this.enable_highlight_style_tag) {
43
- styles = await loadHighlightStyle(this.env, this.highlightTheme);
44
- }
45
- const allStyles = (styles ? styles + "\n" : "") + this.styles.join("\n");
46
- return allStyles;
34
+
35
+ // Theme Registry
36
+ this.themes = {
37
+ "atom-one-dark": atomOneDark
47
38
  };
39
+ this.currentTheme = "atom-one-dark";
48
40
  }
49
41
 
50
- // ========================================================================== //
51
- // Style Management //
52
- // ========================================================================== //
53
- get HighlightThemes() {
54
- return this.enable_highlight_link_Style || this.enable_highlight_style_tag ? HighlightThemes : [];
42
+ registerHighlightTheme(themes) {
43
+ this.themes = { ...this.themes, ...themes };
55
44
  }
56
45
 
57
- async loadCss(path) {
58
- const css = await loadCss(this.env, path);
59
- if (css && css.trim()) {
60
- this.addStyle(css);
46
+ selectHighlightTheme(themeName) {
47
+ if (this.themes[themeName]) {
48
+ this.currentTheme = themeName;
49
+ } else {
50
+ console.warn(`Theme '${themeName}' not found in registry.`);
61
51
  }
62
52
  }
63
53
 
54
+ getStyle() {
55
+ const themeCss = this.themes[this.currentTheme] || "";
56
+ const customCss = this.styles.join("\n");
57
+ return (themeCss + "\n" + customCss).trim();
58
+ }
59
+
60
+ // ========================================================================== //
61
+ // Style Management //
62
+ // ========================================================================== //
63
+
64
+
64
65
  addStyle(css) {
65
66
  if (typeof css === "object" && css !== null) {
66
67
  let styleString = "";
@@ -171,7 +172,6 @@ class Mapper {
171
172
  // Formatters //
172
173
  // ========================================================================== //
173
174
  code = (args, content) => {
174
- this.hasCode = true;
175
175
  const value = highlightCode(content, args && args[0] ? args[0].trim() : "text");
176
176
  return this.tag("pre").body(
177
177
  this.tag("code")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sommark",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "description": "SomMark is a structural markup language for writing structured documents and converting them into HTML or Markdown or MDX(only ready components).",
5
5
  "main": "index.js",
6
6
  "directories": {
@@ -48,4 +48,4 @@
48
48
  "devDependencies": {
49
49
  "vitest": "^4.0.16"
50
50
  }
51
- }
51
+ }
@@ -1,28 +0,0 @@
1
- export async function loadHighlightStyle(env, theme = "atom-one-dark.min", targetPath = "./node_modules/highlight.js/styles/") {
2
- if (!env) {
3
- env = typeof window !== "undefined" && typeof window.document !== "undefined" ? "browser" : "node";
4
- }
5
-
6
- try {
7
- if (env === "node") {
8
- const fs = await import("fs/promises");
9
- const path = await import("path");
10
- const stylePath = path.join(process.cwd(), targetPath, theme + ".css");
11
- return await fs.readFile(stylePath, "utf-8");
12
- } else if (env === "browser") {
13
- const url = new URL("../" + targetPath + theme + ".css", import.meta.url);
14
- const response = await fetch(url);
15
- if (!response.ok) {
16
- throw new Error(`Failed to fetch style: ${response.statusText}`);
17
- }
18
- return await response.text();
19
- } else {
20
- throw new Error("Invalid environment");
21
- }
22
- } catch (error) {
23
- console.error("Error loading style:", error);
24
- return "";
25
- }
26
- }
27
-
28
- export default loadHighlightStyle;