sommark 3.3.4 → 4.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.
Files changed (61) hide show
  1. package/README.md +98 -82
  2. package/assets/logo.json +28 -0
  3. package/assets/smark.logo.png +0 -0
  4. package/assets/smark.logo.svg +21 -0
  5. package/cli/cli.mjs +7 -17
  6. package/cli/commands/build.js +24 -4
  7. package/cli/commands/color.js +22 -26
  8. package/cli/commands/help.js +10 -10
  9. package/cli/commands/init.js +20 -31
  10. package/cli/commands/print.js +18 -16
  11. package/cli/commands/show.js +4 -0
  12. package/cli/commands/version.js +6 -0
  13. package/cli/constants.js +9 -5
  14. package/cli/helpers/config.js +11 -0
  15. package/cli/helpers/file.js +17 -6
  16. package/cli/helpers/transpile.js +7 -12
  17. package/core/errors.js +49 -25
  18. package/core/formats.js +7 -3
  19. package/core/formatter.js +215 -0
  20. package/core/helpers/config-loader.js +29 -74
  21. package/core/labels.js +21 -9
  22. package/core/lexer.js +491 -212
  23. package/core/modules.js +164 -0
  24. package/core/parser.js +516 -389
  25. package/core/tokenTypes.js +36 -1
  26. package/core/transpiler.js +237 -154
  27. package/core/validator.js +79 -0
  28. package/formatter/mark.js +203 -43
  29. package/formatter/tag.js +202 -32
  30. package/grammar.ebnf +57 -50
  31. package/helpers/colorize.js +26 -13
  32. package/helpers/escapeHTML.js +13 -6
  33. package/helpers/kebabize.js +6 -0
  34. package/helpers/peek.js +9 -0
  35. package/helpers/removeChar.js +26 -13
  36. package/helpers/safeDataParser.js +114 -0
  37. package/helpers/utils.js +140 -158
  38. package/index.js +198 -188
  39. package/mappers/languages/html.js +105 -213
  40. package/mappers/languages/json.js +122 -171
  41. package/mappers/languages/markdown.js +355 -108
  42. package/mappers/languages/mdx.js +76 -120
  43. package/mappers/languages/xml.js +114 -0
  44. package/mappers/mapper.js +152 -123
  45. package/mappers/shared/index.js +22 -0
  46. package/package.json +26 -6
  47. package/SOMMARK-SPEC.md +0 -481
  48. package/cli/commands/list.js +0 -124
  49. package/constants/html_tags.js +0 -146
  50. package/core/pluginManager.js +0 -149
  51. package/core/plugins/comment-remover.js +0 -47
  52. package/core/plugins/module-system.js +0 -176
  53. package/core/plugins/raw-content-plugin.js +0 -78
  54. package/core/plugins/rules-validation-plugin.js +0 -231
  55. package/core/plugins/sommark-format.js +0 -244
  56. package/coverage_test.js +0 -21
  57. package/debug.js +0 -15
  58. package/helpers/camelize.js +0 -2
  59. package/helpers/defaultTheme.js +0 -3
  60. package/test_format_fix.js +0 -42
  61. package/v3-todo.smark +0 -73
@@ -1,51 +1,20 @@
1
1
  import path from "node:path";
2
- import os from "node:os";
3
2
  import fs from "node:fs/promises";
4
- import { pathToFileURL, fileURLToPath } from "node:url";
3
+ import { pathToFileURL } from "node:url";
5
4
 
6
5
  const CONFIG_FILE_NAME = "smark.config.js";
7
6
 
8
7
  /**
9
- * Gets the global configuration directory based on the OS.
10
- */
11
- export function getConfigDir() {
12
- const homeDir = os.homedir();
13
- if (process.platform === "win32") {
14
- return path.join(process.env.APPDATA || path.join(homeDir, "AppData", "Roaming"), "sommark");
15
- } else if (process.platform === "darwin") {
16
- return path.join(homeDir, "Library", "Application Support", "sommark");
17
- } else {
18
- return path.join(process.env.XDG_CONFIG_HOME || path.join(homeDir, ".config"), "sommark");
19
- }
20
- }
21
-
22
- /**
23
- * Recursively searches for smark.config.js up the directory tree starting from startDir.
24
- */
25
- async function findConfig(startDir) {
26
- let currentDir = path.resolve(startDir);
27
- const root = path.parse(currentDir).root;
28
-
29
- while (true) {
30
- const configPath = path.join(currentDir, CONFIG_FILE_NAME);
31
- try {
32
- await fs.access(configPath);
33
- return configPath;
34
- } catch {
35
- if (currentDir === root) break;
36
- currentDir = path.dirname(currentDir);
37
- }
38
- }
39
- return null;
40
- }
41
-
42
- /**
43
- * Loads the configuration from a file.
8
+ * Loads a configuration object from a Javascript file.
9
+ * We add the current time to the file path. This makes Node.js read
10
+ * the file again instead of using an old copy from its memory.
11
+ *
12
+ * @param {string} configPath - The absolute path to the config file.
13
+ * @returns {Promise<Object|null>} - The configuration object or null on error.
44
14
  */
