Skip to content

DevOashim/RegX-DomDocument

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

regxdomdocument - Complete Guide & Reference

Pure regex-based DOM manipulation library with React/JSX Template Literal Support. No DOMDocument, no XML parsing - just regex magic!

Perfect for preserving exact HTML structure, React/Vue components, and template variables.

Installation

composer require devoashim/regxdomdocument

Table of Contents


Quick Start

Basic HTML Manipulation

use devoashim\regxdomdocument\XDOM;

$dom = XDOM::load($html);

// Find and modify elements
$dom->find('#app')->setInnerHTML('<Component />');
$dom->find('.header')->addClass('active');

echo $dom->html();

Template Literal Generation

Convert static className to dynamic React template literal:

$dom = XDOM::loadFromFile('index.html');

// Convert static to dynamic
$dom->find('.stricky-header')
    ->setDynamicClass('isStick', 'stricky-fixed');

// Output HTML
echo $dom->html();

Before:

<div className="stricky-header stricked-menu main-menu">

After:

<div className={`stricky-header stricked-menu main-menu ${isStick ? 'stricky-fixed' : ''}`}>

Loading HTML

Returns: XDOM instance

// From string
$dom = XDOM::load($htmlString);

// From file
$dom = XDOM::loadFromFile('/path/to/file.html');

// From Laravel Storage
$path = Storage::disk('public')->path('index.html');
$dom = XDOM::loadFromFile($path);

Finding Elements

Returns: RegexNodeCollection

// By ID
$element = $dom->find('#header');
$element = $dom->find('#main-content');

// By Class
$elements = $dom->find('.container');
$elements = $dom->find('.nav-item');

// By Tag
$elements = $dom->find('div');
$elements = $dom->find('nav');
$elements = $dom->find('section');

// Combined Selectors
$element = $dom->find('div#main');        // Tag + ID
$element = $dom->find('section#about');

$elements = $dom->find('div.container');  // Tag + Class
$elements = $dom->find('nav.main-nav');

// Descendant (parent child)
$elements = $dom->find('header nav');
$elements = $dom->find('div .content');
$elements = $dom->find('main section');

Getting Content

String Returns

// Get inner HTML (content between tags)
$content = $dom->find('#app')->innerHTML();
// <div id="app">THIS CONTENT</div>
// Returns: "THIS CONTENT"

// Get outer HTML (full element with tags)
$html = $dom->find('#app')->outerHTML();
// Returns: "<div id="app">Content</div>"

// Get text content (strip all HTML)
$text = $dom->find('#app')->text();
// <div id="app"><p>Hello <b>World</b></p></div>
// Returns: "Hello World"

// Get complete HTML document
$fullHtml = $dom->html();

// Get attribute value
$value = $dom->find('#app')->attr('data-value');
$id = $dom->find('div')->attr('id');
$class = $dom->find('nav')->attr('class');

Array Returns

// Get first element
$first = $dom->find('.item')->first();
// Returns: ['html' => '...', 'position' => ..., 'tag' => '...']

// Get last element
$last = $dom->find('.item')->last();

// Get element by index
$third = $dom->find('.item')->get(2);  // 0-based index

// Get all matches as array
$matches = $dom->find('.item')->getMatches();
// Returns: [
//     ['html' => '<div class="item">1</div>', 'position' => 0, 'tag' => 'div', 'type' => 'full'],
//     ['html' => '<div class="item">2</div>', 'position' => 50, 'tag' => 'div', 'type' => 'full'],
// ]

Boolean & Integer Returns

// Count elements
$count = $dom->find('.item')->count();
echo "Found $count items";

// Check if has attribute
if ($dom->find('#app')->hasAttr('data-loaded')) {
    echo "Has data-loaded attribute";
}

// Check if has class
if ($dom->find('#app')->hasClass('active')) {
    echo "Has active class";
}

// Check if empty
if ($dom->find('.item')->isEmpty()) {
    echo "No items found";
}

// Check if not empty
if ($dom->find('.item')->isNotEmpty()) {
    echo "Items found!";
}

Setting Content

Returns: RegexNodeCollection (chainable)

// Set inner HTML (PRESERVES EXACT CONTENT - no encoding)
$dom->find('#app')->setInnerHTML('<Menu /> <Dashboard />');
// Perfect for React/Vue components!

// Set outer HTML (replace entire element)
$dom->find('#old')->setOuterHTML('<section id="new">Content</section>');
// Before: <div id="old">...</div>
// After:  <section id="new">Content</section>

// Set text (HTML encoded for safety)
$dom->find('#title')->setText('Hello & Welcome');
// Output: Hello &amp; Welcome

