sommark 3.2.0 → 3.3.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 CHANGED
@@ -109,3 +109,10 @@ Read our detailed guides in the `docs/` folder:
109
109
  - **[Mapper API](docs/13.mapper.md)**: How to create new output formats.
110
110
  - **[CLI Reference](docs/11.cli.md)**: Terminal commands and flags.
111
111
  - **[API Quick Reference](docs/api)**: Fast lookup for all functions.
112
+
113
+ # Editor Support
114
+
115
+ ### Editor Support
116
+ High-quality syntax highlighting and diagnostics are provided via **LSP Semantic Tokens**. This ensures perfect coloring in any editor that supports the Language Server Protocol (e.g., VS Code, Neovim, CoC).
117
+
118
+ Information for integration can be found in the [SomMark-LSP](https://github.com/Adam-Elmi/SomMark-LSP) project.
@@ -16,7 +16,8 @@ import { transpile } from "../helpers/transpile.js";
16
16
  async function generateOutput(outputDir, outputFile, format, sourcePath, mappingFile) {
17
17
  let source_code = await readContent(sourcePath);
18
18
  source_code = source_code.toString();
19
- const output = await transpile({ src: source_code, format, mappingFile });
19
+ const absolutePath = path.resolve(process.cwd(), sourcePath);
20
+ const output = await transpile({ src: source_code, format, filename: absolutePath, mappingFile });
20
21
  const finalPath = path.join(outputDir, `${outputFile}.${extensions[format]}`);
21
22
  await createFile(outputDir, `${outputFile}.${extensions[format]}`, output);
22
23
  return finalPath;
@@ -20,15 +20,11 @@ export function getConfigDir() {
20
20
 
21
21
  export async function runInit() {
22
22
  try {
23
- const configDir = getConfigDir();
24
- const pluginsDir = path.join(configDir, "plugins");
25
- const configFilePath = path.join(configDir, "smark.config.js");
26
-
27
23
  // ======================================================
28
- // Create directories
24
+ // Create configuration directory
29
25
  // ======================================================
30
26
 
31
- await fs.mkdir(pluginsDir, { recursive: true });
27
+ await fs.mkdir(configDir, { recursive: true });
32
28
 
33
29
  // ======================================================
34
30
  // Default configuration content
@@ -10,7 +10,16 @@ import { formatMessage } from "../../core/errors.js";
10
10
  */
11
11
  export async function runListPlugins(args) {
12
12
  const config = await loadConfig();
13
- const enabledPlugins = config.plugins || [];
13
+
14
+ const sm = new SomMark({
15
+ src: "",
16
+ format: "html",
17
+ plugins: config.plugins,
18
+ excludePlugins: config.excludePlugins,
19
+ priority: config.priority
20
+ });
21
+
22
+ const enabledPlugins = sm.plugins;
14
23
 
15
24
  // Filter flags
16
25
  const showInternal = args.includes("--internal") || args.includes("-i");
@@ -24,16 +33,14 @@ export async function runListPlugins(args) {
24
33
  // 1. Internal Plugins
25
34
  if (showInternal || showAll) {
26
35
  const internal = enabledPlugins.filter(p => {
27
- const name = typeof p === "string" ? p : p.name;
28
- return BUILT_IN_PLUGINS.some(bp => bp.name === name);
36
+ return BUILT_IN_PLUGINS.some(bp => bp.name === p.name);
29
37
  });
30
38
 
31
39
  if (internal.length > 0) {
32
40
  console.log(formatMessage(` <$magenta:Internal Plugins (Built-in):$>{N}`));
33
41
  internal.forEach(p => {
34
- const name = typeof p === "string" ? p : p.name;
35
- const pluginObj = BUILT_IN_PLUGINS.find(bp => bp.name === name);
36
- printPluginInfo(name, pluginObj);
42
+ const pluginObj = BUILT_IN_PLUGINS.find(bp => bp.name === p.name);
43
+ printPluginInfo(p.name, pluginObj);
37
44
  });
38
45
  found = true;
39
46
  }
@@ -42,15 +49,13 @@ export async function runListPlugins(args) {
42
49
  // 2. External Plugins
43
50
  if (showExternal || showAll) {
44
51
  const external = enabledPlugins.filter(p => {
45
- const name = typeof p === "string" ? p : p.name;
46
- return !BUILT_IN_PLUGINS.some(bp => bp.name === name);
52
+ return !BUILT_IN_PLUGINS.some(bp => bp.name === p.name);
47
53
  });
48
54
 
49
55
  if (external.length > 0) {
50
56
  console.log(formatMessage(`${found ? "{N}" : ""} <$magenta:External Plugins (User-defined):$>{N}`));
51
57
  external.forEach(p => {
52
- const name = typeof p === "string" ? p : (p.name || "Unknown");
53
- printPluginInfo(name, typeof p === "object" ? p : null);
58
+ printPluginInfo(p.name || "Unknown", p);
54
59
  });
55
60
  found = true;
56
61
  }
@@ -101,7 +106,7 @@ export async function runListPipeline() {
101
106
  console.log(formatMessage(` <$magenta:${phase.name}$>`));
102
107
  if (matched.length > 0) {
103
108
  matched.forEach(p => {
104
- console.log(formatMessage(` <$green:• ${p.name}$> <$cyan:[${Array.isArray(p.type) ? p.type.join(", ") : p.type}]$>`));
109
+ console.log(formatMessage(` <$green:└── ${p.name}$> <$cyan:[${Array.isArray(p.type) ? p.type.join(", ") : p.type}]$>`));
105
110
  });
106
111
  } else {
107
112
  console.log(formatMessage(` <$yellow: (None registered)$>`));
@@ -114,6 +119,6 @@ export async function runListPipeline() {
114
119
  function printPluginInfo(name, pluginObj) {
115
120
  const author = pluginObj?.author || "Unknown";
116
121
  const desc = pluginObj?.description || "No description provided.";
117
- console.log(formatMessage(` <$green:• ${name}$> <$cyan:by ${author}$>`));
122
+ console.log(formatMessage(` <$green:└── ${name}$> - <$cyan:by ${author}$>`));
118
123
  console.log(formatMessage(` <$yellow:${desc}$>`));
119
124
  }
@@ -13,11 +13,12 @@ export async function printOutput(format, filePath) {
13
13
  const fileName = path.basename(filePath);
14
14
  console.log(formatMessage(`{line}<$blue: Printing output for$> <$yellow:'${fileName}'$>{line}`));
15
15
  let source_code = await readContent(filePath);
16
+ const absolutePath = path.resolve(process.cwd(), filePath);
16
17
  if (format === "json") {
17
- const output = await transpile({ src: source_code.toString(), format });
18
+ const output = await transpile({ src: source_code.toString(), format, filename: absolutePath });
18
19
  console.log(JSON.stringify(JSON.parse(output, null, 2), null, 2));
19
20
  } else {
20
- console.log(await transpile({ src: source_code.toString(), format }));
21
+ console.log(await transpile({ src: source_code.toString(), format, filename: absolutePath }));
21
22
  }
22
23
  } else {
23
24
  cliError([`{line}<$red:File$> <$blue:'${filePath}'$> <$red: is not found$>{line}`]);
@@ -34,9 +35,11 @@ export async function printLex(filePath) {
34
35
  const source_code = await readContent(filePath);
35
36
  const config = await loadConfig();
36
37
 
38
+ const absolutePath = path.resolve(process.cwd(), filePath);
37
39
  const smark = new SomMark({
38
40
  src: source_code.toString(),
39
41
  format: "text",
42
+ filename: absolutePath,
40
43
  plugins: config.plugins,
41
44
  priority: config.priority
42
45
  });
@@ -58,9 +61,11 @@ export async function printParse(filePath) {
58
61
  const source_code = await readContent(filePath);
59
62
  const config = await loadConfig();
60
63
 
64
+ const absolutePath = path.resolve(process.cwd(), filePath);
61
65
  const smark = new SomMark({
62
66
  src: source_code.toString(),
63
67
  format: "text",
68
+ filename: absolutePath,
64
69
  plugins: config.plugins,
65
70
  priority: config.priority
66
71
  });
@@ -15,7 +15,7 @@ const default_mapperFiles = { [htmlFormat]: HTML, [markdownFormat]: MARKDOWN, [m
15
15
  // ========================================================================== //
16
16
  // Transpile Function //
17
17
  // ========================================================================== //
18
- export async function transpile({ src, format, mappingFile = "" }) {
18
+ export async function transpile({ src, format, filename = null, mappingFile = "" }) {
19
19
  const config = await loadConfig();
20
20
  let finalMapper = mappingFile;
21
21
 
@@ -39,6 +39,7 @@ export async function transpile({ src, format, mappingFile = "" }) {
39
39
  const smark = new SomMark({
40
40
  src,
41
41
  format,
42
+ filename,
42
43
  mapperFile: finalMapper,
43
44
  plugins: config.plugins,
44
45
  priority: config.priority
package/core/errors.js CHANGED
@@ -1,18 +1,23 @@
1
1
  import colorize from "../helpers/colorize.js";
2
2
 
3
+ /**
4
+ * SomMark Errors
5
+ * Handles formatting and throwing errors with beautiful CLI coloring and pointers.
6
+ */
7
+
8
+ // ========================================================================== //
9
+ // Message Formatting //
10
+ // ========================================================================== //
11
+
3
12
  function formatMessage(text) {
4
13
  /*
5
- Format:
6
- {line} = Horizontal line
7
- {N} = Newline
8
- <color: Text> = Colored Text
9
-
10
- [No Nest]
11
- -----------------------------
12
- Example: <$red: Expected token$> <$magenta: ']'$> {N} at line <$red: 1$> {N} column <$green: 2$> {line}
14
+ Format System:
15
+ {line} = Draws a horizontal line
16
+ {N} = Inserts a newline
17
+ <$color: Text$> = Colors the text (supports red, yellow, green, blue, magenta, cyan)
13
18
  */
14
19
  const horizontal_rule = "\n----------------------------------------------------------------------------------------------\n";
15
- const pattern = /<\$([^:]+):([^$]+)\$>/g;
20
+ const pattern = /<\$([^:]+):([\s\S]*?)\$>/g;
16
21
 
17
22
  if (Array.isArray(text)) {
18
23
  text = text.join("");
@@ -33,6 +38,10 @@ function formatMessage(text) {
33
38
  return text;
34
39
  }
35
40
 
41
+ // ========================================================================== //
42
+ // Error Classes //
43
+ // ========================================================================== //
44
+
36
45
  class CustomError extends Error {
37
46
  constructor(message, name) {
38
47
  super(message);
@@ -80,6 +89,10 @@ class SommarkError extends CustomError {
80
89
  }
81
90
  }
82
91
 
92
+ // ========================================================================== //
93
+ // Error Dispatcher (Helper) //
94
+ // ========================================================================== //
95
+
83
96
  function getError(type) {
84
97
  const validate_msg = msg => Array.isArray(msg) && msg.length > 0;
85
98
  switch (type) {
package/core/labels.js CHANGED
@@ -3,6 +3,8 @@ export const BLOCK = "Block",
3
3
  INLINE = "Inline",
4
4
  ATBLOCK = "AtBlock",
5
5
  COMMENT = "Comment",
6
+ IMPORT = "Import",
7
+ USE_MODULE = "$use-module",
6
8
  SEMICOLON = "Semicolon",
7
9
  BLOCKCOMMA = "Block-comma",
8
10
  ATBLOCKCOMMA = "Atblock-comma",
@@ -21,4 +23,5 @@ export const BLOCK = "Block",
21
23
  at_value = "At Value",
22
24
  at_id_2 = "At Identifier 2",
23
25
  at_end = "Atblock End",
26
+ block_end_2 = "Block End 2",
24
27
  end_keyword = "end";