sommark 5.0.0 → 5.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/README.md CHANGED
@@ -418,7 +418,7 @@ export default {
418
418
  removeComments: true,
419
419
  placeholders: {},
420
420
  importAliases: { "@": "./" },
421
- fallbackTarget: "style",
421
+ fallbackTarget: true,
422
422
  outputValidator: null,
423
423
  baseDir: null,
424
424
  showSpinner: true,
@@ -26,7 +26,7 @@ export default {
26
26
  importAliases: { // Custom path aliases for modules (e.g. { "@": "./src/components" })
27
27
  "@": "./"
28
28
  },
29
- fallbackTarget: "style", // Where unrecognized attributes go: "style", "class", or false to disable
29
+ fallbackTarget: true, // Enable style fallback for unrecognized attributes (true or false)
30
30
  outputValidator: null, // Custom callback function: async (transpiledOutput) => { ... }
31
31
  baseDir: null, // Base directory for resolving relative module imports
32
32
  showSpinner: true, // Display a dynamic spinner in the terminal during transpilation
@@ -150,10 +150,6 @@ export const HTML_PROPS = new Set([
150
150
  "optimum",
151
151
 
152
152
  // Deprecated (still valid)
153
- "align",
154
- "bgcolor",
155
- "border",
156
- "color",
157
153
  "coords",
158
154
  "shape",
159
155
  "summary",
@@ -161,6 +157,5 @@ export const HTML_PROPS = new Set([
161
157
  // Experimental
162
158
  "elementtiming",
163
159
  "colorspace",
164
- "alpha",
165
160
  "csp",
166
161
  ]);
@@ -83,7 +83,7 @@ export async function findAndLoadConfig(targetPath) {
83
83
  placeholders: {},
84
84
  customProps: [],
85
85
  importAliases: {},
86
- fallbackTarget: "style",
86
+ fallbackTarget: true,
87
87
  outputValidator: null,
88
88
  baseDir: null,
89
89
  showSpinner: true,
@@ -18,7 +18,7 @@ export function registerHostSettings(settings) {
18
18
  hostSettings = settings || {};
19
19
  }
20
20
 
21
- const version = "5.0.0";
21
+ const version = "5.0.2";
22
22
 
23
23
  const SomMark = {
24
24
  version,
package/core/lexer.js CHANGED
@@ -347,7 +347,12 @@ function lexer(src, filename = "anonymous") {
347
347
  if (char === "$" && next === "{") {
348
348
  {
349
349
  const hasExplicitKeyword = last_non_junk_type === TOKEN_TYPES.STATIC_KEYWORD || last_non_junk_type === TOKEN_TYPES.RUNTIME_KEYWORD;
350
- if (!hasExplicitKeyword) addToken(TOKEN_TYPES.STATIC_KEYWORD, "static");
350
+ if (!hasExplicitKeyword) {
351
+ // Zero-width: synthetic token has no source presence, must not shift position
352
+ tokens.push({ type: TOKEN_TYPES.STATIC_KEYWORD, value: "static", source: filename, range: { start: { line, character }, end: { line, character } } });
353
+ prev_type = TOKEN_TYPES.STATIC_KEYWORD;
354
+ last_non_junk_type = TOKEN_TYPES.STATIC_KEYWORD;
355
+ }
351
356
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
352
357
  i += 2;
353
358
 
@@ -220,6 +220,7 @@ async function generateOutput(ast, i, format, mapper_file, security = {}, parent
220
220
 
221
221
  // smark-raw block — body collected verbatim by lexer, bypasses normal body processing pipeline
222
222
  if (node.type === BLOCK && (node.props?.["smark-raw"] === "true" || node.props?.["smark-raw"] === true)) {
223
+ if (generateRuntimeOutput) return "";
223
224
  const rawContent = node.body?.map(n => String(n.text || "")).join("") || "";
224
225
  const { "smark-raw": _, ...cleanArgs } = node.props;
225
226
  const transpiledArgs = await transpileArgs(cleanArgs);
@@ -802,7 +802,12 @@ function lexer(src, filename = "anonymous") {
802
802
  if (char === "$" && next === "{") {
803
803
  {
804
804
  const hasExplicitKeyword = last_non_junk_type === TOKEN_TYPES.STATIC_KEYWORD || last_non_junk_type === TOKEN_TYPES.RUNTIME_KEYWORD;
805
- if (!hasExplicitKeyword) addToken(TOKEN_TYPES.STATIC_KEYWORD, "static");
805
+ if (!hasExplicitKeyword) {
806
+ // Zero-width: synthetic token has no source presence, must not shift position
807
+ tokens.push({ type: TOKEN_TYPES.STATIC_KEYWORD, value: "static", source: filename, range: { start: { line, character }, end: { line, character } } });
808
+ TOKEN_TYPES.STATIC_KEYWORD;
809
+ last_non_junk_type = TOKEN_TYPES.STATIC_KEYWORD;
810
+ }
806
811
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
807
812
  i += 2;
808
813
 
@@ -8587,7 +8592,7 @@ function registerHostSettings(settings) {
8587
8592
  hostSettings = settings || {};
8588
8593
  }
8589
8594
 
8590
- const version = "5.0.0";
8595
+ const version = "5.0.2";
8591
8596
 
8592
8597
  const SomMark$1 = {
8593
8598
  version,
@@ -10153,6 +10158,7 @@ async function generateOutput(ast, i, format, mapper_file, security = {}, parent
10153
10158
 
10154
10159
  // smark-raw block — body collected verbatim by lexer, bypasses normal body processing pipeline
10155
10160
  if (node.type === BLOCK && (node.props?.["smark-raw"] === "true" || node.props?.["smark-raw"] === true)) {
10161
+ if (generateRuntimeOutput) return "";
10156
10162
  const rawContent = node.body?.map(n => String(n.text || "")).join("") || "";
10157
10163
  const { "smark-raw": _, ...cleanArgs } = node.props;
10158
10164
  const transpiledArgs = await transpileArgs(cleanArgs);
@@ -10794,10 +10800,6 @@ const HTML_PROPS = new Set([
10794
10800
  "optimum",
10795
10801
 
10796
10802
  // Deprecated (still valid)
10797
- "align",
10798
- "bgcolor",
10799
- "border",
10800
- "color",
10801
10803
  "coords",
10802
10804
  "shape",
10803
10805
  "summary",
@@ -10805,7 +10807,6 @@ const HTML_PROPS = new Set([
10805
10807
  // Experimental
10806
10808
  "elementtiming",
10807
10809
  "colorspace",
10808
- "alpha",
10809
10810
  "csp",
10810
10811
  ]);
10811
10812
 
@@ -13908,7 +13909,7 @@ class SomMark {
13908
13909
  * @param {string} [options.baseDir=null] - The base directory for resolving relative paths.
13909
13910
  */
13910
13911
  constructor(options = {}) {
13911
- const { src, ast = null, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], fallbackTarget = "style", outputValidator = null, importAliases = {}, importStack = [], baseDir = null, moduleCache = null, showSpinner = true, security = {}, dualOutput = false, moduleIdentityToken = null } = options;
13912
+ const { src, ast = null, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], fallbackTarget = true, outputValidator = null, importAliases = {}, importStack = [], baseDir = null, moduleCache = null, showSpinner = true, security = {}, dualOutput = false, moduleIdentityToken = null } = options;
13912
13913
  this.rawSettings = options;
13913
13914
  this.src = src;
13914
13915
  this.ast = ast;
@@ -13924,15 +13925,15 @@ class SomMark {
13924
13925
  || (options.files ? new VirtualFS(options.files) : null)
13925
13926
  || (isURL(options.baseDir) ? new FetchFS(options.baseDir) : defaultFs);
13926
13927
 
13927
- // Validate fallbackTarget
13928
- const VALID_FALLBACK_TARGETS = new Set(["style", "class", false]);
13928
+ // Validate fallbackTarget — "style" is accepted as an alias for true (backward compat)
13929
+ const VALID_FALLBACK_TARGETS = new Set([true, false, "style"]);
13929
13930
  if (!VALID_FALLBACK_TARGETS.has(fallbackTarget)) {
13930
13931
  runtimeError([
13931
13932
  `{line}<$red:Invalid fallbackTarget$>: <$green:'${fallbackTarget}'$> <$yellow:is not a valid value.$>`,
13932
- `{N}<$yellow:Use$> <$green:'style'$><$yellow:,$> <$green:'class'$><$yellow:, or$> <$green:false$><$yellow:.$>{line}`
13933
+ `{N}<$yellow:Use$> <$green:true$> <$yellow:or$> <$green:false$><$yellow:.$>{line}`
13933
13934
  ]);
13934
13935
  }
13935
- this.fallbackTarget = fallbackTarget;
13936
+ this.fallbackTarget = fallbackTarget === "style" ? true : fallbackTarget;
13936
13937
  this.outputValidator = outputValidator;
13937
13938
  this.importAliases = importAliases;
13938
13939
  this.importStack = importStack;
@@ -802,7 +802,12 @@ function lexer(src, filename = "anonymous") {
802
802
  if (char === "$" && next === "{") {
803
803
  {
804
804
  const hasExplicitKeyword = last_non_junk_type === TOKEN_TYPES.STATIC_KEYWORD || last_non_junk_type === TOKEN_TYPES.RUNTIME_KEYWORD;
805
- if (!hasExplicitKeyword) addToken(TOKEN_TYPES.STATIC_KEYWORD, "static");
805
+ if (!hasExplicitKeyword) {
806
+ // Zero-width: synthetic token has no source presence, must not shift position
807
+ tokens.push({ type: TOKEN_TYPES.STATIC_KEYWORD, value: "static", source: filename, range: { start: { line, character }, end: { line, character } } });
808
+ TOKEN_TYPES.STATIC_KEYWORD;
809
+ last_non_junk_type = TOKEN_TYPES.STATIC_KEYWORD;
810
+ }
806
811
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
807
812
  i += 2;
808
813
 
@@ -9062,6 +9067,7 @@ async function generateOutput(ast, i, format, mapper_file, security = {}, parent
9062
9067
 
9063
9068
  // smark-raw block — body collected verbatim by lexer, bypasses normal body processing pipeline
9064
9069
  if (node.type === BLOCK && (node.props?.["smark-raw"] === "true" || node.props?.["smark-raw"] === true)) {
9070
+ if (generateRuntimeOutput) return "";
9065
9071
  const rawContent = node.body?.map(n => String(n.text || "")).join("") || "";
9066
9072
  const { "smark-raw": _, ...cleanArgs } = node.props;
9067
9073
  const transpiledArgs = await transpileArgs(cleanArgs);
@@ -9703,10 +9709,6 @@ const HTML_PROPS = new Set([
9703
9709
  "optimum",
9704
9710
 
9705
9711
  // Deprecated (still valid)
9706
- "align",
9707
- "bgcolor",
9708
- "border",
9709
- "color",
9710
9712
  "coords",
9711
9713
  "shape",
9712
9714
  "summary",
@@ -9714,7 +9716,6 @@ const HTML_PROPS = new Set([
9714
9716
  // Experimental
9715
9717
  "elementtiming",
9716
9718
  "colorspace",
9717
- "alpha",
9718
9719
  "csp",
9719
9720
  ]);
9720
9721
 
@@ -12817,7 +12818,7 @@ class SomMark {
12817
12818
  * @param {string} [options.baseDir=null] - The base directory for resolving relative paths.
12818
12819
  */
12819
12820
  constructor(options = {}) {
12820
- const { src, ast = null, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], fallbackTarget = "style", outputValidator = null, importAliases = {}, importStack = [], baseDir = null, moduleCache = null, showSpinner = true, security = {}, dualOutput = false, moduleIdentityToken = null } = options;
12821
+ const { src, ast = null, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], fallbackTarget = true, outputValidator = null, importAliases = {}, importStack = [], baseDir = null, moduleCache = null, showSpinner = true, security = {}, dualOutput = false, moduleIdentityToken = null } = options;
12821
12822
  this.rawSettings = options;
12822
12823
  this.src = src;
12823
12824
  this.ast = ast;
@@ -12833,15 +12834,15 @@ class SomMark {
12833
12834
  || (options.files ? new VirtualFS(options.files) : null)
12834
12835
  || (isURL(options.baseDir) ? new FetchFS(options.baseDir) : defaultFs);
12835
12836
 
12836
- // Validate fallbackTarget
12837
- const VALID_FALLBACK_TARGETS = new Set(["style", "class", false]);
12837
+ // Validate fallbackTarget — "style" is accepted as an alias for true (backward compat)
12838
+ const VALID_FALLBACK_TARGETS = new Set([true, false, "style"]);
12838
12839
  if (!VALID_FALLBACK_TARGETS.has(fallbackTarget)) {
12839
12840
  runtimeError([
12840
12841
  `{line}<$red:Invalid fallbackTarget$>: <$green:'${fallbackTarget}'$> <$yellow:is not a valid value.$>`,
12841
- `{N}<$yellow:Use$> <$green:'style'$><$yellow:,$> <$green:'class'$><$yellow:, or$> <$green:false$><$yellow:.$>{line}`
12842
+ `{N}<$yellow:Use$> <$green:true$> <$yellow:or$> <$green:false$><$yellow:.$>{line}`
12842
12843
  ]);
12843
12844
  }
12844
- this.fallbackTarget = fallbackTarget;
12845
+ this.fallbackTarget = fallbackTarget === "style" ? true : fallbackTarget;
12845
12846
  this.outputValidator = outputValidator;
12846
12847
  this.importAliases = importAliases;
12847
12848
  this.importStack = importStack;
@@ -452,7 +452,12 @@ function lexer(src, filename = "anonymous") {
452
452
  if (char === "$" && next === "{") {
453
453
  {
454
454
  const hasExplicitKeyword = last_non_junk_type === TOKEN_TYPES.STATIC_KEYWORD || last_non_junk_type === TOKEN_TYPES.RUNTIME_KEYWORD;
455
- if (!hasExplicitKeyword) addToken(TOKEN_TYPES.STATIC_KEYWORD, "static");
455
+ if (!hasExplicitKeyword) {
456
+ // Zero-width: synthetic token has no source presence, must not shift position
457
+ tokens.push({ type: TOKEN_TYPES.STATIC_KEYWORD, value: "static", source: filename, range: { start: { line, character }, end: { line, character } } });
458
+ TOKEN_TYPES.STATIC_KEYWORD;
459
+ last_non_junk_type = TOKEN_TYPES.STATIC_KEYWORD;
460
+ }
456
461
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
457
462
  i += 2;
458
463
 
@@ -473,7 +473,12 @@ function lexer(src, filename = "anonymous") {
473
473
  if (char === "$" && next === "{") {
474
474
  {
475
475
  const hasExplicitKeyword = last_non_junk_type === TOKEN_TYPES.STATIC_KEYWORD || last_non_junk_type === TOKEN_TYPES.RUNTIME_KEYWORD;
476
- if (!hasExplicitKeyword) addToken(TOKEN_TYPES.STATIC_KEYWORD, "static");
476
+ if (!hasExplicitKeyword) {
477
+ // Zero-width: synthetic token has no source presence, must not shift position
478
+ tokens.push({ type: TOKEN_TYPES.STATIC_KEYWORD, value: "static", source: filename, range: { start: { line, character }, end: { line, character } } });
479
+ TOKEN_TYPES.STATIC_KEYWORD;
480
+ last_non_junk_type = TOKEN_TYPES.STATIC_KEYWORD;
481
+ }
477
482
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
478
483
  i += 2;
479
484
 
package/index.shared.js CHANGED
@@ -74,7 +74,7 @@ class SomMark {
74
74
  * @param {string} [options.baseDir=null] - The base directory for resolving relative paths.
75
75
  */
76
76
  constructor(options = {}) {
77
- const { src, ast = null, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], fallbackTarget = "style", outputValidator = null, importAliases = {}, importStack = [], baseDir = null, moduleCache = null, showSpinner = true, security = {}, dualOutput = false, moduleIdentityToken = null } = options;
77
+ const { src, ast = null, format, mapperFile = null, filename = "anonymous", removeComments = true, placeholders = {}, customProps = [], fallbackTarget = true, outputValidator = null, importAliases = {}, importStack = [], baseDir = null, moduleCache = null, showSpinner = true, security = {}, dualOutput = false, moduleIdentityToken = null } = options;
78
78
  this.rawSettings = options;
79
79
  this.src = src;
80
80
  this.ast = ast;
@@ -90,15 +90,15 @@ class SomMark {
90
90
  || (options.files ? new VirtualFS(options.files) : null)
91
91
  || (isURL(options.baseDir) ? new FetchFS(options.baseDir) : defaultFs);
92
92
 
93
- // Validate fallbackTarget
94
- const VALID_FALLBACK_TARGETS = new Set(["style", "class", false]);
93
+ // Validate fallbackTarget — "style" is accepted as an alias for true (backward compat)
94
+ const VALID_FALLBACK_TARGETS = new Set([true, false, "style"]);
95
95
  if (!VALID_FALLBACK_TARGETS.has(fallbackTarget)) {
96
96
  runtimeError([
97
97
  `{line}<$red:Invalid fallbackTarget$>: <$green:'${fallbackTarget}'$> <$yellow:is not a valid value.$>`,
98
- `{N}<$yellow:Use$> <$green:'style'$><$yellow:,$> <$green:'class'$><$yellow:, or$> <$green:false$><$yellow:.$>{line}`
98
+ `{N}<$yellow:Use$> <$green:true$> <$yellow:or$> <$green:false$><$yellow:.$>{line}`
99
99
  ]);
100
100
  }
101
- this.fallbackTarget = fallbackTarget;
101
+ this.fallbackTarget = fallbackTarget === "style" ? true : fallbackTarget;
102
102
  this.outputValidator = outputValidator;
103
103
  this.importAliases = importAliases;
104
104
  this.importStack = importStack;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sommark",
3
- "version": "5.0.0",
3
+ "version": "5.0.2",
4
4
  "description": "SomMark is a template language that compiles to multiple output formats — HTML, JSON, YAML, TOML, CSV, Markdown, XML, and more.",
5
5
  "main": "index.js",
6
6
  "files": [