// Append content (add at end, inside element)
$dom->find('#list')->append('<li>New Item</li>');

// Prepend content (add at start, inside element)
$dom->find('#list')->prepend('<li>First Item</li>');

// Insert before element
$dom->find('#main')->before('<header>Header</header>');

// Insert after element
$dom->find('#main')->after('<footer>Footer</footer>');

Attributes & Classes

Returns: RegexNodeCollection (chainable)

// Set single attribute
$dom->find('#app')
    ->attr('data-component', 'main')
    ->attr('data-version', '2.0')
    ->attr('data-loaded', 'true');

// Remove attribute
$dom->find('#app')->removeAttr('data-old');

// Add single class
$dom->find('#app')
    ->addClass('active')
    ->addClass('loaded')
    ->addClass('ready');

// Add multiple classes
$dom->find('.header')->addClasses('active loaded ready');
$dom->find('.header')->addClasses(['active', 'loaded', 'ready']);

// Remove class
$dom->find('#app')
    ->removeClass('old')
    ->removeClass('hidden');

// Toggle class
$dom->find('#app')->toggleClass('active');
// If has 'active' → removes it
// If no 'active' → adds it

// Set all classes (replace existing)
$dom->find('.header')->setClasses('new-class another-class');

// Conditional class (PHP-side)
$dom->find('.header')->conditionalClass('active', $isActive);

Template Literals (React/JSX)

Single Conditional Class

$dom->find('.header')->setDynamicClass('isStick', 'sticky-fixed');

Result:

<div className={`header ${isStick ? 'sticky-fixed' : ''}`}>

Multiple Conditional Classes

$dom->find('.header')
    ->setMultipleConditionalClasses([
        'isStick' => 'sticky-fixed',
        'isTransparent' => 'transparent',
        'isScrolled' => 'scrolled'
    ]);

Result:

<div className={`header ${isStick ? 'sticky-fixed' : ''} ${isTransparent ? 'transparent' : ''} ${isScrolled ? 'scrolled' : ''}`}>

Custom Template Expression

$dom->find('.button')
    ->setTemplateExpression('className', 'btn ${type === "primary" ? "btn-primary" : "btn-secondary"}');

Result:

<button className={`btn ${type === "primary" ? "btn-primary" : "btn-secondary"}`}>

Convert class to className

$dom->find('div')->convertToClassName();

Before: <div class="header">
After: <div className="header">


Removing Elements

Returns: RegexNodeCollection (chainable)

// Remove elements from DOM
$dom->find('.old-widget')->remove();
$dom->find('#deprecated')->remove();

Iteration & Filtering

Returns: RegexNodeCollection (chainable) or transformed data

// Iterate each element
$dom->find('.item')->each(function($element, $index) {
    echo "Item $index: " . $element['html'] . "\n";
});

// Map elements (transform)
$texts = $dom->find('.item')->map(function($element, $index) {
    return strip_tags($element['html']);
});
// Returns: Collection or array

// Filter elements
$filtered = $dom->find('.item')->filter(function($element, $index) {
    return strpos($element['html'], 'active') !== false;
});
// Returns: RegexNodeCollection with filtered elements

Saving & Output

Various Return Types

// Get HTML as string
$html = $dom->html();

// Set HTML
$dom->setHtml($newHtmlString);
// Returns: XDOM (chainable)

// Save to file
$dom->saveToFile('/path/to/output.html');
// Returns: XDOM (chainable)

// Save to Laravel Storage
$dom->saveToStorage('public/output.html');
// Returns: XDOM (chainable)

// Return as Laravel Response
return $dom->toResponse();
// Returns: Response
// Automatically sets Content-Type: text/html

Advanced Usage - RegexHelper

For direct regex operations without the fluent interface:

use devoashim\regxdomdocument\RegexHelper;

Extract Content

Returns: string or null

// Extract full element (with tags)
$content = RegexHelper::extractTagContent($html, 'div', 'header', 'class');
// From: <div class="header">Content</div>
// Returns: "<div class="header">Content</div>"

$content = RegexHelper::extractTagContent($html, 'section', 'main', 'id');
// From: <section id="main">Content</section>
// Returns: "<section id="main">Content</section>"

// Extract inner content (without tags)
$inner = RegexHelper::extractInnerContent($html, 'div', 'container', 'class');
// From: <div class="container"><p>Text</p></div>
// Returns: "<p>Text</p>"

Replace Content

Returns: string

// Replace full element
$newHtml = RegexHelper::replaceTagContent(
    $html,
    'div',
    'header',
    '<div class="header"><Header /></div>'
);

