@knowcode/doc-builder 1.5.3 → 1.5.5

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/html/sitemap.xml CHANGED
@@ -2,79 +2,85 @@
2
2
  <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3
3
  <url>
4
4
  <loc>https://doc-builder-delta.vercel.app/404.html</loc>
5
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
5
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
6
6
  <changefreq>monthly</changefreq>
7
7
  <priority>0.6</priority>
8
8
  </url>
9
9
  <url>
10
10
  <loc>https://doc-builder-delta.vercel.app/README.html</loc>
11
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
11
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
12
12
  <changefreq>monthly</changefreq>
13
13
  <priority>0.6</priority>
14
14
  </url>
15
15
  <url>
16
16
  <loc>https://doc-builder-delta.vercel.app/claude-workflow-guide.html</loc>
17
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
17
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
18
18
  <changefreq>monthly</changefreq>
19
19
  <priority>0.8</priority>
20
20
  </url>
21
21
  <url>
22
22
  <loc>https://doc-builder-delta.vercel.app/documentation-index.html</loc>
23
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
23
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
24
24
  <changefreq>monthly</changefreq>
25
25
  <priority>0.6</priority>
26
26
  </url>
27
27
  <url>
28
28
  <loc>https://doc-builder-delta.vercel.app/guides/authentication-guide.html</loc>
29
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
29
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
30
30
  <changefreq>monthly</changefreq>
31
31
  <priority>0.8</priority>
32
32
  </url>
33
33
  <url>
34
34
  <loc>https://doc-builder-delta.vercel.app/guides/claude-workflow-guide.html</loc>
35
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
35
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
36
36
  <changefreq>monthly</changefreq>
37
37
  <priority>0.8</priority>
38
38
  </url>
39
39
  <url>
40
40
  <loc>https://doc-builder-delta.vercel.app/guides/document-standards.html</loc>
41
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
41
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
42
42
  <changefreq>monthly</changefreq>
43
43
  <priority>0.8</priority>
44
44
  </url>
45
45
  <url>
46
46
  <loc>https://doc-builder-delta.vercel.app/guides/documentation-standards.html</loc>
47
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
47
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
48
+ <changefreq>monthly</changefreq>
49
+ <priority>0.8</priority>
50
+ </url>
51
+ <url>
52
+ <loc>https://doc-builder-delta.vercel.app/guides/google-site-verification-guide.html</loc>
53
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
48
54
  <changefreq>monthly</changefreq>
49
55
  <priority>0.8</priority>
50
56
  </url>
51
57
  <url>
52
58
  <loc>https://doc-builder-delta.vercel.app/guides/seo-guide.html</loc>
53
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
59
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
54
60
  <changefreq>monthly</changefreq>
55
61
  <priority>0.8</priority>
56
62
  </url>
57
63
  <url>
58
64
  <loc>https://doc-builder-delta.vercel.app/guides/troubleshooting-guide.html</loc>
59
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
65
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
60
66
  <changefreq>monthly</changefreq>
61
67
  <priority>0.8</priority>
62
68
  </url>
63
69
  <url>
64
70
  <loc>https://doc-builder-delta.vercel.app/index.html</loc>
65
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
71
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
66
72
  <changefreq>weekly</changefreq>
67
73
  <priority>1.0</priority>
68
74
  </url>
69
75
  <url>
70
76
  <loc>https://doc-builder-delta.vercel.app/vercel-cli-setup-guide.html</loc>
71
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
77
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
72
78
  <changefreq>monthly</changefreq>
73
79
  <priority>0.8</priority>
74
80
  </url>
75
81
  <url>
76
82
  <loc>https://doc-builder-delta.vercel.app/vercel-first-time-setup-guide.html</loc>
77
- <lastmod>2025-07-22T06:01:14.316Z</lastmod>
83
+ <lastmod>2025-07-22T07:02:21.540Z</lastmod>
78
84
  <changefreq>monthly</changefreq>
79
85
  <priority>0.8</priority>
80
86
  </url>
@@ -28,6 +28,9 @@
28
28
  <meta name="twitter:description" content="Vercel CLI Setup Guide.">
29
29
  <meta name="twitter:image" content="https://doc-builder-delta.vercel.app/og-default.png">
30
30
 
31
+ <!-- Custom Meta Tags -->
32
+ <meta name="google-site-verification" content="FtzcDTf5BQ9K5EfnGazQkgU2U4FiN3ITzM7gHwqUAqQ">
33
+
31
34
  <!-- Fonts -->
