seemore 1.12.13 → 1.12.16
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/cli/index.js +219 -31
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -78,7 +78,7 @@ import pc5 from "picocolors";
|
|
|
78
78
|
import { mkdirSync as mkdirSync3, mkdtempSync, readFileSync as readFileSync7, rmSync, writeFileSync as writeFileSync7 } from "fs";
|
|
79
79
|
import { createRequire as createRequire4 } from "module";
|
|
80
80
|
import { tmpdir as tmpdir3 } from "os";
|
|
81
|
-
import { isAbsolute as isAbsolute2, join as join12, relative as
|
|
81
|
+
import { isAbsolute as isAbsolute2, join as join12, relative as relative4, resolve as resolve6 } from "path";
|
|
82
82
|
import pc2 from "picocolors";
|
|
83
83
|
import { build as viteBuild } from "vite";
|
|
84
84
|
|
|
@@ -961,9 +961,9 @@ function splitHash(value) {
|
|
|
961
961
|
if (index === -1) return [value, void 0];
|
|
962
962
|
return [value.slice(0, index), value.slice(index + 1)];
|
|
963
963
|
}
|
|
964
|
-
function joinPosix(fromDir,
|
|
964
|
+
function joinPosix(fromDir, relative6) {
|
|
965
965
|
const segments = [...fromDir];
|
|
966
|
-
for (const part of toPosix(
|
|
966
|
+
for (const part of toPosix(relative6).split("/")) {
|
|
967
967
|
if (part === "" || part === ".") continue;
|
|
968
968
|
if (part === "..") segments.pop();
|
|
969
969
|
else segments.push(part);
|
|
@@ -1469,6 +1469,164 @@ function rehypeSeemoreRawHtml() {
|
|
|
1469
1469
|
};
|
|
1470
1470
|
}
|
|
1471
1471
|
|
|
1472
|
+
// src/node/vite/media.ts
|
|
1473
|
+
import { existsSync as existsSync4 } from "fs";
|
|
1474
|
+
import { dirname as dirname7, relative as relative2, resolve as resolve5 } from "path";
|
|
1475
|
+
import { visit as visit3 } from "unist-util-visit";
|
|
1476
|
+
var MEDIA = {
|
|
1477
|
+
video: ["src", "poster"],
|
|
1478
|
+
audio: ["src"],
|
|
1479
|
+
source: ["src"],
|
|
1480
|
+
track: ["src"]
|
|
1481
|
+
};
|
|
1482
|
+
function rehypeSeemoreMedia(options) {
|
|
1483
|
+
return (tree, file) => {
|
|
1484
|
+
const path = file.path ?? "";
|
|
1485
|
+
if (path === "") return;
|
|
1486
|
+
const dir = dirname7(path.split("?")[0] ?? path);
|
|
1487
|
+
const from = toPosix(relative2(options.contentRoot, path.split("?")[0] ?? path));
|
|
1488
|
+
const imports = /* @__PURE__ */ new Map();
|
|
1489
|
+
const importFor = (url) => {
|
|
1490
|
+
if (/^(?:[a-z][a-z0-9+.-]*:|\/\/|\/|#)/i.test(url) || url === "") return void 0;
|
|
1491
|
+
const raw = url.split(/[?#]/)[0] ?? "";
|
|
1492
|
+
let decoded;
|
|
1493
|
+
try {
|
|
1494
|
+
decoded = decodeURIComponent(raw);
|
|
1495
|
+
} catch {
|
|
1496
|
+
decoded = raw;
|
|
1497
|
+
}
|
|
1498
|
+
if (!existsSync4(resolve5(dir, decoded))) {
|
|
1499
|
+
options.onWarning(`Missing asset ${url} referenced by ${from}.`);
|
|
1500
|
+
return void 0;
|
|
1501
|
+
}
|
|
1502
|
+
const specifier = /^\.{1,2}\//.test(decoded) ? decoded : `./${decoded}`;
|
|
1503
|
+
let name = imports.get(specifier);
|
|
1504
|
+
if (name === void 0) {
|
|
1505
|
+
name = `__seemoreMedia${imports.size}`;
|
|
1506
|
+
imports.set(specifier, name);
|
|
1507
|
+
}
|
|
1508
|
+
return name;
|
|
1509
|
+
};
|
|
1510
|
+
visit3(tree, (node, index, parent) => {
|
|
1511
|
+
if (parent === void 0 || index === void 0) return;
|
|
1512
|
+
if (node.type === "element") {
|
|
1513
|
+
const fields = MEDIA[node.tagName];
|
|
1514
|
+
if (fields === void 0) return;
|
|
1515
|
+
const bound = /* @__PURE__ */ new Map();
|
|
1516
|
+
for (const field of fields) {
|
|
1517
|
+
const value = node.properties[field];
|
|
1518
|
+
if (typeof value !== "string") continue;
|
|
1519
|
+
const name = importFor(value);
|
|
1520
|
+
if (name !== void 0) bound.set(field, name);
|
|
1521
|
+
}
|
|
1522
|
+
if (bound.size === 0) return;
|
|
1523
|
+
parent.children[index] = toJsx(node, bound);
|
|
1524
|
+
return;
|
|
1525
|
+
}
|
|
1526
|
+
if (node.type === "mdxJsxFlowElement" || node.type === "mdxJsxTextElement") {
|
|
1527
|
+
const element = node;
|
|
1528
|
+
const fields = element.name === null ? void 0 : MEDIA[element.name];
|
|
1529
|
+
if (fields === void 0) return;
|
|
1530
|
+
for (const attribute of element.attributes) {
|
|
1531
|
+
if (attribute.type !== "mdxJsxAttribute" || !fields.includes(attribute.name)) continue;
|
|
1532
|
+
if (typeof attribute.value !== "string") continue;
|
|
1533
|
+
const name = importFor(attribute.value);
|
|
1534
|
+
if (name !== void 0) attribute.value = identifierValue(name);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
});
|
|
1538
|
+
if (imports.size === 0) return;
|
|
1539
|
+
tree.children.unshift(
|
|
1540
|
+
...[...imports].map(([specifier, name]) => importNode(specifier, name))
|
|
1541
|
+
);
|
|
1542
|
+
};
|
|
1543
|
+
}
|
|
1544
|
+
function toJsx(node, bound) {
|
|
1545
|
+
const attributes = [];
|
|
1546
|
+
for (const [key, value] of Object.entries(node.properties)) {
|
|
1547
|
+
if (value === void 0 || value === null || value === false) continue;
|
|
1548
|
+
const name = attributeName(key);
|
|
1549
|
+
const imported = bound.get(key);
|
|
1550
|
+
if (imported !== void 0) {
|
|
1551
|
+
attributes.push({ type: "mdxJsxAttribute", name, value: identifierValue(imported) });
|
|
1552
|
+
} else if (key === "style" && typeof value === "string") {
|
|
1553
|
+
attributes.push({ type: "mdxJsxAttribute", name, value: styleValue(value) });
|
|
1554
|
+
} else if (value === true) {
|
|
1555
|
+
attributes.push({ type: "mdxJsxAttribute", name, value: null });
|
|
1556
|
+
} else {
|
|
1557
|
+
attributes.push({ type: "mdxJsxAttribute", name, value: Array.isArray(value) ? value.join(" ") : String(value) });
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
return {
|
|
1561
|
+
type: node.children.some((child) => child.type === "element" && child.tagName === "p") ? "mdxJsxFlowElement" : "mdxJsxTextElement",
|
|
1562
|
+
name: node.tagName,
|
|
1563
|
+
attributes,
|
|
1564
|
+
children: node.children
|
|
1565
|
+
};
|
|
1566
|
+
}
|
|
1567
|
+
function attributeName(key) {
|
|
1568
|
+
const match = /^(data|aria)([A-Z].*)$/.exec(key);
|
|
1569
|
+
if (match === null) return key;
|
|
1570
|
+
return `${match[1]}${(match[2] ?? "").replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`)}`;
|
|
1571
|
+
}
|
|
1572
|
+
function identifierValue(name) {
|
|
1573
|
+
return expressionValue(name, { type: "Identifier", name });
|
|
1574
|
+
}
|
|
1575
|
+
function styleValue(css) {
|
|
1576
|
+
const properties = [];
|
|
1577
|
+
for (const declaration of css.split(";")) {
|
|
1578
|
+
const colon = declaration.indexOf(":");
|
|
1579
|
+
if (colon === -1) continue;
|
|
1580
|
+
const property = declaration.slice(0, colon).trim();
|
|
1581
|
+
const value = declaration.slice(colon + 1).trim();
|
|
1582
|
+
if (property === "" || value === "") continue;
|
|
1583
|
+
const key = property.startsWith("--") ? property : property.replace(/^-ms-/, "ms-").replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
1584
|
+
properties.push({
|
|
1585
|
+
type: "Property",
|
|
1586
|
+
kind: "init",
|
|
1587
|
+
method: false,
|
|
1588
|
+
shorthand: false,
|
|
1589
|
+
computed: false,
|
|
1590
|
+
key: { type: "Literal", value: key },
|
|
1591
|
+
value: { type: "Literal", value }
|
|
1592
|
+
});
|
|
1593
|
+
}
|
|
1594
|
+
return expressionValue(JSON.stringify(css), { type: "ObjectExpression", properties });
|
|
1595
|
+
}
|
|
1596
|
+
function expressionValue(source, expression) {
|
|
1597
|
+
return {
|
|
1598
|
+
type: "mdxJsxAttributeValueExpression",
|
|
1599
|
+
value: source,
|
|
1600
|
+
data: {
|
|
1601
|
+
estree: {
|
|
1602
|
+
type: "Program",
|
|
1603
|
+
sourceType: "module",
|
|
1604
|
+
body: [{ type: "ExpressionStatement", expression }]
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
}
|
|
1609
|
+
function importNode(specifier, name) {
|
|
1610
|
+
return {
|
|
1611
|
+
type: "mdxjsEsm",
|
|
1612
|
+
value: "",
|
|
1613
|
+
data: {
|
|
1614
|
+
estree: {
|
|
1615
|
+
type: "Program",
|
|
1616
|
+
sourceType: "module",
|
|
1617
|
+
body: [
|
|
1618
|
+
{
|
|
1619
|
+
type: "ImportDeclaration",
|
|
1620
|
+
attributes: [],
|
|
1621
|
+
specifiers: [{ type: "ImportDefaultSpecifier", local: { type: "Identifier", name } }],
|
|
1622
|
+
source: { type: "Literal", value: specifier }
|
|
1623
|
+
}
|
|
1624
|
+
]
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
};
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1472
1630
|
// src/node/vite/mdx.ts
|
|
1473
1631
|
var MARKDOWN_EXPORT = "_markdown";
|
|
1474
1632
|
function createRemarkPlugins(options) {
|
|
@@ -1483,7 +1641,9 @@ function createRemarkPlugins(options) {
|
|
|
1483
1641
|
// frontmatter strip is the one thing that must come first — its keys are metadata, not
|
|
1484
1642
|
// content. Heading ids stay off: `## Title [#title]` is noise in a paste.
|
|
1485
1643
|
remarkSeemoreMarkdownSource,
|
|
1486
|
-
|
|
1644
|
+
function() {
|
|
1645
|
+
return remarkSeemoreLLMs.call(this, options);
|
|
1646
|
+
},
|
|
1487
1647
|
remarkHeading,
|
|
1488
1648
|
remarkAdmonition,
|
|
1489
1649
|
remarkDirectiveAdmonition,
|
|
@@ -1510,7 +1670,28 @@ function createRemarkPlugins(options) {
|
|
|
1510
1670
|
() => remarkSeemoreLinks(options)
|
|
1511
1671
|
];
|
|
1512
1672
|
}
|
|
1513
|
-
function
|
|
1673
|
+
function remarkSeemoreLLMs(options) {
|
|
1674
|
+
const snapshot = remarkLLMs.call(this, { as: MARKDOWN_EXPORT, headingIds: false });
|
|
1675
|
+
return (tree, file) => {
|
|
1676
|
+
try {
|
|
1677
|
+
snapshot(tree, file);
|
|
1678
|
+
} catch (error) {
|
|
1679
|
+
options.onWarning(
|
|
1680
|
+
`Could not convert ${file.path} back to Markdown for copying (${error.message}); the raw file is copied instead.`
|
|
1681
|
+
);
|
|
1682
|
+
const fallback = { type: "root", children: [{ type: "html", value: sourceOf(tree, file) }] };
|
|
1683
|
+
snapshot(fallback, file);
|
|
1684
|
+
tree.children.unshift(...fallback.children.slice(0, -1));
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
}
|
|
1688
|
+
function sourceOf(tree, file) {
|
|
1689
|
+
const source = String(file.value);
|
|
1690
|
+
const yaml = tree.children[0]?.type === "yaml" ? tree.children[0] : void 0;
|
|
1691
|
+
const end = yaml?.position?.end.offset;
|
|
1692
|
+
return end === void 0 ? source : source.slice(end).trimStart();
|
|
1693
|
+
}
|
|
1694
|
+
function createRehypePlugins(options) {
|
|
1514
1695
|
return [
|
|
1515
1696
|
// A fence in a language Shiki has no grammar for (anything an AI dreamt up) is plain code
|
|
1516
1697
|
// on the page, not a dead one: `plaintext` is special-cased by Shiki and never needs
|
|
@@ -1525,14 +1706,17 @@ function createRehypePlugins(options = {}) {
|
|
|
1525
1706
|
// `rehype-code` reads `noCopy` from. Running it here means each plugin above has already
|
|
1526
1707
|
// taken what it needs, and the elements it creates are not stamped as editable, which is
|
|
1527
1708
|
// right: they have no source range a text editor could be handed.
|
|
1528
|
-
rehypeSeemoreRawHtml
|
|
1709
|
+
rehypeSeemoreRawHtml,
|
|
1710
|
+
// After `rehype-raw`, the first point where a `.md` file's hand-written `<video>` is an
|
|
1711
|
+
// element rather than a string.
|
|
1712
|
+
() => rehypeSeemoreMedia(options)
|
|
1529
1713
|
];
|
|
1530
1714
|
}
|
|
1531
1715
|
|
|
1532
1716
|
// src/node/vite/plugin.ts
|
|
1533
1717
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
1534
1718
|
import { createRequire as createRequire2 } from "module";
|
|
1535
|
-
import { dirname as
|
|
1719
|
+
import { dirname as dirname8 } from "path";
|
|
1536
1720
|
|
|
1537
1721
|
// src/node/search/build.ts
|
|
1538
1722
|
import { readFileSync as readFileSync5 } from "fs";
|
|
@@ -1628,7 +1812,7 @@ var require_2 = createRequire2(import.meta.url);
|
|
|
1628
1812
|
function styleImports(ctx) {
|
|
1629
1813
|
const lines = [`@import 'fumadocs-ui/css/${ctx.config.theme}.css';`];
|
|
1630
1814
|
try {
|
|
1631
|
-
lines.push(`@source '${
|
|
1815
|
+
lines.push(`@source '${dirname8(require_2.resolve("fumadocs-ui/package.json"))}/dist';`);
|
|
1632
1816
|
} catch {
|
|
1633
1817
|
}
|
|
1634
1818
|
return lines.join("\n");
|
|
@@ -1875,7 +2059,7 @@ function readIfExists(path) {
|
|
|
1875
2059
|
}
|
|
1876
2060
|
|
|
1877
2061
|
// src/node/vite/watcher.ts
|
|
1878
|
-
import { relative as
|
|
2062
|
+
import { relative as relative3 } from "path";
|
|
1879
2063
|
import chokidar from "chokidar";
|
|
1880
2064
|
var CONTENT_FILE = /\.(?:mdx?|json)$/i;
|
|
1881
2065
|
var EXCLUDED_DIR = /(?:^|\/)(?:node_modules|dist|build|out|vendor|target|venv|deps|Pods|bower_components|\.[^/]+)(?:$|\/)/;
|
|
@@ -1906,7 +2090,7 @@ function seemoreWatcherPlugin(ctx) {
|
|
|
1906
2090
|
ignoreInitial: true,
|
|
1907
2091
|
ignored: (path, stats) => {
|
|
1908
2092
|
if (path === ctx.config.configFile) return false;
|
|
1909
|
-
return isWatchIgnored(
|
|
2093
|
+
return isWatchIgnored(relative3(ctx.contentRoot, path), stats?.isFile() === true, ctx.config.include);
|
|
1910
2094
|
}
|
|
1911
2095
|
});
|
|
1912
2096
|
const onEvent = (event, path) => {
|
|
@@ -1987,7 +2171,11 @@ function createViteConfig({ ctx, mode, outDir, ssrOutDir, auth = false }) {
|
|
|
1987
2171
|
getResolver: () => ctx.resolver(),
|
|
1988
2172
|
onWarning: (message) => ctx.warnings.add(message)
|
|
1989
2173
|
}),
|
|
1990
|
-
rehypePlugins: createRehypePlugins({
|
|
2174
|
+
rehypePlugins: createRehypePlugins({
|
|
2175
|
+
contentRoot: ctx.contentRoot,
|
|
2176
|
+
onWarning: (message) => ctx.warnings.add(message),
|
|
2177
|
+
positions: mode === "dev" && ctx.config.features["content.edit"]
|
|
2178
|
+
}),
|
|
1991
2179
|
// MDX compiles its own JSX. Vite's builtin transform infers a file's language from its
|
|
1992
2180
|
// extension and does not know `.md`/`.mdx`, so leaving JSX in the output would fail to
|
|
1993
2181
|
// parse. The output is plain JS against the automatic runtime, so nothing downstream has
|
|
@@ -2131,7 +2319,7 @@ async function loadPrerenderModule(ctx, ssrOutDir) {
|
|
|
2131
2319
|
|
|
2132
2320
|
// src/node/social/cards.ts
|
|
2133
2321
|
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
2134
|
-
import { dirname as
|
|
2322
|
+
import { dirname as dirname9, join as join11 } from "path";
|
|
2135
2323
|
|
|
2136
2324
|
// src/shared/og.ts
|
|
2137
2325
|
function ogImagePath(url) {
|
|
@@ -2155,7 +2343,7 @@ async function generateSocialCards(ctx, outDir) {
|
|
|
2155
2343
|
const png = await renderCard(takumi, ctx.config.title, page.data.title, page.data.description);
|
|
2156
2344
|
if (png === void 0) continue;
|
|
2157
2345
|
const target = join11(outDir, ogImagePath(page.url));
|
|
2158
|
-
mkdirSync2(
|
|
2346
|
+
mkdirSync2(dirname9(target), { recursive: true });
|
|
2159
2347
|
writeFileSync6(target, png);
|
|
2160
2348
|
written++;
|
|
2161
2349
|
}
|
|
@@ -2196,7 +2384,7 @@ async function runBuild(options) {
|
|
|
2196
2384
|
const config = { ...loaded.config, base: options.base === void 0 ? loaded.config.base : normaliseBase(options.base) };
|
|
2197
2385
|
warnAboutMissingBase(config.base, loaded.file);
|
|
2198
2386
|
const ctx = createContext({ config, contentRoot });
|
|
2199
|
-
const outDir =
|
|
2387
|
+
const outDir = resolve6(options.cwd, options.outDir ?? "dist");
|
|
2200
2388
|
assertSafeOutDir(outDir, options.cwd, contentRoot);
|
|
2201
2389
|
const password = config.auth === void 0 ? void 0 : readPassword("npx seemore build");
|
|
2202
2390
|
const scan2 = ctx.source.current();
|
|
@@ -2205,7 +2393,7 @@ async function runBuild(options) {
|
|
|
2205
2393
|
throw new Error(`No Markdown files found under ${contentRoot}. Point seemore at a folder that has some, or check \`exclude\`.`);
|
|
2206
2394
|
}
|
|
2207
2395
|
for (const warning of scan2.warnings) ctx.warnings.add(warning);
|
|
2208
|
-
console.log(pc2.dim(`seemore ${scan2.pages.length} pages from ${
|
|
2396
|
+
console.log(pc2.dim(`seemore ${scan2.pages.length} pages from ${relative4(options.cwd, contentRoot) || "."}`));
|
|
2209
2397
|
await viteBuild(createViteConfig({ ctx, mode: "build", outDir, auth: password !== void 0 }));
|
|
2210
2398
|
const template = readFileSync7(join12(outDir, "index.html"), "utf8");
|
|
2211
2399
|
const routes = password === void 0 ? await prerenderPages(ctx, outDir, template) : countRoutes(ctx);
|
|
@@ -2224,7 +2412,7 @@ async function runBuild(options) {
|
|
|
2224
2412
|
console.log(pc2.dim(`seemore ${encrypted} files encrypted; visitors unlock them with the password`));
|
|
2225
2413
|
}
|
|
2226
2414
|
ctx.warnings.flush();
|
|
2227
|
-
console.log(pc2.green(`seemore ${routes} pages written to ${
|
|
2415
|
+
console.log(pc2.green(`seemore ${routes} pages written to ${relative4(options.cwd, outDir) || outDir}`));
|
|
2228
2416
|
return { outDir, routes };
|
|
2229
2417
|
}
|
|
2230
2418
|
async function prerenderPages(ctx, outDir, template) {
|
|
@@ -2253,7 +2441,7 @@ function countRoutes(ctx) {
|
|
|
2253
2441
|
}
|
|
2254
2442
|
function assertSafeOutDir(outDir, cwd, contentRoot) {
|
|
2255
2443
|
const contains = (parent, child) => {
|
|
2256
|
-
const rel =
|
|
2444
|
+
const rel = relative4(parent, child);
|
|
2257
2445
|
return rel === "" || !rel.startsWith("..") && !isAbsolute2(rel);
|
|
2258
2446
|
};
|
|
2259
2447
|
for (const [name, dir] of [
|
|
@@ -2353,8 +2541,8 @@ async function runDev(options) {
|
|
|
2353
2541
|
}
|
|
2354
2542
|
|
|
2355
2543
|
// src/cli/export.ts
|
|
2356
|
-
import { existsSync as
|
|
2357
|
-
import { basename as basename2, dirname as
|
|
2544
|
+
import { existsSync as existsSync5, mkdtempSync as mkdtempSync2, readFileSync as readFileSync8, readdirSync as readdirSync2, rmSync as rmSync2, statSync, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4 } from "fs";
|
|
2545
|
+
import { basename as basename2, dirname as dirname10, extname, join as join13, relative as relative5, resolve as resolve7 } from "path";
|
|
2358
2546
|
import { tmpdir as tmpdir4 } from "os";
|
|
2359
2547
|
import pc4 from "picocolors";
|
|
2360
2548
|
import { build as viteBuild2 } from "vite";
|
|
@@ -2389,11 +2577,11 @@ var THEME_INIT = `<script>(function () {
|
|
|
2389
2577
|
|
|
2390
2578
|
// src/cli/export.ts
|
|
2391
2579
|
async function runExport(options) {
|
|
2392
|
-
const target =
|
|
2393
|
-
if (!
|
|
2580
|
+
const target = resolve7(options.cwd, options.file);
|
|
2581
|
+
if (!existsSync5(target) || !statSync(target).isFile()) {
|
|
2394
2582
|
throw new Error(`No such file: ${options.file}`);
|
|
2395
2583
|
}
|
|
2396
|
-
const contentRoot = resolveContentRoot(options.cwd,
|
|
2584
|
+
const contentRoot = resolveContentRoot(options.cwd, dirname10(target));
|
|
2397
2585
|
const loaded = await loadConfig({ root: contentRoot, configPath: resolveConfigPath(options) });
|
|
2398
2586
|
const config = {
|
|
2399
2587
|
...loaded.config,
|
|
@@ -2413,7 +2601,7 @@ ${errors.join("\n\n")}`);
|
|
|
2413
2601
|
}
|
|
2414
2602
|
const page = ctx.pages().find((candidate) => candidate.absPath === canonicalise(target));
|
|
2415
2603
|
if (page === void 0) {
|
|
2416
|
-
throw new Error(`${options.file} is not part of this site \u2014 excluded in the config, or outside ${
|
|
2604
|
+
throw new Error(`${options.file} is not part of this site \u2014 excluded in the config, or outside ${relative5(options.cwd, contentRoot) || "."}.`);
|
|
2417
2605
|
}
|
|
2418
2606
|
const outDir = mkdtempSync2(join13(tmpdir4(), "seemore-export-"));
|
|
2419
2607
|
const ssrOutDir = mkdtempSync2(join13(tmpdir4(), "seemore-export-ssr-"));
|
|
@@ -2426,14 +2614,14 @@ ${errors.join("\n\n")}`);
|
|
|
2426
2614
|
const runtime = await bundleRuntime();
|
|
2427
2615
|
const html = assemble({ article, css, runtime, config, outDir, contentRoot, template });
|
|
2428
2616
|
const filename = `${basename2(target).replace(/\.(?:md|mdx)$/i, "")}.html`;
|
|
2429
|
-
const targetPath = options.out === void 0 ? join13(
|
|
2430
|
-
if (
|
|
2431
|
-
console.log(pc4.yellow(`seemore replacing existing ${
|
|
2617
|
+
const targetPath = options.out === void 0 ? join13(dirname10(target), filename) : join13(resolve7(options.cwd, options.out), filename);
|
|
2618
|
+
if (existsSync5(targetPath)) {
|
|
2619
|
+
console.log(pc4.yellow(`seemore replacing existing ${relative5(options.cwd, targetPath) || targetPath}`));
|
|
2432
2620
|
}
|
|
2433
|
-
mkdirSync4(
|
|
2621
|
+
mkdirSync4(dirname10(targetPath), { recursive: true });
|
|
2434
2622
|
writeFileSync8(targetPath, html, "utf8");
|
|
2435
2623
|
ctx.warnings.flush();
|
|
2436
|
-
console.log(pc4.green(`seemore wrote ${
|
|
2624
|
+
console.log(pc4.green(`seemore wrote ${relative5(options.cwd, targetPath) || targetPath} (${formatBytes2(html.length)})`));
|
|
2437
2625
|
} finally {
|
|
2438
2626
|
rmSync2(outDir, { recursive: true, force: true });
|
|
2439
2627
|
rmSync2(ssrOutDir, { recursive: true, force: true });
|
|
@@ -2441,7 +2629,7 @@ ${errors.join("\n\n")}`);
|
|
|
2441
2629
|
}
|
|
2442
2630
|
function readBuiltCss(outDir) {
|
|
2443
2631
|
const assets = join13(outDir, "assets");
|
|
2444
|
-
const files =
|
|
2632
|
+
const files = existsSync5(assets) ? readdirSync2(assets).filter((file) => file.endsWith(".css")) : [];
|
|
2445
2633
|
if (files.length === 0) throw new Error("The build produced no stylesheet \u2014 the export would be unstyled.");
|
|
2446
2634
|
return files.map((file) => readFileSync8(join13(assets, file), "utf8")).join("\n");
|
|
2447
2635
|
}
|
|
@@ -2532,7 +2720,7 @@ function resolveAsset(src, base, outDir, contentRoot) {
|
|
|
2532
2720
|
const suffix = path.replace(/^\/+/, "");
|
|
2533
2721
|
for (const root of [outDir, contentRoot]) {
|
|
2534
2722
|
const candidate = join13(root, suffix);
|
|
2535
|
-
if (
|
|
2723
|
+
if (existsSync5(candidate) && statSync(candidate).isFile()) return candidate;
|
|
2536
2724
|
}
|
|
2537
2725
|
return void 0;
|
|
2538
2726
|
}
|
|
@@ -2560,7 +2748,7 @@ function dataUriFor(file) {
|
|
|
2560
2748
|
function faviconLink(config, contentRoot, template) {
|
|
2561
2749
|
if (config.favicon !== void 0) {
|
|
2562
2750
|
const file = join13(contentRoot, config.favicon);
|
|
2563
|
-
if (
|
|
2751
|
+
if (existsSync5(file)) {
|
|
2564
2752
|
try {
|
|
2565
2753
|
return `<link rel="icon" href="${dataUriFor(file)}" />`;
|
|
2566
2754
|
} catch {
|