// Replace inner content only
$newHtml = RegexHelper::replaceInnerContent(
    $html,
    'div',
    'content',
    '<Component />'
);

Find Multiple Elements

Returns: array

// Find all matching elements
$widgets = RegexHelper::findAllTags($html, 'div', 'widget', 'class');
// Returns: ['<div class="widget">1</div>', '<div class="widget">2</div>', ...]

foreach ($widgets as $i => $widget) {
    echo "Widget $i: $widget\n";
}

Remove Elements

Returns: string

// Remove all matching elements
$cleanHtml = RegexHelper::removeAllTags($html, 'div', 'ads', 'class');

Check Existence

Returns: bool

// Check if element exists
if (RegexHelper::hasTag($html, 'div', 'header', 'class')) {
    echo "Header exists!";
}

Attribute Helpers

Returns: array or string

// Extract all attributes from tag
$tag = '<div class="box" id="main" data-value="123">';
$attrs = RegexHelper::extractAttributes($tag);
// Returns: ['class' => 'box', 'id' => 'main', 'data-value' => '123']

// Replace attribute value
$newTag = RegexHelper::replaceAttribute($tag, 'class', 'new-box active');
// Returns: '<div class="new-box active" id="main" data-value="123">'

Template Literal Generation

Returns: string

// Convert to template literal
$reactHtml = RegexHelper::setDynamicClassName(
    $html,
    'div',
    'header',
    'isStick',
    'sticky-fixed'
);

Method Reference

XDOM Methods

Method Returns Description
load($html) XDOM Load HTML string
loadFromFile($path) XDOM Load from file
find($selector) RegexNodeCollection Find elements
html() string Get full HTML
setHtml($html) XDOM Set HTML (chainable)
saveToFile($path) XDOM Save to file (chainable)
saveToStorage($path) XDOM Save to Laravel Storage
toResponse() Response Return as Laravel response

RegexNodeCollection Methods

Method Returns Chainable Description
innerHTML() string No Get inner HTML
outerHTML() string No Get outer HTML
text() string No Get text content
attr($name) string/null No Get attribute value
attr($name, $value) RegexNodeCollection Yes Set attribute
hasAttr($name) bool No Check if has attribute
removeAttr($name) RegexNodeCollection Yes Remove attribute
addClass($class) RegexNodeCollection Yes Add single class
addClasses($classes) RegexNodeCollection Yes Add multiple classes
removeClass($class) RegexNodeCollection Yes Remove class
toggleClass($class) RegexNodeCollection Yes Toggle class
setClasses($classes) RegexNodeCollection Yes Set all classes
hasClass($class) bool No Check if has class
conditionalClass($class, $condition) RegexNodeCollection Yes Add class if condition true
setInnerHTML($html) RegexNodeCollection Yes Set inner HTML
setOuterHTML($html) RegexNodeCollection Yes Replace entire element
setText($text) RegexNodeCollection Yes Set text (encoded)
append($html) RegexNodeCollection Yes Append inside element
prepend($html) RegexNodeCollection Yes Prepend inside element
before($html) RegexNodeCollection Yes Insert before element
after($html) RegexNodeCollection Yes Insert after element
remove() RegexNodeCollection Yes Remove element
setDynamicClass($var, $class) RegexNodeCollection Yes Add template literal
setMultipleConditionalClasses($array) RegexNodeCollection Yes Multiple conditionals
setTemplateExpression($attr, $expr) RegexNodeCollection Yes Custom template
convertToClassName() RegexNodeCollection Yes class → className
each($callback) RegexNodeCollection Yes Iterate elements
map($callback) Collection/array No Transform elements
filter($callback) RegexNodeCollection No Filter elements
first() array/null No Get first element
last() array/null No Get last element
get($index) array/null No Get by index
getMatches() array No Get all matches
count() int No Count elements
isEmpty() bool No Check if empty
isNotEmpty() bool No Check if not empty

RegexHelper Static Methods

Method Returns Description
extractTagContent($html, $tag, $id, $type) string/null Extract full element
extractInnerContent($html, $tag, $id, $type) string/null Extract inner content
replaceTagContent($html, $tag, $id, $new, $type) string Replace full element
replaceInnerContent($html, $tag, $id, $new, $type) string Replace inner content
findAllTags($html, $tag, $id, $type) array Find all matching
removeAllTags($html, $tag, $id, $type) string Remove all matching
hasTag($html, $tag, $id, $type) bool Check if exists
extractAttributes($tag) array Get all attributes
replaceAttribute($tag, $name, $value) string Replace attribute value
setDynamicClassName($html, $tag, $id, $var, $class) string Create template literal

