@b4moss/hyogen-md 0.13.0 → 0.14.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.
package/README.md CHANGED
@@ -140,11 +140,11 @@ Open `http://localhost:3000` (docs) and `/playground`. Uses `../app` via Vite al
140
140
  ## Status
141
141
 
142
142
  This is **0.x**. APIs and output may change until `1.0.0`.
143
- Published: **`@b4moss/hyogen-md@0.13.0`** (git tag `v0.13.0`).
143
+ Published: **`@b4moss/hyogen-md@0.14.0`** (git tag `v0.14.0`).
144
144
 
145
145
  Playground UX ships with the documentation site and is **not** included in the npm tarball.
146
146
 
147
- The coverage badge reflects approximate **statement coverage for `app/`** (library) from Vitest (~84%). Initial release goal is ≥50%. Coverage is uploaded to Codecov from `.github/workflows/quality.yml` on pushes to `main`.
147
+ The coverage badge reflects **statement coverage for `app/`** (library) from Vitest (**≥90%** target; enforced by Vitest thresholds). Coverage is uploaded to Codecov from `.github/workflows/quality.yml` on pushes to `main`.
148
148
 
149
149
  ---
150
150
 
package/README_ja.md CHANGED
@@ -140,11 +140,11 @@ make dev-docs
140
140
  ## ステータス
141
141
 
142
142
  **0.x** です。`1.0.0` まで API・出力は変わりえます。
143
- 公開済み: **`@b4moss/hyogen-md@0.13.0`**(git tag `v0.13.0`)。
143
+ 公開済み: **`@b4moss/hyogen-md@0.14.0`**(git tag `v0.14.0`)。
144
144
 
145
145
  Playground UX はドキュメントサイトに含まれ、**npm の tarball には入りません**。
146
146
 
147
- coverage バッジはライブラリ(`app/`)の Vitest **statement カバレッジ概算(約 84%)**です。初期リリース目標は 50% 以上。カバレッジは `main` への push 時に `.github/workflows/quality.yml` から Codecov へアップロードされます。
147
+ coverage バッジはライブラリ(`app/`)の Vitest **statement カバレッジ(目標 ≥90%、Vitest thresholds で強制)**です。カバレッジは `main` への push 時に `.github/workflows/quality.yml` から Codecov へアップロードされます。
148
148
 
149
149
  ---
150
150
 
package/dist/cli.js CHANGED
@@ -1774,6 +1774,145 @@ async function interpolateExpressions(source, context, options = {}) {
1774
1774
  }
1775
1775
  return result;
1776
1776
  }
