sommark 1.0.0 → 1.1.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/CHANGELOG.md ADDED
@@ -0,0 +1,31 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 (2026-01-04)
4
+ - Initial release
5
+ - Supports HTML, MD, MDX output
6
+ - CLI ready
7
+ - Lightweight 61 KB package
8
+
9
+ ## 1.1.0 (2026-01-08)
10
+
11
+ ### Features
12
+
13
+ - **Highlight.js Integration**:
14
+ - Added support for highlight.js themes.
15
+ - Added `codeThemes` and `selectedTheme` to Mapper configuration.
16
+ - Default theme for HTML output is now `atom-one-dark`.
17
+ - Added `helpers/loadStyle.js` to dynamically load theme CSS (isomorphic: supports both Node.js via `fs` and browser via `fetch`).
18
+ - Automatically injects selected theme CSS into HTML output when code blocks are present.
19
+
20
+ - **Mappers**:
21
+ - Added `includesId(id)` helper method to `Mapper` class for checking output mapping existence.
22
+
23
+ ### Bug Fixes
24
+
25
+ - **Core/Parser**: Fixed a critical issue where global state variables (`block_stack`, `line`, etc.) were not reset between parse calls, causing errors on subsequent runs.
26
+ - **Core/Transpiler**: Removed leftover debug `console.log` calls.
27
+ - **Mappers/Markdown**: Fixed `Heading` block ignoring inner content (text/comments) in MD/MDX output. Now appends nested content after the heading.
28
+ - **Security**: Refactored HTML escaping architecture.
29
+ - **Transpiler**: `AtBlock` content is now **escaped by default** in the transpiler to prevent XSS.
30
+ - **Mapper**: Added `options` to `Mapper.create` (e.g., `{ escape: false }`) to allow specific blocks (like `Code`, `List`, `Table`) to opt-out of automatic escaping when they handle raw content safely or require it for parsing.
31
+ - **Parser**: Removed manual escaping from Parser to support the new transpiler-based architecture.
package/cli/cli.mjs CHANGED
@@ -22,7 +22,7 @@ function getHelp(unknown_option = true) {
22
22
  "{N} <$green:-v or --version$> <$cyan: show version information$>",
23
23
  "{N} <$green:--html$> <$cyan: transpile to html$>",
24
24
  "{N} <$green:--md$> <$cyan: transpile to markdown$>",
25
- "{N} <$green:--mdx> <$cyan: transpile to mdx>"
25
+ "{N} <$green:--mdx$> <$cyan: transpile to mdx$>"
26
26
  ].join("");
27
27
  const help_msg = formatMessage(msg);
