A powerful JavaScript library and CLI tool for parsing and manipulating markdown files as tree structures. Built on top of the battle-tested remark/unified ecosystem.
- 🌳 Tree-based parsing - Treats markdown as manipulable Abstract Syntax Trees (AST)
- ✂️ Section extraction - Extract specific sections with automatic boundary detection
- 🔍 Powerful search - CSS-like selectors and custom search functions
- 📚 Batch processing - Process multiple sections at once
- 🛠️ CLI & Library - Use as a command-line tool or JavaScript library
- 📊 Document analysis - Get statistics and generate table of contents
- 🎯 TypeScript ready - Full type definitions included
# Using npm
npm install -g @kayvan/markdown-tree-parser
# Using pnpm (may require approval for build scripts)
pnpm install -g @kayvan/markdown-tree-parser
pnpm approve-builds -g # If prompted# Using yarn
yarn global add @kayvan/markdown-tree-parsernpm install @kayvan/markdown-tree-parserAfter global installation, use the md-tree command:
md-tree list README.md
md-tree list README.md --format json# Extract one section
md-tree extract README.md "Installation"# Extract to a file
md-tree extract README.md "Installation" --output ./sections# Extract all level-2 sections
md-tree extract-all README.md 2
# Extract to separate files
md-tree extract-all README.md 2 --output ./sectionsmd-tree tree README.md# Find all level-2 headings
md-tree search README.md "heading[depth=2]"# Find all links
md-tree search README.md "link"md-tree stats README.mdmd-tree check-links README.md
md-tree check-links README.md --recursivemd-tree toc README.md --max-level 3md-tree helpimport{MarkdownTreeParser}from'markdown-tree-parser';constparser=newMarkdownTreeParser();// Parse markdown into ASTconstmarkdown=`# My DocumentSome content here.## Section 1Content for section 1.## Section 2Content for section 2.`;consttree=awaitparser.parse(markdown);// Extract a specific sectionconstsection=parser.extractSection(tree,'Section 1');constsectionMarkdown=awaitparser.stringify(section);console.log(sectionMarkdown);// Output:// ## Section 1// Content for section 1.import{MarkdownTreeParser,createParser,extractSection,}from'markdown-tree-parser';// Create parser with custom optionsconstparser=createParser({bullet: '-',// Use '-' for listsemphasis: '_',// Use '_' for emphasisstrong: '__',// Use '__' for strong});// Extract all sections at level 2consttree=awaitparser.parse(markdown);constsections=parser.extractAllSections(tree,2);sections.forEach(async(section,index)=>{constheading=parser.getHeadingText(section.heading);constcontent=awaitparser.stringify(section.tree);console.log(`Section ${index+1}: ${heading}`);console.log(content);});// Use convenience functionsconstsectionMarkdown=awaitextractSection(markdown,'Installation');// CSS-like selectorsconstheadings=parser.selectAll(tree,'heading[depth=2]');constlinks=parser.selectAll(tree,'link');constcodeBlocks=parser.selectAll(tree,'code');// Custom searchconstcustomNode=parser.findNode(tree,(node)=>{returnnode.type==='heading'&&parser.getHeadingText(node).includes('API');});// Transform contentparser.transform(tree,(node)=>{if(node.type==='heading'&&node.depth===1){node.depth=2;// Convert h1 to h2}});// Get document statisticsconststats=parser.getStats(tree);console.log(`Document has ${stats.wordCount} words and ${stats.headings.total} headings`);// Generate table of contentsconsttoc=parser.generateTableOfContents(tree,3);console.log(toc);importfsfrom'fs/promises';// Read and process a fileconstcontent=awaitfs.readFile('README.md','utf-8');consttree=awaitparser.parse(content);// Extract all sections and save to filesconstsections=parser.extractAllSections(tree,2);for(leti=0;i<sections.length;i++){constsection=sections[i];constfilename=`section-${i+1}.md`;constmarkdown=awaitparser.stringify(section.tree);awaitfs.writeFile(filename,markdown);}- 📖 Documentation Management - Split large docs into manageable sections
- 🌐 Static Site Generation - Process markdown for blogs and websites
- 📝 Content Organization - Restructure and reorganize markdown content
- 🔍 Content Analysis - Analyze document structure and extract insights
- 📋 Documentation Tools - Build custom documentation processing tools
- 🚀 Content Migration - Extract and transform content between formats
newMarkdownTreeParser((options={}));parse(markdown)- Parse markdown into ASTstringify(tree)- Convert AST back to markdownextractSection(tree, headingText, level?)- Extract specific sectionextractAllSections(tree, level)- Extract all sections at levelselect(tree, selector)- Find first node matching CSS selectorselectAll(tree, selector)- Find all nodes matching CSS selectorfindNode(tree, condition)- Find node with custom conditiongetHeadingText(headingNode)- Get text content of headinggetHeadingsList(tree)- Get all headings with metadatagetStats(tree)- Get document statisticsgenerateTableOfContents(tree, maxLevel)- Generate TOCtransform(tree, visitor)- Transform tree with visitor function
createParser(options)- Create new parser instanceextractSection(markdown, sectionName, options)- Quick section extractiongetHeadings(markdown, options)- Quick heading extractiongenerateTOC(markdown, maxLevel, options)- Quick TOC generation
The library supports powerful CSS-like selectors for searching:
// Element selectorsparser.selectAll(tree,'heading');// All headingsparser.selectAll(tree,'paragraph');// All paragraphsparser.selectAll(tree,'link');// All links// Attribute selectorsparser.selectAll(tree,'heading[depth=1]');// H1 headingsparser.selectAll(tree,'heading[depth=2]');// H2 headingsparser.selectAll(tree,'link[url*="github"]');// Links containing "github"// Pseudo selectorsparser.selectAll(tree,':first-child');// First child elementsparser.selectAll(tree,':last-child');// Last child elements# Run tests
npm test# Test CLI
npm run test:cli
# Run examples
npm run example- Node.js 18+
- npm
# Clone the repository
git clone https://github.com/ksylvan/markdown-tree-parser.git
cd markdown-tree-parser
# Install dependencies
npm install
# Run tests
npm test# Run linting
npm run lint
# Format code
npm run format
# Test CLI functionality
npm run test:cliThis project uses GitHub Actions for continuous integration. The workflow automatically:
- Tests against Node.js versions 18.x, 20.x, and 22.x
- Runs linting with ESLint
- Executes the full test suite
- Tests CLI functionality
- Verifies the package can be published
The CI badge in the README shows the current build status and links to the Actions page.
Contributions are welcome! Please read our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
Built on top of the excellent unified ecosystem:
- remark - Markdown processing
- mdast - Markdown AST specification
- unist - Universal syntax tree utilities
Made with ❤️ by Kayvan Sylvan
