![Create React App Officially Deprecated Amid React 19 Compatibility Issues](https://cdn.sanity.io/images/cgdhsj6q/production/04fa08cf844d798abc0e1a6391c129363cc7e2ab-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Create React App Officially Deprecated Amid React 19 Compatibility Issues
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
An XML builder / parser that tries to ease the common cases, allowing you to quickly build a model from your document structure and get a builder / parser for free.
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.
Cruftless builds a simplified metamodel of your XML document, and it's not based on a DOM API. So, if this is the XML document:
<person>
<name>John Doe</name>
<age>16</age>
</person>
Then, using the builder API, Cruftless allows you to build a model of your document like this:
const { element, attr, text } = require('cruftless')();
let el = element('person').content(
element('name').content(
text().value('John Doe')
),
element('age').content(
text().value(16)
)
);
… and then to turn it back into XML, you'd use the toXML()
operation:
el.toXML(); // ⇨ '<person><name>John Doe</name><age>16</age></person>'
… or the toDOM()
operation instead to return a DOM representation of the document:
el.toDOM();
Now, this itself doesn't seem all that useful. Where it gets useful is when you start adding references to your document model:
el = element('person').content(
element('name').content(
text().bind('name')
),
element('age').content(
text().bind('age')
)
);
Now, if you want to generate different versions of your XML document for different persons, you can simply pass in an object with name
and age
properties:
let xml = el.toXML({ name: 'John Doe', age: '16'}); // ⇨ '<person><name>John Doe</name><age>16</age></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:
el.fromXML(xml); // ⇨ { name: 'John Doe', age: '16' }
I hope you can see how this is useful. However, I also hope you can see that this is perhaps not ideal. I mean, it's nice that you're able to build a model of XML, but in many cases, you already have the snippets of XML that you need to populate with data. So, the question is if there is an easier way to achieve the same, if you already have snippets of XML. Perhaps not surprisingly, there is:
let template = `<person>
<name>{{name}}</name>
<age>{{age}}</age>
</person>`
let { parse } = require('cruftless')();
el = parse(template)
console.log(el.toXML({ name: 'Jane Doe', age: '18' }));
⇒ <person><name>Jane Doe</name><age>18</age></person>
The example above is rather simple. However, Cruftless allows you also deal with more complex cases. And not only that, it also allows you to set additional metadata on binding expressions, using the pipe symbol. In the template below, we're binding <person/>
elements inside a <persons/>
element to a property persons
, and we're inserting every occurence of it into the persons
array. The <!--…-->
annotation might be feel a little awkward at first. There are other ways to define the binding, including one that requires using attributes of particular namespace. Check the test files for examples.
template = parse(`<persons>
<person><!--persons|array-->
<name>{{name|required}}</name>
<age>{{age|integer|required}}</age>
</person>
</persons>`);
// Note that because of the 'integer' modifier, integer values are
// now automatically getting transfered from and to strings.
console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
⇒ <persons><person><name>John Doe</name><age>16</age></person><person><name>Jane Doe</name><age>18</age></person></persons>
You can add your own value types to convert from and to the string literals included in the XML representation.
const { element, attr, text, parse } = require('cruftless')({
types: {
zeroOrOne: {
type: 'boolean',
from: str => str == '1',
to: value => value ? '1' : '0'
}
}
});
template = parse(`<foo>{{value|zeroOrOne}})</foo>`);
console.log(template.toXML({ value: true }));
console.log(template.toXML({ value: false }));
⇒ <foo>1</foo>
⇒ <foo>0</foo>
By default, all whitespace in text content will be stripped, which probably
makes sense in the case where you're using XML to represent data structures. If
that's now what you want, the you can set the preserveWhitespace
option to
true
.
const { element, attr, text, parse } = require('cruftless')({
preserveWhitespace: true
});
template = parse(`<foo>
<bar>{{a}}</bar>
</foo>`);
console.log(template.toXML({ a: 3 }));
⇒ <foo>
⇒ <bar>3</bar>
⇒ </foo>
The <!--persons|array-->
way of annotating an element is not the only way you are able to add metadata. Another way to add metadata to elements is by using one of the reserved attributes prefixed with c-
.
template = parse(`<persons>
<person c-bind="persons|array">
<name>{{name|required}}</name>
<age>{{age|integer|required}}</age>
</person>
</persons>`);
console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
⇒ <persons><person><name>John Doe</name><age>16</age></person><person><name>Jane Doe</name><age>18</age></person></persons>
If you hate the magic c-
prefixed attributes, then you can also a slightly less readable but admittedly more correct XML namespace:
template = parse(`<persons>
<person xmlns:c="https://github.com/wspringer/cruftless" c:bind="persons|array">
<name>{{name|required}}</name>
<age>{{age|integer|required}}</age>
</person>
</persons>`);
console.log(template.toXML({ persons: [
{ name: 'John Doe', age: 16 },
{ name: 'Jane Doe', age: 18 }
]}));
⇒ <persons><person><name>John Doe</name><age>16</age></person><person><name>Jane Doe</name><age>18</age></person></persons>
There may be times when you want to exclude entire sections of an XML structure if a particular condition is met. Cruftless has some basic support for that, albeit limited. You can set conditions on elements, using the c-if
attribute. In that case, the element will only be included in case the expression of the c-if
attribute is evaluating to something else than undefined
or null
.
template = parse(`<foo><bar c-if="a">text</bar></foo>`);
template.toXML({}); // ⇨ '<foo/>'
template.toXML({ a: null }); // ⇨ '<foo/>'
template.toXML({ a: void 0 }); // ⇨ '<foo/>'
template.toXML({ a: 3 }); // ⇨ '<foo><bar>text</bar></foo>'
If your template contains variable references, and the data structure you are passing in does not contain these references, then — instead of generating the value undefined
, Cruftless will drop the entire element. In fact, if a deeply nested element contains references to variable, and that variable is not defined, then it will not only drop that element, but all elements that included that element referring to a non-existing variable.
template = parse(`<level1>
<level2 b="{{b}}">
<level3>{{a}}</level3>
</level2>
</level1>`);
console.log(template.toXML({ b: 2 }));
⇒ <level1><level2 b="2"></level2></level1>
console.log(template.toXML({ b: 2, a: 3 }));
⇒ <level1><level2 b="2"><level3>3</level3></level2></level1>
console.log(template.toXML({ a: 3 }));
⇒ <level1><level2><level3>3</level3></level2></level1>
Since Cruftless has all of the metadata of your XML document and how it binds to your data structures at its disposal, it also allows you to generate a 'schema' of the data structure it expects.
let schema = template.descriptor();
console.log(JSON.stringify(schema, null, 2));
⇒ {
⇒ "type": "object",
⇒ "keys": {
⇒ "b": {
⇒ "type": "string"
⇒ },
⇒ "a": {
⇒ "type": "string"
⇒ }
⇒ }
⇒ }
The schema will include additional metadata you attached to expressions:
template = parse(`<person>
<name>{{name|sample:Wilfred}}</name>
<age>{{age|integer|sample:45}}</age>
</person>`);
schema = template.descriptor();
console.log(JSON.stringify(schema, null, 2));
⇒ {
⇒ "type": "object",
⇒ "keys": {
⇒ "name": {
⇒ "type": "string",
⇒ "sample": "Wilfred"
⇒ },
⇒ "age": {
⇒ "type": "integer",
⇒ "sample": 45
⇒ }
⇒ }
⇒ }
Markdown generated from ./README.js.md by
0.1.4
preserveWhitespace
option to do exactly that: preserve whitespace.FAQs
Yet another simple way to parse and generate XML
The npm package cruftless receives a total of 168 weekly downloads. As such, cruftless popularity was classified as not popular.
We found that cruftless demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.