@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 +2 -2
- package/README_ja.md +2 -2
- package/dist/cli.js +161 -6
- package/dist/client.js +517 -403
- package/dist/expr/interpolateFenceExpressions.d.ts +8 -0
- package/dist/index.js +585 -471
- package/package.json +1 -1
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.
|
|
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
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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.
|
|
5730
|
+
cli.version("0.14.0");
|
|
5576
5731
|
async function main() {
|
|
5577
5732
|
try {
|
|
5578
5733
|
cli.parse(process.argv, { run: false });
|