45
15
  async function loadConfigFile(configPath) {
46
16
  if (!configPath) return null;
47
17
  try {
48
- // Use a timestamp to bypass cache for dynamic updates in LSP
49
18
  const configURL = `${pathToFileURL(configPath).href}?t=${Date.now()}`;
50
19
  const loadedModule = await import(configURL);
51
20
  return loadedModule.default || loadedModule;
@@ -55,73 +24,59 @@ async function loadConfigFile(configPath) {
55
24
  }
56
25
 
57
26
  /**
58
- * Finds and loads the configuration starting from targetPath.
59
- * Checks local directory, parent directories, and finally the global config directory.
27
+ * Finds and loads the SomMark configuration file.
28
+ * It looks in the current folder or a specific path if provided.
29
+ *
30
+ * @param {string|null} targetPath - A specific file or folder to look in.
31
+ * @returns {Promise<Object>} - The final configuration merged with defaults.
60
32
  */
61
33
  export async function findAndLoadConfig(targetPath) {
62
- let startDir;
34
+ let startDir = process.cwd();
35
+ let configPath = null;
36
+
37
+ // 1. Check if targetPath is an explicit config file path
63
38
  if (targetPath) {
64
39
  try {
65
40
  const stats = await fs.stat(targetPath);
66
- startDir = stats.isDirectory() ? targetPath : path.dirname(targetPath);
67
- } catch {
68
- startDir = process.cwd();
69
- }
70
- } else {
71
- startDir = process.cwd();
72
- }
73
-
74
- let configPath = await findConfig(startDir);
75
-
76
- if (!configPath) {
77
- // As a fallback, check the current working directory of the process
78
- // This helps LSP find the project config when running in the project root
79
- const localConfigPath = path.join(process.cwd(), CONFIG_FILE_NAME);
80
- try {
81
- await fs.access(localConfigPath);
82
- configPath = localConfigPath;
41
+ if (stats.isFile() && targetPath.endsWith(".js")) {
42
+ configPath = path.resolve(targetPath);
43
+ } else {
44
+ startDir = stats.isDirectory() ? targetPath : path.dirname(targetPath);
45
+ }
83
46
  } catch {
84
- // Not in CWD
47
+ // Path doesn't exist
85
48
  }
86
49
  }
87
50
 
51
+ // 2. Check the current folder
88
52
  if (!configPath) {
89
- const globalConfigPath = path.join(getConfigDir(), CONFIG_FILE_NAME);
53
+ const localConfig = path.join(startDir, CONFIG_FILE_NAME);
90
54
  try {
91
- await fs.access(globalConfigPath);
92
- configPath = globalConfigPath;
55
+ await fs.access(localConfig);
56
+ configPath = localConfig;
93
57
  } catch {
94
- // No config found
58
+ // No local config found
95
59
  }
96
60
  }
97
-
61
+
98
62
  const defaultConfig = {
99
63
  outputFile: "output",
100
64
  outputDir: startDir,
101
65
  mappingFile: null,
102
- plugins: [],
103
- priority: [],
104
- excludePlugins: [],
105
- includeDocument: true
66
+ removeComments: true,
106
67
  };
107
68
 
108
69
  if (configPath) {
109
70
  const loadedConfig = await loadConfigFile(configPath);
110
71
  if (loadedConfig) {
111
72
  const finalConfig = { ...defaultConfig, ...loadedConfig, resolvedConfigPath: configPath };
112
-
113
- // Ensure outputDir is resolved if it's relative in the config
114
73
  if (loadedConfig.outputDir) {
115
74
  const configDir = path.dirname(configPath);
116
75
  finalConfig.outputDir = path.resolve(configDir, loadedConfig.outputDir);
117
76
  }
118
-
119
77
  return finalConfig;
120
78
  }
121
79
  }
122
80
 
123
81
  return { ...defaultConfig, resolvedConfigPath: null };
124
82
  }
125
-
126
-
127
-
package/core/labels.js CHANGED
@@ -1,27 +1,39 @@
1
+ /**
2
+ * These labels identify different parts of the code (like blocks or text)
3
+ * so the system knows how to handle them.
4
+ */
1
5
  export const BLOCK = "Block",
2
6
  TEXT = "Text",
3
7
  INLINE = "Inline",
4
8
  ATBLOCK = "AtBlock",
5
9
  COMMENT = "Comment",
6
10
  IMPORT = "Import",
7
- USE_MODULE = "$use-module",
8
- SEMICOLON = "Semicolon",
11
+ USE_MODULE = "$use-module";
12
+
13
+ /**
14
+ * Names for symbols used to separate parts of the code (like commas and colons).
15
+ */
16
+ export const SEMICOLON = "Semicolon",
9
17
  BLOCKCOMMA = "Block-comma",
10
18
  ATBLOCKCOMMA = "Atblock-comma",
11
19
  INLINECOMMA = "Inline-comma",
12
20
  BLOCKCOLON = "Block-colon",
13
21
  ATBLOCKCOLON = "Atblock-colon",
14
- INLINECOLON = "Inline-colon",
15
- block_id = "Block Identifier",
22
+ INLINECOLON = "Inline-colon";
23
+
24
+ /**
25
+ * These names are used in error messages to tell you exactly which part
26
+ * of your code has a mistake.
27
+ */
28
+ export const block_id = "Block Identifier",
16
29
  block_value = "Block Value",
17
- block_id_2 = "Block Identifier 2",
30
+ block_key = "Block Key",
18
31
  block_end = "Block end",
19
32
  inline_id = "Inline Identifier",
20
- inline_value = "Inline Value",
21
- inline_id_2 = "Inline Identifier 2",
33
+ inline_text = "Inline Text",
22
34
  at_id = "At Identifier",
23
35
  at_value = "At Value",
24
- at_id_2 = "At Identifier 2",
36
+ atblock_key = "AtBlock Key",
25
37
  at_end = "Atblock End",
26
- block_end_2 = "Block End 2",
38
+ /** Reserved keyword for closing blocks */
27
39
  end_keyword = "end";