Skip to content
This repository has been archived by the owner on Jun 1, 2020. It is now read-only.

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
yuheiy committed Sep 11, 2017
0 parents commit c37c179
Show file tree
Hide file tree
Showing 9 changed files with 3,307 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
lib
40 changes: 40 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# ChildNode ponyfill

[`ChildNode`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode) ponyfill.

## Install

```bash
npm i @yuheiy/childnode-ponyfill
```

## Usage

```javascript
import {replaceWith} from '@yuheiy/childnode-ponyfill'
const oldElement = document.getElementById('#old')
const newElement = document.createElement('div')
replaceWith(oldElement, newElement)
```

## API

### before(childNode, ...nodes)

Same API with [`ChildNode.before()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/before)

### after(childNode, ...nodes)

Same API with [`ChildNode.after()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/after)

### replaceWith(childNode, ...nodes)

Same API with [`ChildNode.replaceWith()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith)

### remove(childNode)

Same API with [`ChildNode.remove()`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/remove)

## License

MIT
40 changes: 40 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@yuheiy/childnode-ponyfill",
"description": "ChildNode ponyfill.",
"author": "Yuhei Yasuda <yuhei.yasuda1003@gmail.com>",
"license": "MIT",
"homepage": "https://github.com/yuheiy/childnode-ponyfill",
"repository": {
"type": "git",
"url": "git+https://github.com/yuheiy/childnode-ponyfill.git"
},
"bugs": {
"url": "https://github.com/yuheiy/childnode-ponyfill/issues"
},
"version": "0.0.1",
"main": "lib/childnode-ponyfill.js",
"types": "lib/childnode-ponyfill.d.ts",
"files": [
"lib/",
"src/"
],
"scripts": {
"test": "npm run build && ava",
"build": "NODE_ENV=production tsc -p .",
"watch": "tsc -p . --watch",
"prepublish": "npm run build"
},
"devDependencies": {
"ava": "^0.22.0",
"browser-env": "^3.2.0",
"typescript": "^2.5.2"
},
"publishConfig": {
"access": "public"
},
"ava": {
"require": [
"./test/helpers/setup-browser-env.js"
]
}
}
61 changes: 61 additions & 0 deletions src/childnode-ponyfill.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
type ImplementsOfChildNode = Element | DocumentType | CharacterData
type nodes = Array<string | Node>

const find = <T>(arr: Array<T>, predicate: (item: T, idx: number, arr: Array<T>) => boolean): T | void => {
for (let i = 0; i < arr.length; i++) {
if (predicate(arr[i], i, arr)) {
return arr[i]
}
}
}

const makePonyfill = (methodName: string, method: (childNode: ImplementsOfChildNode, ...nodes: nodes) => void) => {
return (childNode: ImplementsOfChildNode, ...nodes: nodes): void => {
const Implement = find([Element, DocumentType, CharacterData], (Impl) => childNode instanceof Impl)
if (!Implement) {
throw new TypeError('childNode must be Element, DocumentType or CharacterData')
}
if (typeof (Implement as any).prototype[methodName] === 'function') {
return (childNode as any)[methodName](...nodes)
}
return method(childNode, ...nodes)
}
}

const createDocumentFragmentFromNodes = (...nodes: /*nodes*/Array<any>): DocumentFragment => {
return nodes.reduce((frag, node) => {
if (typeof node === 'string') {
const parser = document.createElement('div')
parser.innerHTML = node
while (parser.firstChild) {
frag.appendChild(parser.firstChild)
}
} else {
frag.appendChild(node)
}
return frag
}, document.createDocumentFragment())
}

export const before = makePonyfill('before', (childNode: ImplementsOfChildNode, ...nodes: nodes) => {
const frag = createDocumentFragmentFromNodes(...nodes)
;(childNode as any).parentNode.insertBefore(frag, childNode)
})

export const after = makePonyfill('after', (childNode: ImplementsOfChildNode, ...nodes: nodes) => {
const frag = createDocumentFragmentFromNodes(...nodes)
;(childNode as any).parentNode.insertBefore(frag, childNode.nextSibling)
})

export const replaceWith = makePonyfill('replaceWith', (childNode: ImplementsOfChildNode, ...nodes: nodes) => {
if (childNode.parentNode) {
const frag = createDocumentFragmentFromNodes(...nodes)
childNode.parentNode.replaceChild(frag, childNode)
}
})

export const remove = makePonyfill('remove', (childNode: ImplementsOfChildNode) => {
if (childNode.parentNode) {
childNode.parentNode.removeChild(childNode)
}
})
38 changes: 38 additions & 0 deletions test/childnode-ponyfill.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import test from 'ava'
import {before, after, replaceWith, remove} from '../lib/childnode-ponyfill'

test.beforeEach(t => {
document.body.innerHTML = ''
})

test('before', t => {
document.body.innerHTML = 'preset'
const target = document.createElement('div')
target.id = 'target'
document.body.appendChild(target)
before(target, 'prepend1', '<span>prepend2</span>', document.createElement('p'))
t.is(document.body.innerHTML, 'presetprepend1<span>prepend2</span><p></p><div id="target"></div>')
})

test('after', t => {
document.body.innerHTML = 'preset'
const target = document.createElement('div')
target.id = 'target'
document.body.insertBefore(target, document.body.firstChild)
after(target, '<span>after</span>')
t.is(document.body.innerHTML, '<div id="target"></div><span>after</span>preset')
})

test('replaceWith', t => {
const div = document.createElement('div')
document.body.appendChild(div)
replaceWith(div, 'header', '<span>body</span>', 'footer')
t.is(document.body.innerHTML, 'header<span>body</span>footer')
})

test('remove', t => {
const div = document.createElement('div')
document.body.appendChild(div)
remove(div)
t.is(document.body.innerHTML, '')
})
3 changes: 3 additions & 0 deletions test/helpers/setup-browser-env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// https://github.com/avajs/ava/issues/1506
const browserEnv = require('browser-env')
browserEnv(['document', 'Element', 'DocumentType', 'CharacterData'])
34 changes: 34 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"compilerOptions": {
/* Basic Options */
"target": "es5",
"module": "commonjs",
"lib": [
"dom",
"es2015",
"es2016",
"es2017"
],
"jsx": "preserve",
"declaration": true,
"sourceMap": true,
"outDir": "./lib/",
"rootDir": "./src/",
/* Strict Type-Checking Options */
"strict": true,
/* Additional Checks */
"noUnusedLocals": true,
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
/* Module Resolution Options */
"moduleResolution": "node",
},
"include": [
"src/**/*",
],
"exclude": [
"node_modules",
"test",
]
}
15 changes: 15 additions & 0 deletions tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": false,
"outDir": "./test/",
"rootDir": "./test/",
},
"include": [
"test/**/*",
],
"exclude": [
"node_modules",
"src",
],
}
Loading

0 comments on commit c37c179

Please sign in to comment.