@knowcode/doc-builder 1.9.25 → 1.9.27

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/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ All notable changes to @knowcode/doc-builder will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.9.26] - 2025-08-10
9
+
10
+ ### Added
11
+ - **Non-Printable Character Handling** - Automatically detects and skips files with non-printable ASCII characters (0x00-0x1F, 0x7F-0x9F) in their names
12
+ - **Safe File Processing** - Prevents YAML parsing errors and build failures caused by malformed filenames
13
+ - **Clear User Feedback** - Displays warning messages with sanitized filenames when problematic files are encountered
14
+ - **Cross-Platform Compatibility** - Handles files with special characters from different operating systems
15
+
16
+ ### Fixed
17
+ - **Build Failures** - Resolved "stream contains non-printable characters" YAML parsing errors during deployment
18
+ - **File Scanning Issues** - Fixed crashes when encountering files with control characters or corrupted metadata
19
+ - **Deployment Errors** - Eliminated deployment failures caused by problematic filenames in source directories
20
+
21
+ ### Technical
22
+ - Added `hasNonPrintableChars()` function to detect problematic filenames
23
+ - Added `sanitizeFilename()` function for safe display of problematic names
24
+ - Updated all file scanning functions (`getAllMarkdownFiles`, `getAllAttachmentFiles`, `findHtmlFiles`)
25
+ - Enhanced `fs.readdir` and `fs.readdirSync` operations with safety checks
26
+
8
27
  ## [1.9.18] - 2025-08-02
9
28
 
10
29
  ### Added
package/README.md CHANGED
@@ -310,6 +310,23 @@ doc-builder automatically copies attachment files (Excel, PDF, images, etc.) to
310
310
 
311
311
  To disable attachment copying, use the `--no-attachments` flag with build or deploy commands.
312
312
 
313
+ ### 🛡️ File Safety & Non-Printable Character Handling
314
+
315
+ doc-builder v1.9.26+ automatically handles files with non-printable characters in their names to prevent build failures:
316
+
317
+ - **Automatic Detection**: Files with non-printable ASCII characters (0x00-0x1F, 0x7F-0x9F) are automatically detected
318
+ - **Safe Processing**: Problematic files are skipped during scanning with a warning message
319
+ - **Clear Feedback**: You'll see messages like: `⚠️ Skipping file with non-printable characters: [sanitized name]`
320
+ - **Prevents Errors**: Eliminates YAML parsing errors and build failures caused by malformed filenames
321
+
322
+ **Common scenarios this fixes**:
323
+ - Files copied from certain operating systems with special characters
324
+ - Documents exported from applications that add invisible control characters
325
+ - Files with corruption in their metadata
326
+ - Cross-platform compatibility issues
327
+
328
+ This ensures your documentation builds successfully even when your source directory contains files with problematic names.
329
+
313
330
  ## 📋 Commands Overview
314
331
 
315
332
  <table>
package/cli.js CHANGED
@@ -36,6 +36,7 @@ ${chalk.yellow('What it does:')}
36
36
  • Deploys to Vercel with one command (zero configuration)
37
37
  • ${chalk.green.bold('NEW:')} Shows help by default, use 'deploy' to publish (v1.3.0+)
38
38
  • Optional authentication to protect private documentation
39
+ • Handles files with non-printable characters safely (v1.9.26+)
39
40
 
40
41
  ${chalk.yellow('Requirements:')}
41
42
  • Node.js 14+ installed
@@ -87,6 +88,10 @@ ${chalk.yellow('Examples:')}
87
88
  ${chalk.gray('$')} doc-builder build --no-auth ${chalk.gray('# Build public site without authentication')}
88
89
  ${chalk.gray('$')} doc-builder build --no-static ${chalk.gray('# Skip static output generation')}
89
90
  ${chalk.gray('$')} doc-builder build --static-dir public ${chalk.gray('# Use custom static output directory')}
91
+
92
+ ${chalk.yellow('File Safety:')}
93
+ Files with non-printable characters in their names are automatically skipped
94
+ to prevent build failures. You'll see warnings for any problematic files.
90
95
  `)
91
96
  .action(async (options) => {
92
97
  const spinner = ora('Building documentation...').start();
@@ -628,6 +633,10 @@ ${chalk.yellow('Examples:')}
628
633
  ${chalk.gray('$')} doc-builder deploy --no-prod ${chalk.gray('# Deploy preview only')}
629
634
  ${chalk.gray('$')} doc-builder deploy --no-auth ${chalk.gray('# Deploy public site without authentication')}
630
635
 
636
+ ${chalk.yellow('File Safety:')}
637
+ Files with non-printable characters are automatically skipped during deployment
638
+ to prevent YAML parsing errors. You'll see warnings for any problematic files.
639
+
631
640
  ${chalk.yellow('First-time Vercel Setup:')}
632
641
 
633
642
  ${chalk.cyan('1. Install Vercel CLI:')}
@@ -64,6 +64,19 @@ function escapeHtml(text) {
64
64
  return text.replace(/[&<>"']/g, m => map[m]);
65
65
  }
66
66
 
67
+ // Helper function to check if filename contains non-printable characters
68
+ function hasNonPrintableChars(filename) {
69
+ // Check for non-printable ASCII characters (0x00-0x1F, 0x7F-0x9F)
70
+ // Exclude common allowed control chars like tab (0x09), newline (0x0A), carriage return (0x0D)
71
+ return /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/.test(filename);
72
+ }
73
+
74
+ // Helper function to sanitize filename for safe processing
75
+ function sanitizeFilename(filename) {
76
+ // Remove non-printable characters
77
+ return filename.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F]/g, '');
78
+ }
79
+
67
80
  // Helper function to smartly capitalize text while preserving existing capitalization
68
81
  function smartCapitalize(text) {
69
82
  if (!text) return text;
@@ -1121,6 +1134,12 @@ async function getAllMarkdownFiles(dir, baseDir = dir, options = {}) {
1121
1134
  const items = await fs.readdir(dir);
1122
1135
 
1123
1136
  for (const item of items) {
1137
+ // Skip files with non-printable characters in their names
1138
+ if (hasNonPrintableChars(item)) {
1139
+ console.log(chalk.yellow(`⚠️ Skipping file with non-printable characters: ${sanitizeFilename(item)}`));
1140
+ continue;
1141
+ }
1142
+
1124
1143
  const fullPath = path.join(dir, item);
1125
1144
  const stat = await fs.stat(fullPath);
1126
1145
 
@@ -1183,6 +1202,12 @@ async function getAllAttachmentFiles(dir, baseDir = dir, attachmentTypes) {
1183
1202
  const items = await fs.readdir(dir);
1184
1203
 
1185
1204
  for (const item of items) {
1205
+ // Skip files with non-printable characters in their names
1206
+ if (hasNonPrintableChars(item)) {
1207
+ console.log(chalk.yellow(`⚠️ Skipping attachment with non-printable characters: ${sanitizeFilename(item)}`));
1208
+ continue;
1209
+ }
1210
+
1186
1211
  const fullPath = path.join(dir, item);
1187
1212
  const stat = await fs.stat(fullPath);
1188
1213
 
@@ -1307,7 +1332,8 @@ async function buildDocumentation(config) {
1307
1332
 
1308
1333
  // List all HTML files in output directory
1309
1334
  if (fs.existsSync(outputDir)) {
1310
- const htmlFiles = fs.readdirSync(outputDir).filter(f => f.endsWith('.html'));
1335
+ const htmlFiles = fs.readdirSync(outputDir)
1336
+ .filter(f => !hasNonPrintableChars(f) && f.endsWith('.html'));
1311
1337
  console.log(chalk.gray(` - HTML files in output: [${htmlFiles.join(', ')}]`));
1312
1338
  } else {
1313
1339
  console.log(chalk.red(` - ERROR: Output directory does not exist!`));
@@ -1398,6 +1424,10 @@ async function buildDocumentation(config) {
1398
1424
  const walkDir = (dir, baseDir = '') => {
1399
1425
  const items = fs.readdirSync(dir);
1400
1426
  items.forEach(item => {
1427
+ // Skip files with non-printable characters
1428
+ if (hasNonPrintableChars(item)) {
1429
+ return;
1430
+ }
1401
1431
  const fullPath = path.join(dir, item);
1402
1432
  const stat = fs.statSync(fullPath);
1403
1433
  if (stat.isDirectory()) {
@@ -1548,6 +1578,10 @@ async function buildDocumentation(config) {
1548
1578
  const walkDir = (dir, baseDir = '') => {
1549
1579
  const items = fs.readdirSync(dir);
1550
1580
  items.forEach(item => {
1581
+ // Skip files with non-printable characters
1582
+ if (hasNonPrintableChars(item)) {
1583
+ return;
1584
+ }
1551
1585
  const fullPath = path.join(dir, item);
1552
1586
  const stat = fs.statSync(fullPath);
1553
1587
  if (stat.isDirectory()) {
@@ -1737,6 +1771,10 @@ async function createDefaultIndexPage(outputDir, config, version) {
1737
1771
  async function findHtmlFiles(dir, baseDir = dir) {
1738
1772
  const items = await fs.readdir(dir);
1739
1773
  for (const item of items) {
1774
+ // Skip files with non-printable characters
1775
+ if (hasNonPrintableChars(item)) {
1776
+ continue;
1777
+ }
1740
1778
  const fullPath = path.join(dir, item);
1741
1779
  const stat = await fs.stat(fullPath);
1742
1780
  if (stat.isDirectory() && !item.startsWith('.')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@knowcode/doc-builder",
3
- "version": "1.9.25",
3
+ "version": "1.9.27",
4
4
  "description": "Reusable documentation builder for markdown-based sites with Vercel deployment support",
5
5
  "main": "index.js",
6
6
  "bin": {