Browse Source

Initial implementation

tags/v0.1.0
Gerben 6 years ago
parent
commit
1027c9e883
5 changed files with 187 additions and 0 deletions
  1. +2
    -0
      .gitignore
  2. +28
    -0
      Readme.md
  3. +39
    -0
      package.json
  4. +29
    -0
      src/index.js
  5. +89
    -0
      test/index.js

+ 2
- 0
.gitignore View File

@@ -0,0 +1,2 @@
node_modules
/lib

+ 28
- 0
Readme.md View File

@@ -0,0 +1,28 @@
# document-outerhtml

Like [Element.outerHTML][], but for the whole [Document][].

This means it returns a string containing the `<html>.....</html>` with all the content between, plus the `<!DOCTYPE ....>` declaration (if present), and any comments and stray elements or text nodes.

# Install

npm install document-outerhtml

# Usage

import documentOuterHTML from 'document-outerhtml'

const html = documentOuterHTML(document)

# Licence

[CC0](https://creativecommons.org/publicdomain/zero/1.0/); do whatever you want with this code.

# See also

- [XMLSerializer.serializeToString][]; does nearly the same thing, except it creates XML.


[Element.outerHTML]: https://developer.mozilla.org/en-US/docs/Web/API/Element/outerHTML
[Document]: https://developer.mozilla.org/en-US/docs/Web/API/Document
[XMLSerializer.serializeToString]: https://developer.mozilla.org/en-US/docs/Web/API/XMLSerializer/serializeToString

+ 39
- 0
package.json View File

@@ -0,0 +1,39 @@
{
"name": "document-outerhtml",
"version": "0.0.0",
"description": "Like Element.outerHTML, but for the whole Document.",
"keywords": [
"dom"
],
"main": "lib",
"scripts": {
"build": "babel -d lib src",
"prepublish": "npm run build",
"test": "ava"
},
"author": "Gerben <gerben@treora.com>",
"license": "CC0-1.0",
"files": [
"lib"
],
"devDependencies": {
"ava": "^1.0.0-beta.3",
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1",
"babel-register": "^6.26.0",
"window": "^4.2.5"
},
"babel": {
"presets": [
"env"
]
},
"ava": {
"require": [
"babel-register"
]
},
"dependencies": {
"doctype-to-string": "^0.1.1"
}
}

+ 29
- 0
src/index.js View File

@@ -0,0 +1,29 @@
import doctypeToString from 'doctype-to-string'

export default function documentOuterHTML(document) {
if (!document
|| document.nodeType === undefined
|| document.nodeType !== document.DOCUMENT_NODE
) {
throw new TypeError('Expected a Document')
}
const html = [...document.childNodes]
.map(node => nodeToString(node))
.join('\n')
return html
}

function nodeToString(node) {
switch (node.nodeType) {
case node.ELEMENT_NODE:
return node.outerHTML
case node.TEXT_NODE:
return node.textContent
case node.COMMENT_NODE:
return `<!--${node.textContent}-->`
case node.DOCUMENT_TYPE_NODE:
return doctypeToString(node)
default:
throw new TypeError(`Unexpected node type: ${node.nodeType}`)
}
}

+ 89
- 0
test/index.js View File

@@ -0,0 +1,89 @@
import test from 'ava'
import Window from 'window';

import documentOuterHTML from '../src'

function makeDocument(html) {
const window = new Window()
const parser = new window.DOMParser()
const doc = parser.parseFromString(
html,
'text/html'
)
return doc
}

function normalise(html) {
// Remove whitespace around string and between tags.
return html.trim().replace(/>\s+</g, '><')
}

test('should work with only an html node', t => {
const html = `
<html>
<head></head>
<body><p>blub.</p></body>
</html>
`
const doc = makeDocument(html)
t.is(
normalise(documentOuterHTML(doc)),
normalise(html)
)
})

test('should work with comments', t => {
const html = `
<!-- comment before -->
<html>
<head></head>
<body><p>blub.</p></body>
</html>
<!-- comment after -->
`
const doc = makeDocument(html)
t.is(
normalise(documentOuterHTML(doc)),
normalise(html)
)
})

test('should work with doctype', t => {
const html = `
<!DOCTYPE html>
<html>
<head></head>
<body><p>blub.</p></body>
</html>
`
const doc = makeDocument(html)
t.is(
normalise(documentOuterHTML(doc)),
normalise(html)
)
})

test('should work without a documentElement', t => {
const html = `
<!DOCTYPE html>
<!-- some comment -->
`
const doc = makeDocument(html)
// The html (+head&body) element will have been created automatically. Remove it.
doc.removeChild(doc.documentElement)
t.is(
normalise(documentOuterHTML(doc)),
normalise(html)
)
})

test('should even work on a completely empty document', t => {
const html = ``
const doc = makeDocument(html)
// The html (+head&body) element will have been created automatically. Remove it.
doc.removeChild(doc.documentElement)
t.is(
normalise(documentOuterHTML(doc)),
normalise(html)
)
})

Loading…
Cancel
Save