@markdy/core 0.8.12 → 0.8.14

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 (2) hide show
  1. package/dist/index.js +58 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1571,8 +1571,38 @@ function readIndentedBody(blocks, startIdx, parentIndent) {
1571
1571
  }
1572
1572
  return { body, nextIdx: i };
1573
1573
  }
1574
- function readBody(blocks, startIdx, parentIndent, braceDelimited) {
1575
- if (!braceDelimited) return readIndentedBody(blocks, startIdx, parentIndent);
1574
+ var TOP_LEVEL_KEYWORDS_RE = /^(scene|layout|pattern|group|annotation|edge|beat|var|style)\b/;
1575
+ function isTopLevelStatement(line) {
1576
+ if (line === "}") return true;
1577
+ if (TOP_LEVEL_KEYWORDS_RE.test(line)) return true;
1578
+ const nodeMatch = line.match(/^(\w[\w.-]*)\s+(\w[\w.-]*)/);
1579
+ if (!nodeMatch) return false;
1580
+ const kind = canonicalNodeKind(nodeMatch[1].toLowerCase());
1581
+ return NODE_KINDS.has(kind);
1582
+ }
1583
+ function readColonBody(blocks, startIdx, parentIndent, diagnostics, context, headerLine) {
1584
+ const indented = readIndentedBody(blocks, startIdx, parentIndent);
1585
+ if (indented.body.length > 0 || startIdx >= blocks.length) {
1586
+ return indented;
1587
+ }
1588
+ if (isTopLevelStatement(blocks[startIdx].text)) {
1589
+ return indented;
1590
+ }
1591
+ const body = [];
1592
+ let i = startIdx;
1593
+ while (i < blocks.length) {
1594
+ const block = blocks[i];
1595
+ if (block.indent < parentIndent) break;
1596
+ if (block.indent === parentIndent && isTopLevelStatement(block.text)) break;
1597
+ body.push(block);
1598
+ i++;
1599
+ }
1600
+ return { body, nextIdx: i };
1601
+ }
1602
+ function readBody(blocks, startIdx, parentIndent, braceDelimited, diagnostics = [], context = "block", headerLine = 1) {
1603
+ if (!braceDelimited) {
1604
+ return readColonBody(blocks, startIdx, parentIndent, diagnostics, context, headerLine);
1605
+ }
1576
1606
  const body = [];
1577
1607
  let i = startIdx;
1578
1608
  while (i < blocks.length) {
@@ -1847,7 +1877,15 @@ function parse(source, opts = {}) {
1847
1877
  const m = line.match(/^pattern\s+(\w+)\s*\(([^)]*)\)\s*(?::|\{)\s*$/);
1848
1878
  if (!m) throw new ParseError(`expected pattern name(params):`, lineNo);
1849
1879
  const params = m[2].trim() ? m[2].split(",").map((p) => p.trim()) : [];
1850
- const { body, nextIdx } = readBody(blocks, i + 1, block.indent, line.endsWith("{"));
1880
+ const { body, nextIdx } = readBody(
1881
+ blocks,
1882
+ i + 1,
1883
+ block.indent,
1884
+ line.endsWith("{"),
1885
+ diagnostics,
1886
+ `pattern '${m[1]}'`,
1887
+ lineNo
1888
+ );
1851
1889
  const cues = normalizeCueBlocks(body).map((b) => parseCueLine(b.text, b.line));
1852
1890
  patterns[m[1]] = { name: m[1], params, body: cues, line: lineNo };
1853
1891
  i = nextIdx;
@@ -1868,7 +1906,14 @@ function parse(source, opts = {}) {
1868
1906
  }
1869
1907
  const header = line.match(/^group\s+(\w+)(?:\s+"([^"]*)")?\s*:\s*$/);
1870
1908
  if (!header) throw new ParseError(`expected group name: A B C`, lineNo);
1871
- const { body, nextIdx } = readIndentedBody(blocks, i + 1, block.indent);
1909
+ const { body, nextIdx } = readColonBody(
1910
+ blocks,
1911
+ i + 1,
1912
+ block.indent,
1913
+ diagnostics,
1914
+ `group '${header[1]}'`,
1915
+ lineNo
1916
+ );
1872
1917
  const members = body.flatMap((b) => splitTargets(b.text));
1873
1918
  if (members.length === 0) throw new ParseError(`group '${header[1]}' has no members`, lineNo);
1874
1919
  groups[header[1]] = {
@@ -1919,7 +1964,15 @@ function parse(source, opts = {}) {
1919
1964
  if (line.startsWith("beat ")) {
1920
1965
  const m = line.match(/^beat\s+([\w.-]+)(?:\s+"([^"]*)")?\s*(?::|\{)\s*$/);
1921
1966
  if (!m) throw new ParseError(`expected beat name:`, lineNo);
1922
- const { body, nextIdx } = readBody(blocks, i + 1, block.indent, line.endsWith("{"));
1967
+ const { body, nextIdx } = readBody(
1968
+ blocks,
1969
+ i + 1,
1970
+ block.indent,
1971
+ line.endsWith("{"),
1972
+ diagnostics,
1973
+ `beat '${m[1]}'`,
1974
+ lineNo
1975
+ );
1923
1976
  let cues = normalizeCueBlocks(body).map((b) => parseCueLine(b.text, b.line));
1924
1977
  cues = expandPatternCues(cues, patterns, lineNo);
1925
1978
  beats.push({ name: m[1], label: m[2], cues, line: lineNo });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markdy/core",
3
- "version": "0.8.12",
3
+ "version": "0.8.14",
4
4
  "description": "Diagram-native MarkdyScript parser and compiler (auto-layout, edge routing, cue scheduling) — zero runtime dependencies.",
5
5
  "license": "MIT",
6
6
  "type": "module",