fauxdom
v1.2.2
Published
A fast and lightweight HTML5 parser and DOM for Node.js and browsers.
Downloads
40
Maintainers
Readme
FauxDOM
A fast and lightweight JavaScript library for parsing, modifying, and outputting HTML using a (mostly) standard DOM API, either on the server in Node.js or in any reasonably modern browser.
Description
FauxDOM is meant to parse HTML the same way browsers do, while also being as fast as possible. Some compromises were made for performance reasons that make FauxDOM treat some less-than-valid HTML different from a standards-compliant browser. With this in mind, any major structural differences between what FauxDOM produces and what a browser produces should be safe to view as a problem with the HTML document itself. However, if you come across a scenario where you believe FauxDOM is incorrect, and this same issue hasn't been reported yet, feel free to open a new issue.
Having a mostly standards-compliant DOM API means that some parts of FauxDOM's implementation of the standards fully work, while others either don't or are different in some regard. The documentation will list properties and methods as either standard, semi-standard (when their behaviour is different from the standard), or non-standard to give you a more clear idea of how FauxDOM differs from the standard DOM API.
What Works
Standards-based API
FauxDOM implements a subset of the standard DOM API as defined by the WHATWG, and documented by MDN.
The full list of supported API methods and properties can be found in the documentation.
Selector engine
The main portion of the Selectors Level 4 API that can be used to identify elements has been implemented and is used by
Node.closest()
,Node.matches()
,Node.querySelector()
, andNode.querySelectorAll()
.The full list of supported selectors can be found in the selectors documentation.
What Doesn't
Namespaces
HTML namespaces in general are not supported by FauxDOM. Any standard DOM API methods that end in "NS" are not implemented, and any other methods that should work with namespaces according to the spec will simply ignore any requests to work on namespaces.
Namespaces in selectors (for
Node.querySelector()
, etc.), in addition to not being supported, will actually cause a syntax error to be thrown.Attribute nodes
While FauxDOM fully supports attributes on elements, attribute values are only ever worked with as strings rather than attribute node objects. As such, any standard DOM API methods that work with attribute nodes (eg.
createAttribute()
,getAttributeNode()
,setAttributeNode()
, etc.) are not implemented.Element adoption
For performance reasons, FauxDOM doesn't implement what the WHATWG's HTML 5 spec calls the adoption agency algorithm, instead opting for a significantly more simplistic method of determining which elements can be the children of which other elements when parsing HTML.
What's Different
Array
-like objectsFor many standard DOM API methods that would normally work with a collection of values using an
Array
-like object (such asNamedNodeMap
andNodeList
), FauxDOM instead simply uses anArray
to store the values. The main exception to this isDOMTokenList
, accessible fromNode.classList
, which is a mostly complete implementation of the standard DOM API class of the same name.
Installing
Server-side (Node.js)
npm install fauxdom
Client-side (browsers)
For client-side use, FauxDOM comes in three distinct flavours:
fauxdom.zip
— Old-school everything-lives-in-the-global-scope styleIncluding this in your page will result in a single class called
DOM
being globally defined.fauxdom.legacy.zip
— Like above, but for older browsersJust like the first option, but it's been made compatible with older browsers (IE 9 and similar).
fauxdom.module.zip
— Way-of-the-future ES module styleThe module exports a single class named
DOM
.
Download the latest release in the style you want.
entities.zip
and entities.module.zip
are also available to download if you want to be able to encode and decode the entire set of HTML entities as defined by the HTML 5 standard. Please see the note about the standard set of entities if you intend to use the full set.
Using
In Node.js, as is usual, you'll need to require()
FauxDOM to use it:
const DOM = require( "fauxdom" );
For use on a webpage, include fauxdom.js
before code that uses FauxDOM:
<script src="fauxdom.js" type="text/javascript"></script>
<script>var doc = new DOM();</script>
FauxDOM can also be used as an ES module by importing the module's single export DOM
:
import DOM from "/fauxdom.js";
Once the DOM
class is accessible by your code, you're ready to start creating and working with documents. The DOM
reference documentation is an excellent place to start reading about how to use FauxDOM.
Examples
As a simple example of making an empty document be slightly more meaningful, the following code:
const document = new DOM( "<!DOCTYPE html><html><head></head><body></body></html>" );
document.title = "Page";
const header = document.createElement( "h1" );
header.textContent = "Hello, world.";
document.body.appendChild( header );
console.log( document.innerHTML );
will output (with whitespace added for readability):
<!DOCTYPE html>
<html>
<head>
<title>Page</title>
</head>
<body>
<h1>Hello, world.</h1>
</body>
</html>
A more advanced use-case could be to create a Node.js server that implements a JavaScript-based system similar to PHP:
const html = "<?js '<div>'+ (21 * 2) +'</div>'?>";
const document = new DOM( html, {allowProcessingInstructions: true} );
document.forEach( node =>
{
if ( node.target === "js" )
node.outerHTML = eval( node.textContent );
}, DOM.Node.PROCESSING_INSTRUCTION_NODE );
console.log( document.innerHTML );
Even though the above code isn't anywhere near production quality, with absolutely no error handling or considerations for security, it is the minimum amount of work needed to allow the example code above to output:
<div>42</div>
Requirements
FauxDOM requires at least Node.js 6 (or compatible) on the server side, and Chrome 5, Firefox 4, Internet Explorer 9, Opera 11.6, or Safari 5 (or compatible) on the client side. These browser requirements are driven by the need for Object.defineProperties
, for which no valid polyfill exists (getters and setters are needed, but not supported in versions of IE less than 9).
FauxDOM also requires, and includes, basic polyfills for the following JavaScript APIs. The first version of each browser that supports each API is also listed.
| | Chrome | Edge | Firefox | IE | Opera | Safari |
| :----------------------------------------------------------- | :----: | :--: | :-----: | :--------: | :---: | :----: |
| Symbol
| 38 | 12 | 36 | none | 25 | 9 |
| Object.assign
| 45 | 12 | 34 | none | 32 | 9 |
| Object.freeze
| 6 | 12 | 4 | 9 | 12 | 5.1 |
| Object.hasOwn
| 93 | 93 | 92 | none | 79 | 15.4 |
| String.fromCodePoint
| 41 | 12 | 29 | none | 28 | 10 |
| String.prototype.trimEnd
| 66 | 79 | 61 | none | 53 | 12 |
| String.prototype.trimStart
| 66 | 79 | 61 | none | 53 | 12 |
| Array.prototype.find
| 45 | 12 | 25 | none | 32 | 8 |
| Function.prototype.bind
| 7 | 12 | 4 | 9 | 11.6 | 5.1 |
If your project already includes a polyfill for any of the above, include your polyfill before FauxDOM to keep FauxDOM's simplistic polyfills from being used.