Note: $type parameter can be 'class' (default) or 'id'


Use Cases

1. React Component Conversion

$dom = XDOM::loadFromFile('template.html');

$dom->find('.header')->setInnerHTML('<Header />');
$dom->find('.navigation')->setInnerHTML('<Navigation />');
$dom->find('.content')->setInnerHTML('<Content />');
$dom->find('.footer')->setInnerHTML('<Footer />');

echo $dom->html();

2. Sticky Header with Template Literal

$dom = XDOM::loadFromFile('index.html');

$dom->find('.stricky-header')
    ->setDynamicClass('isStick', 'stricky-fixed')
    ->attr('data-component', 'header');

echo $dom->html();

3. Dynamic Navigation

$dom->find('.nav-item')
    ->setDynamicClass('isActive', 'active');

Result:

<li className={`nav-item ${isActive ? 'active' : ''}`}>

Add ref attribute to element's opening tag

 $dom->find('.main-header')->addRef('headerRef');

Before:

 <header className="main-header">

After:

 <header ref={headerRef} className="main-header">

4. Template Variable Injection

$dom = XDOM::load($template);

$dom->find('#username')->setInnerHTML('{{user.name}}');
$dom->find('#email')->setInnerHTML('{{user.email}}');
$dom->find('#role')->setInnerHTML('{{user.role}}');

return $dom->html();

5. Batch Widget Processing

$dom->find('.widget')
    ->addClass('active')
    ->addClass('featured')
    ->attr('data-loaded', 'true');

6. Complex Component Building

$dom->find('#app')
    ->setInnerHTML('<App />')
    ->addClass('loaded')
    ->addClass('active')
    ->attr('data-component', 'root')
    ->attr('data-version', '2.0')
    ->prepend('<!-- App Start -->')
    ->append('<!-- App End -->');

7. Conditional Modifications

$element = $dom->find('#app');

if ($element->hasClass('old')) {
    $element->removeClass('old')->addClass('new');
}

if (!$element->hasAttr('data-version')) {
    $element->attr('data-version', '2.0');
}

8. Extract and Replace Sections

// Extract
$header = RegexHelper::extractTagContent($html, 'div', 'header', 'class');

// Replace
$newHtml = RegexHelper::replaceTagContent(
    $html,
    'div',
    'header',
    '<header><HeaderComponent /></header>'
);

9. Navigation Menu Processing

// Find nav inside header only
$nav = $dom->find('header nav');

if ($nav->isNotEmpty()) {
    $nav->setInnerHTML('<Navigation items={menuItems} />');
}

10. Multi-Step Content Wrapping

$dom->find('#content')
    ->before('<div class="wrapper">')
    ->after('</div>')
    ->addClass('inner-content');

Method Chaining Examples

All modification methods return RegexNodeCollection, enabling powerful chaining:

// Example 1: Complete component setup
$dom->find('#app')
    ->setInnerHTML('<App />')
    ->addClass('loaded')
    ->addClass('active')
    ->attr('data-component', 'root')
    ->attr('data-version', '2.0')
    ->prepend('<!-- App Start -->')
    ->append('<!-- App End -->');

// Example 2: Style and configure widget
$dom->find('.widget')
    ->addClass('active')
    ->addClass('featured')
    ->attr('data-priority', 'high')
    ->setInnerHTML('<WidgetComponent />');

// Example 3: Update card styling
$dom->find('.card')
    ->removeClass('old-style')
    ->addClass('new-style')
    ->attr('data-updated', 'true')
    ->setInnerHTML('<CardComponent />');

Key Features

Exact Content Preservation - No HTML encoding or modification
React/Vue/JSX Support - Perfect for component templates
Template Literals - Generate dynamic className with conditionals
Template Variables - Works with {{mustache}}, {blade}, etc.
Pure Regex - Fast, lightweight, no dependencies
Method Chaining - Clean, readable code
Laravel Integration - Storage and Response helpers
No DOM Parser - Preserves exact formatting and structure


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the MIT License.

Credits

Created by devoashim

Support

  • GitHub Issues: Create an issue
  • Documentation: Full API reference and examples included

⭐ Star Us!

If you find this package useful, please consider giving it a star on GitHub!


Remember:

  • All content is preserved EXACTLY (no encoding)
  • Perfect for React/Vue/Angular components
  • Works seamlessly with template variables
  • Pure regex - fast and lightweight
  • Method chaining for clean, maintainable code

Last Updated: 2024 Version: Complete Merged Guide

About

Pure regex-based DOM manipulation library. Everything works with regex and string operations!

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages