sommark 5.0.1 → 5.0.3

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.
@@ -18,7 +18,7 @@ export function registerHostSettings(settings) {
18
18
  hostSettings = settings || {};
19
19
  }
20
20
 
21
- const version = "5.0.1";
21
+ const version = "5.0.3";
22
22
 
23
23
  const SomMark = {
24
24
  version,
package/core/lexer.js CHANGED
@@ -346,8 +346,6 @@ function lexer(src, filename = "anonymous") {
346
346
  // LOGIC BLOCKS (${ ... }$) — explicit: static/runtime ${ }$ shorthand: ${ }$ = static ${ }$
347
347
  if (char === "$" && next === "{") {
348
348
  {
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");
351
349
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
352
350
  i += 2;
353
351
 
package/core/parser.js CHANGED
@@ -389,6 +389,22 @@ function parseValue(tokens, i, placeholders = {}, variables = {}, allowLogic = t
389
389
  nextI++;
390
390
  }
391
391
 
392
+ return [node, nextI, false];
393
+ } else if (current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
394
+ if (!allowLogic) {
395
+ parserError(errorMessage(tokens, i, "literal value", "", "Logic blocks are not allowed in this context."));
396
+ }
397
+ let nextI = i + 1;
398
+ const logicToken = current_token(tokens, nextI);
399
+ const node = makeLogicNode(STATIC_LOGIC);
400
+ node.code = logicToken ? logicToken.value : "";
401
+ node.range = logicToken ? logicToken.range : current_token(tokens, i).range;
402
+ nextI++;
403
+
404
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
405
+ nextI++;
406
+ }
407
+
392
408
  return [node, nextI, false];
393
409
  } else if (current_token(tokens, i).type === TOKEN_TYPES.PREFIX_V) {
394
410
  i++; // consume PREFIX_V keyword
@@ -938,6 +954,28 @@ function parseNode(tokens, i, filename = null, placeholders = {}, variables = {}
938
954
  return [node, nextI];
939
955
  }
940
956
  // ========================================================================== //
957
+ // Bare Logic Block (${ }$ without explicit static/runtime — defaults to static)
958
+ // ========================================================================== //
959
+ else if (current_token(tokens, i) && current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
960
+ global_static_logic_count++;
961
+ let nextI = i + 1;
962
+ const logicToken = current_token(tokens, nextI);
963
+ const node = makeLogicNode(STATIC_LOGIC);
964
+ node.code = logicToken ? logicToken.value : "";
965
+ node.depth = depth;
966
+ node.range = {
967
+ start: current_token(tokens, i).range.start,
968
+ end: logicToken ? logicToken.range.end : current_token(tokens, i).range.end
969
+ };
970
+ nextI++;
971
+
972
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
973
+ nextI++;
974
+ }
975
+
976
+ return [node, nextI];
977
+ }
978
+ // ========================================================================== //
941
979
  // Text or Placeholder //
942
980
  // ========================================================================== //
943
981
  else if (
@@ -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);
@@ -801,8 +801,6 @@ function lexer(src, filename = "anonymous") {
801
801
  // LOGIC BLOCKS (${ ... }$) — explicit: static/runtime ${ }$ shorthand: ${ }$ = static ${ }$
802
802
  if (char === "$" && next === "{") {
803
803
  {
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");
806
804
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
807
805
  i += 2;
808
806
 
@@ -1756,6 +1754,22 @@ function parseValue(tokens, i, placeholders = {}, variables = {}, allowLogic = t
1756
1754
  nextI++;
1757
1755
  }
1758
1756
 
1757
+ return [node, nextI, false];
1758
+ } else if (current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
1759
+ if (!allowLogic) {
1760
+ parserError(errorMessage(tokens, i, "literal value", "", "Logic blocks are not allowed in this context."));
1761
+ }
1762
+ let nextI = i + 1;
1763
+ const logicToken = current_token(tokens, nextI);
1764
+ const node = makeLogicNode(STATIC_LOGIC);
1765
+ node.code = logicToken ? logicToken.value : "";
1766
+ node.range = logicToken ? logicToken.range : current_token(tokens, i).range;
1767
+ nextI++;
1768
+
1769
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
1770
+ nextI++;
1771
+ }
1772
+
1759
1773
  return [node, nextI, false];
1760
1774
  } else if (current_token(tokens, i).type === TOKEN_TYPES.PREFIX_V) {
1761
1775
  i++; // consume PREFIX_V keyword
@@ -2264,6 +2278,27 @@ function parseNode(tokens, i, filename = null, placeholders = {}, variables = {}
2264
2278
  return [node, nextI];
2265
2279
  }
2266
2280
  // ========================================================================== //
2281
+ // Bare Logic Block (${ }$ without explicit static/runtime — defaults to static)
2282
+ // ========================================================================== //
2283
+ else if (current_token(tokens, i) && current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
2284
+ let nextI = i + 1;
2285
+ const logicToken = current_token(tokens, nextI);
2286
+ const node = makeLogicNode(STATIC_LOGIC);
2287
+ node.code = logicToken ? logicToken.value : "";
2288
+ node.depth = depth;
2289
+ node.range = {
2290
+ start: current_token(tokens, i).range.start,
2291
+ end: logicToken ? logicToken.range.end : current_token(tokens, i).range.end
2292
+ };
2293
+ nextI++;
2294
+
2295
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
2296
+ nextI++;
2297
+ }
2298
+
2299
+ return [node, nextI];
2300
+ }
2301
+ // ========================================================================== //
2267
2302
  // Text or Placeholder //
2268
2303
  // ========================================================================== //
2269
2304
  else if (
@@ -8587,7 +8622,7 @@ function registerHostSettings(settings) {
8587
8622
  hostSettings = settings || {};
8588
8623
  }
8589
8624
 
8590
- const version = "5.0.1";
8625
+ const version = "5.0.3";
8591
8626
 
8592
8627
  const SomMark$1 = {
8593
8628
  version,
@@ -10153,6 +10188,7 @@ async function generateOutput(ast, i, format, mapper_file, security = {}, parent
10153
10188
 
10154
10189
  // smark-raw block — body collected verbatim by lexer, bypasses normal body processing pipeline
10155
10190
  if (node.type === BLOCK && (node.props?.["smark-raw"] === "true" || node.props?.["smark-raw"] === true)) {
10191
+ if (generateRuntimeOutput) return "";
10156
10192
  const rawContent = node.body?.map(n => String(n.text || "")).join("") || "";
10157
10193
  const { "smark-raw": _, ...cleanArgs } = node.props;
10158
10194
  const transpiledArgs = await transpileArgs(cleanArgs);
@@ -801,8 +801,6 @@ function lexer(src, filename = "anonymous") {
801
801
  // LOGIC BLOCKS (${ ... }$) — explicit: static/runtime ${ }$ shorthand: ${ }$ = static ${ }$
802
802
  if (char === "$" && next === "{") {
803
803
  {
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");
806
804
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
807
805
  i += 2;
808
806
 
@@ -1756,6 +1754,22 @@ function parseValue(tokens, i, placeholders = {}, variables = {}, allowLogic = t
1756
1754
  nextI++;
1757
1755
  }
1758
1756
 
1757
+ return [node, nextI, false];
1758
+ } else if (current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
1759
+ if (!allowLogic) {
1760
+ parserError(errorMessage(tokens, i, "literal value", "", "Logic blocks are not allowed in this context."));
1761
+ }
1762
+ let nextI = i + 1;
1763
+ const logicToken = current_token(tokens, nextI);
1764
+ const node = makeLogicNode(STATIC_LOGIC);
1765
+ node.code = logicToken ? logicToken.value : "";
1766
+ node.range = logicToken ? logicToken.range : current_token(tokens, i).range;
1767
+ nextI++;
1768
+
1769
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
1770
+ nextI++;
1771
+ }
1772
+
1759
1773
  return [node, nextI, false];
1760
1774
  } else if (current_token(tokens, i).type === TOKEN_TYPES.PREFIX_V) {
1761
1775
  i++; // consume PREFIX_V keyword
@@ -2264,6 +2278,27 @@ function parseNode(tokens, i, filename = null, placeholders = {}, variables = {}
2264
2278
  return [node, nextI];
2265
2279
  }
2266
2280
  // ========================================================================== //
2281
+ // Bare Logic Block (${ }$ without explicit static/runtime — defaults to static)
2282
+ // ========================================================================== //
2283
+ else if (current_token(tokens, i) && current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
2284
+ let nextI = i + 1;
2285
+ const logicToken = current_token(tokens, nextI);
2286
+ const node = makeLogicNode(STATIC_LOGIC);
2287
+ node.code = logicToken ? logicToken.value : "";
2288
+ node.depth = depth;
2289
+ node.range = {
2290
+ start: current_token(tokens, i).range.start,
2291
+ end: logicToken ? logicToken.range.end : current_token(tokens, i).range.end
2292
+ };
2293
+ nextI++;
2294
+
2295
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
2296
+ nextI++;
2297
+ }
2298
+
2299
+ return [node, nextI];
2300
+ }
2301
+ // ========================================================================== //
2267
2302
  // Text or Placeholder //
2268
2303
  // ========================================================================== //
2269
2304
  else if (
@@ -9062,6 +9097,7 @@ async function generateOutput(ast, i, format, mapper_file, security = {}, parent
9062
9097
 
9063
9098
  // smark-raw block — body collected verbatim by lexer, bypasses normal body processing pipeline
9064
9099
  if (node.type === BLOCK && (node.props?.["smark-raw"] === "true" || node.props?.["smark-raw"] === true)) {
9100
+ if (generateRuntimeOutput) return "";
9065
9101
  const rawContent = node.body?.map(n => String(n.text || "")).join("") || "";
9066
9102
  const { "smark-raw": _, ...cleanArgs } = node.props;
9067
9103
  const transpiledArgs = await transpileArgs(cleanArgs);
@@ -451,8 +451,6 @@ function lexer(src, filename = "anonymous") {
451
451
  // LOGIC BLOCKS (${ ... }$) — explicit: static/runtime ${ }$ shorthand: ${ }$ = static ${ }$
452
452
  if (char === "$" && next === "{") {
453
453
  {
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");
456
454
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
457
455
  i += 2;
458
456
 
@@ -472,8 +472,6 @@ function lexer(src, filename = "anonymous") {
472
472
  // LOGIC BLOCKS (${ ... }$) — explicit: static/runtime ${ }$ shorthand: ${ }$ = static ${ }$
473
473
  if (char === "$" && next === "{") {
474
474
  {
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");
477
475
  addToken(TOKEN_TYPES.LOGIC_OPEN, "${");
478
476
  i += 2;
479
477
 
@@ -1311,6 +1309,22 @@ function parseValue(tokens, i, placeholders = {}, variables = {}, allowLogic = t
1311
1309
  nextI++;
1312
1310
  }
1313
1311
 
1312
+ return [node, nextI, false];
1313
+ } else if (current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
1314
+ if (!allowLogic) {
1315
+ parserError(errorMessage(tokens, i, "literal value", "", "Logic blocks are not allowed in this context."));
1316
+ }
1317
+ let nextI = i + 1;
1318
+ const logicToken = current_token(tokens, nextI);
1319
+ const node = makeLogicNode(STATIC_LOGIC);
1320
+ node.code = logicToken ? logicToken.value : "";
1321
+ node.range = logicToken ? logicToken.range : current_token(tokens, i).range;
1322
+ nextI++;
1323
+
1324
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
1325
+ nextI++;
1326
+ }
1327
+
1314
1328
  return [node, nextI, false];
1315
1329
  } else if (current_token(tokens, i).type === TOKEN_TYPES.PREFIX_V) {
1316
1330
  i++; // consume PREFIX_V keyword
@@ -1819,6 +1833,27 @@ function parseNode(tokens, i, filename = null, placeholders = {}, variables = {}
1819
1833
  return [node, nextI];
1820
1834
  }
1821
1835
  // ========================================================================== //
1836
+ // Bare Logic Block (${ }$ without explicit static/runtime — defaults to static)
1837
+ // ========================================================================== //
1838
+ else if (current_token(tokens, i) && current_token(tokens, i).type === TOKEN_TYPES.LOGIC_OPEN) {
1839
+ let nextI = i + 1;
1840
+ const logicToken = current_token(tokens, nextI);
1841
+ const node = makeLogicNode(STATIC_LOGIC);
1842
+ node.code = logicToken ? logicToken.value : "";
1843
+ node.depth = depth;
1844
+ node.range = {
1845
+ start: current_token(tokens, i).range.start,
1846
+ end: logicToken ? logicToken.range.end : current_token(tokens, i).range.end
1847
+ };
1848
+ nextI++;
1849
+
1850
+ if (current_token(tokens, nextI) && current_token(tokens, nextI).type === TOKEN_TYPES.LOGIC_CLOSE) {
1851
+ nextI++;
1852
+ }
1853
+
1854
+ return [node, nextI];
1855
+ }
1856
+ // ========================================================================== //
1822
1857
  // Text or Placeholder //
1823
1858
  // ========================================================================== //
1824
1859
  else if (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sommark",
3
- "version": "5.0.1",
3
+ "version": "5.0.3",
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": [