New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

cruftless

Package Overview
Dependencies
Maintainers
1
Versions
32
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cruftless - npm Package Compare versions

Comparing version 0.3.5 to 0.4.0

lib/model/capture.js

5

CHANGES.md
# Changes
## 0.4.0
- Add support for capturing an entire nodeset
- Produce sensible RelaxNG grammars for captures
## 0.3.5

@@ -4,0 +9,0 @@

45

lib/cruftless.js

@@ -8,3 +8,10 @@ // Generated by CoffeeScript 2.5.1

module.exports = function(opts = {}) {
var attr, comment, element, parse, relaxng, text;
/*
Produces a RelaxNG schema for the given template. Refs will be resolved using
the object passed in. If there is a reference to something not defined in the
schema, then we will attempt to resolve it using the refs object. If it
exist, we will add a definition of that name and inline the corresponding
snippet.
*/
var attr, capture, comment, element, parse, relaxng, relaxngAny, text;
opts = _.cloneDeep(opts);

@@ -15,10 +22,38 @@ opts.types = _.merge({}, require('./model/types'), opts.types || {});

text = require('./model/text')(opts);
capture = require('./model/capture')(opts);
comment = require('./model/comment')(opts);
parse = require('./model/builder')({element, attr, text, comment});
relaxng = function(template) {
return element('grammar').ns('http://relaxng.org/ns/structure/1.0').attrs(attr('datatypeLibrary').value('http://www.w3.org/2001/XMLSchema-datatypes')).content(element('start').content(template.relaxng({element, attr, text}))).toXML();
parse = require('./model/builder')({element, attr, text, comment, capture});
relaxngAny = element('zeroOrMore').ns('http://relaxng.org/ns/structure/1.0').content(element('choice').content(element('element').content(element('anyName'), element('ref').attrs(attr('name').value('any'))), element('attribute').content(element('anyName')), element('text')));
relaxng = function(template, refs = {}) {
var definitions, refElementsFound, refsFound, schema, trackingElement;
refElementsFound = [];
trackingElement = function(name) {
var created;
created = element(name);
if (name === 'ref') {
refElementsFound.push(created);
}
return created;
};
schema = template.relaxng({
element: trackingElement,
attr,
text
});
refsFound = refElementsFound.map(function(ref) {
var ref1;
return (ref1 = ref.getAttribute('name')) != null ? ref1.getValue() : void 0;
});
definitions = _.uniq(refsFound).map(function(name) {
if (refs[name] != null) {
return element('define').attrs(attr('name').value(name)).content(refs[name]);
} else {
return element('define').attrs(attr('name').value(name)).content(relaxngAny);
}
});
return element('grammar').ns('http://relaxng.org/ns/structure/1.0').attrs(attr('datatypeLibrary').value('http://www.w3.org/2001/XMLSchema-datatypes')).content(element('start').content(schema), ...definitions).toXML();
};
return {element, attr, text, parse, relaxng};
return {element, attr, text, parse, relaxng, capture};
};
}).call(this);

