@kenjura/ursa 0.45.0 → 0.47.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/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ # 0.47.0
2
+ 2025-12-20
3
+
4
+ - Improved handling of trailing slashes in URLs to ensure consistency across all links and resources
5
+
6
+ # 0.46.0
7
+ 2025-12-20
8
+
9
+ - Normalized handling of trailing slashes in URLs
10
+
11
+ # 0.45.0
12
+ 2025-12-20
13
+
14
+ - Added --exclude flag to ignore specified files or directories during generation
15
+ - Improved performance of the serve command with optimized file watching
16
+ - Automatically generating index.html for directories without an index file
17
+
1
18
  # 0.44.0
2
19
  2025-12-16
3
20
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@kenjura/ursa",
3
3
  "author": "Andrew London <andrew@kenjura.com>",
4
4
  "type": "module",
5
- "version": "0.45.0",
5
+ "version": "0.47.0",
6
6
  "description": "static site generator from MD/wikitext/YML",
7
7
  "main": "lib/index.js",
8
8
  "bin": {
@@ -578,7 +578,7 @@ export async function generate({
578
578
 
579
579
  // Automatic index generation for folders without index.html
580
580
  progress.log(`Checking for missing index files...`);
581
- await generateAutoIndices(output, allSourceFilenamesThatAreDirectories, source, templates, menu, footer);
581
+ await generateAutoIndices(output, allSourceFilenamesThatAreDirectories, source, templates, menu, footer, allSourceFilenamesThatAreArticles);
582
582
 
583
583
  // Save the hash cache to .ursa folder in source directory
584
584
  if (hashCache.size > 0) {
@@ -631,14 +631,30 @@ export async function generate({
631
631
  * @param {string} menu - Rendered menu HTML
632
632
  * @param {string} footer - Footer HTML
633
633
  */
634
- async function generateAutoIndices(output, directories, source, templates, menu, footer) {
634
+ async function generateAutoIndices(output, directories, source, templates, menu, footer, generatedArticles) {
635
635
  // Alternate index file names to look for (in priority order)
636
636
  const INDEX_ALTERNATES = ['_index.html', 'home.html', '_home.html'];
637
637
 
638
+ // Normalize paths (remove trailing slashes for consistent replacement)
639
+ const sourceNorm = source.replace(/\/+$/, '');
640
+ const outputNorm = output.replace(/\/+$/, '');
641
+
642
+ // Build set of directories that already have an index.html from a source index.md/txt/yml
643
+ const dirsWithSourceIndex = new Set();
644
+ for (const articlePath of generatedArticles) {
645
+ const base = basename(articlePath, extname(articlePath));
646
+ if (base === 'index') {
647
+ const dir = dirname(articlePath);
648
+ const outputDir = dir.replace(sourceNorm, outputNorm);
649
+ dirsWithSourceIndex.add(outputDir);
650
+ }
651
+ }
652
+
638
653
  // Get all output directories (including root)
639
- const outputDirs = new Set([output]);
654
+ const outputDirs = new Set([outputNorm]);
640
655
  for (const dir of directories) {
641
- const outputDir = dir.replace(source, output);
656
+ // Handle both with and without trailing slash in source
657
+ const outputDir = dir.replace(sourceNorm, outputNorm);
642
658
  outputDirs.add(outputDir);
643
659
  }
644
660
 
@@ -648,7 +664,12 @@ async function generateAutoIndices(output, directories, source, templates, menu,
648
664
  for (const dir of outputDirs) {
649
665
  const indexPath = join(dir, 'index.html');
650
666
 
651
- // Skip if index.html already exists
667
+ // Skip if this directory had a source index.md/txt/yml that was already processed
668
+ if (dirsWithSourceIndex.has(dir)) {
669
+ continue;
670
+ }
671
+
672
+ // Skip if index.html already exists (e.g., created by previous run)
652
673
  if (existsSync(indexPath)) {
653
674
  continue;
654
675
  }
@@ -673,7 +694,7 @@ async function generateAutoIndices(output, directories, source, templates, menu,
673
694
  const content = await readFile(foundAlternate, 'utf8');
674
695
  await outputFile(indexPath, content);
675
696
  renamedCount++;
676
- progress.status('Auto-index', `Promoted ${basename(foundAlternate)} → index.html in ${dir.replace(output, '')}`);
697
+ progress.status('Auto-index', `Promoted ${basename(foundAlternate)} → index.html in ${dir.replace(outputNorm, '') || '/'}`);
677
698
  } catch (e) {
678
699
  progress.log(`Error promoting ${foundAlternate} to index.html: ${e.message}`);
679
700
  }
@@ -705,7 +726,7 @@ async function generateAutoIndices(output, directories, source, templates, menu,
705
726
  continue;
706
727
  }
707
728
 
708
- const folderDisplayName = dir === output ? 'Home' : toTitleCase(folderName);
729
+ const folderDisplayName = dir === outputNorm ? 'Home' : toTitleCase(folderName);
709
730
  const indexHtml = `<h1>${folderDisplayName}</h1>\n<ul class="auto-index">\n${items.join('\n')}\n</ul>`;
710
731
 
711
732
  const template = templates["default-template"];
@@ -731,7 +752,7 @@ async function generateAutoIndices(output, directories, source, templates, menu,
731
752
 
732
753
  await outputFile(indexPath, finalHtml);
733
754
  generatedCount++;
734
- progress.status('Auto-index', `Generated index.html for ${dir.replace(output, '') || '/'}`);
755
+ progress.status('Auto-index', `Generated index.html for ${dir.replace(outputNorm, '') || '/'}`);
735
756
  } catch (e) {
736
757
  progress.log(`Error generating auto-index for ${dir}: ${e.message}`);
737
758
  }