@clarify-labs/cli 0.8.2 → 0.9.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/output/cli.cjs +2 -2
- package/output/cli.cjs.map +1 -1
- package/output/cli.js +2 -2
- package/output/cli.js.map +1 -1
- package/output/core/dev-routes.d.ts +58 -0
- package/output/core/project-info.d.ts +42 -0
- package/output/core/user-config.d.ts +6 -0
- package/output/index.cjs +1 -1
- package/output/index.js +1 -1
- package/output/{plugin-DyceHdXd.cjs → plugin-JvxU6ZjU.cjs} +204 -37
- package/output/plugin-JvxU6ZjU.cjs.map +1 -0
- package/output/{plugin-D5EF3pYl.js → plugin-_mqQSBqE.js} +205 -38
- package/output/plugin-_mqQSBqE.js.map +1 -0
- package/package.json +3 -3
- package/output/plugin-D5EF3pYl.js.map +0 -1
- package/output/plugin-DyceHdXd.cjs.map +0 -1
|
@@ -1801,6 +1801,126 @@ function resolveProjectConfig(config = {}) {
|
|
|
1801
1801
|
tabs: config.tabs
|
|
1802
1802
|
};
|
|
1803
1803
|
}
|
|
1804
|
+
/** Serialize a ContentRoute into the minimal shape exposed to tooling. */
|
|
1805
|
+
function toDevRouteEntry(route) {
|
|
1806
|
+
return {
|
|
1807
|
+
path: route.path,
|
|
1808
|
+
filePath: route.filePath,
|
|
1809
|
+
locale: route.locale,
|
|
1810
|
+
basePath: route.basePath,
|
|
1811
|
+
kind: route.kind,
|
|
1812
|
+
title: route.title
|
|
1813
|
+
};
|
|
1814
|
+
}
|
|
1815
|
+
/**
|
|
1816
|
+
* Resolve a single file path to its preview route.
|
|
1817
|
+
*
|
|
1818
|
+
* Selection order:
|
|
1819
|
+
* 1. Routes whose `filePath` exactly matches.
|
|
1820
|
+
* 2. Among matches, prefer the one whose `locale` matches the file's locale
|
|
1821
|
+
* directory (e.g. `source/zh-CN/x.mdx` → locale `zh-CN`).
|
|
1822
|
+
* 3. If no locale match, fall back to the default locale (if i18n is enabled)
|
|
1823
|
+
* or the first match.
|
|
1824
|
+
*/
|
|
1825
|
+
function resolveRouteForFile(filePath, routes, defaultLocale) {
|
|
1826
|
+
const matches = routes.filter((r) => r.filePath === filePath);
|
|
1827
|
+
if (matches.length === 0) return void 0;
|
|
1828
|
+
if (matches.length === 1) return matches[0];
|
|
1829
|
+
const fileLocale = inferLocaleFromPath(filePath);
|
|
1830
|
+
if (fileLocale) {
|
|
1831
|
+
const localeMatch = matches.find((r) => r.locale === fileLocale);
|
|
1832
|
+
if (localeMatch) return localeMatch;
|
|
1833
|
+
}
|
|
1834
|
+
if (defaultLocale) {
|
|
1835
|
+
const defaultMatch = matches.find((r) => r.locale === defaultLocale);
|
|
1836
|
+
if (defaultMatch) return defaultMatch;
|
|
1837
|
+
}
|
|
1838
|
+
return matches[0];
|
|
1839
|
+
}
|
|
1840
|
+
/**
|
|
1841
|
+
* Derive a best-effort preview route for a file that is not in the route
|
|
1842
|
+
* manifest (e.g. a draft or newly created file). The path is computed from the
|
|
1843
|
+
* file's location relative to the content root, following the same convention
|
|
1844
|
+
* as route discovery (`source/{locale}/path/index.mdx` → `/{locale}/path`).
|
|
1845
|
+
*
|
|
1846
|
+
* Returns null when the file is outside the content root or is not a
|
|
1847
|
+
* recognized content file type.
|
|
1848
|
+
*/
|
|
1849
|
+
function inferRouteForFile(filePath, contentRoot, defaultLocale) {
|
|
1850
|
+
const ref = (0, node_path.relative)(contentRoot, filePath);
|
|
1851
|
+
if (!ref || ref.startsWith("..")) return null;
|
|
1852
|
+
const isMdx = /\.mdx?$/.test(filePath);
|
|
1853
|
+
const isOpenApi = /\.openapi\.(json|ya?ml)$/.test(filePath);
|
|
1854
|
+
if (!isMdx && !isOpenApi) return null;
|
|
1855
|
+
const segments = ref.split("/");
|
|
1856
|
+
const fileLocale = inferLocaleFromPath(filePath);
|
|
1857
|
+
const localeSegmentIndex = fileLocale ? segments.indexOf(fileLocale) : -1;
|
|
1858
|
+
const basePath = basePathFromRef(localeSegmentIndex >= 0 ? segments.slice(localeSegmentIndex + 1).join("/") : ref);
|
|
1859
|
+
const path = fileLocale && defaultLocale ? localizedRoutePath(basePath, fileLocale, {
|
|
1860
|
+
defaultLocale,
|
|
1861
|
+
missing: "fallback",
|
|
1862
|
+
locales: []
|
|
1863
|
+
}) : basePath;
|
|
1864
|
+
const title = segments[segments.length - 1]?.replace(/\.(mdx?|openapi\.(json|ya?ml))$/, "") || "Untitled";
|
|
1865
|
+
return {
|
|
1866
|
+
path: normalizePath(path),
|
|
1867
|
+
filePath,
|
|
1868
|
+
locale: fileLocale,
|
|
1869
|
+
basePath: normalizePath(basePath),
|
|
1870
|
+
kind: isMdx ? "mdx" : "openapi",
|
|
1871
|
+
title,
|
|
1872
|
+
inferred: true
|
|
1873
|
+
};
|
|
1874
|
+
}
|
|
1875
|
+
/** Best-effort locale inference from a file path segment like `.../zh-CN/x.mdx`. */
|
|
1876
|
+
function inferLocaleFromPath(filePath) {
|
|
1877
|
+
const segments = filePath.split("/");
|
|
1878
|
+
for (const segment of segments) if (/^[a-z]{2,3}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/.test(segment)) return segment;
|
|
1879
|
+
}
|
|
1880
|
+
/** Read and parse the JSON body of an IncomingMessage. */
|
|
1881
|
+
function readJsonBody(req) {
|
|
1882
|
+
return new Promise((resolveBody, reject) => {
|
|
1883
|
+
const chunks = [];
|
|
1884
|
+
req.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)));
|
|
1885
|
+
req.on("error", reject);
|
|
1886
|
+
req.on("end", () => {
|
|
1887
|
+
const raw = Buffer.concat(chunks).toString("utf-8").trim();
|
|
1888
|
+
if (!raw) return resolveBody({});
|
|
1889
|
+
try {
|
|
1890
|
+
resolveBody(JSON.parse(raw));
|
|
1891
|
+
} catch (err) {
|
|
1892
|
+
reject(err);
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
});
|
|
1896
|
+
}
|
|
1897
|
+
/**
|
|
1898
|
+
* Handle a request to the dev route endpoint. Pure function — does not touch
|
|
1899
|
+
* the network directly, only reads the request body and writes to `res`.
|
|
1900
|
+
*/
|
|
1901
|
+
async function handleDevRouteRequest(req, res, routes, projectConfig, contentRoot) {
|
|
1902
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
1903
|
+
let body;
|
|
1904
|
+
try {
|
|
1905
|
+
body = await readJsonBody(req);
|
|
1906
|
+
} catch {
|
|
1907
|
+
res.statusCode = 400;
|
|
1908
|
+
res.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
1909
|
+
return;
|
|
1910
|
+
}
|
|
1911
|
+
const file = typeof body === "object" && body !== null ? body.file : void 0;
|
|
1912
|
+
if (typeof file === "string" && file.length > 0) {
|
|
1913
|
+
const route = resolveRouteForFile(file, routes, projectConfig.i18n?.defaultLocale);
|
|
1914
|
+
if (route) {
|
|
1915
|
+
res.end(JSON.stringify(toDevRouteEntry(route)));
|
|
1916
|
+
return;
|
|
1917
|
+
}
|
|
1918
|
+
const inferred = inferRouteForFile(file, contentRoot, projectConfig.i18n?.defaultLocale);
|
|
1919
|
+
res.end(JSON.stringify(inferred));
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
res.end(JSON.stringify(routes.map(toDevRouteEntry)));
|
|
1923
|
+
}
|
|
1804
1924
|
//#endregion
|
|
1805
1925
|
//#region source/core/env-types.ts
|
|
1806
1926
|
var GENERATED_FILE_NAME = "clarify-env.d.ts";
|
|
@@ -1860,6 +1980,84 @@ function resolveBuildOptions(options = {}) {
|
|
|
1860
1980
|
};
|
|
1861
1981
|
}
|
|
1862
1982
|
//#endregion
|
|
1983
|
+
//#region source/core/user-config.ts
|
|
1984
|
+
function defineConfig(config) {
|
|
1985
|
+
validateProjectConfig(config);
|
|
1986
|
+
return config;
|
|
1987
|
+
}
|
|
1988
|
+
/**
|
|
1989
|
+
* Config filenames Clarify CLI looks for at the project root, in resolution
|
|
1990
|
+
* order. Exported so other modules (e.g. the dev `project-info` endpoint) can
|
|
1991
|
+
* surface the same list to tooling without duplicating it.
|
|
1992
|
+
*/
|
|
1993
|
+
var CONFIG_FILENAMES = [
|
|
1994
|
+
"clarify.ts",
|
|
1995
|
+
"clarify.js",
|
|
1996
|
+
"clarify.json"
|
|
1997
|
+
];
|
|
1998
|
+
function findClarifyConfigFile(root) {
|
|
1999
|
+
for (const filename of CONFIG_FILENAMES) {
|
|
2000
|
+
const filePath = (0, node_path.resolve)(root, filename);
|
|
2001
|
+
if ((0, node_fs.existsSync)(filePath)) return filePath;
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
function assertConfigObject(config, configFile) {
|
|
2005
|
+
if (!config || typeof config !== "object" || Array.isArray(config)) throw new Error(`[clarify] ${configFile} must export a configuration object`);
|
|
2006
|
+
return config;
|
|
2007
|
+
}
|
|
2008
|
+
function loadJsonConfig(configFile) {
|
|
2009
|
+
const config = assertConfigObject(JSON.parse((0, node_fs.readFileSync)(configFile, "utf-8")), configFile);
|
|
2010
|
+
const projectConfig = validateProjectConfig(config);
|
|
2011
|
+
const ssg = config.ssg && typeof config.ssg === "object" && !Array.isArray(config.ssg) ? config.ssg : void 0;
|
|
2012
|
+
return {
|
|
2013
|
+
...projectConfig,
|
|
2014
|
+
...ssg ? { ssg } : {}
|
|
2015
|
+
};
|
|
2016
|
+
}
|
|
2017
|
+
async function loadClarifyConfig(root, env) {
|
|
2018
|
+
const configFile = findClarifyConfigFile(root);
|
|
2019
|
+
if (!configFile) return {};
|
|
2020
|
+
if (configFile.endsWith(".json")) return loadJsonConfig(configFile);
|
|
2021
|
+
return assertConfigObject((await (0, vite.loadConfigFromFile)(env, configFile, root, "silent"))?.config, configFile);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* File extensions Clarify treats as content files. Kept in sync with the
|
|
2025
|
+
* patterns used by route discovery in `parsers/routes.ts` and the OpenAPI
|
|
2026
|
+
* page generator. Exposed to tooling so the extension's "is this a content
|
|
2027
|
+
* file?" check stays accurate without duplicating the regex.
|
|
2028
|
+
*/
|
|
2029
|
+
var CONTENT_FILE_EXTENSIONS = [
|
|
2030
|
+
".md",
|
|
2031
|
+
".mdx",
|
|
2032
|
+
".openapi.json",
|
|
2033
|
+
".openapi.yaml",
|
|
2034
|
+
".openapi.yml"
|
|
2035
|
+
];
|
|
2036
|
+
/**
|
|
2037
|
+
* Build the project-info response payload from the resolved plugin state.
|
|
2038
|
+
*/
|
|
2039
|
+
function buildProjectInfo(projectRoot, contentRoot, projectConfig) {
|
|
2040
|
+
const response = {
|
|
2041
|
+
configFilenames: CONFIG_FILENAMES,
|
|
2042
|
+
contentFileExtensions: CONTENT_FILE_EXTENSIONS,
|
|
2043
|
+
contentRoot: (contentRoot.startsWith(projectRoot) ? contentRoot.slice(projectRoot.length).replace(/^[/\\]+/, "") : contentRoot) || "source",
|
|
2044
|
+
projectRoot
|
|
2045
|
+
};
|
|
2046
|
+
if (projectConfig.i18n) response.i18n = {
|
|
2047
|
+
defaultLocale: projectConfig.i18n.defaultLocale,
|
|
2048
|
+
locales: projectConfig.i18n.locales.map((l) => l.code)
|
|
2049
|
+
};
|
|
2050
|
+
return response;
|
|
2051
|
+
}
|
|
2052
|
+
/**
|
|
2053
|
+
* Handle a request to the project-info endpoint. Responds to any method
|
|
2054
|
+
* (GET is typical) with the JSON payload — there is no request body to parse.
|
|
2055
|
+
*/
|
|
2056
|
+
function handleProjectInfoRequest(_req, res, projectRoot, contentRoot, projectConfig) {
|
|
2057
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
2058
|
+
res.end(JSON.stringify(buildProjectInfo(projectRoot, contentRoot, projectConfig)));
|
|
2059
|
+
}
|
|
2060
|
+
//#endregion
|
|
1863
2061
|
//#region source/core/site.ts
|
|
1864
2062
|
async function discoverRoutesForRoot(routeRoot, locale, plugins, ctx) {
|
|
1865
2063
|
return (await runHooks(plugins, "routes:discover", {
|
|
@@ -2133,42 +2331,6 @@ async function renderSSGRoutes(routes, projectConfig, outputDirectory, ssrBundle
|
|
|
2133
2331
|
}
|
|
2134
2332
|
}
|
|
2135
2333
|
//#endregion
|
|
2136
|
-
//#region source/core/user-config.ts
|
|
2137
|
-
function defineConfig(config) {
|
|
2138
|
-
validateProjectConfig(config);
|
|
2139
|
-
return config;
|
|
2140
|
-
}
|
|
2141
|
-
var CONFIG_FILENAMES = [
|
|
2142
|
-
"clarify.ts",
|
|
2143
|
-
"clarify.js",
|
|
2144
|
-
"clarify.json"
|
|
2145
|
-
];
|
|
2146
|
-
function findClarifyConfigFile(root) {
|
|
2147
|
-
for (const filename of CONFIG_FILENAMES) {
|
|
2148
|
-
const filePath = (0, node_path.resolve)(root, filename);
|
|
2149
|
-
if ((0, node_fs.existsSync)(filePath)) return filePath;
|
|
2150
|
-
}
|
|
2151
|
-
}
|
|
2152
|
-
function assertConfigObject(config, configFile) {
|
|
2153
|
-
if (!config || typeof config !== "object" || Array.isArray(config)) throw new Error(`[clarify] ${configFile} must export a configuration object`);
|
|
2154
|
-
return config;
|
|
2155
|
-
}
|
|
2156
|
-
function loadJsonConfig(configFile) {
|
|
2157
|
-
const config = assertConfigObject(JSON.parse((0, node_fs.readFileSync)(configFile, "utf-8")), configFile);
|
|
2158
|
-
const projectConfig = validateProjectConfig(config);
|
|
2159
|
-
const ssg = config.ssg && typeof config.ssg === "object" && !Array.isArray(config.ssg) ? config.ssg : void 0;
|
|
2160
|
-
return {
|
|
2161
|
-
...projectConfig,
|
|
2162
|
-
...ssg ? { ssg } : {}
|
|
2163
|
-
};
|
|
2164
|
-
}
|
|
2165
|
-
async function loadClarifyConfig(root, env) {
|
|
2166
|
-
const configFile = findClarifyConfigFile(root);
|
|
2167
|
-
if (!configFile) return {};
|
|
2168
|
-
if (configFile.endsWith(".json")) return loadJsonConfig(configFile);
|
|
2169
|
-
return assertConfigObject((await (0, vite.loadConfigFromFile)(env, configFile, root, "silent"))?.config, configFile);
|
|
2170
|
-
}
|
|
2171
|
-
//#endregion
|
|
2172
2334
|
//#region source/core/plugin.ts
|
|
2173
2335
|
function loadVirtualModule(id, modules) {
|
|
2174
2336
|
const bareId = stripVirtualPrefix(id);
|
|
@@ -2316,6 +2478,11 @@ function clarifyPlugin(options = {}) {
|
|
|
2316
2478
|
async configureServer(server) {
|
|
2317
2479
|
server.watcher.add(contentRoot);
|
|
2318
2480
|
if (configFilePath) server.watcher.add(configFilePath);
|
|
2481
|
+
server.middlewares.use((req, res, next) => {
|
|
2482
|
+
if (req.url === "/dev/query-preview-route" && req.method === "POST") return handleDevRouteRequest(req, res, routes, projectConfig, contentRoot);
|
|
2483
|
+
if (req.url === "/dev/project-info" && (req.method === "GET" || req.method === "HEAD")) return handleProjectInfoRequest(req, res, root, contentRoot, projectConfig);
|
|
2484
|
+
next();
|
|
2485
|
+
});
|
|
2319
2486
|
const handleContentTreeChange = async (filePath) => {
|
|
2320
2487
|
const relativeContentFile = (0, node_path.relative)(contentRoot, (0, node_path.isAbsolute)(filePath) ? filePath : (0, node_path.join)(root, filePath));
|
|
2321
2488
|
if (!(relativeContentFile && !relativeContentFile.startsWith("..") && !(0, node_path.isAbsolute)(relativeContentFile))) return;
|
|
@@ -2434,4 +2601,4 @@ Object.defineProperty(exports, "resolveClarifySite", {
|
|
|
2434
2601
|
}
|
|
2435
2602
|
});
|
|
2436
2603
|
|
|
2437
|
-
//# sourceMappingURL=plugin-
|
|
2604
|
+
//# sourceMappingURL=plugin-JvxU6ZjU.cjs.map
|