Skip to content

Commit

Permalink
Fixes and additions
Browse files Browse the repository at this point in the history
* Added a much more complete whitespace minifier (document.minifyWhitespace()), as compared to the simplistic `trimWhitespace` and `collapseWhitespace` options.

* Added a handful of DOM APIs (append, prepend, remove, etc).

* Fixed several bugs with `document.head` and `document.body` not being updated correctly during node insertion, replacement, and removal.

* Fixed other various bugs with node insertion.

* Minor updates to some syntax and JS API usage.
  • Loading branch information
sedouri committed Apr 2, 2024
1 parent d2d8f3a commit 09aed14
Show file tree
Hide file tree
Showing 33 changed files with 4,257 additions and 834 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ For client-side use, FauxDOM comes in two distinct flavours:

The module exports a single class named `DOM`.

Download the [latest release](../../releases/latest) of the style you want.
Download the [latest release](../../releases/latest) in the style you want.

<a name="entities-variants"></a>`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](docs/DOM.md#standard-entities-note) if you intend to use the full set.

Expand Down Expand Up @@ -109,7 +109,7 @@ document.body.appendChild( header );
console.log( document.innerHTML );
```

will output (with spaces and line breaks added for readability):
will output (with whitespace added for readability):

```html
<!DOCTYPE html>
Expand Down Expand Up @@ -138,7 +138,7 @@ document.forEach( 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 HTML code like the above `<?js '<div>'+ (21 * 2) +'</div>'?>` to be output as:
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:

```html
<div>42</div>
Expand All @@ -155,7 +155,11 @@ FauxDOM also requires, and includes, basic polyfills for the following JavaScrip
| [`Symbol`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Browser_compatibility) | 38 | 12 | 36 | ***none*** | 25 | 9 |
| [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Browser_compatibility) | 45 | 12 | 34 | ***none*** | 32 | 9 |
| [`Object.freeze`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#Browser_compatibility) | 6 | 12 | 4 | 9 | 12 | 5.1 |
| [`Object.hasOwn`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwn#browser_compatibility) | 93 | 93 | 92 | ***none*** | 79 | 15.4 |
| [`String.fromCodePoint`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/fromCodePoint#Browser_compatibility) | 41 | 12 | 29 | ***none*** | 28 | 10 |
| [`String.prototype.trimEnd`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimEnd#Browser_compatibility) | 66 | 79 | 61 | ***none*** | 53 | 12 |
| [`String.prototype.trimStart`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trimStart#Browser_compatibility) | 66 | 79 | 61 | ***none*** | 53 | 12 |
| [`Array.prototype.find`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#browser_compatibility) | 45 | 12 | 25 | ***none*** | 32 | 8 |
| [`Function.prototype.bind`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Browser_compatibility) | 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.
Expand Down
125 changes: 124 additions & 1 deletion docs/DOM.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ The `DOM` class, when instantiated, parses the HTML that is passed as the first
- [createProcessingInstruction](#methods-create-processing-instruction)
- [createTextNode](#methods-create-text-node)
- [getElementsByName](#methods-get-elements-by-name)
- [minifyWhitespace](#methods-minify-whitespace)
- [Node.js Only (Non-standard)](#nodejs-only-non-standard)
- [importStandardEntities](#methods-import-standard-entities)
- [importStandardEntities (static)](#methods-static-import-standard-entities)
Expand Down Expand Up @@ -91,10 +92,14 @@ new DOM( htmlContent[, options] )
- <a name="option-collapse-whitespace"></a>**`collapseWhitespace`** Boolean *(default:* `false`*)*

Whether to collapse multiple consecutive whitespace characters in text nodes into a single space character, mimicking how browsers render consecutive whitespace characters. This option is ignored if `trimWhitespace` is `true`.

> **ℹ️ Note:** [`DOM.minifyWhitespace()`](#methods-minify-whitespace) may be a better choice depending on your usage of `collapseWhitespace`.
- <a name="option-trim-whitespace"></a>**`trimWhitespace`** Boolean *(default:* `false`*)*

Whether to remove whitespace characters from both ends of text nodes, which is useful for minifying HTML documents. When this option is `true`, the `collapseWhitespace` option is ignored.

> **ℹ️ Note:** [`DOM.minifyWhitespace()`](#methods-minify-whitespace) may be a better choice depending on your usage of `trimWhitespace`.
- <a name="option-lower-attribute-case"></a>**`lowerAttributeCase`** Boolean *(default:* `false`*)*

Expand Down Expand Up @@ -323,6 +328,116 @@ An `Array` of all elements in the document whose `name` attribute matches the sp

----

<a name="methods-minify-whitespace"></a>

```javascript
document.minifyWhitespace( [inlineElements[, transforms[, userValue]]] )
```

[non-standard]

Minifies whitespace within the entire HTML document in a manner that closely replicates browser rendering behavior. This method replaces line breaks and tab characters with spaces, collapses multiple spaces to a single space, removes leading and trailing spaces inside block elements, and adjusts spaces inside and around inline elements accordingly.

The result is a document that maintains its visual appearance when rendered by a browser, but with reduced file size due to whitespace removal.

**Parameters**

- **`inlineElements`** Array *(optional)*

An `Array` of strings representing additional HTML tag names to treat as inline elements, supplementing the built-in list.

> **Built-in Inline Elements:** a, abbr, acronym, audio, b, bdi, bdo, big, button, cite, code, data, del, dfn, em, font, i, img, input, ins, kbd, label, mark, math, meter, nobr, noscript, object, output, picture, progress, q, rp, rt, rtc, ruby, s, samp, select, slot, small, span, strike, strong, sub, sup, svg, textarea, time, tt, u, var, video, wbr
- **`transforms`** Object *(optional)*

An `Object` containing methods for custom transformation of specific text elements.

- `inlineStyles( node, value, userValue )`

Transforms `style` attribute values.

- `style( node, value, userValue )`

Transforms inline CSS within `style` elements.

- `script( node, value, userValue )`

Transforms inline JavaScript within `script` elements.

The return value of these methods replaces the original content. Returning `null` or `undefined` removes the element from the document.

The arguments for the transformation methods are:

- **`node`** Node

The node whose value or attribute should be transformed.

> **⚠️ Caution:** You should not remove this node (or any of its parent nodes) from its document from inside your transformation method or an error will occur. To remove this node, simply return `null` or `undefined` from your method and the node will be removed when it is safe to do so.
- **`value`** String

The value to be transformed.

- **`userValue`** Any

The value you passed, if any, to `minifyWhitespace()` in its `userValue` parameter.

- **`userValue`** Any *(optional)*

Any value you wish to pass to the transformation methods. This can be used for tracking any necessary context between transformations.

**Return Value**

Nothing. Use [`DOM.innerHTML`](#properties-inner-html) to retrieve the modified HTML markup.

**Example**

```javascript
document.minifyWhitespace( null, {
inlineStyles()
{
// Remove all "style" attributes from every element.
return null;
},

style( node, value )
{
// Remove all "style" elements that have the "debug" attribute.
if ( node.hasAttribute( "debug" ) )
return null;

// Keep all other "style" elements as they are by simply returning the
// CSS unchanged.
return value;
},

// Minify JavaScript using "JSMinifier" and pass the file path as context.
script( node, value, filePath )
{
// Create the minifier instance.
const minifier = new JSMinifier( value, filePath );

// Return the minified JavaScript code.
return minifier.minifiedValue;
}
}, filePath );

// Output the minified HTML document.
console.log( document.innerHTML );
```

In this example, we show how `minifyWhitespace` can be used to optimize an HTML document:

- **Removing Inline Styles:** All inline "style" attributes from elements are eliminated.
- **Filtering Out Debug Styles:** "style" elements marked with a "debug" attribute are removed.
- **Minifying JavaScript:** JavaScript code within `script` tags is minified using a fictional library called "JSMinifier". This library requires the file path of the script for its processing.

While in this simple example it isn't really necessary, the `userValue` parameter is used to pass the file path to the "script" transformation method. This is particularly useful when your transformation methods are located in a separate file or module. By passing contextual information like file paths via `userValue`, you enable these external methods to access and use data that they wouldn’t otherwise have direct access to.

Finally, the processed HTML is output to the console. This showcases this method's capability to reduce file size while preserving the visual layout, which is especially useful for preparing HTML files for production environments.

----

### Node.js Only (Non-standard)

The below convenience methods read and parse the file "lib/entities.json" (which includes all standard HTML 5 entities) and are only available when using FauxDOM in Node.js.
Expand All @@ -341,6 +456,10 @@ document.importStandardEntities()

Sets the [`entities`](EntityEncoder.md#properties-entities) of this document's [`entityEncoder`](#properties-entity-encoder) to the standard set of HTML 5 entities.

**Return Value**

Nothing.

----

<a name="methods-static-import-standard-entities"></a>
Expand All @@ -349,4 +468,8 @@ Sets the [`entities`](EntityEncoder.md#properties-entities) of this document's [
DOM.importStandardEntities()
```

The static version of the above method. Sets [`EntityEncoder.defaultEntities`](EntityEncoder.md#properties-default-entities) to the standard set of HTML 5 entities.
The static version of the above method. Sets [`EntityEncoder.defaultEntities`](EntityEncoder.md#properties-default-entities) to the standard set of HTML 5 entities.

**Return Value**

Nothing.
10 changes: 9 additions & 1 deletion docs/DOMTokenList.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ The `DOMTokenList` class, as used by FauxDOM, is only used to implement [`Node.c

- <a name="properties-value"></a>**`value`** String — [[standard](https://dom.spec.whatwg.org/#dom-domtokenlist-value)] [[MDN](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/value)]

Gets the value of the list as a `String` of all tokens in the list (in list order) separated by single ASCII space characters. Setting `value` clears the list and, if set to a string value, separates the string treating one or more white space characters in a row as delimiters, with each item in the resulting list (if valid) then being added to this `DOMTokenList` instance.
Gets the value of the list as a `String` of all tokens in the list (in list order) separated by single ASCII space characters. Setting `value` clears the list and, if set to a string value, separates the string treating one or more whitespace characters in a row as delimiters, with each item in the resulting list (if valid) then being added to this `DOMTokenList` instance.

## Methods

Expand Down Expand Up @@ -72,6 +72,10 @@ Adds the specified tokens to the list.

One or more tokens to add to the list. If a specified token already exists, or [isn't valid](#methods-supports), it is ignored and nothing happens.

**Return Value**

Nothing.

----

<a name="methods-contains"></a>
Expand Down Expand Up @@ -134,6 +138,10 @@ Removes the specified tokens from the list.

One or more tokens to remove from the list. If a specified token doesn't exist, or [isn't valid](#methods-supports), it is ignored and nothing happens.

**Return Value**

Nothing.

----

<a name="methods-replace"></a>
Expand Down

0 comments on commit 09aed14

Please sign in to comment.