32
35
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
33
36
 
@@ -58,8 +61,8 @@
58
61
  "name": "Knowcode Ltd",
59
62
  "url": "https://knowcode.tech"
60
63
  },
61
- "datePublished": "2025-07-22T06:01:14.298Z",
62
- "dateModified": "2025-07-22T06:01:14.298Z",
64
+ "datePublished": "2025-07-22T07:02:21.526Z",
65
+ "dateModified": "2025-07-22T07:02:21.526Z",
63
66
  "mainEntityOfPage": {
64
67
  "@type": "WebPage",
65
68
  "@id": "https://doc-builder-delta.vercel.app/vercel-cli-setup-guide.html"
@@ -92,7 +95,7 @@
92
95
 
93
96
  <div class="header-actions">
94
97
  <div class="deployment-info">
95
- <span class="deployment-date" title="Built with doc-builder v1.5.2">Last updated: Jul 22, 2025, 06:01 AM UTC</span>
98
+ <span class="deployment-date" title="Built with doc-builder v1.5.4">Last updated: Jul 22, 2025, 07:02 AM UTC</span>
96
99
  </div>
97
100
 
98
101
 
@@ -153,6 +156,7 @@
153
156
  <a href="/guides/authentication-guide.html" class="nav-item" data-tooltip="This guide explains how to configure and use the built-in authentication feature in @knowcode/doc-builder to protect your documentation with basic..."><i class="fas fa-file-alt"></i> Authentication Guide</a>
154
157
  <a href="/guides/claude-workflow-guide.html" class="nav-item" data-tooltip="This guide demonstrates an efficient workflow for using Claude Code with a refined CLAUDE.md file to create high-quality documentation and deploy it..."><i class="fas fa-file-alt"></i> Claude Workflow Guide</a>
155
158
  <a href="/guides/documentation-standards.html" class="nav-item" data-tooltip="This document defines the documentation standards and conventions for the @knowcode/doc-builder project."><i class="fas fa-file-alt"></i> Documentation Standards</a>
159
+ <a href="/guides/google-site-verification-guide.html" class="nav-item" data-tooltip="Google Search Console verification allows you to: Monitor your site&#039;s performance in Google Search Submit sitemaps for better indexing View search..."><i class="fas fa-file-alt"></i> Google Site Verification Guide</a>
156
160
  <a href="/guides/seo-guide.html" class="nav-item" data-tooltip="@knowcode/doc-builder includes comprehensive SEO (Search Engine Optimization) features to help your documentation rank better in search results and..."><i class="fas fa-file-alt"></i> Seo Guide</a>
157
161
  <a href="/guides/troubleshooting-guide.html" class="nav-item" data-tooltip="This guide helps you resolve common issues when using @knowcode/doc-builder."><i class="fas fa-file-alt"></i> Troubleshooting Guide</a></div></div>
158
162
  </nav>
@@ -28,6 +28,9 @@
28
28
  <meta name="twitter:description" content="Vercel First-Time Setup Guide - Complete Prompt-by-Prompt Walkthrough.">
29
29
  <meta name="twitter:image" content="https://doc-builder-delta.vercel.app/og-default.png">
30
30
 
31
+ <!-- Custom Meta Tags -->
32
+ <meta name="google-site-verification" content="FtzcDTf5BQ9K5EfnGazQkgU2U4FiN3ITzM7gHwqUAqQ">
33
+
31
34
  <!-- Fonts -->
32
35
  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
33
36
 
@@ -58,8 +61,8 @@
58
61
  "name": "Knowcode Ltd",
59
62
  "url": "https://knowcode.tech"
60
63
  },
