@farming-labs/next 0.0.57 → 0.0.58
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/config.mjs +81 -6
- package/package.json +3 -3
package/dist/config.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { join } from "node:path";
|
|
2
|
+
import { join, relative } from "node:path";
|
|
3
3
|
import createMDX from "@next/mdx";
|
|
4
4
|
|
|
5
5
|
//#region src/config.ts
|
|
@@ -31,6 +31,7 @@ function getNextAppDir(root) {
|
|
|
31
31
|
return "app";
|
|
32
32
|
}
|
|
33
33
|
const GENERATED_BANNER = "// Auto-generated by @farming-labs/next — do not edit manually.\n";
|
|
34
|
+
const GENERATED_CSS_BANNER = "/* Auto-generated by @farming-labs/next — do not edit manually. */\n";
|
|
34
35
|
const MDX_COMPONENTS_TEMPLATE = `\
|
|
35
36
|
${GENERATED_BANNER}
|
|
36
37
|
import { getMDXComponents } from "@farming-labs/theme/mdx";
|
|
@@ -54,6 +55,7 @@ const DOCS_LAYOUT_TEMPLATE = `\
|
|
|
54
55
|
${GENERATED_BANNER}
|
|
55
56
|
import docsConfig from "@/docs.config";
|
|
56
57
|
import { createNextDocsLayout, createNextDocsMetadata } from "@farming-labs/next/layout";
|
|
58
|
+
import "./docs-theme.css";
|
|
57
59
|
|
|
58
60
|
export const metadata = createNextDocsMetadata(docsConfig);
|
|
59
61
|
|
|
@@ -75,6 +77,13 @@ export const { GET, POST } = createDocsAPI({
|
|
|
75
77
|
|
|
76
78
|
export const revalidate = false;
|
|
77
79
|
`;
|
|
80
|
+
function docsThemeCssTemplate(cssImport) {
|
|
81
|
+
return `\
|
|
82
|
+
${GENERATED_CSS_BANNER}
|
|
83
|
+
@reference "tailwindcss";
|
|
84
|
+
@import "${cssImport}";
|
|
85
|
+
`;
|
|
86
|
+
}
|
|
78
87
|
const API_REFERENCE_ROUTE_TEMPLATE = `\
|
|
79
88
|
${GENERATED_BANNER}
|
|
80
89
|
import docsConfig from "@/docs.config";
|
|
@@ -93,6 +102,14 @@ const FILE_EXTS = [
|
|
|
93
102
|
function hasFile(root, baseName) {
|
|
94
103
|
return FILE_EXTS.some((ext) => existsSync(join(root, `${baseName}.${ext}`)));
|
|
95
104
|
}
|
|
105
|
+
function isManagedGeneratedFile(filePath) {
|
|
106
|
+
if (!existsSync(filePath)) return false;
|
|
107
|
+
try {
|
|
108
|
+
return readFileSync(filePath, "utf-8").startsWith(GENERATED_BANNER);
|
|
109
|
+
} catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
96
113
|
/** Read the docs entry path from docs.config.ts[x] (defaults to "docs"). */
|
|
97
114
|
function readDocsEntry(root) {
|
|
98
115
|
for (const ext of FILE_EXTS) {
|
|
@@ -171,17 +188,75 @@ function extractObjectLiteral(content, key) {
|
|
|
171
188
|
if (depth === 0) return content.slice(braceStart + 1, index);
|
|
172
189
|
}
|
|
173
190
|
}
|
|
191
|
+
function parseImportSource(content, localName) {
|
|
192
|
+
for (const match of content.matchAll(/import\s+([^;]+?)\s+from\s+["']([^"']+)["'];?/g)) {
|
|
193
|
+
const clause = match[1]?.trim();
|
|
194
|
+
const source = match[2];
|
|
195
|
+
if (!clause || !source) continue;
|
|
196
|
+
if (clause.startsWith("* as ")) {
|
|
197
|
+
if (clause.slice(5).trim() === localName) return source;
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const namedMatch = clause.match(/\{([\s\S]+)\}/);
|
|
201
|
+
if (namedMatch) {
|
|
202
|
+
const entries = namedMatch[1].split(",");
|
|
203
|
+
for (const entry of entries) {
|
|
204
|
+
const part = entry.trim();
|
|
205
|
+
if (!part) continue;
|
|
206
|
+
const aliasMatch = part.match(/^([A-Za-z_$][\w$]*)\s+as\s+([A-Za-z_$][\w$]*)$/);
|
|
207
|
+
if ((aliasMatch ? aliasMatch[2] : part) === localName) return source;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
const defaultClause = clause.split(",")[0]?.trim();
|
|
211
|
+
if (defaultClause && !defaultClause.startsWith("{") && !defaultClause.startsWith("* as ") && defaultClause === localName) return source;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
function resolveThemeCssImportPath(source, root, layoutDir) {
|
|
215
|
+
const builtIn = {
|
|
216
|
+
"@farming-labs/theme": "@farming-labs/theme/default/css",
|
|
217
|
+
"@farming-labs/theme/default": "@farming-labs/theme/default/css",
|
|
218
|
+
"@farming-labs/theme/colorful": "@farming-labs/theme/colorful/css",
|
|
219
|
+
"@farming-labs/theme/darksharp": "@farming-labs/theme/darksharp/css",
|
|
220
|
+
"@farming-labs/theme/pixel-border": "@farming-labs/theme/pixel-border/css",
|
|
221
|
+
"@farming-labs/theme/shiny": "@farming-labs/theme/shiny/css",
|
|
222
|
+
"@farming-labs/theme/darkbold": "@farming-labs/theme/darkbold/css",
|
|
223
|
+
"@farming-labs/theme/greentree": "@farming-labs/theme/greentree/css"
|
|
224
|
+
}[source];
|
|
225
|
+
if (builtIn) return builtIn;
|
|
226
|
+
let resolvedModulePath;
|
|
227
|
+
if (source.startsWith("@/")) resolvedModulePath = join(root, source.slice(2));
|
|
228
|
+
else if (source.startsWith("./") || source.startsWith("../")) resolvedModulePath = join(root, source);
|
|
229
|
+
if (!resolvedModulePath) return void 0;
|
|
230
|
+
const cssPath = resolvedModulePath.replace(/\.(tsx?|jsx?|mts|cts)$/i, ".css").replace(/$/, "");
|
|
231
|
+
const rel = relative(layoutDir, /\.(css)$/i.test(cssPath) ? cssPath : `${cssPath}.css`).replaceAll("\\", "/");
|
|
232
|
+
return rel.startsWith(".") ? rel : `./${rel}`;
|
|
233
|
+
}
|
|
234
|
+
function readThemeCssImport(root, layoutDir) {
|
|
235
|
+
for (const ext of FILE_EXTS) {
|
|
236
|
+
const configPath = join(root, `docs.config.${ext}`);
|
|
237
|
+
if (!existsSync(configPath)) continue;
|
|
238
|
+
try {
|
|
239
|
+
const content = readFileSync(configPath, "utf-8");
|
|
240
|
+
const themeIdentifier = content.match(/theme\s*:\s*([A-Za-z_$][\w$]*)\s*\(/)?.[1];
|
|
241
|
+
if (!themeIdentifier) continue;
|
|
242
|
+
const source = parseImportSource(content, themeIdentifier);
|
|
243
|
+
if (!source) continue;
|
|
244
|
+
const cssImport = resolveThemeCssImportPath(source, root, layoutDir);
|
|
245
|
+
if (cssImport) return cssImport;
|
|
246
|
+
} catch {}
|
|
247
|
+
}
|
|
248
|
+
return "@farming-labs/theme/default/css";
|
|
249
|
+
}
|
|
174
250
|
function withDocs(nextConfig = {}) {
|
|
175
251
|
const root = process.cwd();
|
|
176
252
|
if (!hasFile(root, "mdx-components")) writeFileSync(join(root, "mdx-components.tsx"), MDX_COMPONENTS_TEMPLATE);
|
|
177
253
|
const entry = readDocsEntry(root);
|
|
178
254
|
const appDir = getNextAppDir(root);
|
|
179
255
|
const layoutDir = join(root, appDir, entry);
|
|
180
|
-
if (existsSync(layoutDir)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
}
|
|
256
|
+
if (!existsSync(layoutDir)) mkdirSync(layoutDir, { recursive: true });
|
|
257
|
+
const docsLayoutPath = join(layoutDir, "layout.tsx");
|
|
258
|
+
if (!hasFile(layoutDir, "layout") || isManagedGeneratedFile(docsLayoutPath)) writeFileSync(join(layoutDir, "layout.tsx"), DOCS_LAYOUT_TEMPLATE);
|
|
259
|
+
writeFileSync(join(layoutDir, "docs-theme.css"), docsThemeCssTemplate(readThemeCssImport(root, layoutDir)));
|
|
185
260
|
const isStaticExport = nextConfig.output === "export";
|
|
186
261
|
const docsApiRouteDir = join(root, appDir, "api", "docs");
|
|
187
262
|
if (!isStaticExport && !hasFile(docsApiRouteDir, "route")) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farming-labs/next",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.58",
|
|
4
4
|
"description": "Next.js adapter for @farming-labs/docs — MDX config wrapper",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"docs",
|
|
@@ -79,8 +79,8 @@
|
|
|
79
79
|
"tsdown": "^0.20.3",
|
|
80
80
|
"typescript": "^5.9.3",
|
|
81
81
|
"vitest": "^3.2.4",
|
|
82
|
-
"@farming-labs/docs": "0.0.
|
|
83
|
-
"@farming-labs/theme": "0.0.
|
|
82
|
+
"@farming-labs/docs": "0.0.58",
|
|
83
|
+
"@farming-labs/theme": "0.0.58"
|
|
84
84
|
},
|
|
85
85
|
"peerDependencies": {
|
|
86
86
|
"@farming-labs/docs": ">=0.0.1",
|