Skip to content

Commit

Permalink
Merge 3ccd25f into f7abd01
Browse files Browse the repository at this point in the history
  • Loading branch information
mchalapuk committed Jul 5, 2016
2 parents f7abd01 + 3ccd25f commit eec27ea
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 12 deletions.
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@ Using npm:

## Usage

The module provides functions for describing and locating a DOM Node using
an XPath expression.
The module provides functions for describing and locating a DOM Node using an
XPath expression. It can be used in web browsers via [browserify][browserify]
and on node when using JavaScript DOM implementation like [jsdom][jsdom].

[browserify]: https://github.com/substack/node-browserify
[jsdom]: https://github.com/tmpvar/jsdom

The presence of a working XPath evaluator is not strictly required. Without it,
the library will only support XPath expressions that use a child axis and
Expand Down Expand Up @@ -69,6 +73,10 @@ including any necessary test and documentation updates.

You can run the command-line test suite by executing `npm test`.

To run the test suite, install the karma test runner with the command
`npm install -g karma-cli` and then run `karma start`. Karma will print
instructions for debugging the tests in a browser.
To run the test suite in a browser, install the karma test runner with the
command `npm install -g karma-cli` and then run `karma start`. Karma will print
instructions for debugging the tests.

To run tests on node, install mocha test runner with command `npm install -g
mocha-cli` and then run `mocha --require "babel-core/register" nodetest/*`.

23 changes: 23 additions & 0 deletions nodetest/xpath_node_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { jsdom } from 'jsdom'
import { assert } from 'assertive-chai'
import * as xpath from '../src/xpath'

describe('xpath in nodejs environment', () => {
let doc = jsdom('<body><div></div><body>')

describe('#fromNode', () => {
it("generetes an XPath expression from element in the document", () => {
assert.equal('/html[1]/body[1]/div[1]', xpath.fromNode(doc.body.firstChild, doc))
})
it('raises InvalidNodeTypeError if root doesn\'t contain node', () => {
assert.throws(() => xpath.fromNode(doc.body, doc.body.firstChild))
})
})

describe('#toNode', () => {
it("parses a standard xpath string", () => {
assert.strictEqual(doc.body.firstChild, xpath.toNode('/html[1]/body[1]/div[1]', doc))
})
})
})

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Create and evaluate simple XPath position expressions.",
"main": "index.js",
"scripts": {
"test": "eslint src && karma start --single-run",
"test": "eslint src && karma start --single-run && mocha --require babel-core/register nodetest/*",
"prepublish": "babel --source-maps inline src --out-dir lib --loose all"
},
"repository": {
Expand Down Expand Up @@ -32,6 +32,7 @@
"browserify-istanbul": "^0.2.1",
"eslint": "^1.6.0",
"isparta": "^3.1.0",
"jsdom": "^9.4.0",
"karma": "^0.13.10",
"karma-browserify": "^4.4.0",
"karma-chai": "^0.1.0",
Expand Down
16 changes: 10 additions & 6 deletions src/xpath.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ const FIRST_ORDERED_NODE_TYPE = 9
// Default namespace for XHTML documents
const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'

/**
* Document object that will be used as default root.
*/
export let globalDocument = typeof window !== 'undefined'? window.document: null;

/**
* Compute an XPath expression for the given node.
Expand All @@ -19,7 +23,7 @@ const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml'
* @param {Node} [root] The root context for the XPath expression.
* @returns {string}
*/
export function fromNode(node, root = document) {
export function fromNode(node, root = globalDocument) {
let path = '/'
while (node !== root) {
if (!node) {
Expand Down Expand Up @@ -47,18 +51,18 @@ export function fromNode(node, root = document) {
* @param {Node} [root] The root context for the XPath expression.
* @returns {Node|null} The first matching Node or null if none is found.
*/
export function toNode(path, root = document, resolver = null) {
export function toNode(path, root = globalDocument, resolver = null) {
// Check for resolver but no root argument.
if (typeof(root) === 'function') {
resolver = root
root = document
root = globalDocument
}

// Make the path relative to the root, if not the document.
if (root !== document) path = path.replace(/^\//, './')
if (root !== globalDocument) path = path.replace(/^\//, './')

// Make a default resolver.
if (resolver === null && document.lookupNamespaceURI) {
if (resolver === null && globalDocument && globalDocument.lookupNamespaceURI) {
let documentElement = getDocument(root).documentElement
let defaultNS = documentElement.lookupNamespaceURI(null) || HTML_NAMESPACE
resolver = (prefix) => {
Expand Down Expand Up @@ -124,7 +128,7 @@ function fallbackResolve(path, root) {

// Find a single node with XPath `path` using `document.evaluate`.
function platformResolve(path, root, resolver) {
let r = document.evaluate(path, root, resolver, FIRST_ORDERED_NODE_TYPE, null)
let r = globalDocument.evaluate(path, root, resolver, FIRST_ORDERED_NODE_TYPE, null)
return r.singleNodeValue
}

Expand Down

0 comments on commit eec27ea

Please sign in to comment.