@@ -41,2 +41,8 @@ // Generated by CoffeeScript 2.5.1

},
getName: function() {
return meta.name;
},
getValue: function() {
return meta.value;
},
generate: function(obj, elem) {

@@ -43,0 +49,0 @@ var value;

14

lib/model/builder.js

@@ -26,6 +26,6 @@ // Generated by CoffeeScript 2.5.1

module.exports = function(opts) {
var attr, comment, element, parse, text;
({element, attr, text, comment} = opts);
var attr, capture, comment, element, parse, text;
({element, attr, text, comment, capture} = opts);
parse = function(node) {
var attrs, childNodes, content, el, empty, piNode;
var attrs, captured, childNodes, content, el, empty, piNode;
switch (node.nodeType) {

@@ -44,5 +44,7 @@ case 1:

}
// commentNode = childNodes.find (node) -> node.nodeType is 8
// if commentNode?
// binding.raw(commentNode.textContent).apply(el)
if ((piNode != null) && piNode.target === 'capture') {
captured = capture();
binding.raw(piNode.data).apply(captured);
el.content(captured);
}
content = childNodes.map(parse).filter(_.negate(_.isUndefined));

@@ -49,0 +51,0 @@ el.content(...content);

@@ -217,2 +217,7 @@ // Generated by CoffeeScript 2.5.1

},
getAttribute: function(name) {
return meta.attrs.find(function(attr) {
return attr.getName() === name;
});
},
descriptor: function() {

@@ -219,0 +224,0 @@ return meta.descriptor();

{
"name": "cruftless",
"version": "0.3.5",
"version": "0.4.0",
"description": "Yet another simple way to parse and generate XML",

@@ -5,0 +5,0 @@ "main": "lib/cruftless.js",

```javascript --hide
require('coffeescript/register');
const format = require('xml-formatter');
runmd.onRequire = function(path) {
if (path === 'cruftless') {
return './readme.cruftless.coffee';
require("coffeescript/register");
const format = require("xml-formatter");
runmd.onRequire = function (path) {
if (path === "cruftless") {
return "./readme.cruftless.coffee";
}
}
};
```

@@ -19,6 +19,5 @@

## Yet another XML binding framework?
I hate to say this, but: 'yes'. Or, perhaps: 'no'. Because Cruftless is not really an XML binding framework as you know it. It's almost more like Handlebars. But where Handlebars allows you to only *generate* documents, Cruftless also allows you to *extract* data from documents.
I hate to say this, but: 'yes'. Or, perhaps: 'no'. Because Cruftless is not really an XML binding framework as you know it. It's almost more like Handlebars. But where Handlebars allows you to only _generate_ documents, Cruftless also allows you to _extract_ data from documents.

@@ -36,14 +35,10 @@ ## Building XML documents

Then, using the builder API, Cruftless allows you to *build* a model of your document like this:
Then, using the builder API, Cruftless allows you to _build_ a model of your document like this:
```javascript --run simple
const { element, attr, text } = require('cruftless')();
const { element, attr, text } = require("cruftless")();
let el = element('person').content(
element('name').content(
text().value('John Doe')
),
element('age').content(
text().value(16)
)
let el = element("person").content(
element("name").content(text().value("John Doe")),
element("age").content(text().value(16))
);

@@ -69,9 +64,5 @@ ```

```javascript --run simple
el = element('person').content(
element('name').content(
text().bind('name')
),
element('age').content(
text().bind('age')
)
el = element("person").content(
element("name").content(text().bind("name")),
element("age").content(text().bind("age"))
);

@@ -83,6 +74,6 @@ ```

```javascript --run simple
let xml = el.toXML({ name: 'John Doe', age: '16'}); // RESULT
let xml = el.toXML({ name: "John Doe", age: "16" }); // RESULT
```
But the beauty is, it also works the other way around. If you have your model with binding expressions, then you're able to *extract* data from XML like this:
But the beauty is, it also works the other way around. If you have your model with binding expressions, then you're able to _extract_ data from XML like this:

@@ -101,8 +92,8 @@ ```javascript --run simple

<age>{{age}}</age>
</person>`
</person>`;
let { parse } = require('cruftless')();
let { parse } = require("cruftless")();
el = parse(template)
console.log(el.toXML({ name: 'Jane Doe', age: '18' }));
el = parse(template);
console.log(el.toXML({ name: "Jane Doe", age: "18" }));
```

@@ -132,6 +123,10 @@

console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
console.log(
template.toXML({
persons: [
{ name: "John Doe", age: 16 },
{ name: "Jane Doe", age: 18 },
],
})
);
```

@@ -143,10 +138,10 @@

```javascript --run simple-2
const { element, attr, text, parse } = require('cruftless')({
const { element, attr, text, parse } = require("cruftless")({
types: {
zeroOrOne: {
type: 'boolean',
from: str => str == '1',
to: value => value ? '1' : '0'
}
}
type: "boolean",
from: (str) => str == "1",
to: (value) => (value ? "1" : "0"),
},
},
});

@@ -166,3 +161,3 @@

// The second argument defaults to false, so might as well leave it out
console.log(template.fromXML('<foo>1</foo>', false));
console.log(template.fromXML("<foo>1</foo>", false));
```

@@ -173,6 +168,5 @@

```javascript --run simple-2
console.log(template.fromXML('<foo>1</foo>', true));
console.log(template.fromXML("<foo>1</foo>", true));
```
## Alternative notation

@@ -190,6 +184,10 @@

console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
console.log(
template.toXML({
persons: [
{ name: "John Doe", age: 16 },
{ name: "Jane Doe", age: 18 },
],
})
);
```

@@ -208,6 +206,10 @@

console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
console.log(
template.toXML({
persons: [
{ name: "John Doe", age: 16 },
{ name: "Jane Doe", age: 18 },
],
})
);
```

@@ -236,3 +238,3 @@

nested element contains references to variable, and that variable is not
defined, then it will not only drop *that* element, but all elements that
defined, then it will not only drop _that_ element, but all elements that
included that element referring to a non-existing variable.

@@ -274,7 +276,7 @@

However, if you would *produce* XML, then — by default — it will always produce
However, if you would _produce_ XML, then — by default — it will always produce
a text node:
```javascript --run simple-2
console.log(template.toXML({ name: 'Alice' }));
console.log(template.toXML({ name: "Alice" }));
```

@@ -286,6 +288,5 @@

template = parse(`<person>{{name|cdata}}</person>`);
console.log(template.toXML({ name: 'Alice' }));
console.log(template.toXML({ name: "Alice" }));
```
## JSON-ish Schema (incomplete, subject to change)

@@ -325,3 +326,3 @@

```javascript --run simple-2
const { relaxng } = require('cruftless')();
const { relaxng } = require("cruftless")();

@@ -331,1 +332,21 @@ console.log(relaxng(template));

## Nodeset Capture
There are situations where it makes very little sense to have one template
dictating the structure of the entire document. Typically, in those cases, you
want to slowly peel the entire structure about, starting with the outer envelope
/ container, and then slowly work your way in.
In order to support that, Cruftless offers a solution to capture parts of the
DOM tree as is and store it in a variable to be processed further downstream.
The syntax is not all that different than the bind syntax and might be
harmonized at some point.
This is how you use it:
```javascript --run simple-2
template = parse(`<foo><?capture nodes?></foo>`);
const { nodes } = template.fromXML(`<foo><bar/><bar/></foo>`);
console.log(nodes.length);
console.log(nodes[0].tagName);
```

@@ -13,6 +13,5 @@ <!--

## Yet another XML binding framework?
I hate to say this, but: 'yes'. Or, perhaps: 'no'. Because Cruftless is not really an XML binding framework as you know it. It's almost more like Handlebars. But where Handlebars allows you to only *generate* documents, Cruftless also allows you to *extract* data from documents.
I hate to say this, but: 'yes'. Or, perhaps: 'no'. Because Cruftless is not really an XML binding framework as you know it. It's almost more like Handlebars. But where Handlebars allows you to only _generate_ documents, Cruftless also allows you to _extract_ data from documents.

@@ -30,14 +29,10 @@ ## Building XML documents

Then, using the builder API, Cruftless allows you to *build* a model of your document like this:
Then, using the builder API, Cruftless allows you to _build_ a model of your document like this:
```javascript
const { element, attr, text } = require('cruftless')();
const { element, attr, text } = require("cruftless")();
let el = element('person').content(
element('name').content(
text().value('John Doe')
),
element('age').content(
text().value(16)
)
let el = element("person").content(
element("name").content(text().value("John Doe")),
element("age").content(text().value(16))
);

@@ -63,9 +58,5 @@ ```

```javascript
el = element('person').content(
element('name').content(
text().bind('name')
),
element('age').content(
text().bind('age')
)
el = element("person").content(
element("name").content(text().bind("name")),
element("age").content(text().bind("age"))
);

@@ -77,6 +68,6 @@ ```

```javascript
let xml = el.toXML({ name: 'John Doe', age: '16'}); // ⇨ '<person>\r\n <name>John Doe</name>\r\n <age>16</age>\r\n</person>'
let xml = el.toXML({ name: "John Doe", age: "16" }); // ⇨ '<person>\r\n <name>John Doe</name>\r\n <age>16</age>\r\n</person>'
```
But the beauty is, it also works the other way around. If you have your model with binding expressions, then you're able to *extract* data from XML like this:
But the beauty is, it also works the other way around. If you have your model with binding expressions, then you're able to _extract_ data from XML like this:

@@ -95,8 +86,8 @@ ```javascript

<age>{{age}}</age>
</person>`
</person>`;
let { parse } = require('cruftless')();
let { parse } = require("cruftless")();
el = parse(template)
console.log(el.toXML({ name: 'Jane Doe', age: '18' }));
el = parse(template);
console.log(el.toXML({ name: "Jane Doe", age: "18" }));
⇒ <person>

@@ -130,6 +121,10 @@ ⇒ <name>Jane Doe</name>

console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
console.log(
template.toXML({
persons: [
{ name: "John Doe", age: 16 },
{ name: "Jane Doe", age: 18 },
],
})
);
⇒ <persons>

@@ -151,10 +146,10 @@ ⇒ <person>

```javascript
const { element, attr, text, parse } = require('cruftless')({
const { element, attr, text, parse } = require("cruftless")({
types: {
zeroOrOne: {
type: 'boolean',
from: str => str == '1',
to: value => value ? '1' : '0'
}
}
type: "boolean",
from: (str) => str == "1",
to: (value) => (value ? "1" : "0"),
},
},
});

@@ -176,3 +171,3 @@

// The second argument defaults to false, so might as well leave it out
console.log(template.fromXML('<foo>1</foo>', false));
console.log(template.fromXML("<foo>1</foo>", false));
⇒ { value: true }

@@ -184,7 +179,6 @@ ```

```javascript
console.log(template.fromXML('<foo>1</foo>', true));
console.log(template.fromXML("<foo>1</foo>", true));
⇒ { value: '1' }
```
## Alternative notation

@@ -202,6 +196,10 @@

console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
console.log(
template.toXML({
persons: [
{ name: "John Doe", age: 16 },
{ name: "Jane Doe", age: 18 },
],
})
);
⇒ <persons>

@@ -230,6 +228,10 @@ ⇒ <person>

console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
console.log(
template.toXML({
persons: [
{ name: "John Doe", age: 16 },
{ name: "Jane Doe", age: 18 },
],
})
);
⇒ <persons>

@@ -268,3 +270,3 @@ ⇒ <person>

nested element contains references to variable, and that variable is not
defined, then it will not only drop *that* element, but all elements that
defined, then it will not only drop _that_ element, but all elements that
included that element referring to a non-existing variable.

@@ -321,7 +323,7 @@

However, if you would *produce* XML, then — by default — it will always produce
However, if you would _produce_ XML, then — by default — it will always produce
a text node:
```javascript
console.log(template.toXML({ name: 'Alice' }));
console.log(template.toXML({ name: "Alice" }));
⇒ <person>Alice</person>

@@ -334,3 +336,3 @@ ```

template = parse(`<person>{{name|cdata}}</person>`);
console.log(template.toXML({ name: 'Alice' }));
console.log(template.toXML({ name: "Alice" }));
⇒ <person>

@@ -341,3 +343,2 @@ ⇒ <![CDATA[Alice]]>

## JSON-ish Schema (incomplete, subject to change)

@@ -398,3 +399,3 @@

```javascript
const { relaxng } = require('cruftless')();
const { relaxng } = require("cruftless")();

@@ -420,4 +421,26 @@ console.log(relaxng(template));

## Nodeset Capture
There are situations where it makes very little sense to have one template
dictating the structure of the entire document. Typically, in those cases, you
want to slowly peel the entire structure about, starting with the outer envelope
/ container, and then slowly work your way in.
In order to support that, Cruftless offers a solution to capture parts of the
DOM tree as is and store it in a variable to be processed further downstream.
The syntax is not all that different than the bind syntax and might be
harmonized at some point.
This is how you use it:
```javascript
template = parse(`<foo><?capture nodes?></foo>`);
const { nodes } = template.fromXML(`<foo><bar/><bar/></foo>`);
console.log(nodes.length);
console.log(nodes[0].tagName);
⇒ 2
⇒ bar
```
----
Markdown generated from [./README.js.md](./README.js.md) by [![RunMD Logo](http://i.imgur.com/h0FVyzU.png)](https://github.com/broofa/runmd)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc