@windrun-huaiin/third-ui 5.12.4 → 5.13.1
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/lib/server.d.mts +2 -2
- package/dist/lib/server.d.ts +2 -2
- package/dist/lib/server.js +29 -21
- package/dist/lib/server.js.map +1 -1
- package/dist/lib/server.mjs +29 -21
- package/dist/lib/server.mjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/seo-util.ts +36 -25
package/dist/lib/server.d.mts
CHANGED
|
@@ -4455,7 +4455,7 @@ declare function generateRobots(baseUrl: string): MetadataRoute.Robots;
|
|
|
4455
4455
|
* @param baseUrl - The base URL of the website
|
|
4456
4456
|
* @param locales - Supported locales array
|
|
4457
4457
|
* @param mdxSourceDir - MDX source directory path
|
|
4458
|
-
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap
|
|
4458
|
+
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true
|
|
4459
4459
|
* @returns Sitemap entries
|
|
4460
4460
|
*/
|
|
4461
4461
|
declare function generateSitemap(baseUrl: string, locales: string[], mdxSourceDir: string, openMdxSEOSiteMap?: boolean): MetadataRoute.Sitemap;
|
|
@@ -4470,7 +4470,7 @@ declare function createRobotsHandler(baseUrl: string): () => MetadataRoute.Robot
|
|
|
4470
4470
|
* @param baseUrl - The base URL of the website
|
|
4471
4471
|
* @param locales - Supported locales array
|
|
4472
4472
|
* @param mdxSourceDir - MDX source directory path
|
|
4473
|
-
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap
|
|
4473
|
+
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true
|
|
4474
4474
|
* @returns Sitemap handler function
|
|
4475
4475
|
*/
|
|
4476
4476
|
declare function createSitemapHandler(baseUrl: string, locales: string[], mdxSourceDir: string, openMdxSEOSiteMap?: boolean): () => MetadataRoute.Sitemap;
|
package/dist/lib/server.d.ts
CHANGED
|
@@ -4455,7 +4455,7 @@ declare function generateRobots(baseUrl: string): MetadataRoute.Robots;
|
|
|
4455
4455
|
* @param baseUrl - The base URL of the website
|
|
4456
4456
|
* @param locales - Supported locales array
|
|
4457
4457
|
* @param mdxSourceDir - MDX source directory path
|
|
4458
|
-
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap
|
|
4458
|
+
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true
|
|
4459
4459
|
* @returns Sitemap entries
|
|
4460
4460
|
*/
|
|
4461
4461
|
declare function generateSitemap(baseUrl: string, locales: string[], mdxSourceDir: string, openMdxSEOSiteMap?: boolean): MetadataRoute.Sitemap;
|
|
@@ -4470,7 +4470,7 @@ declare function createRobotsHandler(baseUrl: string): () => MetadataRoute.Robot
|
|
|
4470
4470
|
* @param baseUrl - The base URL of the website
|
|
4471
4471
|
* @param locales - Supported locales array
|
|
4472
4472
|
* @param mdxSourceDir - MDX source directory path
|
|
4473
|
-
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap
|
|
4473
|
+
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true
|
|
4474
4474
|
* @returns Sitemap handler function
|
|
4475
4475
|
*/
|
|
4476
4476
|
declare function createSitemapHandler(baseUrl: string, locales: string[], mdxSourceDir: string, openMdxSEOSiteMap?: boolean): () => MetadataRoute.Sitemap;
|
package/dist/lib/server.js
CHANGED
|
@@ -138,28 +138,36 @@ function generateRobots(baseUrl) {
|
|
|
138
138
|
sitemap: `${baseUrl}/sitemap.xml`
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
|
-
function generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap =
|
|
142
|
-
const blogDir = import_path.default.join(process.cwd(), mdxSourceDir);
|
|
143
|
-
const blogFiles = import_fs.default.readdirSync(blogDir).filter((f) => f.endsWith(".mdx"));
|
|
141
|
+
function generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap = true) {
|
|
144
142
|
const blogRoutes = [];
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
143
|
+
if (mdxSourceDir && mdxSourceDir.trim() !== "") {
|
|
144
|
+
const blogDir = import_path.default.join(process.cwd(), mdxSourceDir);
|
|
145
|
+
try {
|
|
146
|
+
if (import_fs.default.existsSync(blogDir) && import_fs.default.statSync(blogDir).isDirectory()) {
|
|
147
|
+
const blogFiles = import_fs.default.readdirSync(blogDir).filter((f) => f.endsWith(".mdx"));
|
|
148
|
+
for (const locale of locales) {
|
|
149
|
+
for (const f of blogFiles) {
|
|
150
|
+
if (f === "index.mdx") {
|
|
151
|
+
blogRoutes.push({
|
|
152
|
+
url: `${baseUrl}/${locale}/blog`,
|
|
153
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
154
|
+
changeFrequency: "daily",
|
|
155
|
+
priority: 1
|
|
156
|
+
});
|
|
157
|
+
} else {
|
|
158
|
+
const slug = f.replace(/\.mdx$/, "");
|
|
159
|
+
blogRoutes.push({
|
|
160
|
+
url: `${baseUrl}/${locale}/blog/${slug}`,
|
|
161
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
162
|
+
changeFrequency: f === "ioc.mdx" ? "daily" : "monthly",
|
|
163
|
+
priority: 0.8
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
162
168
|
}
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.warn(`Warning: Could not read MDX directory "${mdxSourceDir}":`, error);
|
|
163
171
|
}
|
|
164
172
|
}
|
|
165
173
|
const mainRoutes = locales.map((locale) => ({
|
|
@@ -175,7 +183,7 @@ function createRobotsHandler(baseUrl) {
|
|
|
175
183
|
return generateRobots(baseUrl);
|
|
176
184
|
};
|
|
177
185
|
}
|
|
178
|
-
function createSitemapHandler(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap =
|
|
186
|
+
function createSitemapHandler(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap = true) {
|
|
179
187
|
const sitemapHandler = function sitemap() {
|
|
180
188
|
return generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap);
|
|
181
189
|
};
|
package/dist/lib/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/server.ts","../../src/lib/fuma-search-util.ts","../../src/lib/clerk-intl.ts","../../src/lib/fuma-schema-check-util.ts","../../src/lib/seo-util.ts"],"sourcesContent":["// This is a server component!\n\nexport * from './fuma-search-util';\nexport * from './clerk-intl';\nexport * from './fuma-schema-check-util';\nexport * from './seo-util';","import { Translations } from 'fumadocs-ui/i18n';\n\nexport const fumaI18nCn: Partial<Translations> = {\n search: 'Translated Content',\n // other translations\n};\n","import { enUS, zhCN } from '@clerk/localizations';\nimport type { LocalizationResource } from '@clerk/types';\n\n// https://github.com/clerk/javascript/blob/main/packages/localizations/src/en-US.ts#L492\n// https://clerk.com/docs/customization/localization\nconst customZH: LocalizationResource = {\n ...zhCN,\n}\n\nexport const clerkIntl = {\n en: enUS,\n zh: customZH,\n}","import { z } from 'zod';\nimport { frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';\n\n\n// Reusable schema for title\nexport const createTitleSchema = () =>\n z.string({\n required_error: \"Title is required\",\n invalid_type_error: \"Title must be a string and cannot be null\",\n })\n .trim()\n .min(1, { message: \"Title cannot be empty or consist only of whitespace\" });\n\n// Reusable schema for description\nexport const createDescriptionSchema = () =>\n z.preprocess(\n (val: any) => {\n if (typeof val === 'string') {\n return val.trim() === \"\" || val === null ? undefined : val.trim();\n }\n return val === null ? undefined : val;\n },\n z.string().optional()\n );\n\n// Reusable schema for icon\nexport const createIconSchema = () =>\n z.preprocess(\n (val: any) => (val === \"\" || val === null ? undefined : val),\n z.string().optional()\n );\n\n// Reusable schema for date\nexport const createDateSchema = () =>\n z.preprocess((arg: any) => {\n if (arg instanceof Date) {\n // Format Date object to YYYY-MM-DD string\n const year = arg.getFullYear();\n const month = (arg.getMonth() + 1).toString().padStart(2, '0');\n const day = arg.getDate().toString().padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n if (typeof arg === 'string') {\n return arg.trim();\n }\n // For other types or null/undefined, let the subsequent string validation handle it\n return arg; \n },\n z.string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format or a valid Date object\")\n .refine((val: any) => !isNaN(new Date(val).getTime()), 'Invalid date!')\n );\n\n// common docs frontmatter schema\nexport const createCommonDocsSchema = () => frontmatterSchema.extend({\n title: createTitleSchema(),\n description: createDescriptionSchema(),\n icon: createIconSchema(),\n date: createDateSchema(),\n author: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n});\n\n// common meta schema\nexport const createCommonMetaSchema = () => metaSchema.extend({\n description: z.string().optional(),\n});\n\nexport const remarkInstallOptions = {\n persist: {\n id: 'package-manager',\n },\n};","import type { MetadataRoute } from 'next';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Generate robots.txt content\n * @param baseUrl - The base URL of the website\n * @returns Robots configuration\n */\nexport function generateRobots(baseUrl: string): MetadataRoute.Robots {\n return {\n rules: {\n userAgent: \"*\",\n allow: \"/\",\n },\n sitemap: `${baseUrl}/sitemap.xml`,\n };\n}\n\n/**\n * Generate sitemap.xml content\n * @param baseUrl - The base URL of the website\n * @param locales - Supported locales array\n * @param mdxSourceDir - MDX source directory path\n * @param openMdxSEOSiteMap - Whether to include MDX content in sitemap\n * @returns Sitemap entries\n */\nexport function generateSitemap(\n baseUrl: string,\n locales: string[],\n mdxSourceDir: string,\n openMdxSEOSiteMap: boolean =
|
|
1
|
+
{"version":3,"sources":["../../src/lib/server.ts","../../src/lib/fuma-search-util.ts","../../src/lib/clerk-intl.ts","../../src/lib/fuma-schema-check-util.ts","../../src/lib/seo-util.ts"],"sourcesContent":["// This is a server component!\n\nexport * from './fuma-search-util';\nexport * from './clerk-intl';\nexport * from './fuma-schema-check-util';\nexport * from './seo-util';","import { Translations } from 'fumadocs-ui/i18n';\n\nexport const fumaI18nCn: Partial<Translations> = {\n search: 'Translated Content',\n // other translations\n};\n","import { enUS, zhCN } from '@clerk/localizations';\nimport type { LocalizationResource } from '@clerk/types';\n\n// https://github.com/clerk/javascript/blob/main/packages/localizations/src/en-US.ts#L492\n// https://clerk.com/docs/customization/localization\nconst customZH: LocalizationResource = {\n ...zhCN,\n}\n\nexport const clerkIntl = {\n en: enUS,\n zh: customZH,\n}","import { z } from 'zod';\nimport { frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';\n\n\n// Reusable schema for title\nexport const createTitleSchema = () =>\n z.string({\n required_error: \"Title is required\",\n invalid_type_error: \"Title must be a string and cannot be null\",\n })\n .trim()\n .min(1, { message: \"Title cannot be empty or consist only of whitespace\" });\n\n// Reusable schema for description\nexport const createDescriptionSchema = () =>\n z.preprocess(\n (val: any) => {\n if (typeof val === 'string') {\n return val.trim() === \"\" || val === null ? undefined : val.trim();\n }\n return val === null ? undefined : val;\n },\n z.string().optional()\n );\n\n// Reusable schema for icon\nexport const createIconSchema = () =>\n z.preprocess(\n (val: any) => (val === \"\" || val === null ? undefined : val),\n z.string().optional()\n );\n\n// Reusable schema for date\nexport const createDateSchema = () =>\n z.preprocess((arg: any) => {\n if (arg instanceof Date) {\n // Format Date object to YYYY-MM-DD string\n const year = arg.getFullYear();\n const month = (arg.getMonth() + 1).toString().padStart(2, '0');\n const day = arg.getDate().toString().padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n if (typeof arg === 'string') {\n return arg.trim();\n }\n // For other types or null/undefined, let the subsequent string validation handle it\n return arg; \n },\n z.string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format or a valid Date object\")\n .refine((val: any) => !isNaN(new Date(val).getTime()), 'Invalid date!')\n );\n\n// common docs frontmatter schema\nexport const createCommonDocsSchema = () => frontmatterSchema.extend({\n title: createTitleSchema(),\n description: createDescriptionSchema(),\n icon: createIconSchema(),\n date: createDateSchema(),\n author: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n});\n\n// common meta schema\nexport const createCommonMetaSchema = () => metaSchema.extend({\n description: z.string().optional(),\n});\n\nexport const remarkInstallOptions = {\n persist: {\n id: 'package-manager',\n },\n};","import type { MetadataRoute } from 'next';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Generate robots.txt content\n * @param baseUrl - The base URL of the website\n * @returns Robots configuration\n */\nexport function generateRobots(baseUrl: string): MetadataRoute.Robots {\n return {\n rules: {\n userAgent: \"*\",\n allow: \"/\",\n },\n sitemap: `${baseUrl}/sitemap.xml`,\n };\n}\n\n/**\n * Generate sitemap.xml content\n * @param baseUrl - The base URL of the website\n * @param locales - Supported locales array\n * @param mdxSourceDir - MDX source directory path\n * @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true\n * @returns Sitemap entries\n */\nexport function generateSitemap(\n baseUrl: string,\n locales: string[],\n mdxSourceDir: string,\n openMdxSEOSiteMap: boolean = true\n): MetadataRoute.Sitemap {\n // 2. handle index.mdx (blog start page) and other slugs\n const blogRoutes: MetadataRoute.Sitemap = [];\n\n // 1. read all blog mdx file names with error handling\n if (mdxSourceDir && mdxSourceDir.trim() !== '') {\n const blogDir = path.join(process.cwd(), mdxSourceDir);\n \n // Check if directory exists and is readable\n try {\n if (fs.existsSync(blogDir) && fs.statSync(blogDir).isDirectory()) {\n const blogFiles = fs.readdirSync(blogDir).filter(f => f.endsWith('.mdx'));\n\n for (const locale of locales) {\n for (const f of blogFiles) {\n if (f === 'index.mdx') {\n blogRoutes.push({\n url: `${baseUrl}/${locale}/blog`,\n lastModified: new Date(),\n changeFrequency: 'daily',\n priority: 1.0\n });\n } else {\n const slug = f.replace(/\\.mdx$/, '');\n blogRoutes.push({\n url: `${baseUrl}/${locale}/blog/${slug}`,\n lastModified: new Date(),\n changeFrequency: f === 'ioc.mdx' ? 'daily' : 'monthly',\n priority: 0.8\n });\n }\n }\n }\n }\n } catch (error) {\n // Handle edge cases like race conditions, permission changes, or filesystem errors\n console.warn(`Warning: Could not read MDX directory \"${mdxSourceDir}\":`, error);\n }\n }\n\n // 3. main page (all language versions)\n const mainRoutes = locales.map(locale => ({\n url: `${baseUrl}/${locale}`,\n lastModified: new Date(),\n changeFrequency: 'weekly' as const,\n priority: 1.0\n }));\n\n return openMdxSEOSiteMap ? [...mainRoutes, ...blogRoutes] : [...mainRoutes];\n}\n\n/**\n * Create robots.txt handler function\n * @param baseUrl - The base URL of the website\n * @returns Robots handler function\n */\nexport function createRobotsHandler(baseUrl: string) {\n return function robots(): MetadataRoute.Robots {\n return generateRobots(baseUrl);\n };\n}\n\n/**\n * Create sitemap.xml handler function\n * @param baseUrl - The base URL of the website\n * @param locales - Supported locales array\n * @param mdxSourceDir - MDX source directory path\n * @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true\n * @returns Sitemap handler function\n */\nexport function createSitemapHandler(\n baseUrl: string,\n locales: string[],\n mdxSourceDir: string,\n openMdxSEOSiteMap: boolean = true\n) {\n // force static generation\n const sitemapHandler = function sitemap(): MetadataRoute.Sitemap {\n return generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap);\n };\n \n // Add static generation directive\n (sitemapHandler as any).dynamic = 'force-static';\n \n return sitemapHandler;\n}"],"mappings":"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","names":["path","fs"]}
|
package/dist/lib/server.mjs
CHANGED
|
@@ -93,28 +93,36 @@ function generateRobots(baseUrl) {
|
|
|
93
93
|
sitemap: `${baseUrl}/sitemap.xml`
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
|
-
function generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap =
|
|
97
|
-
const blogDir = path.join(process.cwd(), mdxSourceDir);
|
|
98
|
-
const blogFiles = fs.readdirSync(blogDir).filter((f) => f.endsWith(".mdx"));
|
|
96
|
+
function generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap = true) {
|
|
99
97
|
const blogRoutes = [];
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
98
|
+
if (mdxSourceDir && mdxSourceDir.trim() !== "") {
|
|
99
|
+
const blogDir = path.join(process.cwd(), mdxSourceDir);
|
|
100
|
+
try {
|
|
101
|
+
if (fs.existsSync(blogDir) && fs.statSync(blogDir).isDirectory()) {
|
|
102
|
+
const blogFiles = fs.readdirSync(blogDir).filter((f) => f.endsWith(".mdx"));
|
|
103
|
+
for (const locale of locales) {
|
|
104
|
+
for (const f of blogFiles) {
|
|
105
|
+
if (f === "index.mdx") {
|
|
106
|
+
blogRoutes.push({
|
|
107
|
+
url: `${baseUrl}/${locale}/blog`,
|
|
108
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
109
|
+
changeFrequency: "daily",
|
|
110
|
+
priority: 1
|
|
111
|
+
});
|
|
112
|
+
} else {
|
|
113
|
+
const slug = f.replace(/\.mdx$/, "");
|
|
114
|
+
blogRoutes.push({
|
|
115
|
+
url: `${baseUrl}/${locale}/blog/${slug}`,
|
|
116
|
+
lastModified: /* @__PURE__ */ new Date(),
|
|
117
|
+
changeFrequency: f === "ioc.mdx" ? "daily" : "monthly",
|
|
118
|
+
priority: 0.8
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
117
123
|
}
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.warn(`Warning: Could not read MDX directory "${mdxSourceDir}":`, error);
|
|
118
126
|
}
|
|
119
127
|
}
|
|
120
128
|
const mainRoutes = locales.map((locale) => ({
|
|
@@ -130,7 +138,7 @@ function createRobotsHandler(baseUrl) {
|
|
|
130
138
|
return generateRobots(baseUrl);
|
|
131
139
|
};
|
|
132
140
|
}
|
|
133
|
-
function createSitemapHandler(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap =
|
|
141
|
+
function createSitemapHandler(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap = true) {
|
|
134
142
|
const sitemapHandler = function sitemap() {
|
|
135
143
|
return generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap);
|
|
136
144
|
};
|
package/dist/lib/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/fuma-search-util.ts","../../src/lib/clerk-intl.ts","../../src/lib/fuma-schema-check-util.ts","../../src/lib/seo-util.ts"],"sourcesContent":["import { Translations } from 'fumadocs-ui/i18n';\n\nexport const fumaI18nCn: Partial<Translations> = {\n search: 'Translated Content',\n // other translations\n};\n","import { enUS, zhCN } from '@clerk/localizations';\nimport type { LocalizationResource } from '@clerk/types';\n\n// https://github.com/clerk/javascript/blob/main/packages/localizations/src/en-US.ts#L492\n// https://clerk.com/docs/customization/localization\nconst customZH: LocalizationResource = {\n ...zhCN,\n}\n\nexport const clerkIntl = {\n en: enUS,\n zh: customZH,\n}","import { z } from 'zod';\nimport { frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';\n\n\n// Reusable schema for title\nexport const createTitleSchema = () =>\n z.string({\n required_error: \"Title is required\",\n invalid_type_error: \"Title must be a string and cannot be null\",\n })\n .trim()\n .min(1, { message: \"Title cannot be empty or consist only of whitespace\" });\n\n// Reusable schema for description\nexport const createDescriptionSchema = () =>\n z.preprocess(\n (val: any) => {\n if (typeof val === 'string') {\n return val.trim() === \"\" || val === null ? undefined : val.trim();\n }\n return val === null ? undefined : val;\n },\n z.string().optional()\n );\n\n// Reusable schema for icon\nexport const createIconSchema = () =>\n z.preprocess(\n (val: any) => (val === \"\" || val === null ? undefined : val),\n z.string().optional()\n );\n\n// Reusable schema for date\nexport const createDateSchema = () =>\n z.preprocess((arg: any) => {\n if (arg instanceof Date) {\n // Format Date object to YYYY-MM-DD string\n const year = arg.getFullYear();\n const month = (arg.getMonth() + 1).toString().padStart(2, '0');\n const day = arg.getDate().toString().padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n if (typeof arg === 'string') {\n return arg.trim();\n }\n // For other types or null/undefined, let the subsequent string validation handle it\n return arg; \n },\n z.string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format or a valid Date object\")\n .refine((val: any) => !isNaN(new Date(val).getTime()), 'Invalid date!')\n );\n\n// common docs frontmatter schema\nexport const createCommonDocsSchema = () => frontmatterSchema.extend({\n title: createTitleSchema(),\n description: createDescriptionSchema(),\n icon: createIconSchema(),\n date: createDateSchema(),\n author: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n});\n\n// common meta schema\nexport const createCommonMetaSchema = () => metaSchema.extend({\n description: z.string().optional(),\n});\n\nexport const remarkInstallOptions = {\n persist: {\n id: 'package-manager',\n },\n};","import type { MetadataRoute } from 'next';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Generate robots.txt content\n * @param baseUrl - The base URL of the website\n * @returns Robots configuration\n */\nexport function generateRobots(baseUrl: string): MetadataRoute.Robots {\n return {\n rules: {\n userAgent: \"*\",\n allow: \"/\",\n },\n sitemap: `${baseUrl}/sitemap.xml`,\n };\n}\n\n/**\n * Generate sitemap.xml content\n * @param baseUrl - The base URL of the website\n * @param locales - Supported locales array\n * @param mdxSourceDir - MDX source directory path\n * @param openMdxSEOSiteMap - Whether to include MDX content in sitemap\n * @returns Sitemap entries\n */\nexport function generateSitemap(\n baseUrl: string,\n locales: string[],\n mdxSourceDir: string,\n openMdxSEOSiteMap: boolean =
|
|
1
|
+
{"version":3,"sources":["../../src/lib/fuma-search-util.ts","../../src/lib/clerk-intl.ts","../../src/lib/fuma-schema-check-util.ts","../../src/lib/seo-util.ts"],"sourcesContent":["import { Translations } from 'fumadocs-ui/i18n';\n\nexport const fumaI18nCn: Partial<Translations> = {\n search: 'Translated Content',\n // other translations\n};\n","import { enUS, zhCN } from '@clerk/localizations';\nimport type { LocalizationResource } from '@clerk/types';\n\n// https://github.com/clerk/javascript/blob/main/packages/localizations/src/en-US.ts#L492\n// https://clerk.com/docs/customization/localization\nconst customZH: LocalizationResource = {\n ...zhCN,\n}\n\nexport const clerkIntl = {\n en: enUS,\n zh: customZH,\n}","import { z } from 'zod';\nimport { frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';\n\n\n// Reusable schema for title\nexport const createTitleSchema = () =>\n z.string({\n required_error: \"Title is required\",\n invalid_type_error: \"Title must be a string and cannot be null\",\n })\n .trim()\n .min(1, { message: \"Title cannot be empty or consist only of whitespace\" });\n\n// Reusable schema for description\nexport const createDescriptionSchema = () =>\n z.preprocess(\n (val: any) => {\n if (typeof val === 'string') {\n return val.trim() === \"\" || val === null ? undefined : val.trim();\n }\n return val === null ? undefined : val;\n },\n z.string().optional()\n );\n\n// Reusable schema for icon\nexport const createIconSchema = () =>\n z.preprocess(\n (val: any) => (val === \"\" || val === null ? undefined : val),\n z.string().optional()\n );\n\n// Reusable schema for date\nexport const createDateSchema = () =>\n z.preprocess((arg: any) => {\n if (arg instanceof Date) {\n // Format Date object to YYYY-MM-DD string\n const year = arg.getFullYear();\n const month = (arg.getMonth() + 1).toString().padStart(2, '0');\n const day = arg.getDate().toString().padStart(2, '0');\n return `${year}-${month}-${day}`;\n }\n if (typeof arg === 'string') {\n return arg.trim();\n }\n // For other types or null/undefined, let the subsequent string validation handle it\n return arg; \n },\n z.string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format or a valid Date object\")\n .refine((val: any) => !isNaN(new Date(val).getTime()), 'Invalid date!')\n );\n\n// common docs frontmatter schema\nexport const createCommonDocsSchema = () => frontmatterSchema.extend({\n title: createTitleSchema(),\n description: createDescriptionSchema(),\n icon: createIconSchema(),\n date: createDateSchema(),\n author: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n});\n\n// common meta schema\nexport const createCommonMetaSchema = () => metaSchema.extend({\n description: z.string().optional(),\n});\n\nexport const remarkInstallOptions = {\n persist: {\n id: 'package-manager',\n },\n};","import type { MetadataRoute } from 'next';\nimport fs from 'fs';\nimport path from 'path';\n\n/**\n * Generate robots.txt content\n * @param baseUrl - The base URL of the website\n * @returns Robots configuration\n */\nexport function generateRobots(baseUrl: string): MetadataRoute.Robots {\n return {\n rules: {\n userAgent: \"*\",\n allow: \"/\",\n },\n sitemap: `${baseUrl}/sitemap.xml`,\n };\n}\n\n/**\n * Generate sitemap.xml content\n * @param baseUrl - The base URL of the website\n * @param locales - Supported locales array\n * @param mdxSourceDir - MDX source directory path\n * @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true\n * @returns Sitemap entries\n */\nexport function generateSitemap(\n baseUrl: string,\n locales: string[],\n mdxSourceDir: string,\n openMdxSEOSiteMap: boolean = true\n): MetadataRoute.Sitemap {\n // 2. handle index.mdx (blog start page) and other slugs\n const blogRoutes: MetadataRoute.Sitemap = [];\n\n // 1. read all blog mdx file names with error handling\n if (mdxSourceDir && mdxSourceDir.trim() !== '') {\n const blogDir = path.join(process.cwd(), mdxSourceDir);\n \n // Check if directory exists and is readable\n try {\n if (fs.existsSync(blogDir) && fs.statSync(blogDir).isDirectory()) {\n const blogFiles = fs.readdirSync(blogDir).filter(f => f.endsWith('.mdx'));\n\n for (const locale of locales) {\n for (const f of blogFiles) {\n if (f === 'index.mdx') {\n blogRoutes.push({\n url: `${baseUrl}/${locale}/blog`,\n lastModified: new Date(),\n changeFrequency: 'daily',\n priority: 1.0\n });\n } else {\n const slug = f.replace(/\\.mdx$/, '');\n blogRoutes.push({\n url: `${baseUrl}/${locale}/blog/${slug}`,\n lastModified: new Date(),\n changeFrequency: f === 'ioc.mdx' ? 'daily' : 'monthly',\n priority: 0.8\n });\n }\n }\n }\n }\n } catch (error) {\n // Handle edge cases like race conditions, permission changes, or filesystem errors\n console.warn(`Warning: Could not read MDX directory \"${mdxSourceDir}\":`, error);\n }\n }\n\n // 3. main page (all language versions)\n const mainRoutes = locales.map(locale => ({\n url: `${baseUrl}/${locale}`,\n lastModified: new Date(),\n changeFrequency: 'weekly' as const,\n priority: 1.0\n }));\n\n return openMdxSEOSiteMap ? [...mainRoutes, ...blogRoutes] : [...mainRoutes];\n}\n\n/**\n * Create robots.txt handler function\n * @param baseUrl - The base URL of the website\n * @returns Robots handler function\n */\nexport function createRobotsHandler(baseUrl: string) {\n return function robots(): MetadataRoute.Robots {\n return generateRobots(baseUrl);\n };\n}\n\n/**\n * Create sitemap.xml handler function\n * @param baseUrl - The base URL of the website\n * @param locales - Supported locales array\n * @param mdxSourceDir - MDX source directory path\n * @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true\n * @returns Sitemap handler function\n */\nexport function createSitemapHandler(\n baseUrl: string,\n locales: string[],\n mdxSourceDir: string,\n openMdxSEOSiteMap: boolean = true\n) {\n // force static generation\n const sitemapHandler = function sitemap(): MetadataRoute.Sitemap {\n return generateSitemap(baseUrl, locales, mdxSourceDir, openMdxSEOSiteMap);\n };\n \n // Add static generation directive\n (sitemapHandler as any).dynamic = 'force-static';\n \n return sitemapHandler;\n}"],"mappings":";;;;;;;;;;;;;;;;;;AAEO,IAAM,aAAoC;AAAA,EAC/C,QAAQ;AAAA;AAEV;;;ACLA,SAAS,MAAM,YAAY;AAK3B,IAAM,WAAiC,mBAClC;AAGE,IAAM,YAAY;AAAA,EACvB,IAAI;AAAA,EACJ,IAAI;AACN;;;ACZA,SAAS,SAAS;AAClB,SAAS,mBAAmB,kBAAkB;AAIvC,IAAM,oBAAoB,MAC/B,EAAE,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,oBAAoB;AACtB,CAAC,EACA,KAAK,EACL,IAAI,GAAG,EAAE,SAAS,sDAAsD,CAAC;AAGrE,IAAM,0BAA0B,MACrC,EAAE;AAAA,EACA,CAAC,QAAa;AACZ,QAAI,OAAO,QAAQ,UAAU;AAC3B,aAAO,IAAI,KAAK,MAAM,MAAM,QAAQ,OAAO,SAAY,IAAI,KAAK;AAAA,IAClE;AACA,WAAO,QAAQ,OAAO,SAAY;AAAA,EACpC;AAAA,EACA,EAAE,OAAO,EAAE,SAAS;AACtB;AAGK,IAAM,mBAAmB,MAC9B,EAAE;AAAA,EACA,CAAC,QAAc,QAAQ,MAAM,QAAQ,OAAO,SAAY;AAAA,EACxD,EAAE,OAAO,EAAE,SAAS;AACtB;AAGK,IAAM,mBAAmB,MAC9B,EAAE;AAAA,EAAW,CAAC,QAAa;AACzB,QAAI,eAAe,MAAM;AAEvB,YAAM,OAAO,IAAI,YAAY;AAC7B,YAAM,SAAS,IAAI,SAAS,IAAI,GAAG,SAAS,EAAE,SAAS,GAAG,GAAG;AAC7D,YAAM,MAAM,IAAI,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACpD,aAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG;AAAA,IAChC;AACA,QAAI,OAAO,QAAQ,UAAU;AAC3B,aAAO,IAAI,KAAK;AAAA,IAClB;AAEA,WAAO;AAAA,EACT;AAAA,EACA,EAAE,OAAO,EACN,MAAM,uBAAuB,0DAA0D,EACvF,OAAO,CAAC,QAAa,CAAC,MAAM,IAAI,KAAK,GAAG,EAAE,QAAQ,CAAC,GAAG,eAAe;AACxE;AAGK,IAAM,yBAAyB,MAAM,kBAAkB,OAAO;AAAA,EACnE,OAAO,kBAAkB;AAAA,EACzB,aAAa,wBAAwB;AAAA,EACrC,MAAM,iBAAiB;AAAA,EACvB,MAAM,iBAAiB;AAAA,EACvB,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AACzC,CAAC;AAGM,IAAM,yBAAyB,MAAM,WAAW,OAAO;AAAA,EAC5D,aAAa,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AAEM,IAAM,uBAAuB;AAAA,EAClC,SAAS;AAAA,IACP,IAAI;AAAA,EACN;AACF;;;ACvEA,OAAO,QAAQ;AACf,OAAO,UAAU;AAOV,SAAS,eAAe,SAAuC;AACpE,SAAO;AAAA,IACL,OAAO;AAAA,MACL,WAAW;AAAA,MACX,OAAO;AAAA,IACT;AAAA,IACA,SAAS,GAAG,OAAO;AAAA,EACrB;AACF;AAUO,SAAS,gBACd,SACA,SACA,cACA,oBAA6B,MACN;AAEvB,QAAM,aAAoC,CAAC;AAG3C,MAAI,gBAAgB,aAAa,KAAK,MAAM,IAAI;AAC9C,UAAM,UAAU,KAAK,KAAK,QAAQ,IAAI,GAAG,YAAY;AAGrD,QAAI;AACF,UAAI,GAAG,WAAW,OAAO,KAAK,GAAG,SAAS,OAAO,EAAE,YAAY,GAAG;AAChE,cAAM,YAAY,GAAG,YAAY,OAAO,EAAE,OAAO,OAAK,EAAE,SAAS,MAAM,CAAC;AAExE,mBAAW,UAAU,SAAS;AAC5B,qBAAW,KAAK,WAAW;AACzB,gBAAI,MAAM,aAAa;AACrB,yBAAW,KAAK;AAAA,gBACd,KAAK,GAAG,OAAO,IAAI,MAAM;AAAA,gBACzB,cAAc,oBAAI,KAAK;AAAA,gBACvB,iBAAiB;AAAA,gBACjB,UAAU;AAAA,cACZ,CAAC;AAAA,YACH,OAAO;AACL,oBAAM,OAAO,EAAE,QAAQ,UAAU,EAAE;AACnC,yBAAW,KAAK;AAAA,gBACd,KAAK,GAAG,OAAO,IAAI,MAAM,SAAS,IAAI;AAAA,gBACtC,cAAc,oBAAI,KAAK;AAAA,gBACvB,iBAAiB,MAAM,YAAY,UAAU;AAAA,gBAC7C,UAAU;AAAA,cACZ,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,OAAO;AAEd,cAAQ,KAAK,0CAA0C,YAAY,MAAM,KAAK;AAAA,IAChF;AAAA,EACF;AAGA,QAAM,aAAa,QAAQ,IAAI,aAAW;AAAA,IACxC,KAAK,GAAG,OAAO,IAAI,MAAM;AAAA,IACzB,cAAc,oBAAI,KAAK;AAAA,IACvB,iBAAiB;AAAA,IACjB,UAAU;AAAA,EACZ,EAAE;AAEF,SAAO,oBAAoB,CAAC,GAAG,YAAY,GAAG,UAAU,IAAI,CAAC,GAAG,UAAU;AAC5E;AAOO,SAAS,oBAAoB,SAAiB;AACnD,SAAO,SAAS,SAA+B;AAC7C,WAAO,eAAe,OAAO;AAAA,EAC/B;AACF;AAUO,SAAS,qBACd,SACA,SACA,cACA,oBAA6B,MAC7B;AAEA,QAAM,iBAAiB,SAAS,UAAiC;AAC/D,WAAO,gBAAgB,SAAS,SAAS,cAAc,iBAAiB;AAAA,EAC1E;AAGA,EAAC,eAAuB,UAAU;AAElC,SAAO;AACT;","names":[]}
|
package/package.json
CHANGED
package/src/lib/seo-util.ts
CHANGED
|
@@ -22,40 +22,51 @@ export function generateRobots(baseUrl: string): MetadataRoute.Robots {
|
|
|
22
22
|
* @param baseUrl - The base URL of the website
|
|
23
23
|
* @param locales - Supported locales array
|
|
24
24
|
* @param mdxSourceDir - MDX source directory path
|
|
25
|
-
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap
|
|
25
|
+
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true
|
|
26
26
|
* @returns Sitemap entries
|
|
27
27
|
*/
|
|
28
28
|
export function generateSitemap(
|
|
29
29
|
baseUrl: string,
|
|
30
30
|
locales: string[],
|
|
31
31
|
mdxSourceDir: string,
|
|
32
|
-
openMdxSEOSiteMap: boolean =
|
|
32
|
+
openMdxSEOSiteMap: boolean = true
|
|
33
33
|
): MetadataRoute.Sitemap {
|
|
34
|
-
// 1. read all blog mdx file names
|
|
35
|
-
const blogDir = path.join(process.cwd(), mdxSourceDir);
|
|
36
|
-
const blogFiles = fs.readdirSync(blogDir).filter(f => f.endsWith('.mdx'));
|
|
37
|
-
|
|
38
34
|
// 2. handle index.mdx (blog start page) and other slugs
|
|
39
35
|
const blogRoutes: MetadataRoute.Sitemap = [];
|
|
40
36
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
37
|
+
// 1. read all blog mdx file names with error handling
|
|
38
|
+
if (mdxSourceDir && mdxSourceDir.trim() !== '') {
|
|
39
|
+
const blogDir = path.join(process.cwd(), mdxSourceDir);
|
|
40
|
+
|
|
41
|
+
// Check if directory exists and is readable
|
|
42
|
+
try {
|
|
43
|
+
if (fs.existsSync(blogDir) && fs.statSync(blogDir).isDirectory()) {
|
|
44
|
+
const blogFiles = fs.readdirSync(blogDir).filter(f => f.endsWith('.mdx'));
|
|
45
|
+
|
|
46
|
+
for (const locale of locales) {
|
|
47
|
+
for (const f of blogFiles) {
|
|
48
|
+
if (f === 'index.mdx') {
|
|
49
|
+
blogRoutes.push({
|
|
50
|
+
url: `${baseUrl}/${locale}/blog`,
|
|
51
|
+
lastModified: new Date(),
|
|
52
|
+
changeFrequency: 'daily',
|
|
53
|
+
priority: 1.0
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
const slug = f.replace(/\.mdx$/, '');
|
|
57
|
+
blogRoutes.push({
|
|
58
|
+
url: `${baseUrl}/${locale}/blog/${slug}`,
|
|
59
|
+
lastModified: new Date(),
|
|
60
|
+
changeFrequency: f === 'ioc.mdx' ? 'daily' : 'monthly',
|
|
61
|
+
priority: 0.8
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
58
66
|
}
|
|
67
|
+
} catch (error) {
|
|
68
|
+
// Handle edge cases like race conditions, permission changes, or filesystem errors
|
|
69
|
+
console.warn(`Warning: Could not read MDX directory "${mdxSourceDir}":`, error);
|
|
59
70
|
}
|
|
60
71
|
}
|
|
61
72
|
|
|
@@ -86,14 +97,14 @@ export function createRobotsHandler(baseUrl: string) {
|
|
|
86
97
|
* @param baseUrl - The base URL of the website
|
|
87
98
|
* @param locales - Supported locales array
|
|
88
99
|
* @param mdxSourceDir - MDX source directory path
|
|
89
|
-
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap
|
|
100
|
+
* @param openMdxSEOSiteMap - Whether to include MDX content in sitemap, default is true
|
|
90
101
|
* @returns Sitemap handler function
|
|
91
102
|
*/
|
|
92
103
|
export function createSitemapHandler(
|
|
93
104
|
baseUrl: string,
|
|
94
105
|
locales: string[],
|
|
95
106
|
mdxSourceDir: string,
|
|
96
|
-
openMdxSEOSiteMap: boolean =
|
|
107
|
+
openMdxSEOSiteMap: boolean = true
|
|
97
108
|
) {
|
|
98
109
|
// force static generation
|
|
99
110
|
const sitemapHandler = function sitemap(): MetadataRoute.Sitemap {
|