Skip to content
This repository was archived by the owner on Sep 25, 2021. It is now read-only.

Commit 1103a02

Browse files
committedAug 16, 2015
Use a data attribute to store namespaced attribute settings.
1 parent 5bac977 commit 1103a02

File tree

7 files changed

+73
-96
lines changed

7 files changed

+73
-96
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
npm-debug.log
33
/node_modules/*
44
/build.js
5+
/*.tgz

‎helpers.js

+28-29
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,36 @@
1-
var React = require('react');
2-
var keys = require('lodash/object/keys');
3-
var rootKey = 'xmlReactLoader-root';
4-
5-
var NS_SEPARATOR = ':';
1+
var React = require('react');
2+
var forEach = require('lodash/collection/forEach');
3+
var ATTR_KEY = 'data-svgreactloader';
64

75
module.exports = {
6+
/**
7+
* @param {HTMLElement}
8+
*/
9+
applyAttributes: function (el) {
10+
var data = this.hasXmlAttributes(el);
11+
if (data) {
12+
forEach(JSON.parse(data), function (args) {
13+
var method = 'setAttribute' + (args.length === 3 ? 'NS' : '');
14+
el[method].apply(el, args);
15+
});
16+
}
17+
},
18+
/**
19+
* @param {HTMLElement}
20+
*/
21+
hasXmlAttributes: function (el) {
22+
return el && el.getAttribute(ATTR_KEY);
23+
},
824
/**
925
* @param {React.Component}
1026
*/
11-
applyUnsafe: function (component) {
12-
var context = component.xmlReactLoader;
13-
var namespaces = context.ns;
14-
var map = context.map;
15-
16-
keys(map).
17-
forEach(function (key) {
18-
var ref = key === rootKey ? component : component.refs[key];
19-
var el = React.findDOMNode(ref);
20-
var attrs = map[key];
27+
applyXmlAttributes: function (component) {
28+
var domEl = React.findDOMNode(component);
29+
var fn = this.applyAttributes.bind(this);
2130

22-
keys(attrs).
23-
forEach(function (key) {
24-
var i = key.indexOf(NS_SEPARATOR);
25-
var nskey = key.slice(0, i);
26-
var attr = key.slice(i + 1);
27-
28-
if (namespaces[nskey]) {
29-
el.setAttributeNS(namespaces[nskey], attr, attrs[key]);
30-
}
31-
else {
32-
el.setAttribute(key, attrs[key]);
33-
}
34-
});
35-
});
31+
if (domEl) {
32+
fn(domEl);
33+
forEach(domEl.querySelectorAll('[' + ATTR_KEY + ']'), fn);
34+
}
3635
}
3736
};

‎index.js

+6-9
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module.exports = function (source) {
3434

3535
if (params.attrs) {
3636
// easier than having to write json in the query
37-
// if anyone wants to exploit it, its their build process
37+
// if anyone wants to exploit it, it's their build process
3838
/*eslint no-eval:0*/
3939
eval('assign(attrs, ' + params.attrs + ');');
4040
}
@@ -49,26 +49,23 @@ module.exports = function (source) {
4949

5050
var tagName = keys(result)[0];
5151
var root = result[tagName];
52-
var context = {};
53-
var props = sanitize(root, context).$ || {};
5452

5553
if (tag) {
56-
result[tag] = root;
54+
root = result[tag] = root;
5755
delete result[tagName];
5856
tagName = tag;
59-
props = {};
57+
props = root.$ = {};
6058
}
6159

62-
props = assign(props, attrs);
60+
var props = assign(sanitize(root).$ || {}, attrs);
6361

6462
var xmlBuilder = new xml2js.Builder({ headless: true });
6563
var xmlSrc = xmlBuilder.buildObject(result);
6664
var component = tmpl({
6765
tagName: tagName,
6866
displayName: displayName,
69-
initialProps: props,
70-
innerXml: xmlSrc.split(/\n/).slice(1, -1).join('\n'),
71-
context: context
67+
defaultProps: props,
68+
innerXml: xmlSrc.split(/\n/).slice(1, -1).join('\n')
7269
});
7370

7471
callback(null, component);

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "svg-react-loader",
33
"fullname": "SVG to React Loader",
44
"description": "A Webpack Loader to turn SVGs into React Components",
5-
"version": "0.1.2",
5+
"version": "0.1.3",
66
"keywords": [
77
"webpack",
88
"loader",

‎test/test-test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*globals describe, it*/
2-
var loader = require('../');
2+
var loader = require('svg-react-loader');
33
var babel = require('babel-core');
44
var fs = require('fs');
55
var path = require('path');
@@ -50,6 +50,7 @@ describe('something', function () {
5050
done();
5151
},
5252
resourcePath: filename
53+
// resourceQuery: '?tag=foo&attrs={foo: \'bar\'}'
5354
});
5455
});
5556
});

‎utility/sanitize.js

+33-52
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,65 @@
11
var keys = require('lodash/object/keys');
22
var omit = require('lodash/object/omit');
3-
var pick = require('lodash/object/pick');
43

