Skip to content

Commit fb08e85

Browse files
authored
Merge pull request #9 from ksylvan/0822-fix-truncation-in-code-blocks
Fix heading detection in fenced code blocks
2 parents b59fb70 + 418a88d commit fb08e85

8 files changed

Lines changed: 176 additions & 145 deletions

File tree

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@
3232
"[markdown]": {
3333
"editor.defaultFormatter": "esbenp.prettier-vscode",
3434
"files.trimTrailingWhitespace": false
35-
}
35+
},
36+
"biome.enabled": false
3637
}

bin/md-tree.js

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
* A powerful CLI tool for parsing and manipulating markdown files as tree structures.
77
*/
88

9-
import { MarkdownTreeParser } from '../lib/markdown-parser.js';
109
import fs from 'node:fs/promises';
1110
import path from 'node:path';
1211
import { fileURLToPath } from 'node:url';
12+
import { MarkdownTreeParser } from '../lib/markdown-parser.js';
1313

1414
const __dirname = path.dirname(fileURLToPath(import.meta.url));
1515
const packagePath = path.join(__dirname, '..', 'package.json');
@@ -352,7 +352,7 @@ For more information, visit: https://github.com/ksylvan/markdown-tree-parser
352352
if (Object.keys(stats.headings.byLevel).length > 0) {
353353
console.log(' By level:');
354354
for (const [level, count] of Object.entries(stats.headings.byLevel).sort(
355-
([a], [b]) => Number.parseInt(a) - Number.parseInt(b)
355+
([a], [b]) => Number.parseInt(a, 10) - Number.parseInt(b, 10)
356356
)) {
357357
console.log(` Level ${level}: ${count}`);
358358
}
@@ -468,13 +468,13 @@ For more information, visit: https://github.com/ksylvan/markdown-tree-parser
468468
options.output = args[i + 1];
469469
i++; // skip next arg
470470
} else if (arg === '--level' || arg === '-l') {
471-
options.level = Number.parseInt(args[i + 1]) || 2;
471+
options.level = Number.parseInt(args[i + 1], 10) || 2;
472472
i++; // skip next arg
473473
} else if (arg === '--format' || arg === '-f') {
474474
options.format = args[i + 1] || 'text';
475475
i++; // skip next arg
476476
} else if (arg === '--max-level') {
477-
options.maxLevel = Number.parseInt(args[i + 1]) || 3;
477+
options.maxLevel = Number.parseInt(args[i + 1], 10) || 3;
478478
i++; // skip next arg
479479
} else if (arg === '--recursive' || arg === '-r') {
480480
options.recursive = true;
@@ -517,7 +517,7 @@ For more information, visit: https://github.com/ksylvan/markdown-tree-parser
517517
console.error(MESSAGES.USAGE_EXTRACT_ALL);
518518
process.exit(1);
519519
}
520-
const level = args[2] ? Number.parseInt(args[2]) : options.level;
520+
const level = args[2] ? Number.parseInt(args[2], 10) : options.level;
521521
await this.extractAllSections(args[1], level, options.output);
522522
}
523523

@@ -645,9 +645,27 @@ For more information, visit: https://github.com/ksylvan/markdown-tree-parser
645645
// Find all level 2 headings and their positions
646646
const sections = [];
647647
let currentSection = null;
648+
let inCodeBlock = false;
648649

649650
for (let i = 0; i < lines.length; i++) {
650651
const line = lines[i];
652+
const trimmed = line.trim();
653+
654+
// Track fenced code blocks and ignore headings within them
655+
if (trimmed.startsWith('```') || trimmed.startsWith('~~~')) {
656+
if (currentSection) {
657+
currentSection.lines.push(line);
658+
}
659+
inCodeBlock = !inCodeBlock;
660+
continue;
661+
}
662+
663+
if (inCodeBlock) {
664+
if (currentSection) {
665+
currentSection.lines.push(line);
666+
}
667+
continue;
668+
}
651669

652670
// Check for main title (level 1)
653671
if (line.match(/^# /)) {
@@ -819,8 +837,20 @@ For more information, visit: https://github.com/ksylvan/markdown-tree-parser
819837
*/
820838
adjustHeadingLevels(content, adjustment) {
821839
const lines = content.split('\n');
840+
let inCodeBlock = false;
822841

823842
const adjustedLines = lines.map((line) => {
843+
// Check for code block boundaries (``` or ~~~)
844+
if (line.trim().startsWith('```') || line.trim().startsWith('~~~')) {
845+
inCodeBlock = !inCodeBlock;
846+
return line;
847+
}
848+
849+
// Skip heading adjustment if we're inside a code block
850+
if (inCodeBlock) {
851+
return line;
852+
}
853+
824854
const headingMatch = line.match(PATTERNS.HEADING_LEVEL_1_5);
825855
if (headingMatch) {
826856
const [, hashes, rest] = headingMatch;

index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ export default MarkdownTreeParser;
1919

2020
// Export additional utilities that might be useful
2121
export { unified } from 'unified';
22-
export { visit } from 'unist-util-visit';
23-
export { selectAll, select } from 'unist-util-select';
2422
export { find } from 'unist-util-find';
23+
export { select, selectAll } from 'unist-util-select';
24+
export { visit } from 'unist-util-visit';
2525

2626
/**
2727
* Convenience function to create a new parser instance

package-lock.json

Lines changed: 49 additions & 62 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@kayvan/markdown-tree-parser",
3-
"version": "1.6.0",
3+
"version": "1.6.1",
44
"description": "A powerful JavaScript library and CLI tool for parsing and manipulating markdown files as tree structures using the remark/unified ecosystem",
55
"type": "module",
66
"main": "index.js",
@@ -34,10 +34,10 @@
3434
"unist-util-visit": "^5.0.0"
3535
},
3636
"devDependencies": {
37-
"@eslint/js": "^9.29.0",
38-
"@types/node": "^24.0.3",
39-
"eslint": "^9.29.0",
40-
"prettier": "^3.5.3"
37+
"@eslint/js": "^9.34.0",
38+
"@types/node": "^24.3.0",
39+
"eslint": "^9.34.0",
40+
"prettier": "^3.6.2"
4141
},
4242
"engines": {
4343
"node": ">=16.0.0"

0 commit comments

Comments
 (0)