Skip to content

Commit

Permalink
chore: update readme
Browse files Browse the repository at this point in the history
  • Loading branch information
43081j committed Aug 13, 2022
1 parent 17c8022 commit d30b5ad
Showing 1 changed file with 170 additions and 77 deletions.
247 changes: 170 additions & 77 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,80 +1,173 @@
# parse5-tools
# @parse5/tools

A set of tools for interacting with and manipulating a parse5 AST.

# WIP

This is a work in progress until we achieve the same functionality dom5 and modernweb have.

## Suggested interface

* Tree interaction
* replaceWith
* Attributes
* setAttribute
* getAttribute
* hasAttribute
* removeAttribute
* getAttributeIndex
* getAttributes
* Node interaction
* getTextContent
* setTextContent
* normalizeNode
* Traversal
* query
* queryAll
* treeMap
* ancestors
* previousSiblings
* nextSiblings
* prior
* walk

## dom5

* Mutation
* [x] replaceNode
* [x] removeNodeSaveChildren - use `replaceWith`
* [ ] removeFakeRootElements
* Iteration
* [x] treeMap
* [x] depthFirst
* [x] depthFirstReversed
* [x] depthFirstIncludingTemplates
* [x] ancestors
* [x] previousSiblings
* [x] prior
* [x] query
* [x] queryAll
* Utilities
* [x] getTextContent
* [x] getAttribute
* [x] getAttributeIndex
* [x] hasAttribute
* [x] setAttribute
* [x] removeAttribute
* [x] normalize
* [x] setTextContent

Many of the iteration functions use a predicate concept to allow filtering.

## modernweb

* Mutation
* [ ] createScript - use `createElement` instead
* [x] setAttribute
* [ ] setAttributes - use `setAttribute` instead
* [x] removeAttribute
* [ ] prependToDocument
* [ ] appendToDocument
* Utilities
* [ ] isHtmlFragment
* [x] hasAttribute
* [x] getAttribute
* [x] getAttributes
* Iteration
* [x] findNode
* [x] findNodes
* [ ] findElement - use `findNode` with a type guard
* [ ] findElements - use `findNodes` with a type guard
## Why?

The parse5 tree adapter architecture can make AST types, traversal and
manipulation difficult due to its customisability.

This package introduces some assumptions (i.e. removes some customisability)
in order to provide a more trivial interface to the parse5 AST for the common
use case.

Due to this, the types in various places are also simplified and improved.

## Tools

### Node type guards

A full set of node type guard functions are availabile:

* `isDocument`
* `isDocumentFragment`
* `isTemplateNode`
* `isElementNode`
* `isCommentNode`
* `isDocumentTypeNode`
* `isTextNode`

Each of these consumes a `Node` and acts as a TypeScript type guard:

```ts
if (isDocument(node)) {
// access document-specific properties
}
```

### Parent/child type guards

These help with determining if a given node can have children, or can be
a child.

* `isChildNode`
* `isParentNode`

These too are TypeScript type guards:

```ts
if (isChildNode(node)) {
// interact with node.parentNode
}

if (isParentNode(node)) {
// interact with node.childNodes
}
```

### Child manipulation

If you need to mutate a child:

* `replaceWith(node, ...replacements)` - replaces a given node with one or more
nodes
* `spliceChildren(node, start, deleteCount[, ...children])` - splices the
children of a node just the same as `Array#splice`

### Attributes

For interacting with and mutating attributes of an element:

* `setAttribute(node, name, value)`
* `getAttribute(node, name)`
* `hasAttribute(node, name)`
* `removeAttribute(node, name)`
* `getAttributeIndex(node, name)`

### Text manipulation

For dealing with text content of nodes:

* `getTextContent(node)`
* `setTextContent(node, str)`

### Traversal

Unless otherwise specified, all traversal functions are _depth first_.

Additionally, all capable of returning multiple nodes are iterators.

#### `query(node, condition)`

From a given node, this queries for a child at any depth which matches the
condition.

For example, to find the first document fragment:

```ts
query(
node,
(node) => isDocumentFragment(node)
);
```

### `queryAll(node[, condition])`

From a given node, this queries for all children at any depth which match
the condition.

For example, to find all elements:

```ts
const elements = query(
node,
(node) => isElementNode(node)
);

for (const element of elements) {
// do something
}
```

### `ancestors(node)`

Discovers all parents of the specified node until the root document.

### `walkChildren(node)`

Discovers all children of the specified node, depth-first.

### `previousSiblings(node)`

Discovers all previous siblings of the specified node.

### `nextSiblings(node)`

Discovers all next siblings of the specified node.

### `traverse`

The traverse function allows you to specify a visitor which will be called
for each matching type encountered while traversing the tree depth-first.

For example:

```ts
traverse(node, {
text: (textNode) => {
// do something with a text node
}
});
```

Each node type can have a visitor (e.g. you could have an `element` function).

#### `pre:node`

There is one special visit function: `pre:node`.

This is called before visiting any node and will prevent traversing into
the current node's children if it returns false.

For example:

```ts
traverse(node, {
'pre:node': (node) => {
return isElement(node);
}
});
```

This example would traverse into the children of only element nodes as all
others would have returned false.

0 comments on commit d30b5ad

Please sign in to comment.