28
28
  if (!options.includes(process.argv[2]) && unknown_option) {
package/core/parser.js CHANGED
@@ -78,7 +78,7 @@ let block_stack = [];
78
78
  let end_stack = [];
79
79
  let tokens_stack = [];
80
80
  let line = 1,
81
- start = 1,
81
+ start = 1,
82
82
  end = 1,
83
83
  value = "";
84
84
 
@@ -430,6 +430,13 @@ function parseNode(tokens, i) {
430
430
  }
431
431
 
432
432
  function parser(tokens) {
433
+ block_stack = [];
434
+ end_stack = [];
435
+ tokens_stack = [];
436
+ line = 1;
437
+ start = 1;
438
+ end = 1;
439
+ value = "";
433
440
  let ast = [];
434
441
  for (let i = 0; i < tokens.length; i++) {
435
442
  let [nodes, nextIndex] = parseNode(tokens, i);
@@ -455,4 +462,4 @@ function parser(tokens) {
455
462
  return ast;
456
463
  }
457
464
 
458
- export default parser;
465
+ export default parser;
@@ -1,9 +1,10 @@
1
1
  import PREDEFINED_IDS from "./ids.js";
2
2
  import { BLOCK, TEXT, INLINE, ATBLOCK, COMMENT, NEWLINE } from "./names.js";
3
+ import escapeHTML from "../helpers/escapeHTML.js";
3
4
  import { transpilerError } from "./validator.js";
4
5
 
5
- const formats = { html: "html", md: "md", mdx: "mdx" };
6
- const { html, md, mdx } = formats;
6
+ const formats = { htmlFormat: "html", markdownFormat: "md", mdxFormat: "mdx" };
7
+ const { htmlFormat, markdownFormat, mdxFormat } = formats;
7
8
 
8
9
  // Extracting target identifier
9
10
  function matchedValue(outputs, targetId) {
@@ -29,15 +30,15 @@ function matchedValue(outputs, targetId) {
29
30
  function generateOutput(ast, i, format, file) {
30
31
  const node = Array.isArray(ast) ? ast[i] : ast;
31
32
  let result = "";
33
+ let context = "";
32
34
  let target = matchedValue(file.outputs, node.id);
33
35
  if (target) {
34
36
  result +=
35
- format === html || format === mdx
37
+ format === htmlFormat || format === mdxFormat
36
38
  ? (node.depth > 1 ? " ".repeat(node.depth) : "") +
37
- target.render({ args: node.args, content: "\n<%smark>" + (node.depth > 1 ? " ".repeat(node.depth) : "") }) +
38
- "\n"
39
+ target.render({ args: node.args, content: "\n<%smark>" + (node.depth > 1 ? " ".repeat(node.depth) : "") }) +
40
+ "\n"
39
41
  : target.render({ args: node.args, content: "" });
40
- let context = "";
41
42
  for (const body_node of node.body) {
42
43
  switch (body_node.type) {
43
44
  case TEXT:
@@ -48,11 +49,7 @@ function generateOutput(ast, i, format, file) {
48
49
  body_node.text = body_node.text.slice(1, body_node.text.length - 1);
49
50
  }
50
51
  }
51
- if (format === html) {
52
- context += " ".repeat(body_node.depth) + `<p>${body_node.text}</p>`;
53
- } else {
54
- context += body_node.text;
55
- }
52
+ context += (format === htmlFormat || format === mdxFormat) ? escapeHTML(body_node.text) : body_node.text;
56
53
  break;
57
54
  case INLINE:
58
55
  target = matchedValue(file.outputs, body_node.id);
@@ -64,15 +61,15 @@ function generateOutput(ast, i, format, file) {
64
61
  metadata.push(body_node.data);
65
62
  }
66
63
  if (body_node.hasOwnProperty("title")) {
67
- if (format === html) body_node.title = body_node.title.replaceAll('"', "");
64
+ if (format === htmlFormat) body_node.title = body_node.title.replaceAll('"', "");
68
65
  metadata.push(body_node.title);
69
66
  }
70
67
  break;
71
68
  }
72
69
  }
73
70
  context +=
74
- (format === html || format === mdx ? "\n" : "") +
75
- target.render({ args: metadata.length > 0 ? metadata : "", content: body_node.value });
71
+ (format === htmlFormat || format === mdxFormat ? "\n" : "") +
72
+ target.render({ args: metadata.length > 0 ? metadata : "", content: (format === htmlFormat || format === mdxFormat) ? escapeHTML(body_node.value) : body_node.value });
76
73
  }
77
74
  break;
78
75
  case NEWLINE:
@@ -81,17 +78,24 @@ function generateOutput(ast, i, format, file) {
81
78
  case ATBLOCK:
82
79
  target = matchedValue(file.outputs, body_node.id);
83
80
  if (target) {
81
+ const shouldEscape = target.options?.escape ?? true;
84
82
  let content = "";
85
83
  for (let v = 0; v < body_node.content.length; v++) {
86
84
  let value = body_node.content[v];
85
+ if (shouldEscape) {
86
+ value = escapeHTML(value);
87
+ }
87
88
  content += v === 0 ? value : "\n" + value;
88
89
  }
89
90
  context += target.render({ args: body_node.args, content });
90
91
  }
91
92
  break;
92
93
  case COMMENT:
93
- let commentFormat = `<!--${body_node.text.replace("#", "")}-->`;
94
- context += " ".repeat(body_node.depth) + commentFormat;
94
+ if (format === htmlFormat || format === markdownFormat) {
95
+ context += " ".repeat(body_node.depth) + `<!--${body_node.text.replace("#", "")}-->`;
96
+ } else if (format === mdxFormat) {
97
+ context += " ".repeat(body_node.depth) + `{/*${body_node.text.replace("#", "")} */}`;
98
+ }
95
99
  break;
96
100
  case BLOCK:
97
101
  target = matchedValue(file.outputs, body_node.id);
@@ -99,7 +103,7 @@ function generateOutput(ast, i, format, file) {
99
103
  break;
100
104
  }
101
105
  }
102
- if (format === html || format === mdx) {
106
+ if (format === htmlFormat || format === mdxFormat) {
103
107
  result = result.replace("<%smark>", context);
104
108
  } else {
105
109
  result += context;
@@ -113,17 +117,28 @@ function generateOutput(ast, i, format, file) {
113
117
  return result;
114
118
  }
115
119
 
116
- function transpiler({ast, format, mapperFile, includeDocument = true }) {
120
+ function transpiler({ ast, format, mapperFile, includeDocument = true }) {
117
121
  let output = "";
118
122
  for (let i = 0; i < ast.length; i++) {
119
123
  if (ast[i].type === BLOCK) {
120
124
  output += generateOutput(ast, i, format, mapperFile);
121
125
  } else if (ast[i].type === COMMENT) {
122
- let commentFormat = `<!--${ast[i].text.replace("#", "")}-->`;
123
- output += commentFormat + "\n";
126
+ if (format === htmlFormat || format === markdownFormat) {
127
+ output += `<!--${ast[i].text.replace("#", "")}-->\n`;
128
+ } else if (format === mdxFormat) {
129
+ output += `{/*${ast[i].text.replace("#", "")} */}\n`;
130
+ }
131
+ }
132
+ }
133
+ if (format === htmlFormat && (output.includes("<code>") || output.includes("<pre>"))) {
134
+ if (mapperFile.enableLoadStyle) {
135
+ mapperFile.setHeader([mapperFile.loadStyle(mapperFile.env, mapperFile.selectedTheme)]);
136
+ }
137
+ if (mapperFile.enableLinkStyle) {
138
+ mapperFile.setHeader([mapperFile.cssTheme(mapperFile.selectedTheme)]);
124
139
  }
125
140
  }
126
- if (includeDocument && format === html) {
141
+ if (includeDocument && format === htmlFormat) {
127
142
  const document = "<!DOCTYPE html>\n" + "<html>\n" + mapperFile.header + "<body>\n" + output + "</body>\n" + "</html>\n";
128
143
  return document;
129
144
  }
package/formatter/tag.js CHANGED
@@ -1,3 +1,4 @@
1
+ import escapeHTML from "../helpers/escapeHTML.js";
1
2
  class TagBuilder {
2
3
  #children;
3
4
  #attr;
@@ -11,7 +12,7 @@ class TagBuilder {
11
12
  attributes(obj, ...arr) {
12
13
  if (obj && obj instanceof Object) {
13
14
  Object.entries(obj).forEach(([key, value]) => {
14
- this.#attr.push(`${key}="${ value ?? ""}"`);
15
+ this.#attr.push(`${key}="${escapeHTML(value ?? "")}"`);
15
16
  });
16
17
  }
17
18
  if (arr && Array.isArray(arr)) {
@@ -32,10 +33,10 @@ class TagBuilder {
32
33
  if (prop && type) {
33
34
  switch (type) {
34
35
  case "string":
35
- this.#attr.push(`${key2}="${value}"`);
36
+ this.#attr.push(`${key2}="${escapeHTML(value)}"`);
36
37
  break;
37
38
  case "other":
38
- this.#attr.push(`${key2}={${value}}`);
39
+ this.#attr.push(`${key2}={${value}}`); // React/MDX props might need different handling, but usually raw JS expression?
39
40
  break;
40
41
  }
41
42
  }
@@ -0,0 +1,25 @@
1
+ export async function loadStyle(env = "node", theme = 'atom-one-dark.min', targetPath = "./node_modules/highlight.js/styles/") {
2
+ try {
3
+ if (env === "node" || env === "browser") {
4
+ if (env === "node") {
5
+ const fs = await import("fs/promises");
6
+ const path = await import("path");
7
+ return await fs.readFile(path.join(process.cwd(), targetPath, theme + ".css"), "utf-8");
8
+ } else if (env === "browser") {
9
+ const url = new URL("../" + targetPath + theme + ".css", import.meta.url);
10
+ if (typeof process !== "undefined" && process.versions && process.versions.node) {
11
+ const fs = await import("fs/promises");
12
+ return await fs.readFile(url, "utf-8");
13
+ }
14
+ const response = await fetch(url);
15
+ return await response.text();
16
+ }
17
+ } else {
18
+ throw new Error("Invalid environment");
19
+ }
20
+ } catch (error) {
21
+ console.error("Error loading style:", error);
22
+ return "";
23
+ }
24
+ }
25
+ export default loadStyle;
package/index.js CHANGED
@@ -8,6 +8,7 @@ import mdx from "./mappers/default_mode/smark.mdx.js";
8
8
  import TagBuilder from "./formatter/tag.js";
9
9
  import MarkdownBuilder from "./formatter/mark.js";
10
10
  import { runtimeError } from "./core/validator.js";
11
+ import { loadStyle } from "./helpers/loadStyle.js";
11
12
 
12
13
  class SomMark {
13
14
  constructor({ src, format, mapperFile = null, mode = "default", includeDocument = true }) {
@@ -57,7 +58,7 @@ class SomMark {
57
58
  const lex = src => lexer(src);
58
59
 
59
60
  function parse(src) {
60
- if(!src) {
61
+ if (!src) {
61
62
  runtimeError([
62
63
  `{line}<$red:Missing Source:$> <$yellow:The 'src' argument is required for parsing.$>{line}`
63
64
  ]);
@@ -100,5 +101,5 @@ function transpile(options = {}) {
100
101
  return transpiler({ ast, format, mapperFile, includeDocument });
101
102
  }
102
103
 
103
- export { html, markdown, mdx, Mapper, TagBuilder, MarkdownBuilder, lex, parse, transpile };
104
+ export { html, markdown, mdx, Mapper, TagBuilder, MarkdownBuilder, lex, parse, transpile, loadStyle };
104
105
  export default SomMark;
package/lib/highlight.js CHANGED
@@ -1,12 +1,183 @@
1
1
  import hljs from "highlight.js";
2
2
 
3
- export function highlightCode(code, language = "plaintext") {
3
+ function highlightCode(code, language = "plaintext") {
4
4
  if (!hljs.getLanguage(language)) {
5
5
  language = "plaintext";
6
6
  }
7
7
  return hljs.highlight(code, { language }).value;
8
8
  }
9
+ const themes = [
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"];
9
169
 
10
- export function cssTheme(theme = "atom-one-dark") {
170
+ let selectedTheme = "atom-one-dark.min";
171
+ function cssTheme(theme = selectedTheme) {
172
+ if (!themes.includes(theme)) {
173
+ theme = "atom-one-dark.min";
174
+ }
11
175
  return `<link rel="stylesheet" href="node_modules/highlight.js/styles/${theme}.css">`;
12
176
  }
177
+
178
+ export {
179
+ highlightCode,
180
+ cssTheme,
181
+ selectedTheme,
182
+ themes,
183
+ };
@@ -1,6 +1,9 @@
1
1
  import Mapper from "../mapper.js";
2
2
  const html = new Mapper();
3
- const { tag, setHeader, code, cssTheme, list } = html;
3
+ const { tag, code, list } = html;
4
+
5
+ html.selectedTheme = "paraiso-dark";
6
+ html.env = "browser";
4
7
 
5
8
  // Block
6
9
  html.create("Block", ({ content }) => {
@@ -58,18 +61,18 @@ html.create("image", ({ args, content }) => {
58
61
  // Code
59
62
  html.create("code", ({ args, content }) => {
60
63
  return code(args, content);
61
- });
64
+ }, { escape: false });
62
65
  // List
63
66
  html.create(["list", "List"], ({ content }) => {
64
67
  return list(content);
65
- });
68
+ }, { escape: false });
66
69
  // Table
67
70
  html.create("table", ({ content, args }) => {
68
71
  return html.htmlTable(content.split(/\n/), args);
69
- });
72
+ }, { escape: false });
70
73
  // Horizontal Rule
71
74
  html.create("hr", () => {
72
75
  return tag("hr").selfClose();
73
76
  });
74
- setHeader([cssTheme()]);
77
+
75
78
  export default html;
@@ -7,8 +7,7 @@ markdown.create("Block", ({ content }) => {
7
7
  });
8
8
  // Headings
9
9
  markdown.create("Heading", ({ args, content }) => {
10
- console.log(args, content);
11
- return md.heading(args[1], args[0]);
10
+ return md.heading(args[1], args[0]) + content;
12
11
  });
13
12
  // Inline Headings
14
13
  markdown.create("h1", ({ content }) => {
@@ -44,7 +43,7 @@ markdown.create(["emphasis", "e"], ({ content }) => {
44
43
  // Code Blocks
45
44
  markdown.create(["code", "Code", "codeBlock", "CodeBlock"], ({ args, content }) => {
46
45
  return md.codeBlock(content, args[0]);
47
- });
46
+ }, { escape: false });
48
47
  // Link
49
48
  markdown.create("link", ({ args, content }) => {
50
49
  return md.url("link", content, args[0], args[1]);
@@ -64,10 +63,10 @@ markdown.create(["escape", "s"], ({ content }) => {
64
63
  // Table
65
64
  markdown.create("table", ({ args, content }) => {
66
65
  return md.table(args, content.split("\n"));
67
- });
66
+ }, { escape: false });
68
67
  // List
69
68
  markdown.create(["list", "List"], ({ content }) => {
70
69
  return content;
71
- });
70
+ }, { escape: false });
72
71
  export default markdown;
73
72
 
package/mappers/mapper.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import TagBuilder from "../formatter/tag.js";
2
2
  import MarkdownBuilder from "../formatter/mark.js";
3
- import { highlightCode, cssTheme } from "../lib/highlight.js";
3
+ import { highlightCode, cssTheme, selectedTheme, themes } from "../lib/highlight.js";
4
4
  import escapeHTML from "../helpers/escapeHTML.js";
5
+ import loadStyle from "../helpers/loadStyle.js";
5
6
  class Mapper {
6
7
  #predefinedHeaderData;
7
8
  #customElements;
@@ -22,9 +23,15 @@ class Mapper {
22
23
  this.#customElements = "";
23
24
  this.highlightCode = highlightCode;
24
25
  this.cssTheme = cssTheme;
26
+ this.selectedTheme = selectedTheme;
27
+ this.codeThemes = themes;
25
28
  this.escapeHTML = escapeHTML;
29
+ this.enableLoadStyle = false;
30
+ this.enableLinkStyle = true;
31
+ this.loadStyle = loadStyle;
32
+ this.env = "node";
26
33
  }
27
- create(id, renderOutput) {
34
+ create(id, renderOutput, options = { escape: true }) {
28
35
  if (!id || !renderOutput) {
29
36
  throw new Error("Expected arguments are not defined");
30
37
  }
@@ -48,7 +55,7 @@ class Mapper {
48
55
  return renderOutput(data);
49
56
  };
50
57
 
51
- this.outputs.push({ id, render });
58
+ this.outputs.push({ id, render, options });
52
59
  }
53
60
  removeOutput(id) {
54
61
  this.outputs = this.outputs.filter(output => {
@@ -188,5 +195,15 @@ class Mapper {
188
195
 
189
196
  return renderItems(nodes);
190
197
  };
198
+ includesId = id => {
199
+ if (Array.isArray(id)) {
200
+ return this.outputs.some(output => {
201
+ return id.some(singleId => singleId === output.id);
202
+ });
203
+ }
204
+ return this.outputs.some(output => {
205
+ return output.id === id;
206
+ });
207
+ }
191
208
  }
192
209
  export default Mapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sommark",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
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": {
@@ -23,19 +23,19 @@
23
23
  "url": "git+https://github.com/Adam-Elmi/SomMark.git"
24
24
  },
25
25
  "keywords": [
26
- "language",
27
- "markup",
28
- "markup-lanuage",
29
- "documentation",
30
- "parser",
31
- "transpiler",
32
- "html",
33
- "markdown",
34
- "mdx",
35
- "dsl",
36
- "mapper",
37
- "mapping"
38
- ],
26
+ "language",
27
+ "markup",
28
+ "markup-lanuage",
29
+ "documentation",
30
+ "parser",
31
+ "transpiler",
32
+ "html",
33
+ "markdown",
34
+ "mdx",
35
+ "dsl",
36
+ "mapper",
37
+ "mapping"
38
+ ],
39
39
  "author": "Adam Elmi",
40
40
  "license": "MIT",
41
41
  "bugs": {
@@ -48,4 +48,4 @@
48
48
  "devDependencies": {
49
49
  "vitest": "^4.0.16"
50
50
  }
51
- }
51
+ }