@chronoter/main 0.1.10 → 0.2.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/dist/cli.js +99 -22
- package/dist/index.js +98 -21
- package/dist/server/client/main.css +209 -11
- package/dist/server/client/main.js +584 -1728
- package/package.json +5 -1
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,10 @@ import { visit } from 'unist-util-visit';
|
|
|
8
8
|
import { compile } from '@mdx-js/mdx';
|
|
9
9
|
import matter from 'gray-matter';
|
|
10
10
|
import remarkGfm from 'remark-gfm';
|
|
11
|
+
import rehypeSlug from 'rehype-slug';
|
|
12
|
+
import { unified } from 'unified';
|
|
13
|
+
import remarkParse from 'remark-parse';
|
|
14
|
+
import GithubSlugger from 'github-slugger';
|
|
11
15
|
import { fileURLToPath } from 'url';
|
|
12
16
|
import { Command } from 'commander';
|
|
13
17
|
import chalk2 from 'chalk';
|
|
@@ -237,12 +241,14 @@ var init_processor = __esm({
|
|
|
237
241
|
throw new MDXError(`Failed to parse frontmatter: ${message}`, filePath);
|
|
238
242
|
}
|
|
239
243
|
const code = await this.compile(content, filePath, options?.baseUrl);
|
|
244
|
+
const headings = this.extractHeadings(content);
|
|
240
245
|
const slug = this.generateSlug(filePath);
|
|
241
246
|
const frontmatter = this.parseFrontmatter(data);
|
|
242
247
|
return {
|
|
243
248
|
code,
|
|
244
249
|
frontmatter,
|
|
245
|
-
slug
|
|
250
|
+
slug,
|
|
251
|
+
headings
|
|
246
252
|
};
|
|
247
253
|
} catch (error) {
|
|
248
254
|
if (error instanceof MDXError) {
|
|
@@ -295,7 +301,8 @@ var init_processor = __esm({
|
|
|
295
301
|
const result = await compile(source, {
|
|
296
302
|
outputFormat: "function-body",
|
|
297
303
|
development: false,
|
|
298
|
-
remarkPlugins
|
|
304
|
+
remarkPlugins,
|
|
305
|
+
rehypePlugins: [rehypeSlug]
|
|
299
306
|
});
|
|
300
307
|
return String(result);
|
|
301
308
|
} catch (error) {
|
|
@@ -320,6 +327,52 @@ var init_processor = __esm({
|
|
|
320
327
|
const fileName = basename(filePath, extname(filePath));
|
|
321
328
|
return fileName;
|
|
322
329
|
}
|
|
330
|
+
/**
|
|
331
|
+
* Markdownコンテンツから見出しを抽出する
|
|
332
|
+
*
|
|
333
|
+
* @param content - Markdownコンテンツ
|
|
334
|
+
* @returns 見出しの配列(h2, h3のみ)
|
|
335
|
+
* @private
|
|
336
|
+
*/
|
|
337
|
+
extractHeadings(content) {
|
|
338
|
+
const headings = [];
|
|
339
|
+
const slugger = new GithubSlugger();
|
|
340
|
+
try {
|
|
341
|
+
const tree = unified().use(remarkParse).parse(content);
|
|
342
|
+
visit(tree, "heading", (node) => {
|
|
343
|
+
if (node.depth === 2 || node.depth === 3) {
|
|
344
|
+
const text = this.extractTextFromNode(node.children);
|
|
345
|
+
const id = slugger.slug(text);
|
|
346
|
+
headings.push({
|
|
347
|
+
id,
|
|
348
|
+
text,
|
|
349
|
+
level: node.depth
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
});
|
|
353
|
+
} catch (error) {
|
|
354
|
+
console.warn("Failed to extract headings:", error);
|
|
355
|
+
}
|
|
356
|
+
return headings;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* 見出しノードの子要素からテキストを抽出する
|
|
360
|
+
*
|
|
361
|
+
* @param children - 見出しノードの子要素
|
|
362
|
+
* @returns テキスト
|
|
363
|
+
* @private
|
|
364
|
+
*/
|
|
365
|
+
extractTextFromNode(children) {
|
|
366
|
+
return children.map((child) => {
|
|
367
|
+
if (child.type === "text") {
|
|
368
|
+
return child.value;
|
|
369
|
+
}
|
|
370
|
+
if ("children" in child && Array.isArray(child.children)) {
|
|
371
|
+
return this.extractTextFromNode(child.children);
|
|
372
|
+
}
|
|
373
|
+
return "";
|
|
374
|
+
}).join("");
|
|
375
|
+
}
|
|
323
376
|
};
|
|
324
377
|
}
|
|
325
378
|
});
|
|
@@ -446,16 +499,17 @@ var init_router = __esm({
|
|
|
446
499
|
/**
|
|
447
500
|
* ファイルパスからルートを作成
|
|
448
501
|
*
|
|
449
|
-
* @param filePath - MDXまたはMD
|
|
450
|
-
* @param baseDir -
|
|
502
|
+
* @param filePath - MDXまたはMDファイルの絶対パス
|
|
503
|
+
* @param baseDir - ベースディレクトリパス(docsDir)
|
|
451
504
|
* @returns 生成されたルート
|
|
452
505
|
*/
|
|
453
506
|
async createRoute(filePath, baseDir) {
|
|
454
507
|
const frontmatter = await this.extractFrontmatter(filePath);
|
|
455
508
|
const urlPath = this.filePathToUrlPath(filePath, baseDir);
|
|
509
|
+
const relativeFilePath = path.relative(baseDir, filePath);
|
|
456
510
|
return {
|
|
457
511
|
path: urlPath,
|
|
458
|
-
filePath,
|
|
512
|
+
filePath: relativeFilePath,
|
|
459
513
|
frontmatter
|
|
460
514
|
};
|
|
461
515
|
}
|
|
@@ -513,12 +567,17 @@ var routing_middleware_exports = {};
|
|
|
513
567
|
__export(routing_middleware_exports, {
|
|
514
568
|
createRoutingMiddleware: () => createRoutingMiddleware
|
|
515
569
|
});
|
|
516
|
-
var __filename$1, __dirname$1, createRoutingMiddleware, handleAllRoutesRequest, handleRouteRequest, handleMDXRequest, handle500;
|
|
570
|
+
var __filename$1, __dirname$1, hasFileExtension, createRoutingMiddleware, handleAllRoutesRequest, handleRouteRequest, handleMDXRequest, handle500;
|
|
517
571
|
var init_routing_middleware = __esm({
|
|
518
572
|
"src/server/routing-middleware.ts"() {
|
|
519
573
|
init_router();
|
|
520
574
|
__filename$1 = fileURLToPath(import.meta.url);
|
|
521
575
|
__dirname$1 = dirname(__filename$1);
|
|
576
|
+
hasFileExtension = (urlPath) => {
|
|
577
|
+
const lastSegment = urlPath.split("/").pop() || "";
|
|
578
|
+
const dotIndex = lastSegment.lastIndexOf(".");
|
|
579
|
+
return dotIndex > 0;
|
|
580
|
+
};
|
|
522
581
|
createRoutingMiddleware = (server, options) => {
|
|
523
582
|
const { config, cwd } = options;
|
|
524
583
|
const routeGenerator = new RouteGenerator();
|
|
@@ -569,7 +628,8 @@ var init_routing_middleware = __esm({
|
|
|
569
628
|
}
|
|
570
629
|
const urlPath = url.split("?")[0];
|
|
571
630
|
if (urlPath === "/__chronoter_mdx__") {
|
|
572
|
-
|
|
631
|
+
const docsDir = config.docsDir ? resolve(cwd, config.docsDir) : cwd;
|
|
632
|
+
return handleMDXRequest(req, res, docsDir);
|
|
573
633
|
}
|
|
574
634
|
if (urlPath === "/__chronoter_routes__") {
|
|
575
635
|
return handleRouteRequest(req, res, getRoutes, routeGenerator);
|
|
@@ -579,7 +639,7 @@ var init_routing_middleware = __esm({
|
|
|
579
639
|
}
|
|
580
640
|
if (urlPath.startsWith("/@") || // Vite内部リクエスト
|
|
581
641
|
urlPath.startsWith("/node_modules") || urlPath.startsWith("/src/") || // Viteが処理するソースファイル
|
|
582
|
-
urlPath
|
|
642
|
+
hasFileExtension(urlPath) && !urlPath.endsWith("/") && !urlPath.startsWith("/src/")) {
|
|
583
643
|
return next();
|
|
584
644
|
}
|
|
585
645
|
try {
|
|
@@ -689,7 +749,7 @@ var init_routing_middleware = __esm({
|
|
|
689
749
|
);
|
|
690
750
|
}
|
|
691
751
|
};
|
|
692
|
-
handleMDXRequest = async (req, res,
|
|
752
|
+
handleMDXRequest = async (req, res, docsDir) => {
|
|
693
753
|
try {
|
|
694
754
|
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
|
695
755
|
const filePath = url.searchParams.get("path");
|
|
@@ -699,8 +759,8 @@ var init_routing_middleware = __esm({
|
|
|
699
759
|
res.end(JSON.stringify({ error: "Missing 'path' query parameter" }));
|
|
700
760
|
return;
|
|
701
761
|
}
|
|
702
|
-
const absolutePath = resolve(
|
|
703
|
-
if (!absolutePath.startsWith(
|
|
762
|
+
const absolutePath = resolve(docsDir, filePath);
|
|
763
|
+
if (!absolutePath.startsWith(docsDir)) {
|
|
704
764
|
res.statusCode = 403;
|
|
705
765
|
res.setHeader("Content-Type", "application/json");
|
|
706
766
|
res.end(JSON.stringify({ error: "Access denied" }));
|
|
@@ -715,7 +775,8 @@ var init_routing_middleware = __esm({
|
|
|
715
775
|
JSON.stringify({
|
|
716
776
|
code: processedMDX.code,
|
|
717
777
|
frontmatter: processedMDX.frontmatter,
|
|
718
|
-
slug: processedMDX.slug
|
|
778
|
+
slug: processedMDX.slug,
|
|
779
|
+
headings: processedMDX.headings
|
|
719
780
|
})
|
|
720
781
|
);
|
|
721
782
|
} catch (error) {
|
|
@@ -824,7 +885,7 @@ var ConfigError = class _ConfigError extends Error {
|
|
|
824
885
|
}
|
|
825
886
|
};
|
|
826
887
|
var siteConfigSchema = z.object({
|
|
827
|
-
title: z.string().min(1, "site.title
|
|
888
|
+
title: z.string().min(1, "site.title must not be empty").optional(),
|
|
828
889
|
description: z.string().optional(),
|
|
829
890
|
baseUrl: z.string().url("site.baseUrl must be a valid URL").optional()
|
|
830
891
|
});
|
|
@@ -840,7 +901,7 @@ var themeConfigSchema = z.object({
|
|
|
840
901
|
logo: z.string().optional()
|
|
841
902
|
});
|
|
842
903
|
var chronoterConfigSchema = z.object({
|
|
843
|
-
site: siteConfigSchema,
|
|
904
|
+
site: siteConfigSchema.optional(),
|
|
844
905
|
navigation: z.array(navigationItemSchema).optional(),
|
|
845
906
|
docsDir: z.string().min(1, "docsDir must not be empty").optional(),
|
|
846
907
|
outDir: z.string().optional(),
|
|
@@ -850,6 +911,10 @@ var chronoterConfigSchema = z.object({
|
|
|
850
911
|
|
|
851
912
|
// src/core/config/defaults.ts
|
|
852
913
|
var defaultConfig = {
|
|
914
|
+
site: {
|
|
915
|
+
title: "Chronoter Documentation"
|
|
916
|
+
// デフォルトタイトル
|
|
917
|
+
},
|
|
853
918
|
docsDir: ".",
|
|
854
919
|
// デフォルトはルートディレクトリ
|
|
855
920
|
theme: {
|
|
@@ -858,9 +923,12 @@ var defaultConfig = {
|
|
|
858
923
|
}
|
|
859
924
|
};
|
|
860
925
|
var mergeWithDefaults = (userConfig) => {
|
|
861
|
-
const site = userConfig.site;
|
|
862
926
|
return {
|
|
863
|
-
site
|
|
927
|
+
site: {
|
|
928
|
+
title: userConfig.site?.title ?? defaultConfig.site.title,
|
|
929
|
+
description: userConfig.site?.description,
|
|
930
|
+
baseUrl: userConfig.site?.baseUrl
|
|
931
|
+
},
|
|
864
932
|
docsDir: userConfig.docsDir ?? defaultConfig.docsDir,
|
|
865
933
|
navigation: userConfig.navigation,
|
|
866
934
|
theme: {
|
|
@@ -896,10 +964,7 @@ var ConfigLoader = class {
|
|
|
896
964
|
return this.validate(parsedConfig);
|
|
897
965
|
} catch (error) {
|
|
898
966
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
899
|
-
|
|
900
|
-
`Config file not found: ${configPath}
|
|
901
|
-
Please create a chronoter.config.json file.`
|
|
902
|
-
);
|
|
967
|
+
return defaultConfig;
|
|
903
968
|
}
|
|
904
969
|
if (error instanceof ConfigError) {
|
|
905
970
|
throw error;
|
|
@@ -1015,10 +1080,22 @@ var createViteConfig = (config, options = {}) => {
|
|
|
1015
1080
|
);
|
|
1016
1081
|
}
|
|
1017
1082
|
},
|
|
1018
|
-
//
|
|
1083
|
+
// ビルド済みクライアントファイル配信プラグイン
|
|
1019
1084
|
// npmパッケージとして使用時、/server/client/ へのリクエストをdist内のファイルから配信
|
|
1020
1085
|
{
|
|
1021
1086
|
name: "chronoter-built-client",
|
|
1087
|
+
// Viteのモジュール解決フック: /server/client/main.js を解決
|
|
1088
|
+
// transformIndexHtml がHTMLを解析する際にモジュール解決を試みるため必要
|
|
1089
|
+
resolveId(id) {
|
|
1090
|
+
if (id === "/server/client/main.js" || id === "/server/client/main.css") {
|
|
1091
|
+
const fileName = id.replace("/server/client/", "");
|
|
1092
|
+
const clientFilePath = resolve(__dirname2, "server/client", fileName);
|
|
1093
|
+
if (existsSync(clientFilePath)) {
|
|
1094
|
+
return clientFilePath;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
return null;
|
|
1098
|
+
},
|
|
1022
1099
|
configureServer(server) {
|
|
1023
1100
|
server.middlewares.use((req, res, next) => {
|
|
1024
1101
|
const url = req.url || "";
|
|
@@ -1649,7 +1726,7 @@ var runVersionCheck = async (packageName, currentVersion) => {
|
|
|
1649
1726
|
|
|
1650
1727
|
// src/cli/index.ts
|
|
1651
1728
|
var PACKAGE_NAME = "chronoter";
|
|
1652
|
-
var CURRENT_VERSION = "0.
|
|
1729
|
+
var CURRENT_VERSION = "0.2.0";
|
|
1653
1730
|
var createCliProgram = () => {
|
|
1654
1731
|
const program = new Command();
|
|
1655
1732
|
program.name("chronoter").description("Chronoter - MDX-based documentation site generator").version(CURRENT_VERSION);
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,10 @@ import { visit } from 'unist-util-visit';
|
|
|
7
7
|
import { compile } from '@mdx-js/mdx';
|
|
8
8
|
import matter from 'gray-matter';
|
|
9
9
|
import remarkGfm from 'remark-gfm';
|
|
10
|
+
import rehypeSlug from 'rehype-slug';
|
|
11
|
+
import { unified } from 'unified';
|
|
12
|
+
import remarkParse from 'remark-parse';
|
|
13
|
+
import GithubSlugger from 'github-slugger';
|
|
10
14
|
import { fileURLToPath } from 'url';
|
|
11
15
|
import chalk2 from 'chalk';
|
|
12
16
|
import { defineConfig, createServer } from 'vite';
|
|
@@ -232,12 +236,14 @@ var init_processor = __esm({
|
|
|
232
236
|
throw new MDXError(`Failed to parse frontmatter: ${message}`, filePath);
|
|
233
237
|
}
|
|
234
238
|
const code = await this.compile(content, filePath, options?.baseUrl);
|
|
239
|
+
const headings = this.extractHeadings(content);
|
|
235
240
|
const slug = this.generateSlug(filePath);
|
|
236
241
|
const frontmatter = this.parseFrontmatter(data);
|
|
237
242
|
return {
|
|
238
243
|
code,
|
|
239
244
|
frontmatter,
|
|
240
|
-
slug
|
|
245
|
+
slug,
|
|
246
|
+
headings
|
|
241
247
|
};
|
|
242
248
|
} catch (error) {
|
|
243
249
|
if (error instanceof MDXError) {
|
|
@@ -290,7 +296,8 @@ var init_processor = __esm({
|
|
|
290
296
|
const result = await compile(source, {
|
|
291
297
|
outputFormat: "function-body",
|
|
292
298
|
development: false,
|
|
293
|
-
remarkPlugins
|
|
299
|
+
remarkPlugins,
|
|
300
|
+
rehypePlugins: [rehypeSlug]
|
|
294
301
|
});
|
|
295
302
|
return String(result);
|
|
296
303
|
} catch (error) {
|
|
@@ -315,6 +322,52 @@ var init_processor = __esm({
|
|
|
315
322
|
const fileName = basename(filePath, extname(filePath));
|
|
316
323
|
return fileName;
|
|
317
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Markdownコンテンツから見出しを抽出する
|
|
327
|
+
*
|
|
328
|
+
* @param content - Markdownコンテンツ
|
|
329
|
+
* @returns 見出しの配列(h2, h3のみ)
|
|
330
|
+
* @private
|
|
331
|
+
*/
|
|
332
|
+
extractHeadings(content) {
|
|
333
|
+
const headings = [];
|
|
334
|
+
const slugger = new GithubSlugger();
|
|
335
|
+
try {
|
|
336
|
+
const tree = unified().use(remarkParse).parse(content);
|
|
337
|
+
visit(tree, "heading", (node) => {
|
|
338
|
+
if (node.depth === 2 || node.depth === 3) {
|
|
339
|
+
const text = this.extractTextFromNode(node.children);
|
|
340
|
+
const id = slugger.slug(text);
|
|
341
|
+
headings.push({
|
|
342
|
+
id,
|
|
343
|
+
text,
|
|
344
|
+
level: node.depth
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
});
|
|
348
|
+
} catch (error) {
|
|
349
|
+
console.warn("Failed to extract headings:", error);
|
|
350
|
+
}
|
|
351
|
+
return headings;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* 見出しノードの子要素からテキストを抽出する
|
|
355
|
+
*
|
|
356
|
+
* @param children - 見出しノードの子要素
|
|
357
|
+
* @returns テキスト
|
|
358
|
+
* @private
|
|
359
|
+
*/
|
|
360
|
+
extractTextFromNode(children) {
|
|
361
|
+
return children.map((child) => {
|
|
362
|
+
if (child.type === "text") {
|
|
363
|
+
return child.value;
|
|
364
|
+
}
|
|
365
|
+
if ("children" in child && Array.isArray(child.children)) {
|
|
366
|
+
return this.extractTextFromNode(child.children);
|
|
367
|
+
}
|
|
368
|
+
return "";
|
|
369
|
+
}).join("");
|
|
370
|
+
}
|
|
318
371
|
};
|
|
319
372
|
}
|
|
320
373
|
});
|
|
@@ -441,16 +494,17 @@ var init_router = __esm({
|
|
|
441
494
|
/**
|
|
442
495
|
* ファイルパスからルートを作成
|
|
443
496
|
*
|
|
444
|
-
* @param filePath - MDXまたはMD
|
|
445
|
-
* @param baseDir -
|
|
497
|
+
* @param filePath - MDXまたはMDファイルの絶対パス
|
|
498
|
+
* @param baseDir - ベースディレクトリパス(docsDir)
|
|
446
499
|
* @returns 生成されたルート
|
|
447
500
|
*/
|
|
448
501
|
async createRoute(filePath, baseDir) {
|
|
449
502
|
const frontmatter = await this.extractFrontmatter(filePath);
|
|
450
503
|
const urlPath = this.filePathToUrlPath(filePath, baseDir);
|
|
504
|
+
const relativeFilePath = path.relative(baseDir, filePath);
|
|
451
505
|
return {
|
|
452
506
|
path: urlPath,
|
|
453
|
-
filePath,
|
|
507
|
+
filePath: relativeFilePath,
|
|
454
508
|
frontmatter
|
|
455
509
|
};
|
|
456
510
|
}
|
|
@@ -508,12 +562,17 @@ var routing_middleware_exports = {};
|
|
|
508
562
|
__export(routing_middleware_exports, {
|
|
509
563
|
createRoutingMiddleware: () => createRoutingMiddleware
|
|
510
564
|
});
|
|
511
|
-
var __filename$1, __dirname$1, createRoutingMiddleware, handleAllRoutesRequest, handleRouteRequest, handleMDXRequest, handle500;
|
|
565
|
+
var __filename$1, __dirname$1, hasFileExtension, createRoutingMiddleware, handleAllRoutesRequest, handleRouteRequest, handleMDXRequest, handle500;
|
|
512
566
|
var init_routing_middleware = __esm({
|
|
513
567
|
"src/server/routing-middleware.ts"() {
|
|
514
568
|
init_router();
|
|
515
569
|
__filename$1 = fileURLToPath(import.meta.url);
|
|
516
570
|
__dirname$1 = dirname(__filename$1);
|
|
571
|
+
hasFileExtension = (urlPath) => {
|
|
572
|
+
const lastSegment = urlPath.split("/").pop() || "";
|
|
573
|
+
const dotIndex = lastSegment.lastIndexOf(".");
|
|
574
|
+
return dotIndex > 0;
|
|
575
|
+
};
|
|
517
576
|
createRoutingMiddleware = (server, options) => {
|
|
518
577
|
const { config, cwd } = options;
|
|
519
578
|
const routeGenerator = new RouteGenerator();
|
|
@@ -564,7 +623,8 @@ var init_routing_middleware = __esm({
|
|
|
564
623
|
}
|
|
565
624
|
const urlPath = url.split("?")[0];
|
|
566
625
|
if (urlPath === "/__chronoter_mdx__") {
|
|
567
|
-
|
|
626
|
+
const docsDir = config.docsDir ? resolve(cwd, config.docsDir) : cwd;
|
|
627
|
+
return handleMDXRequest(req, res, docsDir);
|
|
568
628
|
}
|
|
569
629
|
if (urlPath === "/__chronoter_routes__") {
|
|
570
630
|
return handleRouteRequest(req, res, getRoutes, routeGenerator);
|
|
@@ -574,7 +634,7 @@ var init_routing_middleware = __esm({
|
|
|
574
634
|
}
|
|
575
635
|
if (urlPath.startsWith("/@") || // Vite内部リクエスト
|
|
576
636
|
urlPath.startsWith("/node_modules") || urlPath.startsWith("/src/") || // Viteが処理するソースファイル
|
|
577
|
-
urlPath
|
|
637
|
+
hasFileExtension(urlPath) && !urlPath.endsWith("/") && !urlPath.startsWith("/src/")) {
|
|
578
638
|
return next();
|
|
579
639
|
}
|
|
580
640
|
try {
|
|
@@ -684,7 +744,7 @@ var init_routing_middleware = __esm({
|
|
|
684
744
|
);
|
|
685
745
|
}
|
|
686
746
|
};
|
|
687
|
-
handleMDXRequest = async (req, res,
|
|
747
|
+
handleMDXRequest = async (req, res, docsDir) => {
|
|
688
748
|
try {
|
|
689
749
|
const url = new URL(req.url || "", `http://${req.headers.host}`);
|
|
690
750
|
const filePath = url.searchParams.get("path");
|
|
@@ -694,8 +754,8 @@ var init_routing_middleware = __esm({
|
|
|
694
754
|
res.end(JSON.stringify({ error: "Missing 'path' query parameter" }));
|
|
695
755
|
return;
|
|
696
756
|
}
|
|
697
|
-
const absolutePath = resolve(
|
|
698
|
-
if (!absolutePath.startsWith(
|
|
757
|
+
const absolutePath = resolve(docsDir, filePath);
|
|
758
|
+
if (!absolutePath.startsWith(docsDir)) {
|
|
699
759
|
res.statusCode = 403;
|
|
700
760
|
res.setHeader("Content-Type", "application/json");
|
|
701
761
|
res.end(JSON.stringify({ error: "Access denied" }));
|
|
@@ -710,7 +770,8 @@ var init_routing_middleware = __esm({
|
|
|
710
770
|
JSON.stringify({
|
|
711
771
|
code: processedMDX.code,
|
|
712
772
|
frontmatter: processedMDX.frontmatter,
|
|
713
|
-
slug: processedMDX.slug
|
|
773
|
+
slug: processedMDX.slug,
|
|
774
|
+
headings: processedMDX.headings
|
|
714
775
|
})
|
|
715
776
|
);
|
|
716
777
|
} catch (error) {
|
|
@@ -819,7 +880,7 @@ var ConfigError = class _ConfigError extends Error {
|
|
|
819
880
|
}
|
|
820
881
|
};
|
|
821
882
|
var siteConfigSchema = z.object({
|
|
822
|
-
title: z.string().min(1, "site.title
|
|
883
|
+
title: z.string().min(1, "site.title must not be empty").optional(),
|
|
823
884
|
description: z.string().optional(),
|
|
824
885
|
baseUrl: z.string().url("site.baseUrl must be a valid URL").optional()
|
|
825
886
|
});
|
|
@@ -835,7 +896,7 @@ var themeConfigSchema = z.object({
|
|
|
835
896
|
logo: z.string().optional()
|
|
836
897
|
});
|
|
837
898
|
var chronoterConfigSchema = z.object({
|
|
838
|
-
site: siteConfigSchema,
|
|
899
|
+
site: siteConfigSchema.optional(),
|
|
839
900
|
navigation: z.array(navigationItemSchema).optional(),
|
|
840
901
|
docsDir: z.string().min(1, "docsDir must not be empty").optional(),
|
|
841
902
|
outDir: z.string().optional(),
|
|
@@ -845,6 +906,10 @@ var chronoterConfigSchema = z.object({
|
|
|
845
906
|
|
|
846
907
|
// src/core/config/defaults.ts
|
|
847
908
|
var defaultConfig = {
|
|
909
|
+
site: {
|
|
910
|
+
title: "Chronoter Documentation"
|
|
911
|
+
// デフォルトタイトル
|
|
912
|
+
},
|
|
848
913
|
docsDir: ".",
|
|
849
914
|
// デフォルトはルートディレクトリ
|
|
850
915
|
theme: {
|
|
@@ -853,9 +918,12 @@ var defaultConfig = {
|
|
|
853
918
|
}
|
|
854
919
|
};
|
|
855
920
|
var mergeWithDefaults = (userConfig) => {
|
|
856
|
-
const site = userConfig.site;
|
|
857
921
|
return {
|
|
858
|
-
site
|
|
922
|
+
site: {
|
|
923
|
+
title: userConfig.site?.title ?? defaultConfig.site.title,
|
|
924
|
+
description: userConfig.site?.description,
|
|
925
|
+
baseUrl: userConfig.site?.baseUrl
|
|
926
|
+
},
|
|
859
927
|
docsDir: userConfig.docsDir ?? defaultConfig.docsDir,
|
|
860
928
|
navigation: userConfig.navigation,
|
|
861
929
|
theme: {
|
|
@@ -891,10 +959,7 @@ var ConfigLoader = class {
|
|
|
891
959
|
return this.validate(parsedConfig);
|
|
892
960
|
} catch (error) {
|
|
893
961
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
894
|
-
|
|
895
|
-
`Config file not found: ${configPath}
|
|
896
|
-
Please create a chronoter.config.json file.`
|
|
897
|
-
);
|
|
962
|
+
return defaultConfig;
|
|
898
963
|
}
|
|
899
964
|
if (error instanceof ConfigError) {
|
|
900
965
|
throw error;
|
|
@@ -1010,10 +1075,22 @@ var createViteConfig = (config, options = {}) => {
|
|
|
1010
1075
|
);
|
|
1011
1076
|
}
|
|
1012
1077
|
},
|
|
1013
|
-
//
|
|
1078
|
+
// ビルド済みクライアントファイル配信プラグイン
|
|
1014
1079
|
// npmパッケージとして使用時、/server/client/ へのリクエストをdist内のファイルから配信
|
|
1015
1080
|
{
|
|
1016
1081
|
name: "chronoter-built-client",
|
|
1082
|
+
// Viteのモジュール解決フック: /server/client/main.js を解決
|
|
1083
|
+
// transformIndexHtml がHTMLを解析する際にモジュール解決を試みるため必要
|
|
1084
|
+
resolveId(id) {
|
|
1085
|
+
if (id === "/server/client/main.js" || id === "/server/client/main.css") {
|
|
1086
|
+
const fileName = id.replace("/server/client/", "");
|
|
1087
|
+
const clientFilePath = resolve(__dirname2, "server/client", fileName);
|
|
1088
|
+
if (existsSync(clientFilePath)) {
|
|
1089
|
+
return clientFilePath;
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
return null;
|
|
1093
|
+
},
|
|
1017
1094
|
configureServer(server) {
|
|
1018
1095
|
server.middlewares.use((req, res, next) => {
|
|
1019
1096
|
const url = req.url || "";
|