The fast, lightweight, and modern HTML/XML parser and manipulator.
Zero dependencies. jQuery-like API. Built from scratch.
| Feature | Yestee | Cheerio | JSDOM |
|---|---|---|---|
| Zero Dependencies | β | β (parse5 + css-select + ...) | β |
| Own Parser | β Built-in | β Wraps parse5/htmlparser2 | β |
| Own Selector Engine | β Built-in | β Wraps css-select | β |
| TypeScript Native | β | β | |
| jQuery-like API | β | β | β |
| ESM + CJS | β | β | β |
| Bundle Size | πͺΆ Tiny | Medium | Heavy |
npm install yesteeimport { load } from 'yestee';
const $ = load(`
<html>
<body>
<h1 class="title">Hello World</h1>
<ul id="fruits">
<li class="fruit">Apple</li>
<li class="fruit">Orange</li>
<li class="fruit">Pear</li>
</ul>
</body>
</html>
`);
// Select & extract
$('h1.title').text(); // => 'Hello World'
$('.fruit').first().text(); // => 'Apple'
$('#fruits li').length; // => 3
// Manipulate
$('h1').text('Hello Yestee!');
$('h1').addClass('welcome');
$('#fruits').append('<li class="fruit">Grape</li>');
$('.fruit').first().remove();
// Render
console.log($.html());import { load } from 'yestee';
// Load HTML
const $ = load('<div>Hello</div>');
// Load with options
const $ = load('<root><item/></root>', { xml: true });Yestee supports a comprehensive set of CSS selectors:
// Tag, Class, ID
$('div')
$('.class-name')
$('#element-id')
// Attributes
$('[href]')
$('[type="text"]')
$('[href^="https"]') // starts with
$('[href$=".com"]') // ends with
$('[href*="example"]') // contains
// Combinators
$('div p') // descendant
$('ul > li') // child
$('h1 + p') // adjacent sibling
$('h1 ~ p') // general sibling
// Pseudo-classes
$('li:first-child')
$('li:last-child')
$('li:nth-child(2)')
$('li:nth-child(odd)')
$('li:not(.active)')
$('div:empty')
$(':root')
// Comma groups
$('h1, h2, h3')
// Compound
$('li.active[data-id="1"]:first-child')// Text
$('p').text(); // Get text
$('p').text('New text'); // Set text
// HTML
$('div').html(); // Get inner HTML
$('div').html('<p>New</p>'); // Set inner HTML
// Attributes
$('a').attr('href'); // Get attribute
$('a').attr('href', '/new'); // Set attribute
$('a').attr({ href: '/', target: '_blank' }); // Set multiple
$('a').removeAttr('target'); // Remove attribute
// Data attributes
$('div').data('name'); // Get data-name
$('div').data('name', 'value'); // Set data-name
// Properties
$('p').prop('outerHTML'); // Get outer HTML
$('p').prop('tagName'); // => 'P'
// Value (form elements)
$('input').val(); // Get value
$('input').val('new value'); // Set value$('div').addClass('active');
$('div').addClass('a b c'); // Multiple
$('div').removeClass('active');
$('div').removeClass(); // Remove all
$('div').toggleClass('active');
$('div').hasClass('active'); // => true/false$('div').find('span'); // Find descendants
$('span').parent(); // Direct parent
$('span').parents(); // All ancestors
$('span').parents('div'); // Filtered ancestors
$('span').closest('div'); // Closest ancestor (or self)
$('ul').children(); // Direct children
$('ul').children('.active'); // Filtered children
$('li').siblings(); // Sibling elements
$('li').next(); // Next element sibling
$('li').next('.special'); // Next matching sibling
$('li').nextAll(); // All following siblings
$('li').prev(); // Previous element sibling
$('li').prevAll(); // All preceding siblings
$('li').first(); // First in set
$('li').last(); // Last in set
$('li').eq(2); // Element at index
$('li').eq(-1); // Last element$('ul').append('<li>New</li>'); // Append child
$('ul').prepend('<li>First</li>'); // Prepend child
$('p').after('<hr>'); // Insert after
$('p').before('<h2>Title</h2>'); // Insert before
$('span').remove(); // Remove from DOM
$('div').empty(); // Remove all children
$('old').replaceWith('<new/>'); // Replace element
$('div').wrap('<section></section>'); // Wrap element
$('div').clone(); // Deep clone$('li').filter('.active'); // Filter by selector
$('li').filter((i, el) => i > 0); // Filter by function
$('li').not('.active'); // Exclude matching
$('li').has('.child'); // Has matching descendant
$('li').is('.active'); // Check if matches
$('li').slice(0, 2); // Slice collection// Each
$('li').each((index, element) => {
console.log(index, element.tagName);
});
// Map
const texts = $('li').map((i, el) => $(el).text());
// For...of
for (const el of $('li')) {
console.log(el.tagName);
}
// To array
const elements = $('li').toArray();
// Length
$('li').length; // => 3// Full document HTML
$.html();
// Full document XML
$.xml();
// All text content
$.text();
// Root elements
$.root();Yestee also exposes its internals for advanced use:
import {
// Parser
parse,
parseFragment,
tokenize,
// Selector engine
querySelectorAll,
querySelector,
matches,
// Serializer
serialize,
innerHTML,
outerHTML,
textContent,
// DOM utilities
createElement,
createTextNode,
appendChild,
removeChild,
cloneNode,
NodeType,
} from 'yestee';
// Use the tokenizer directly
const tokens = tokenize('<div class="test">Hello</div>');
// Use the parser directly
const doc = parse('<div>Hello</div>');
// Query the DOM directly
const elements = querySelectorAll(doc, '.test');
// Serialize back to HTML
const html = serialize(doc, { pretty: true, indent: ' ' });- π·οΈ Web Scraping β Extract data from static HTML
- π§ Email Templates β Parse and modify HTML emails
- π SEO Auditing β Extract meta tags, headings, links
- π§Ή HTML Sanitization β Clean user-submitted HTML
- ποΈ Static Site Generation β Transform HTML during build
- π‘ RSS/XML Parsing β Process feeds and XML data
- β Testing β Assert HTML structure in unit tests
- π SSR Post-processing β Modify server-rendered output
Yestee is written in TypeScript and ships with full type definitions:
import { load, type ElementNode, type Yestee } from 'yestee';
const $ = load('<div>Hello</div>');
const el: ElementNode = $('div').get(0) as ElementNode;Contributions are welcome! Please see CONTRIBUTING.md for details.
# Clone the repo
git clone https://github.com/Sathish27/Yestee.git
cd yestee
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run buildMIT Β© Sathish