54
var ATTR_KEY = '$';
65
var NS_SEPARATOR = ':';
7-
var REF_TMPL = 'xmlReactLoader-';
8-
var ROOT_REF = REF_TMPL + 'root';
6+
var DATA_ATTR_KEY = 'data-svgreactloader';
97
var XML_NAMESPACE_KEY = 'xmlns';
108

119
/**
1210
* Remove any non-jsx xml attributes from the given node and any of its child
1311
* nodes. Return the original node sanitized.
1412
*
15-
* The optional context argument can be used to get a mapping of reference
16-
* strings to unsafe attributes for that reference key.
17-
*
1813
* @param {Object} xmlNode
19-
* @param {Object} [context]
2014
* @returns {Object} the node that was given
2115
*/
22-
module.exports = function sanitize (xmlNode, context) {
23-
var attrs = xmlNode.$;
24-
var unsafeAttrs =
25-
attrs &&
26-
pick(attrs, function (value, key) {
27-
return !!~key.indexOf(NS_SEPARATOR);
28-
});
29-
var unsafeKeys = unsafeAttrs && keys(unsafeAttrs);
30-
var isRoot = false;
16+
module.exports = function sanitize (xmlNode, namespaces) {
17+
namespaces = namespaces || {};
3118

32-
// first time through?
33-
if (!context || !context._) {
34-
isRoot = true;
35-
context = context || {};
36-
context._ = { refCount: 0 };
37-
context.ns = context.ns || {};
38-
context.map = context.map || {};
39-
}
19+
xmlNode.$ =
20+
keys(xmlNode.$).
21+
reduce(function (acc, key) {
22+
var i = key.indexOf(NS_SEPARATOR);
23+
var hasSep = !!~i;
24+
var ns = hasSep && key.slice(0, i);
25+
var attr = hasSep ? key.slice(i + 1) : key;
26+
var value = xmlNode.$[key];
27+
var nsKey = hasSep ? ns : attr;
4028

41-
if (unsafeKeys && unsafeKeys.length) {
42-
var refKey;
29+
if (nsKey === XML_NAMESPACE_KEY && !hasSep) {
30+
namespaces.xml = value;
31+
}
32+
else if (nsKey === XML_NAMESPACE_KEY) {
33+
namespaces[attr] = value;
34+
}
4335

44-
if (isRoot) {
45-
refKey = ROOT_REF;
46-
}
47-
else {
48-
refKey = REF_TMPL + context._.refCount++;
49-
}
36+
nsKey = nsKey === XML_NAMESPACE_KEY ? 'xml' : nsKey;
5037

51-
var namespaces = context.ns;
52-
var map = context.map;
53-
// determine if we have any namespace definitions
54-
// add them to our internal references
55-
// otherwise just flag them to be used later
56-
unsafeKeys.
57-
forEach(function (key) {
58-
var i = key.indexOf(NS_SEPARATOR);
59-
var ns = key.slice(0, i);
60-
var attr = key.slice(i + 1);
38+
if (ns && attr) {
39+
acc[DATA_ATTR_KEY] = acc[DATA_ATTR_KEY] || [];
40+
acc[DATA_ATTR_KEY].push([namespaces[nsKey], attr, value]);
41+
}
42+
else {
43+
acc[key] = value;
44+
}
6145

62-
if (ns === XML_NAMESPACE_KEY) {
63-
namespaces[attr] = unsafeAttrs[key];
64-
}
65-
});
46+
return acc;
47+
}, {});
6648

67-
xmlNode[ATTR_KEY] = omit(attrs, unsafeKeys);
68-
xmlNode[ATTR_KEY].ref = refKey;
69-
map[refKey] = unsafeAttrs;
49+
if (xmlNode.$[DATA_ATTR_KEY]) {
50+
xmlNode.$[DATA_ATTR_KEY] = JSON.stringify(xmlNode.$[DATA_ATTR_KEY]);
7051
}
7152

7253
keys(omit(xmlNode, ATTR_KEY)).
7354
forEach(function (key) {
7455
var child = xmlNode[key];
7556
if (Array.isArray(child)) {
76-
child.forEach(function (c) {
77-
sanitize(c, context);
57+
child.forEach(function (child) {
58+
sanitize(child, namespaces);
7859
});
7960
}
8061
else {
81-
sanitize(xmlNode[key], context);
62+
sanitize(child, namespaces);
8263
}
8364
});
8465

‎utility/template.txt

+2-4
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,11 @@ module.exports = React.createClass({
66
displayName: <%= JSON.stringify(displayName) %>,
77

88
getDefaultProps () {
9-
return <%= JSON.stringify(initialProps) %>;
9+
return <%= JSON.stringify(defaultProps) %>;
1010
},
1111

12-
xmlReactLoader: <%= JSON.stringify(context) %>,
13-
1412
componentDidMount () {
15-
helpers.applyUnsafe(this);
13+
helpers.applyXmlAttributes(this);
1614
},
1715

1816
render () {

0 commit comments

Comments
 (0)
Failed to load comments.