61
- "datePublished": "2025-07-22T06:01:14.306Z",
62
- "dateModified": "2025-07-22T06:01:14.306Z",
64
+ "datePublished": "2025-07-22T07:02:21.530Z",
65
+ "dateModified": "2025-07-22T07:02:21.530Z",
63
66
  "mainEntityOfPage": {
64
67
  "@type": "WebPage",
65
68
  "@id": "https://doc-builder-delta.vercel.app/vercel-first-time-setup-guide.html"
@@ -92,7 +95,7 @@
92
95
 
93
96
  <div class="header-actions">
94
97
  <div class="deployment-info">
95
- <span class="deployment-date" title="Built with doc-builder v1.5.2">Last updated: Jul 22, 2025, 06:01 AM UTC</span>
98
+ <span class="deployment-date" title="Built with doc-builder v1.5.4">Last updated: Jul 22, 2025, 07:02 AM UTC</span>
96
99
  </div>
97
100
 
98
101
 
@@ -153,6 +156,7 @@
153
156
  <a href="/guides/authentication-guide.html" class="nav-item" data-tooltip="This guide explains how to configure and use the built-in authentication feature in @knowcode/doc-builder to protect your documentation with basic..."><i class="fas fa-file-alt"></i> Authentication Guide</a>
154
157
  <a href="/guides/claude-workflow-guide.html" class="nav-item" data-tooltip="This guide demonstrates an efficient workflow for using Claude Code with a refined CLAUDE.md file to create high-quality documentation and deploy it..."><i class="fas fa-file-alt"></i> Claude Workflow Guide</a>
155
158
  <a href="/guides/documentation-standards.html" class="nav-item" data-tooltip="This document defines the documentation standards and conventions for the @knowcode/doc-builder project."><i class="fas fa-file-alt"></i> Documentation Standards</a>
159
+ <a href="/guides/google-site-verification-guide.html" class="nav-item" data-tooltip="Google Search Console verification allows you to: Monitor your site&#039;s performance in Google Search Submit sitemaps for better indexing View search..."><i class="fas fa-file-alt"></i> Google Site Verification Guide</a>
156
160
  <a href="/guides/seo-guide.html" class="nav-item" data-tooltip="@knowcode/doc-builder includes comprehensive SEO (Search Engine Optimization) features to help your documentation rank better in search results and..."><i class="fas fa-file-alt"></i> Seo Guide</a>
157
161
  <a href="/guides/troubleshooting-guide.html" class="nav-item" data-tooltip="This guide helps you resolve common issues when using @knowcode/doc-builder."><i class="fas fa-file-alt"></i> Troubleshooting Guide</a></div></div>
158
162
  </nav>
package/lib/config.js CHANGED
@@ -55,6 +55,10 @@ const defaultConfig = {
55
55
  twitterHandle: '',
56
56
  language: 'en-US',
57
57
  keywords: [],
58
+ titleTemplate: '{pageTitle} | {siteName}', // Customizable title format
59
+ autoKeywords: true, // Extract keywords from content
60
+ keywordLimit: 7, // Max keywords per page
61
+ descriptionFallback: 'smart', // 'smart' or 'first-paragraph'
58
62
  organization: {
59
63
  name: '',
60
64
  url: '',
@@ -2,6 +2,7 @@ const fs = require('fs-extra');
2
2
  const path = require('path');
3
3
  const marked = require('marked');
4
4
  const chalk = require('chalk');
5
+ const matter = require('gray-matter');
5
6
  const {
6
7
  generateMetaTags,
7
8
  generateJSONLD,
@@ -189,7 +190,7 @@ function processMarkdownContent(content) {
189
190
  }
190
191
 
191
192
  // Generate HTML from template
192
- function generateHTML(title, content, navigation, currentPath = '', config = {}, originalContent = '') {
193
+ function generateHTML(title, content, navigation, currentPath = '', config = {}, originalContent = '', frontMatter = {}) {
193
194
  const depth = currentPath.split('/').filter(p => p).length;
194
195
  const relativePath = depth > 0 ? '../'.repeat(depth) : '';
195
196
 
@@ -203,24 +204,40 @@ function generateHTML(title, content, navigation, currentPath = '', config = {},
203
204
  // SEO preparation
204
205
  let seoTags = '';
205
206
  let jsonLd = '';
207
+ let finalSeoTitle = `${title} - ${siteName}`;
208
+ let pageDescription = frontMatter.description ||
209
+ generateDescription(originalContent || content, config.seo?.descriptionFallback) ||
210
+ siteDescription;
206
211
 
207
212
  if (config.seo?.enabled && config.seo?.siteUrl) {
208
213
  // Generate page URL
209
214
  const pageUrl = `${config.seo.siteUrl}/${currentPath}`;
210
215
 
211
- // Extract or generate description
212
- const pageDescription = generateDescription(originalContent || content) || siteDescription;
213
-
214
- // Extract keywords from content
215
- const contentKeywords = extractKeywords(originalContent || content, 5);
216
- const keywords = [...new Set([...(config.seo.keywords || []), ...contentKeywords])];
216
+ // Extract keywords - priority: front matter > content extraction + global
217
+ const contentKeywords = config.seo?.autoKeywords !== false ?
218
+ extractKeywords(originalContent || content, config.seo?.keywordLimit || 7) :
219
+ [];
220
+ const pageKeywords = frontMatter.keywords || [];
221
+ const keywords = [...new Set([...(config.seo.keywords || []), ...pageKeywords, ...contentKeywords])]
222
+ .slice(0, config.seo?.keywordLimit || 7);
217
223
 
218
224
  // Generate breadcrumbs
219
225
  const breadcrumbs = generateBreadcrumbs(currentPath, config.seo.siteUrl, siteName);
220
226
 
227
+ // Generate SEO-optimized title
228
+ const titleTemplate = config.seo?.titleTemplate || '{pageTitle} | {siteName}';
229
+ const seoTitle = titleTemplate
230
+ .replace('{pageTitle}', title)
231
+ .replace('{siteName}', siteName);
232
+
233
+ // Ensure title is within 50-60 characters
234
+ finalSeoTitle = seoTitle.length > 60 ?
235
+ title.length > 50 ? title.substring(0, 50) + '...' : title
236
+ : seoTitle;
237
+
221
238
  // Generate meta tags
222
239
  seoTags = generateMetaTags({
223
- title: `${title} - ${siteName}`,
240
+ title: finalSeoTitle,
224
241
  description: pageDescription,
225
242
  url: pageUrl,
226
243
  author: config.seo.author,
@@ -229,7 +246,8 @@ function generateHTML(title, content, navigation, currentPath = '', config = {},
229
246
  ogImage: config.seo.ogImage,
230
247
  siteName: siteName,
231
248
  language: config.seo.language,
232
- type: 'article'
249
+ type: 'article',
250
+ customMetaTags: config.seo.customMetaTags || []
233
251
  });
234
252
 
235
253
  // Generate JSON-LD
@@ -253,8 +271,8 @@ function generateHTML(title, content, navigation, currentPath = '', config = {},
253
271
  <head>
254
272
  <meta charset="UTF-8">
255
273
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
256
- <meta name="description" content="${escapeHtml(generateDescription(originalContent || content) || siteDescription)}">
257
- <title>${escapeHtml(title)} - ${escapeHtml(siteName)}</title>
274
+ <meta name="description" content="${escapeHtml(pageDescription || generateDescription(originalContent || content) || siteDescription)}">
275
+ <title>${escapeHtml(finalSeoTitle || `${title} - ${siteName}`)}</title>
258
276
 
259
277
  ${seoTags}
260
278
 
@@ -577,17 +595,21 @@ function buildNavigationStructure(files, currentFile) {
577
595
 
578
596
  // Process single markdown file
579
597
  async function processMarkdownFile(filePath, outputPath, allFiles, config) {
580
- const content = await fs.readFile(filePath, 'utf-8');
598
+ const rawContent = await fs.readFile(filePath, 'utf-8');
581
599
  const fileName = path.basename(filePath, '.md');
582
600
  const relativePath = path.relative(config.docsDir, filePath);
583
601
  const urlPath = relativePath.replace(/\.md$/, '.html').replace(/\\/g, '/');
584
602
 
585
- // Extract title from content
586
- const titleMatch = content.match(/^#\s+(.+)$/m);
587
- const title = titleMatch ? titleMatch[1] : fileName;
603
+ // Parse front matter
604
+ const { data: frontMatter, content } = matter(rawContent);
605
+
606
+ // Extract title - priority: front matter > H1 > filename
607
+ const h1Match = content.match(/^#\s+(.+)$/m);
608
+ const h1Title = h1Match ? h1Match[1] : null;
609
+ const title = frontMatter.title || h1Title || fileName;
588
610
 
589
- // Extract summary for tooltip
590
- const summary = extractSummary(content);
611
+ // Extract summary for tooltip - priority: front matter > auto-extract
612
+ const summary = frontMatter.description || extractSummary(content);
591
613
 
592
614
  // Process content
593
615
  const htmlContent = processMarkdownContent(content);
@@ -595,14 +617,14 @@ async function processMarkdownFile(filePath, outputPath, allFiles, config) {
595
617
  // Build navigation
596
618
  const navigation = buildNavigationStructure(allFiles, urlPath);
597
619
 
598
- // Generate full HTML (pass original content for SEO)
599
- const html = generateHTML(title, htmlContent, navigation, urlPath, config, content);
620
+ // Generate full HTML (pass original content and front matter for SEO)
621
+ const html = generateHTML(title, htmlContent, navigation, urlPath, config, content, frontMatter);
600
622
 
601
623
  // Write file
602
624
  await fs.ensureDir(path.dirname(outputPath));
603
625
  await fs.writeFile(outputPath, html);
604
626
 
605
- return { title, urlPath, summary };
627
+ return { title, urlPath, summary, frontMatter };
606
628
  }
607
629
 
608
630
  // Get all markdown files
package/lib/seo.js CHANGED
@@ -48,23 +48,60 @@ function extractKeywords(content, maxKeywords = 10) {
48
48
  /**
49
49
  * Generate meta description from content
50
50
  */
51
- function generateDescription(content, maxLength = 160) {
52
- // Remove markdown syntax and get first paragraph
51
+ function generateDescription(content, mode = 'smart', maxLength = 160) {
52
+ // Remove markdown syntax
53
53
  const plainText = content
54
54
  .replace(/```[\s\S]*?```/g, '') // Remove code blocks
55
+ .replace(/^---[\s\S]*?---/m, '') // Remove front matter
55
56
  .replace(/#+\s(.+)/g, '$1. ') // Convert headers to sentences
56
57
  .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // Extract link text
57
58
  .replace(/[*_~]/g, '') // Remove emphasis
58
59
  .replace(/\n+/g, ' ') // Replace newlines with spaces
59
60
  .trim();
60
61
 
61
- // Find first sentence or use first maxLength characters
62
- const firstSentence = plainText.match(/^[^.!?]+[.!?]/);
63
- let description = firstSentence ? firstSentence[0] : plainText;
62
+ let description = '';
63
+
64
+ if (mode === 'smart') {
65
+ // Try to find intro paragraph after first header
66
+ const lines = content.split('\n');
67
+ let foundH1 = false;
68
+ let introText = '';
69
+
70
+ for (const line of lines) {
71
+ if (line.match(/^#\s+/)) {
72
+ foundH1 = true;
73
+ continue;
74
+ }
75
+ if (foundH1 && line.trim() && !line.match(/^#/)) {
76
+ introText = line.trim();
77
+ break;
78
+ }
79
+ }
80
+
81
+ if (introText) {
82
+ // Clean markdown from intro text
83
+ description = introText
84
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
85
+ .replace(/[*_~]/g, '');
86
+ }
87
+ }
64
88
 
65
- // Truncate if needed
89
+ // Fallback to first paragraph
90
+ if (!description) {
91
+ const firstSentence = plainText.match(/^[^.!?]+[.!?]/);
92
+ description = firstSentence ? firstSentence[0] : plainText;
93
+ }
94
+
95
+ // Ensure optimal length (140-160 chars)
66
96
  if (description.length > maxLength) {
67
- description = description.substring(0, maxLength - 3) + '...';
97
+ // Try to cut at word boundary
98
+ const cutPoint = description.lastIndexOf(' ', maxLength - 3);
99
+ description = description.substring(0, cutPoint > 100 ? cutPoint : maxLength - 3) + '...';
100
+ } else if (description.length < 140 && description.length > 100) {
101
+ // Maybe add a call to action if too short
102
+ if (!description.match(/[.!?]$/)) {
103
+ description += '.';
104
+ }
68
105
  }
69
106
 
70
107
  return description;
@@ -84,7 +121,8 @@ function generateMetaTags(options) {
84
121
  ogImage,
85
122
  siteName,
86
123
  language = 'en-US',
87
- type = 'article'
124
+ type = 'article',
125
+ customMetaTags = []
88
126
  } = options;
89
127
 
90
128
  const tags = [];
@@ -157,6 +195,18 @@ function generateMetaTags(options) {
157
195
  }
158
196
  }
159
197
 
198
+ // Add custom meta tags
199
+ if (customMetaTags && customMetaTags.length > 0) {
200
+ tags.push(` \n <!-- Custom Meta Tags -->`);
201
+ customMetaTags.forEach(tag => {
202
+ if (tag.name && tag.content) {
203
+ tags.push(` <meta name="${escapeHtml(tag.name)}" content="${escapeHtml(tag.content)}">`);
204
+ } else if (tag.property && tag.content) {
205
+ tags.push(` <meta property="${escapeHtml(tag.property)}" content="${escapeHtml(tag.content)}">`);
206
+ }
207
+ });
208
+ }
209
+
160
210
  return tags.join('\n');
161
211
  }
162
212
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -27,6 +27,7 @@
27
27
  "chalk": "^4.1.2",
28
28
  "commander": "^11.0.0",
29
29
  "fs-extra": "^11.2.0",
30
+ "gray-matter": "^4.0.3",
30
31
  "marked": "^15.0.12",
31
32
  "ora": "5.4.1",
32
33
  "prompts": "^2.4.2"