1777
+ function splitPreservingEol(source) {
1778
+ const parts = [];
1779
+ let i = 0;
1780
+ while (i < source.length) {
1781
+ const nl = source.indexOf("\n", i);
1782
+ if (nl === -1) {
1783
+ parts.push({ content: source.slice(i), eol: "" });
1784
+ break;
1785
+ }
1786
+ let content = source.slice(i, nl);
1787
+ let eol = "\n";
1788
+ if (content.endsWith("\r")) {
1789
+ content = content.slice(0, -1);
1790
+ eol = "\r\n";
1791
+ }
1792
+ parts.push({ content, eol });
1793
+ i = nl + 1;
1794
+ }
1795
+ return parts;
1796
+ }
1797
+ function readTemplateExpression(source, start, path2) {
1798
+ let depth = 1;
1799
+ let index = start;
1800
+ let inString = null;
1801
+ while (index < source.length) {
1802
+ const ch = source[index];
1803
+ if (inString) {
1804
+ if (ch === "\\") {
1805
+ index += 2;
1806
+ continue;
1807
+ }
1808
+ if (ch === inString) {
1809
+ inString = null;
1810
+ }
1811
+ index++;
1812
+ continue;
1813
+ }
1814
+ if (ch === '"' || ch === "'" || ch === "`") {
1815
+ inString = ch;
1816
+ index++;
1817
+ continue;
1818
+ }
1819
+ if (ch === "{") {
1820
+ depth++;
1821
+ index++;
1822
+ continue;
1823
+ }
1824
+ if (ch === "}") {
1825
+ depth--;
1826
+ if (depth === 0) {
1827
+ return {
1828
+ expr: source.slice(start, index),
1829
+ end: index + 1
1830
+ };
1831
+ }
1832
+ index++;
1833
+ continue;
1834
+ }
1835
+ index++;
1836
+ }
1837
+ throw createHyogenError({
1838
+ code: "parse_error",
1839
+ path: path2,
1840
+ details: { message: "unclosed template expression" }
1841
+ });
1842
+ }
1843
+ function isEscapedDollar(source, dollarIndex) {
1844
+ let backslashes = 0;
1845
+ let j = dollarIndex - 1;
1846
+ while (j >= 0 && source[j] === "\\") {
1847
+ backslashes++;
1848
+ j--;
1849
+ }
1850
+ return backslashes % 2 === 1;
1851
+ }
1852
+ async function interpolateDollarExpressions(text, context, options) {
1853
+ const path2 = options.path;
1854
+ let result = "";
1855
+ let i = 0;
1856
+ while (i < text.length) {
1857
+ const dollar = text.indexOf("${", i);
1858
+ if (dollar === -1) {
1859
+ result += text.slice(i);
1860
+ break;
1861
+ }
1862
+ if (isEscapedDollar(text, dollar)) {
1863
+ result += text.slice(i, dollar - 1);
1864
+ result += "${";
1865
+ i = dollar + 2;
1866
+ continue;
1867
+ }
1868
+ result += text.slice(i, dollar);
1869
+ const { expr, end } = readTemplateExpression(text, dollar + 2, path2);
1870
+ const node = parseExpression(expr.trim(), path2, { allowCalls: false });
1871
+ const value = await evaluateExpression(node, {
1872
+ ...options,
1873
+ context,
1874
+ path: path2,
1875
+ parentContext: options.parentContext ?? context
1876
+ });
1877
+ result += value === void 0 || value === null ? "" : String(value);
1878
+ i = end;
1879
+ }
1880
+ return result;
1881
+ }
1882
+ async function interpolateFenceExpressions(source, context, options = {}) {
1883
+ const lines = splitPreservingEol(source);
1884
+ if (lines.length === 0) {
1885
+ return source;
1886
+ }
1887
+ const fence = createFenceState();
1888
+ let result = "";
1889
+ let insideBuffer = "";
1890
+ let bufferingInside = false;
1891
+ const flushInside = async () => {
1892
+ if (!bufferingInside) {
1893
+ return;
1894
+ }
1895
+ result += await interpolateDollarExpressions(insideBuffer, context, options);
1896
+ insideBuffer = "";
1897
+ bufferingInside = false;
1898
+ };
1899
+ for (const { content, eol } of lines) {
1900
+ const inside = consumeFenceLine(fence, content);
1901
+ const chunk = content + eol;
1902
+ if (inside) {
1903
+ if (!bufferingInside) {
1904
+ bufferingInside = true;
1905
+ insideBuffer = "";
1906
+ }
1907
+ insideBuffer += chunk;
1908
+ } else {
1909
+ await flushInside();
1910
+ result += chunk;
1911
+ }
1912
+ }
1913
+ await flushInside();
1914
+ return result;
1915
+ }
1777
1916
  function countOccurrences(haystack, needle) {
1778
1917
  let count = 0;
1779
1918
  let pos = 0;
@@ -2373,7 +2512,7 @@ async function expandEach(node, options, tracker, warnings2) {
2373
2512
  if (!preserve) {
2374
2513
  bodyText = chompLeadingNewline(bodyText);
2375
2514
  }
2376
- const interpolated = await interpolateExpressions(bodyText, scopedContext, {
2515
+ const interpolateOpts = {
2377
2516
  path: options.path,
2378
2517
  registry: options.registry,
2379
2518
  loader: options.loader,
@@ -2383,7 +2522,17 @@ async function expandEach(node, options, tracker, warnings2) {
2383
2522
  parentContext: options.parentContext ?? options.context,
2384
2523
  preserveHgComments: options.preserveHgComments,
2385
2524
  constrainToRoot: options.constrainToRoot
2386
- });
2525
+ };
2526
+ let interpolated = await interpolateExpressions(
2527
+ bodyText,
2528
+ scopedContext,
2529
+ interpolateOpts
2530
+ );
2531
+ interpolated = await interpolateFenceExpressions(
2532
+ interpolated,
2533
+ scopedContext,
2534
+ interpolateOpts
2535
+ );
2387
2536
  result += interpolated;
2388
2537
  if (preserve) {
2389
2538
  result += node.closer.raw;
@@ -4263,7 +4412,7 @@ async function renderDocumentBody(body, options) {
4263
4412
  preserveHgComments: options.preserveHgComments,
4264
4413
  constrainToRoot: options.constrainToRoot
4265
4414
  });
4266
- markdown = await interpolateExpressions(markdown, mergedContext, {
4415
+ const interpolateOpts = {
4267
4416
  path: path2,
4268
4417
  registry,
4269
4418
  loader,
@@ -4273,7 +4422,13 @@ async function renderDocumentBody(body, options) {
4273
4422
  parentContext: mergedContext,
4274
4423
  preserveHgComments: options.preserveHgComments,
4275
4424
  constrainToRoot: options.constrainToRoot
4276
- });
4425
+ };
4426
+ markdown = await interpolateExpressions(markdown, mergedContext, interpolateOpts);
4427
+ markdown = await interpolateFenceExpressions(
4428
+ markdown,
4429
+ mergedContext,
4430
+ interpolateOpts
4431
+ );
4277
4432
  markdown = expandToc(markdown, { path: path2 });
4278
4433
  markdown = stripHgComments(markdown, options.preserveHgComments);
4279
4434
  return markdown;
@@ -4817,7 +4972,7 @@ function packageJsonContents(packageName) {
4817
4972
  build: "hyogen-md build"
4818
4973
  },
4819
4974
  dependencies: {
4820
- "@b4moss/hyogen-md": "^0.13.0"
4975
+ "@b4moss/hyogen-md": "^0.14.0"
4821
4976
  }
4822
4977
  },
4823
4978
  null,
@@ -5572,7 +5727,7 @@ cli.command("dev", "Start writing preview server with HMR").option("--config <fi
5572
5727
  }
5573
5728
  );
5574
5729
  cli.help();
5575
- cli.version("0.13.0");
5730
+ cli.version("0.14.0");
5576
5731
  async function main() {
5577
5732
  try {
5578
5733
  cli.parse(process.argv, { run: false });