@tmlmt/cooklang-parser 3.0.0-alpha.22 → 3.0.0-alpha.23

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/dist/index.cjs CHANGED
@@ -1833,6 +1833,10 @@ function parseNestedMetaVar(content, varName) {
1833
1833
  const match = content.match(nestedMetaVarRegex(varName));
1834
1834
  if (!match) return void 0;
1835
1835
  const nestedContent = match[1];
1836
+ const lines = nestedContent.split(/\r?\n/).filter((line) => line.trim() !== "");
1837
+ if (lines.length > 0 && lines[0].trim().startsWith("- ")) {
1838
+ return parseListItems(lines);
1839
+ }
1836
1840
  return parseNestedBlock(nestedContent);
1837
1841
  }
1838
1842
  function parseNestedBlock(content) {
@@ -1859,7 +1863,7 @@ function parseNestedBlock(content) {
1859
1863
  if (currentIndent !== baseIndent) {
1860
1864
  throw new BadIndentationError();
1861
1865
  }
1862
- const keyValueMatch = line.match(/^[ ]*([^:\n]+?):\s*(.*)$/);
1866
+ const keyValueMatch = line.match(/^ *([^:\n]+?):\s*(.*)$/);
1863
1867
  if (!keyValueMatch) {
1864
1868
  i2++;
1865
1869
  continue;
@@ -1871,7 +1875,7 @@ function parseNestedBlock(content) {
1871
1875
  let j = i2 + 1;
1872
1876
  while (j < lines.length) {
1873
1877
  const childLine = lines[j];
1874
- const childIndent = childLine.match(/^([ ]*)/)?.[1]?.length;
1878
+ const childIndent = childLine.match(/^( *)/)?.[1]?.length;
1875
1879
  if (childIndent && childIndent > baseIndent) {
1876
1880
  childLines.push(childLine);
1877
1881
  j++;
@@ -1882,14 +1886,7 @@ function parseNestedBlock(content) {
1882
1886
  if (childLines.length > 0) {
1883
1887
  const firstChildTrimmed = childLines[0].trim();
1884
1888
  if (firstChildTrimmed.startsWith("- ")) {
1885
- const reconstructedContent = `${key}:
1886
- ${childLines.join("\n")}`;
1887
- const listResult = parseListMetaVar(reconstructedContent, key);
1888
- if (listResult) {
1889
- result[key] = listResult.map(
1890
- (item) => parseMetadataValue(item)
1891
- );
1892
- }
1889
+ result[key] = parseListItems(childLines);
1893
1890
  } else {
1894
1891
  const childContent = childLines.join("\n");
1895
1892
  const nested = parseNestedBlock(childContent);
@@ -1897,16 +1894,67 @@ ${childLines.join("\n")}`;
1897
1894
  result[key] = nested;
1898
1895
  }
1899
1896
  }
1897
+ } else {
1898
+ result[key] = "";
1900
1899
  }
1901
1900
  i2 = j;
1902
1901
  } else {
1903
- result[key] = parseMetadataValue(rawValue);
1902
+ result[key] = parseSingleLineMetadataValue(rawValue);
1904
1903
  i2++;
1905
1904
  }
1906
1905
  }
1907
1906
  return result;
1908
1907
  }
1909
- function parseMetadataValue(rawValue) {
1908
+ function parseListItems(childLines) {
1909
+ const listIndent = childLines[0].match(/^( *)/)?.[1]?.length;
1910
+ const groups = [];
1911
+ let currentGroup = [];
1912
+ for (const line of childLines) {
1913
+ const indent = line.match(/^( *)/)?.[1]?.length;
1914
+ if (indent === listIndent && line.trim().startsWith("- ")) {
1915
+ if (currentGroup.length > 0) {
1916
+ groups.push(currentGroup);
1917
+ }
1918
+ currentGroup = [line];
1919
+ } else {
1920
+ currentGroup.push(line);
1921
+ }
1922
+ }
1923
+ groups.push(currentGroup);
1924
+ const isObjectItem = (group) => {
1925
+ if (group.length > 1) return true;
1926
+ const value = group[0].replace(/^\s*-\s*/, "").trim();
1927
+ return /^[^:\n]+:\s/.test(value);
1928
+ };
1929
+ const hasObjectItems = groups.some(isObjectItem);
1930
+ if (!hasObjectItems) {
1931
+ return groups.map((group) => {
1932
+ const value = group[0].replace(/^\s*-\s*/, "").trim();
1933
+ return parseSingleLineMetadataValue(value);
1934
+ });
1935
+ }
1936
+ const items = [];
1937
+ for (const group of groups) {
1938
+ const firstLine = group[0];
1939
+ const afterDash = firstLine.replace(/^\s*-\s*/, "");
1940
+ const dashPrefixMatch = firstLine.match(/^( *-\s*)/);
1941
+ const contentIndent = dashPrefixMatch?.[1]?.length;
1942
+ const objectLines = [" ".repeat(contentIndent) + afterDash];
1943
+ for (let k = 1; k < group.length; k++) {
1944
+ objectLines.push(group[k]);
1945
+ }
1946
+ const parsed = parseNestedBlock(objectLines.join("\n"));
1947
+ if (parsed) {
1948
+ items.push(parsed);
1949
+ } else {
1950
+ items.push(
1951
+ parseSingleLineMetadataValue(afterDash.trim())
1952
+ );
1953
+ }
1954
+ }
1955
+ return items;
1956
+ }
1957
+ function parseSingleLineMetadataValue(rawValue) {
1910
1958
  if (rawValue.startsWith("[") && rawValue.endsWith("]")) {
1911
1959
  return rawValue.slice(1, -1).split(",").map((item) => item.trim());
1912
1960
  }
@@ -1921,7 +1969,7 @@ function parseAnyMetaVar(content, varName) {
1921
1969
  const list = parseListMetaVar(content, varName);
1922
1970
  if (list) return list;
1923
1971
  const simple = parseSimpleMetaVar(content, varName);
1924
- if (simple) return parseMetadataValue(simple);
1972
+ if (simple) return parseSingleLineMetadataValue(simple);
1925
1973
  return void 0;
1926
1974
  }
1927
1975
  function getNumericValueFromYield(v) {
@@ -2005,7 +2053,7 @@ function extractMetadata(content) {
2005
2053
  const sourceName = parseSimpleMetaVar(metadataContent, "source.name");
2006
2054
  const sourceUrl = parseSimpleMetaVar(metadataContent, "source.url");
2007
2055
  const sourceAuthor = parseSimpleMetaVar(metadataContent, "source.author");
2008
- if (sourceNested) {
2056
+ if (sourceNested && !Array.isArray(sourceNested)) {
2009
2057
  const source = {};
2010
2058
  if (typeof sourceNested.name === "string") source.name = sourceNested.name;
2011
2059
  if (typeof sourceNested.url === "string") source.url = sourceNested.url;
@@ -2025,7 +2073,7 @@ function extractMetadata(content) {
2025
2073
  const prepTime = parseSimpleMetaVar(metadataContent, "prep time") ?? parseSimpleMetaVar(metadataContent, "time.prep");
2026
2074
  const cookTime = parseSimpleMetaVar(metadataContent, "cook time") ?? parseSimpleMetaVar(metadataContent, "time.cook");
2027
2075
  const totalTime = parseSimpleMetaVar(metadataContent, "time required") ?? parseSimpleMetaVar(metadataContent, "time") ?? parseSimpleMetaVar(metadataContent, "duration");
2028
- if (timeNested) {
2076
+ if (timeNested && !Array.isArray(timeNested)) {
2029
2077
  const time = {};
2030
2078
  if (typeof timeNested.prep === "string") time.prep = timeNested.prep;
2031
2079
  if (typeof timeNested.cook === "string") time.cook = timeNested.cook;
@@ -5160,6 +5208,7 @@ function getEffectiveChoices(recipe, variant) {
5160
5208
  // v8 ignore if -- @preserve
5161
5209
  /* v8 ignore else -- expliciting error type -- @preserve */
5162
5210
  /* v8 ignore next 4 -- @preserve: defensive guard; regex always matches */
5211
+ /* v8 ignore else -- @preserve: empty non nested block will in practice be detected earlier */
5163
5212
  // v8 ignore if -- @preserve: defensive type guard
5164
5213
  /* v8 ignore if -- @preserve */
5165
5214
  // v8 ignore next -- @preserve