Current Dev State

This commit is contained in:
Tim Lorsbach
2025-06-23 20:13:54 +02:00
parent b4f9bb277d
commit ded50edaa2
22617 changed files with 4345095 additions and 174 deletions

130
static/js/ketcher2/node_modules/xpath/README.md generated vendored Normal file
View File

@ -0,0 +1,130 @@
## xpath
DOM 3 XPath 1.0 implemention and helper for JavaScript, with node.js support.
Originally written by Cameron McCormack ([blog](http://mcc.id.au/xpathjs)).
Additional contributions from
Yaron Naveh ([blog](http://webservices20.blogspot.com/))
goto100
Thomas Weinert
Jimmy Rishe
and [others](https://github.com/goto100/xpath/graphs/contributors)
## Install
Install with [npm](http://github.com/isaacs/npm):
npm install xpath
xpath is xml engine agnostic but I recommend to use [xmldom](https://github.com/jindw/xmldom):
npm install xmldom
## API Documentation
Can be found [here](https://github.com/goto100/xpath/blob/master/docs/xpath%20methods.md). See below for example usage.
## Your first xpath:
`````javascript
var xpath = require('xpath')
, dom = require('xmldom').DOMParser
var xml = "<book><title>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var nodes = xpath.select("//title", doc)
console.log(nodes[0].localName + ": " + nodes[0].firstChild.data)
console.log("Node: " + nodes[0].toString())
`````
title: Harry Potter
Node: <title>Harry Potter</title>
### Alternatively
Using the same interface you have on modern browsers ([MDN])
`````javascript
var node = null;
var xml = "<book author='J. K. Rowling'><title>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var result = xpath.evaluate(
"/book/title", // xpathExpression
doc, // contextNode
null, // namespaceResolver
xpath.XPathResult.ANY_TYPE, // resultType
null // result
)
node = result.iterateNext();
while (node) {
console.log(node.localName + ": " + node.firstChild.data);
console.log("Node: " + node.toString());
node = result.iterateNext();
}
`````
title: Harry Potter
Node: <title>Harry Potter</title>
## Evaluate string values directly:
`````javascript
var xml = "<book><title>Harry Potter</title></book>";
var doc = new dom().parseFromString(xml);
var title = xpath.select("string(//title)", doc);
console.log(title);
`````
Harry Potter
## Namespaces
`````javascript
var xml = "<book><title xmlns='myns'>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var node = xpath.select("//*[local-name(.)='title' and namespace-uri(.)='myns']", doc)[0]
console.log(node.namespaceURI)
`````
myns
## Namespaces with easy mappings
`````javascript
var xml = "<book xmlns:bookml='http://example.com/book'><bookml:title>Harry Potter</bookml:title></book>"
var select = xpath.useNamespaces({"bookml": "http://example.com/book"});
console.log(select('//bookml:title/text()', doc)[0].nodeValue);
`````
Harry Potter
## Default namespace with mapping
`````javascript
var xml = "<book xmlns='http://example.com/book'><title>Harry Potter</title></book>"
var select = xpath.useNamespaces({"bookml": "http://example.com/book"});
console.log(select('//bookml:title/text()', doc)[0].nodeValue);
`````
Harry Potter
## Attributes
`````javascript
var xml = "<book author='J. K. Rowling'><title>Harry Potter</title></book>"
var doc = new dom().parseFromString(xml)
var author = xpath.select1("/book/@author", doc).value
console.log(author)
`````
J. K. Rowling
[MDN]: https://developer.mozilla.org/en/docs/Web/API/Document/evaluate

View File

@ -0,0 +1,68 @@
# `XPathEvaluator`
The `xpath.parse()` method returns an `XPathEvaluator`, which contains the following methods.
Each of these methods takes an optional `options` object, which can contain any of the following properties:
`namespaces` - a namespace resolver. See the [documentation page](namespace resolvers.md) for details.
`variables` - a variable resolver. See the [documentation page](variable resolvers.md) for details.
`functions` - a function resolver. See the [documentation page](function resolvers.md) for details.
`node` - the context node for evaluating the expression
Example usage:
```js
var evaluator = xpath.parse('/characters/character[@greeting = $greeting]');
var character = evaluator.select1({
node: myCharacterDoc,
variables: {
greeting: 'Hello, I'm Harry, Harry Potter.`
}
});
```
## `XPathEvaluator` methods
`evaluate([options])`
Evaluates the XPath expression and returns the result. The resulting type is determined based on the type of the expression, using the same criteria as [`xpath.select`](xpath methods.md).
`evaluateNumber([options])`
Evaluates the XPath expression and returns the result as a number.
`evaluateString([options])`
Evaluates the XPath expression and returns the result as a string.
`evaluateBoolean([options])`
Evaluates the XPath expression and returns the result as a boolean value.
`evaluateNodeSet([options])`
Evaluates the XPath expression and returns the result as an XNodeSet. See the [documentation page](#) for details on this interface.
This is only valid for expressions that evaluate to a node set.
`select([options])`
Evaluates the XPath expression and returns an array of the resulting nodes, in document order.
This is only valid for expressions that evaluate to a node set.
`select([options])`
Evaluates the XPath expression and returns an array of the resulting nodes, in document order.
This is only valid for expressions that evaluate to a node set.
`select1([options])`
Evaluates the XPath expression and the first node in the resulting node set, in document order. Returns `undefined`
This is only valid for expressions that evaluate to a node set.

View File

@ -0,0 +1,47 @@
# XPathResult interface
Represents the result of an XPath expression. This interface is used for the parameters passed into custom functions
used in [function resolvers](function resolvers.md) and can represent a number, a string, a boolean value, or a node set.
## Methods
```js
booleanValue() -> boolean
```
Returns the boolean value of the result in accordance with the XPath 1.0 spec.
```js
numberValue() -> number
```
Returns the numeric value of the result in accordance with the XPath 1.0 spec.
```js
stringValue() -> string
```
Returns the string value of the result in accordance with the XPath 1.0 spec.
## Methods and properties that are only present on `XPathResult`s representing node sets
```js
toArray() -> Array of nodes
```
Returns an array of the nodes in the node set, in document order.
```js
first() -> Node
```
Returns the first node in the node set, in document order.
```js
size -> number
```
Returns the number of nodes in this node set

View File

@ -0,0 +1,88 @@
# Function Resolvers
The methods on the [XPathEvaluator](XPathEvaluator.md) type can optionally take a function resolver to resolve
function references in the XPath expression being evaluated.
There are three ways to specify a function resolver and you can use any one of them depending on which is
most suited to your particular situation.
Note that if your functions are in a namespace (e.g. `fn:myFunction()`), you must use the second or third
type as the plain object implementation does not support namespaces.
## Function implementations
Custom XPath functions are implemented as JavaScript functions taking one or more arguments.
The first argument passed in is a context object containing a number of properties relating to the execution context,
the most important being `contextNode`, the context in which the function is being evaluated.
The remaining arguments are the arguments passed into the XPath function, as instances of the `XPathResult` interface.
Please see [the documentation on that interface](XPathResult.md) for details.
As the return value, you can return a string, number, boolean, single node, or array of nodes.
## Function Resolver Type 1: Plain object
A plain object with function names as the keys and function implementations as the values.
Example usage:
```js
var evaluator = xpath.parse('squareRoot(10)');
var aboutPi = evaluator.evaluateNumber({
functions: {
'squareRoot': function (c, value) {
return Math.sqrt(value.numberValue());
}
}
});
```
## Function Resolver Type 2: Function
A function that takes a function name as its first parameter and an optional namespace URI as its second parameter
and returns a function based on the name and namespace.
Example usage:
```js
var evaluator = xpath.parse('math:squareRoot(10)');
var aboutPi = evaluator.evaluateNumber({
functions: function (name, namespace) {
if (name === 'squareRoot' && namespace === 'http://sample.org/math/') {
return function (c, value) {
return Math.sqrt(value.numberValue());
};
}
},
namespaces: {
math: 'http://sample.org/math/'
}
});
```
## Function Resolver Type 3: Object with `getFunction` method
An object with a method named `getFunction` that works in the same way as the function-based function resolver
described above.
Example usage:
```js
var evaluator = xpath.parse('math:squareRoot(10)');
var aboutPi = evaluator.evaluateNumber({
functions: {
getFunction: function (name, namespace) {
if (name === 'squareRoot' && namespace === 'http://sample.org/math/') {
return function (c, value) {
return Math.sqrt(value.numberValue());
};
}
}
},
namespaces: {
math: 'http://sample.org/math/'
}
});
```

View File

@ -0,0 +1,69 @@
# Namespace Resolvers
The methods on the [XPathEvaluator](XPathEvaluator.md) type can optionally take a namespace resolver to resolve
namespace references in the XPath expression being evaluated.
There are three ways to specify a namespace resolver and you can use any one of them depending on which is
most suited to your particular situation.
## Namespace Resolver Type 1: Plain object
A plain object with namespace prefixes as the keys and namespace URIs as the values:
Example usage:
```js
var evaluator = xpath.parse('/bk:book/hp:characters');
var characters = evaluator.select({
node: myBookNode,
namespaces: {
'bk': 'http://sample.org/books/',
'hp': 'http://sample.org/harrypotter/'
}
});
```
## Namespace Resolver Type 2: Function
A function that takes a namespace prefix as a parameter and returns the corresponding namespace URI.
Example usage:
```js
var evaluator = xpath.parse('/bk:book/hp:characters');
var characters = evaluator.select({
node: myBookNode,
namespaces: function (prefix) {
if (prefix === 'bk') {
return 'http://sample.org/books/';
}
if (prefix === 'hp') {
return 'http://sample.org/books/';
}
}
});
```
## Namespace Resolver Type 3: Object with `getNamespace` method
An object with a method named `getNamespace` that works in the same way as the function-based namespace resolver
described above.
Example usage:
```js
var evaluator = xpath.parse('/bk:book/hp:characters');
var characters = evaluator.select({
node: myBookNode,
namespaces: {
getNamespace: function (prefix) {
if (prefix === 'bk') {
return 'http://sample.org/books/';
}
if (prefix === 'hp') {
return 'http://sample.org/books/';
}
}
}
});
```

View File

@ -0,0 +1,21 @@
# Using Parsed Expressions
The `xpath.parse()` method allows pre-parsing an XPath expression and creating an XPath executor to evaluate the XPath as many times as needed.
This can provide a performance benefit if you plan to evaluate the same XPath multiple times because the expression only needs to be parsed once.
This also provides access to additional features such as the use of variables and custom XPath functinos, which are not available using the evaluation methods on the `xpath` object.
#### xpath.parse(expression)
Parses the specified XPath expression and returns an `XPathEvaluator`. See the [documentation page](XPathEvaluator.md) for API details.
`expression` should be a string.
Example usage:
```js
var evaluator = xpath.parse('/book/characters');
```

View File

@ -0,0 +1,89 @@
# Variable Resolvers
The methods on the [XPathEvaluator](#) type can optionally take a variable resolver to resolve
variable references in the XPath expression being evaluated.
There are three ways to specify a variable resolver and you can use any one of them depending on which is
most suited to your particular situation.
Note that if your variables are in a namespace (e.g. `$myVars:var`), you must use the second or third
type as the plain object implementation does not support namespaces.
## Variable values
You can use any of five types of values to specify the values of variables:
- string
- number
- boolean
- single node (will be treated as a node set)
- array of nodes or array-like collection of nodes (will be treated as a node set)
## Variable Resolver Type 1: Plain object
A plain object with variable names as the keys and variable values as the values.
Example usage:
````
var evaluator = xpath.parse('concat($character1, ", ", $character2, ", and ", $character3)');
var mainCharacters = evaluator.evaluateString({
variables: {
character1: 'Harry',
character2: 'Ron',
character3: 'Hermione'
}
});
````
## Variable Resolver Type 2: Function
A function that takes a variable name as its first parameter and an optional namespace URI as its second parameter
and returns a value based on the name and namespace.
Example usage:
````
var evaluator = xpath.parse('concat($hp:character1, ", ", $hp:character2, ", and ", $hp:character3)');
var mainCharacters = evaluator.evaluateString({
variables: function (name, namespace) {
if (namespace === 'http://sample.org/harrypotter/') {
switch (name) {
case 'character1': return 'Harry';
case 'character2': return 'Ron';
case 'character3': return 'Hermione';
}
}
},
namespaces: {
hp: 'http://sample.org/harrypotter/'
}
});
````
## Function Resolver Type 3: Object with `getFunction` method
An object with a method named `getVariable` that works in the same way as the function-based variable resolver
described above.
Example usage:
````
var evaluator = xpath.parse('concat($hp:character1, ", ", $hp:character2, ", and ", $hp:character3)');
var mainCharacters = evaluator.evaluateString({
variables: {
getVariable: function (name, namespace) {
if (namespace === 'http://sample.org/harrypotter/') {
switch (name) {
case 'character1': return 'Harry';
case 'character2': return 'Ron';
case 'character3': return 'Hermione';
}
}
}
},
namespaces: {
hp: 'http://sample.org/harrypotter/'
}
});
````

View File

@ -0,0 +1,39 @@
#xpath methods
This page details the methods exposed on the `xpath` object.
### `xpath.select(expression[, node[, single]])`
Evaluates an XPath expression and returns the result. The return value is determined based on the result type of the expression (which can always be predicted ahead of time):
- A boolean value if the expression evaluates to a boolean value.
- A number if the expression evaluates to a numeric value.
- A string if the expression evaluates to a string.
- If the expression evaluates to a nodeset:
- An array of nodes if `single` is unspecified or falsy
- A single node (the first node in document order) or `undefined` if `single` is truthy
`node` is optional and if specified, is used as the context node for evaluating the expression. (It is necessary if the expression includes any node tests.)
`single` is optional and is ignored if the expression evaluates to anything other than a nodeset.
### `xpath.useNamespaces(mappings)`
Produces a function with the signature `func(expression, node)` that evaluates the provided xpath expression with the XML namespace definitions provided in `mapppings`.
`mappings` should be an object with namespace prefixes as its property names and namespace URIs as its property values.
Example usage:
```js
var expr = xpath.useNamespaces({ hp: 'http://www.example.com/harryPotter', bk: 'http://www.example.com/books' });
var result = expr('/bk:books/bk:book[@name = "Harry Potter and the Half-Blood Prince"]/hp:characters', myBooks);
```
### `xpath.select1(expression[, node])`
Alias for [`xpath.select(expression, node, true)`](#xpathselectexpression-node-single). Selects a single node or value.
### `xpath.parse(expression)`
Creates a parsed expression. See the [documentation page](parsed expressions.md) for details.

67
static/js/ketcher2/node_modules/xpath/package.json generated vendored Normal file
View File

@ -0,0 +1,67 @@
{
"_from": "xpath@0.0.24",
"_id": "xpath@0.0.24",
"_inBundle": false,
"_integrity": "sha1-Gt4WLhzFI8jTn8fQavwW6iFvKfs=",
"_location": "/xpath",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "xpath@0.0.24",
"name": "xpath",
"escapedName": "xpath",
"rawSpec": "0.0.24",
"saveSpec": null,
"fetchSpec": "0.0.24"
},
"_requiredBy": [
"#DEV:/"
],
"_resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.24.tgz",
"_shasum": "1ade162e1cc523c8d39fc7d06afc16ea216f29fb",
"_spec": "xpath@0.0.24",
"_where": "/home/manfred/enviPath/ketcher2/ketcher",
"author": {
"name": "Cameron McCormac"
},
"bugs": {
"url": "https://github.com/goto100/xpath/issues"
},
"bundleDependencies": false,
"contributors": [
{
"name": "goto100"
},
{
"name": "James Rishe"
}
],
"dependencies": {},
"deprecated": false,
"description": "DOM 3 XPath implemention and helper for node.js.",
"devDependencies": {
"nodeunit": ">=0.6.4",
"xmldom": "^0.1.19"
},
"engines": {
"node": ">=0.6.0"
},
"homepage": "https://github.com/goto100/xpath#readme",
"keywords": [
"xpath",
"xml"
],
"license": "CC-BY-SA-2.0",
"main": "./xpath.js",
"name": "xpath",
"repository": {
"type": "git",
"url": "git+https://github.com/goto100/xpath.git"
},
"scripts": {
"test": "nodeunit test.js"
},
"typings": "./xpath.d.ts",
"version": "0.0.24"
}

855
static/js/ketcher2/node_modules/xpath/test.js generated vendored Normal file
View File

@ -0,0 +1,855 @@
var xpath = require('./xpath.js')
, dom = require('xmldom').DOMParser
, assert = require('assert');
module.exports = {
'api': function(test) {
assert.ok(xpath.evaluate, 'evaluate api ok.');
assert.ok(xpath.select, 'select api ok.');
assert.ok(xpath.parse, 'parse api ok.');
test.done();
},
'evaluate': function(test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var nodes = xpath.evaluate('//title', doc, null, xpath.XPathResult.ANY_TYPE, null).nodes;
assert.equal('title', nodes[0].localName);
assert.equal('Harry Potter', nodes[0].firstChild.data);
assert.equal('<title>Harry Potter</title>', nodes[0].toString());
test.done();
},
'select': function(test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var nodes = xpath.select('//title', doc);
assert.equal('title', nodes[0].localName);
assert.equal('Harry Potter', nodes[0].firstChild.data);
assert.equal('<title>Harry Potter</title>', nodes[0].toString());
test.done();
},
'select single node': function(test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
assert.equal('title', xpath.select('//title[1]', doc)[0].localName);
test.done();
},
'select text node': function (test) {
var xml = '<book><title>Harry</title><title>Potter</title></book>';
var doc = new dom().parseFromString(xml);
assert.deepEqual('book', xpath.select('local-name(/book)', doc));
assert.deepEqual('Harry,Potter', xpath.select('//title/text()', doc).toString());
test.done();
},
'select number node': function(test) {
var xml = '<book><title>Harry</title><title>Potter</title></book>';
var doc = new dom().parseFromString(xml);
assert.deepEqual(2, xpath.select('count(//title)', doc));
test.done();
},
'select xpath with namespaces': function (test) {
var xml = '<book><title xmlns="myns">Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var nodes = xpath.select('//*[local-name(.)="title" and namespace-uri(.)="myns"]', doc);
assert.equal('title', nodes[0].localName);
assert.equal('myns', nodes[0].namespaceURI) ;
test.done();
},
'select xpath with namespaces, using a resolver': function (test) {
var xml = '<book xmlns:testns="http://example.com/test"><testns:title>Harry Potter</testns:title><testns:field testns:type="author">JKR</testns:field></book>';
var doc = new dom().parseFromString(xml);
var resolver = {
mappings: {
'testns': 'http://example.com/test'
},
lookupNamespaceURI: function(prefix) {
return this.mappings[prefix];
}
}
var nodes = xpath.selectWithResolver('//testns:title/text()', doc, resolver);
assert.equal('Harry Potter', xpath.selectWithResolver('//testns:title/text()', doc, resolver)[0].nodeValue);
assert.equal('JKR', xpath.selectWithResolver('//testns:field[@testns:type="author"]/text()', doc, resolver)[0].nodeValue);
test.done();
},
'select xpath with default namespace, using a resolver': function (test) {
var xml = '<book xmlns="http://example.com/test"><title>Harry Potter</title><field type="author">JKR</field></book>';
var doc = new dom().parseFromString(xml);
var resolver = {
mappings: {
'testns': 'http://example.com/test'
},
lookupNamespaceURI: function(prefix) {
return this.mappings[prefix];
}
}
var nodes = xpath.selectWithResolver('//testns:title/text()', doc, resolver);
assert.equal('Harry Potter', xpath.selectWithResolver('//testns:title/text()', doc, resolver)[0].nodeValue);
assert.equal('JKR', xpath.selectWithResolver('//testns:field[@type="author"]/text()', doc, resolver)[0].nodeValue);
test.done();
},
'select xpath with namespaces, prefixes different in xml and xpath, using a resolver': function (test) {
var xml = '<book xmlns:testns="http://example.com/test"><testns:title>Harry Potter</testns:title><testns:field testns:type="author">JKR</testns:field></book>';
var doc = new dom().parseFromString(xml);
var resolver = {
mappings: {
'ns': 'http://example.com/test'
},
lookupNamespaceURI: function(prefix) {
return this.mappings[prefix];
}
}
var nodes = xpath.selectWithResolver('//ns:title/text()', doc, resolver);
assert.equal('Harry Potter', xpath.selectWithResolver('//ns:title/text()', doc, resolver)[0].nodeValue);
assert.equal('JKR', xpath.selectWithResolver('//ns:field[@ns:type="author"]/text()', doc, resolver)[0].nodeValue);
test.done();
},
'select xpath with namespaces, using namespace mappings': function (test) {
var xml = '<book xmlns:testns="http://example.com/test"><testns:title>Harry Potter</testns:title><testns:field testns:type="author">JKR</testns:field></book>';
var doc = new dom().parseFromString(xml);
var select = xpath.useNamespaces({'testns': 'http://example.com/test'});
assert.equal('Harry Potter', select('//testns:title/text()', doc)[0].nodeValue);
assert.equal('JKR', select('//testns:field[@testns:type="author"]/text()', doc)[0].nodeValue);
test.done();
},
'select attribute': function (test) {
var xml = '<author name="J. K. Rowling"></author>';
var doc = new dom().parseFromString(xml);
var author = xpath.select1('/author/@name', doc).value;
assert.equal('J. K. Rowling', author);
test.done();
}
// https://github.com/goto100/xpath/issues/37
,'select multiple attributes': function (test) {
var xml = '<authors><author name="J. K. Rowling" /><author name="Saeed Akl" /></authors>';
var doc = new dom().parseFromString(xml);
var authors = xpath.select('/authors/author/@name', doc);
assert.equal(2, authors.length);
assert.equal('J. K. Rowling', authors[0].value);
// https://github.com/goto100/xpath/issues/41
doc = new dom().parseFromString('<chapters><chapter v="1"/><chapter v="2"/><chapter v="3"/></chapters>');
var nodes = xpath.select("/chapters/chapter/@v", doc);
var values = nodes.map(function(n) { return n.value; });
assert.equal(3, values.length);
assert.equal("1", values[0]);
assert.equal("2", values[1]);
assert.equal("3", values[2]);
test.done();
}
,'XPathException acts like Error': function (test) {
try {
xpath.evaluate('1', null, null, null);
assert.fail(null, null, 'evaluate() should throw exception');
} catch (e) {
assert.ok('code' in e, 'must have a code');
assert.ok('stack' in e, 'must have a stack');
}
test.done();
},
'string() with no arguments': function (test) {
var doc = new dom().parseFromString('<book>Harry Potter</book>');
var rootElement = xpath.select1('/book', doc);
assert.ok(rootElement, 'rootElement is null');
assert.equal('Harry Potter', xpath.select1('string()', doc));
test.done();
},
'string value of document fragment': function (test) {
var doc = new dom().parseFromString('<n />');
var docFragment = doc.createDocumentFragment();
var el = doc.createElement("book");
docFragment.appendChild(el);
var testValue = "Harry Potter";
el.appendChild(doc.createTextNode(testValue));
assert.equal(testValue, xpath.select1("string()", docFragment));
test.done();
},
'compare string of a number with a number': function (test) {
assert.ok(xpath.select1('"000" = 0'), '000');
assert.ok(xpath.select1('"45.0" = 45'), '45');
test.done();
},
'string(boolean) is a string': function (test) {
assert.equal('string', typeof xpath.select1('string(true())'));
assert.equal('string', typeof xpath.select1('string(false())'));
assert.equal('string', typeof xpath.select1('string(1 = 2)'));
assert.ok(xpath.select1('"true" = string(true())'), '"true" = string(true())');
test.done();
},
'string should downcast to boolean': function (test) {
assert.equal(false, xpath.select1('"false" = false()'), '"false" = false()');
assert.equal(true, xpath.select1('"a" = true()'), '"a" = true()');
assert.equal(true, xpath.select1('"" = false()'), '"" = false()');
test.done();
},
'string(number) is a string': function (test) {
assert.equal('string', typeof xpath.select1('string(45)'));
assert.ok(xpath.select1('"45" = string(45)'), '"45" = string(45)');
test.done();
},
'correct string to number conversion': function (test) {
assert.equal(45.2, xpath.select1('number("45.200")'));
assert.equal(55.0, xpath.select1('number("000055")'));
assert.equal(65.0, xpath.select1('number(" 65 ")'));
assert.equal(true, xpath.select1('"" != 0'), '"" != 0');
assert.equal(false, xpath.select1('"" = 0'), '"" = 0');
assert.equal(false, xpath.select1('0 = ""'), '0 = ""');
assert.equal(false, xpath.select1('0 = " "'), '0 = " "');
assert.ok(Number.isNaN(xpath.select('number("")')), 'number("")');
assert.ok(Number.isNaN(xpath.select('number("45.8g")')), 'number("45.8g")');
assert.ok(Number.isNaN(xpath.select('number("2e9")')), 'number("2e9")');
assert.ok(Number.isNaN(xpath.select('number("+33")')), 'number("+33")');
test.done();
}
,'correct number to string conversion': function (test) {
assert.equal('0.0000000000000000000000005250000000000001', xpath.parse('0.525 div 1000000 div 1000000 div 1000000 div 1000000').evaluateString());
assert.equal('525000000000000000000000', xpath.parse('0.525 * 1000000 * 1000000 * 1000000 * 1000000').evaluateString());
test.done();
}
,'local-name() and name() of processing instruction': function (test) {
var xml = '<?book-record added="2015-01-16" author="J.K. Rowling" ?><book>Harry Potter</book>';
var doc = new dom().parseFromString(xml);
var expectedName = 'book-record';
var localName = xpath.select('local-name(/processing-instruction())', doc);
var name = xpath.select('name(/processing-instruction())', doc);
assert.deepEqual(expectedName, localName, 'local-name() - "' + expectedName + '" !== "' + localName + '"');
assert.deepEqual(expectedName, name, 'name() - "' + expectedName + '" !== "' + name + '"');
test.done();
},
'evaluate substring-after': function (test) {
var xml = '<classmate>Hermione</classmate>';
var doc = new dom().parseFromString(xml);
var part = xpath.select('substring-after(/classmate, "Her")', doc);
assert.deepEqual('mione', part);
test.done();
}
,'parsed expression with no options': function (test) {
var parsed = xpath.parse('5 + 7');
assert.equal(typeof parsed, "object", "parse() should return an object");
assert.equal(typeof parsed.evaluate, "function", "parsed.evaluate should be a function");
assert.equal(typeof parsed.evaluateNumber, "function", "parsed.evaluateNumber should be a function");
assert.equal(parsed.evaluateNumber(), 12);
// evaluating twice should yield the same result
assert.equal(parsed.evaluateNumber(), 12);
test.done();
}
,'select1() on parsed expression': function (test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var parsed = xpath.parse('/*/title');
assert.equal(typeof parsed, 'object', 'parse() should return an object');
assert.equal(typeof parsed.select1, 'function', 'parsed.select1 should be a function');
var single = parsed.select1({ node: doc });
assert.equal('title', single.localName);
assert.equal('Harry Potter', single.firstChild.data);
assert.equal('<title>Harry Potter</title>', single.toString());
test.done();
}
,'select() on parsed expression': function (test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var parsed = xpath.parse('/*/title');
assert.equal(typeof parsed, 'object', 'parse() should return an object');
assert.equal(typeof parsed.select, 'function', 'parsed.select should be a function');
var nodes = parsed.select({ node: doc });
assert.ok(nodes, 'parsed.select() should return a value');
assert.equal(1, nodes.length);
assert.equal('title', nodes[0].localName);
assert.equal('Harry Potter', nodes[0].firstChild.data);
assert.equal('<title>Harry Potter</title>', nodes[0].toString());
test.done();
}
,'evaluateString(), and evaluateNumber() on parsed expression with node': function (test) {
var xml = '<book><title>Harry Potter</title><numVolumes>7</numVolumes></book>';
var doc = new dom().parseFromString(xml);
var parsed = xpath.parse('/*/numVolumes');
assert.equal(typeof parsed, 'object', 'parse() should return an object');
assert.equal(typeof parsed.evaluateString, 'function', 'parsed.evaluateString should be a function');
assert.equal('7', parsed.evaluateString({ node: doc }));
assert.equal(typeof parsed.evaluateBoolean, 'function', 'parsed.evaluateBoolean should be a function');
assert.equal(true, parsed.evaluateBoolean({ node: doc }));
assert.equal(typeof parsed.evaluateNumber, 'function', 'parsed.evaluateNumber should be a function');
assert.equal(7, parsed.evaluateNumber({ node: doc }));
test.done();
}
,'evaluateBoolean() on parsed empty node set and boolean expressions': function (test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var context = { node: doc };
function evaluate(path) {
return xpath.parse(path).evaluateBoolean({ node: doc });
}
assert.equal(false, evaluate('/*/myrtle'), 'boolean value of empty node set should be false');
assert.equal(true, evaluate('not(/*/myrtle)'), 'not() of empty nodeset should be true');
assert.equal(true, evaluate('/*/title'), 'boolean value of non-empty nodeset should be true');
assert.equal(true, evaluate('/*/title = "Harry Potter"'), 'title equals Harry Potter');
assert.equal(false, evaluate('/*/title != "Harry Potter"'), 'title != Harry Potter should be false');
assert.equal(false, evaluate('/*/title = "Percy Jackson"'), 'title should not equal Percy Jackson');
test.done();
}
,'namespaces with parsed expression': function (test) {
var xml = '<characters xmlns:ps="http://philosophers-stone.com" xmlns:cs="http://chamber-secrets.com">' +
'<ps:character>Quirrell</ps:character><ps:character>Fluffy</ps:character>' +
'<cs:character>Myrtle</cs:character><cs:character>Tom Riddle</cs:character>' +
'</characters>';
var doc = new dom().parseFromString(xml);
var expr = xpath.parse('/characters/c:character');
var countExpr = xpath.parse('count(/characters/c:character)');
var csns = 'http://chamber-secrets.com';
function resolve(prefix) {
if (prefix === 'c') {
return csns;
}
}
function testContext(context, description) {
try {
var value = expr.evaluateString(context);
var count = countExpr.evaluateNumber(context);
assert.equal('Myrtle', value, description + ' - string value - ' + value);
assert.equal(2, count, description + ' map - count - ' + count);
} catch(e) {
e.message = description + ': ' + (e.message || '');
throw e;
}
}
testContext({
node: doc,
namespaces: {
c: csns
}
}, 'Namespace map');
testContext({
node: doc,
namespaces: resolve
}, 'Namespace function');
testContext({
node: doc,
namespaces: {
getNamespace: resolve
}
}, 'Namespace object');
test.done();
}
,'custom functions': function (test) {
var xml = '<book><title>Harry Potter</title></book>';
var doc = new dom().parseFromString(xml);
var parsed = xpath.parse('concat(double(/*/title), " is cool")');
function doubleString(context, value) {
assert.equal(2, arguments.length);
var str = value.stringValue();
return str + str;
}
function functions(name, namespace) {
if(name === 'double') {
return doubleString;
}
return null;
}
function testContext(context, description) {
try{
var actual = parsed.evaluateString(context);
var expected = 'Harry PotterHarry Potter is cool';
assert.equal(expected, actual, description + ' - ' + expected + ' != ' + actual);
} catch (e) {
e.message = description + ": " + (e.message || '');
throw e;
}
}
testContext({
node: doc,
functions: functions
}, 'Functions function');
testContext({
node: doc,
functions: {
getFunction: functions
}
}, 'Functions object');
testContext({
node: doc,
functions: {
double: doubleString
}
}, 'Functions map');
test.done();
}
,'custom function namespaces': function (test) {
var xml = '<book><title>Harry Potter</title><friend>Ron</friend><friend>Hermione</friend><friend>Neville</friend></book>';
var doc = new dom().parseFromString(xml);
var parsed = xpath.parse('concat(hp:double(/*/title), " is 2 cool ", hp:square(2), " school")');
var hpns = 'http://harry-potter.com';
var namespaces = {
hp: hpns
};
var context = {
node: doc,
namespaces: {
hp: hpns
},
functions: function (name, namespace) {
if (namespace === hpns) {
switch (name) {
case "double":
return function (context, value) {
assert.equal(2, arguments.length);
var str = value.stringValue();
return str + str;
};
case "square":
return function (context, value) {
var num = value.numberValue();
return num * num;
};
case "xor":
return function (context, l, r) {
assert.equal(3, arguments.length);
var lbool = l.booleanValue();
var rbool = r.booleanValue();
return (lbool || rbool) && !(lbool && rbool);
};
case "second":
return function (context, nodes) {
var nodesArr = nodes.toArray();
var second = nodesArr[1];
return second ? [second] : [];
};
}
}
return null;
}
};
assert.equal('Harry PotterHarry Potter is 2 cool 4 school', parsed.evaluateString(context));
assert.equal(false, xpath.parse('hp:xor(false(), false())').evaluateBoolean(context));
assert.equal(true, xpath.parse('hp:xor(false(), true())').evaluateBoolean(context));
assert.equal(true, xpath.parse('hp:xor(true(), false())').evaluateBoolean(context));
assert.equal(false, xpath.parse('hp:xor(true(), true())').evaluateBoolean(context));
assert.equal('Hermione', xpath.parse('hp:second(/*/friend)').evaluateString(context));
assert.equal(1, xpath.parse('count(hp:second(/*/friend))').evaluateNumber(context));
assert.equal(0, xpath.parse('count(hp:second(/*/friendz))').evaluateNumber(context));
test.done();
}
,'xpath variables': function (test) {
var xml = '<book><title>Harry Potter</title><volumes>7</volumes></book>';
var doc = new dom().parseFromString(xml);
var variables = {
title: 'Harry Potter',
notTitle: 'Percy Jackson',
houses: 4
};
function variableFunction(name) {
return variables[name];
}
function testContext(context, description) {
try{
assert.equal(true, xpath.parse('$title = /*/title').evaluateBoolean(context));
assert.equal(false, xpath.parse('$notTitle = /*/title').evaluateBoolean(context));
assert.equal(11, xpath.parse('$houses + /*/volumes').evaluateNumber(context));
} catch (e) {
e.message = description + ": " + (e.message || '');
throw e;
}
}
testContext({
node: doc,
variables: variableFunction
}, 'Variables function');
testContext({
node: doc,
variables: {
getVariable: variableFunction
}
}, 'Variables object');
testContext({
node: doc,
variables: variables
}, 'Variables map');
test.done();
}
,'xpath variable namespaces': function (test) {
var xml = '<book><title>Harry Potter</title><volumes>7</volumes></book>';
var doc = new dom().parseFromString(xml);
var hpns = 'http://harry-potter.com';
var context = {
node: doc,
namespaces: {
hp: hpns
},
variables: function(name, namespace) {
if (namespace === hpns) {
switch (name) {
case 'title': return 'Harry Potter';
case 'houses': return 4;
case 'false': return false;
case 'falseStr': return 'false';
}
} else if (namespace === '') {
switch (name) {
case 'title': return 'World';
}
}
return null;
}
};
assert.equal(true, xpath.parse('$hp:title = /*/title').evaluateBoolean(context));
assert.equal(false, xpath.parse('$title = /*/title').evaluateBoolean(context));
assert.equal('World', xpath.parse('$title').evaluateString(context));
assert.equal(false, xpath.parse('$hp:false').evaluateBoolean(context));
assert.notEqual(false, xpath.parse('$hp:falseStr').evaluateBoolean(context));
assert.throws(function () {
xpath.parse('$hp:hello').evaluateString(context);
}, function (err) {
return err.message === 'Undeclared variable: $hp:hello';
});
test.done();
}
,"detect unterminated string literals": function (test) {
function testUnterminated(path) {
assert.throws(function () {
xpath.evaluate('"hello');
}, function (err) {
return err.message.indexOf('Unterminated') !== -1;
});
}
testUnterminated('"Hello');
testUnterminated("'Hello");
testUnterminated('self::text() = "\""');
testUnterminated('"\""');
test.done();
}
,"string value for CDATA sections": function (test) {
var xml = "<people><person><![CDATA[Harry Potter]]></person><person>Ron <![CDATA[Weasley]]></person></people>",
doc = new dom().parseFromString(xml),
person1 = xpath.parse("/people/person").evaluateString({ node: doc }),
person2 = xpath.parse("/people/person/text()").evaluateString({ node: doc }),
person3 = xpath.select("string(/people/person/text())", doc);
person4 = xpath.parse("/people/person[2]").evaluateString({ node: doc });
assert.equal(person1, 'Harry Potter');
assert.equal(person2, 'Harry Potter');
assert.equal(person3, 'Harry Potter');
assert.equal(person4, 'Ron Weasley');
test.done();
}
,"string value of various node types": function (test) {
var xml = "<book xmlns:hp='http://harry'><!-- This describes the Harry Potter Book --><?author name='J.K. Rowling' ?><title lang='en'><![CDATA[Harry Potter & the Philosopher's Stone]]></title><character>Harry Potter</character></book>",
doc = new dom().parseFromString(xml),
allText = xpath.parse('.').evaluateString({ node: doc }),
ns = xpath.parse('*/namespace::*[name() = "hp"]').evaluateString({ node: doc }),
title = xpath.parse('*/title').evaluateString({ node: doc }),
child = xpath.parse('*/*').evaluateString({ node: doc }),
titleLang = xpath.parse('*/*/@lang').evaluateString({ node: doc }),
pi = xpath.parse('*/processing-instruction()').evaluateString({ node: doc }),
comment = xpath.parse('*/comment()').evaluateString({ node: doc });
assert.equal(allText, "Harry Potter & the Philosopher's StoneHarry Potter");
assert.equal(ns, 'http://harry');
assert.equal(title, "Harry Potter & the Philosopher's Stone");
assert.equal(child, "Harry Potter & the Philosopher's Stone");
assert.equal(titleLang, 'en');
assert.equal(pi.trim(), "name='J.K. Rowling'");
assert.equal(comment, ' This describes the Harry Potter Book ');
test.done();
}
,"exposes custom types": function (test) {
assert.ok(xpath.XPath, "xpath.XPath");
assert.ok(xpath.XPathParser, "xpath.XPathParser");
assert.ok(xpath.XPathResult, "xpath.XPathResult");
assert.ok(xpath.Step, "xpath.Step");
assert.ok(xpath.NodeTest, "xpath.NodeTest");
assert.ok(xpath.BarOperation, "xpath.BarOperation");
assert.ok(xpath.NamespaceResolver, "xpath.NamespaceResolver");
assert.ok(xpath.FunctionResolver, "xpath.FunctionResolver");
assert.ok(xpath.VariableResolver, "xpath.VariableResolver");
assert.ok(xpath.Utilities, "xpath.Utilities");
assert.ok(xpath.XPathContext, "xpath.XPathContext");
assert.ok(xpath.XNodeSet, "xpath.XNodeSet");
assert.ok(xpath.XBoolean, "xpath.XBoolean");
assert.ok(xpath.XString, "xpath.XString");
assert.ok(xpath.XNumber, "xpath.XNumber");
test.done();
}
,"work with nodes created using DOM1 createElement()": function (test) {
var doc = new dom().parseFromString('<book />');
doc.documentElement.appendChild(doc.createElement('characters'));
assert.ok(xpath.select1('/book/characters', doc));
assert.equal(xpath.select1('local-name(/book/characters)', doc), 'characters');
test.done();
}
,"preceding:: axis works on document fragments": function (test) {
var doc = new dom().parseFromString('<n />'),
df = doc.createDocumentFragment(),
root = doc.createElement('book');
df.appendChild(root);
for (var i = 0; i < 10; i += 1) {
root.appendChild(doc.createElement('chapter'));
}
var chapter = xpath.select1("book/chapter[5]", df);
assert.ok(chapter, 'chapter');
assert.equal(xpath.select("count(preceding::chapter)", chapter), 4);
test.done();
}
,"node set sorted and unsorted arrays": function (test) {
var doc = new dom().parseFromString('<book><character>Harry</character><character>Ron</character><character>Hermione</character></book>'),
path = xpath.parse("/*/*[3] | /*/*[2] | /*/*[1]")
nset = path.evaluateNodeSet({ node: doc }),
sorted = nset.toArray(),
unsorted = nset.toUnsortedArray();
assert.equal(sorted.length, 3);
assert.equal(unsorted.length, 3);
assert.equal(sorted[0].textContent, 'Harry');
assert.equal(sorted[1].textContent, 'Ron');
assert.equal(sorted[2].textContent, 'Hermione');
assert.notEqual(sorted[0], unsorted[0], "first nodeset element equal");
test.done();
}
,'meaningful error for invalid function': function(test) {
var path = xpath.parse('invalidFunc()');
assert.throws(function () {
path.evaluateString();
}, function (err) {
return err.message.indexOf('invalidFunc') !== -1;
});
var path2 = xpath.parse('funcs:invalidFunc()');
assert.throws(function () {
path2.evaluateString({
namespaces: {
funcs: 'myfunctions'
}
});
}, function (err) {
return err.message.indexOf('invalidFunc') !== -1;
});
test.done();
}
// https://github.com/goto100/xpath/issues/32
,'supports contains() function on attributes': function (test) {
var doc = new dom().parseFromString("<books><book title='Harry Potter and the Philosopher\"s Stone' /><book title='Harry Potter and the Chamber of Secrets' /></books>"),
andTheBooks = xpath.select("/books/book[contains(@title, ' ')]", doc),
secretBooks = xpath.select("/books/book[contains(@title, 'Secrets')]", doc);
assert.equal(andTheBooks.length, 2);
assert.equal(secretBooks.length, 1);
test.done();
}
,'compare multiple nodes to multiple nodes (equals)': function (test) {
var xml = '<school><houses>' +
'<house name="Gryffindor"><student>Harry</student><student>Hermione</student></house>' +
'<house name="Slytherin"><student>Draco</student><student>Crabbe</student></house>' +
'<house name="Ravenclaw"><student>Luna</student><student>Cho</student></house>' +
'</houses>' +
'<honorStudents><student>Hermione</student><student>Luna</student></honorStudents></school>';
var doc = new dom().parseFromString(xml);
var houses = xpath.parse('/school/houses/house[student = /school/honorStudents/student]').select({ node: doc });
assert.equal(houses.length, 2);
var houseNames = houses.map(function (node) { return node.getAttribute('name'); }).sort();
assert.equal(houseNames[0], 'Gryffindor');
assert.equal(houseNames[1], 'Ravenclaw');
test.done();
}
,'compare multiple nodes to multiple nodes (gte)': function (test) {
var xml = '<school><houses>' +
'<house name="Gryffindor"><student level="5">Harry</student><student level="9">Hermione</student></house>' +
'<house name="Slytherin"><student level="1">Goyle</student><student level="1">Crabbe</student></house>' +
'<house name="Ravenclaw"><student level="4">Luna</student><student level="3">Cho</student></house>' +
'</houses>' +
'<courses><course minLevel="9">DADA</course><course minLevel="4">Charms</course></courses>' +
'</school>';
var doc = new dom().parseFromString(xml);
var houses = xpath.parse('/school/houses/house[student/@level >= /school/courses/course/@minLevel]').select({ node: doc });
assert.equal(houses.length, 2);
var houseNames = houses.map(function (node) { return node.getAttribute('name'); }).sort();
assert.equal(houseNames[0], 'Gryffindor');
assert.equal(houseNames[1], 'Ravenclaw');
test.done();
}
}

9
static/js/ketcher2/node_modules/xpath/xpath.d.ts generated vendored Normal file
View File

@ -0,0 +1,9 @@
type SelectedValue = Node | Attr | string | number | boolean;
interface XPathSelect {
(expression: string, node?: Node): Array<SelectedValue>;
(expression: string, node: Node, single: true): SelectedValue;
}
export var select: XPathSelect;
export function select1(expression: string, node?: Node): SelectedValue;
export function evaluate(expression: string, contextNode: Node, resolver: XPathNSResolver, type: number, result: XPathResult): XPathResult;
export function useNamespaces(namespaceMap: { [name: string]: string }): XPathSelect;

4728
static/js/ketcher2/node_modules/xpath/xpath.js generated vendored Normal file

File diff suppressed because it is too large Load Diff