Skip to content

Commit

Permalink
issue: #24 Add method insertAdjacentHTML
Browse files Browse the repository at this point in the history
  • Loading branch information
taoqf committed Feb 16, 2020
1 parent 45e77f3 commit a72c0da
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 16 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ Query CSS Selector to find matching node.

Append a child node to childNodes

### HTMLElement#insertAdjacentHTML(where, html)

parses the specified text as HTML and inserts the resulting nodes into the DOM tree at a specified position.

### HTMLElement#firstChild

Get first child node
Expand Down
49 changes: 38 additions & 11 deletions src/nodes/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export interface RawAttributes {
[key: string]: string;
}

export type InsertPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend';

const kBlockElements = {
div: true,
p: true,
Expand Down Expand Up @@ -57,7 +59,7 @@ export default class HTMLElement extends Node {
*
* @memberof HTMLElement
*/
constructor(public tagName: string, keyAttrs: KeyAttributes, private rawAttrs = '', public parentNode = null as Node) {
public constructor(public tagName: string, keyAttrs: KeyAttributes, private rawAttrs = '', public parentNode = null as Node) {
super();
this.rawAttrs = rawAttrs || '';
this.parentNode = parentNode || null;
Expand Down Expand Up @@ -97,7 +99,7 @@ export default class HTMLElement extends Node {
* Get escpaed (as-it) text value of current node and its children.
* @return {string} text content
*/
get rawText() {
public get rawText() {
return this.childNodes.reduce((pre, cur) => {
return pre += cur.rawText;
}, '');
Expand All @@ -106,14 +108,14 @@ export default class HTMLElement extends Node {
* Get unescaped text value of current node and its children.
* @return {string} text content
*/
get text() {
public get text() {
return decode(this.rawText);
}
/**
* Get structured Text (with '\n' etc.)
* @return {string} structured text
*/
get structuredText() {
public get structuredText() {
let currentBlock = [] as string[];
const blocks = [currentBlock];
function dfs(node: Node) {
Expand Down Expand Up @@ -170,7 +172,7 @@ export default class HTMLElement extends Node {
}
}

get innerHTML() {
public get innerHTML() {
return this.childNodes.map((child) => {
return child.toString();
}).join('');
Expand All @@ -186,7 +188,7 @@ export default class HTMLElement extends Node {
this.childNodes = content;
}

get outerHTML() {
public get outerHTML() {
return this.toString();
}

Expand Down Expand Up @@ -215,7 +217,7 @@ export default class HTMLElement extends Node {
* Get DOM structure
* @return {string} strucutre
*/
get structure() {
public get structure() {
const res = [] as string[];
let indention = 0;
function write(str: string) {
Expand Down Expand Up @@ -383,23 +385,23 @@ export default class HTMLElement extends Node {
* Get first child node
* @return {Node} first child node
*/
get firstChild() {
public get firstChild() {
return this.childNodes[0];
}

/**
* Get last child node
* @return {Node} last child node
*/
get lastChild() {
public get lastChild() {
return arr_back(this.childNodes);
}

/**
* Get attributes
* @return {Object} parsed and unescaped attributes
*/
get attributes() {
public get attributes() {
if (this._attrs) {
return this._attrs;
}
Expand All @@ -416,7 +418,7 @@ export default class HTMLElement extends Node {
* Get escaped (as-it) attributes
* @return {Object} parsed attributes
*/
get rawAttributes() {
public get rawAttributes() {
if (this._rawAttrs)
return this._rawAttrs;
const attrs = {} as RawAttributes;
Expand Down Expand Up @@ -510,4 +512,29 @@ export default class HTMLElement extends Node {
}
}).join(' ');
}

public insertAdjacentHTML(where: InsertPosition, html: string) {
if (arguments.length < 2) {
throw new Error('2 arguments required');
}
const p = parse(html) as HTMLElement;
if (where === 'afterend') {
p.childNodes.forEach((n) => {
(this.parentNode as HTMLElement).appendChild(n);
});
} else if (where === 'afterbegin') {
this.childNodes.unshift(...p.childNodes);
} else if (where === 'beforeend') {
p.childNodes.forEach((n) => {
this.appendChild(n);
});
} else if (where === 'beforebegin') {
(this.parentNode as HTMLElement).childNodes.unshift(...p.childNodes);
} else {
throw new Error(`The value provided ('${where}') is not one of 'beforebegin', 'afterbegin', 'beforeend', or 'afterend'`);
}
if (!where || html === undefined || html === null) {
return;
}
}
}
52 changes: 47 additions & 5 deletions test/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -416,11 +416,13 @@ describe('HTML Parser', function () {
});

describe('#hasAttribute', function () {
var root = parseHTML('<input required>');
var input = root.firstChild;
input.hasAttribute('required').should.eql(true);
input.removeAttribute('required');
input.hasAttribute('required').should.eql(false);
it('should return true or false when has or has not some attribute', function () {
var root = parseHTML('<input required>');
var input = root.firstChild;
input.hasAttribute('required').should.eql(true);
input.removeAttribute('required');
input.hasAttribute('required').should.eql(false);
});
});

describe('#querySelector()', function () {
Expand Down Expand Up @@ -514,6 +516,46 @@ describe('HTML Parser', function () {
root.firstChild.rawAttributes.alt.should.eql('&laquo;Sogno');
});
});

describe('#insertAdjacentHTML() should parse and insert childrens', function () {
it('shoud insert children after current node', function () {
const html = '<a><b></b></a>';
const root = parseHTML(html);
const a = root.firstChild;
const b = a.firstChild;
b.insertAdjacentHTML('afterend', '<c><d></d></c>');
a.toString().should.eql('<a><b></b><c><d></d></c></a>');
});

it('shoud insert children before current node', function () {
const html = '<a><b></b></a>';
const root = parseHTML(html);
const a = root.firstChild;
const b = a.firstChild;
b.insertAdjacentHTML('beforebegin', '<c></c>');
a.toString().should.eql('<a><c></c><b></b></a>');
});

it('shoud append children in current node', function () {
const html = '<a></a>';
const root = parseHTML(html);
const a = root.firstChild;
a.insertAdjacentHTML('beforeend', '<b></b>');
a.toString().should.eql('<a><b></b></a>');
a.insertAdjacentHTML('beforeend', '<c></c>');
a.toString().should.eql('<a><b></b><c></c></a>');
});

it('shoud insert children at position 0', function () {
const html = '<a></a>';
const root = parseHTML(html);
const a = root.firstChild;
a.insertAdjacentHTML('afterbegin', '<b></b>');
a.toString().should.eql('<a><b></b></a>');
a.insertAdjacentHTML('afterbegin', '<c></c>');
a.toString().should.eql('<a><c></c><b></b></a>');
});
});
});

describe('stringify', function () {
Expand Down

0 comments on commit a72c0da

Please sign in to comment.