Skip to content
Merged
10 changes: 10 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"main": "src/htmltojsx.js",
"bin": "src/cli.js",
"dependencies": {
"react": "~0.13.0",
"yargs": "~1.3.1",
"jsdom": "~4.4.0"
},
Expand Down
21 changes: 21 additions & 0 deletions src/htmltojsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,21 @@ var ELEMENT_ATTRIBUTE_MAPPING = {
}
};

var HTMLDOMPropertyConfig = require('react/lib/HTMLDOMPropertyConfig');

// Populate property map with ReactJS's attribute and property mappings
// TODO handle/use .Properties value eg: MUST_USE_PROPERTY is not HTML attr
for (var propname in HTMLDOMPropertyConfig.Properties) {
if (!HTMLDOMPropertyConfig.Properties.hasOwnProperty(propname)) {
continue;
}

var mapFrom = HTMLDOMPropertyConfig.DOMAttributeNames[propname] || propname.toLowerCase();

if (!ATTRIBUTE_MAPPING[mapFrom])
ATTRIBUTE_MAPPING[mapFrom] = propname;
}

/**
* Repeats a string a certain number of times.
* Also: the future is bright and consists of native string repetition:
Expand Down Expand Up @@ -468,6 +483,8 @@ StyleParser.prototype = {
var key = style.substr(0, firstColon);
var value = style.substr(firstColon + 1).trim();
if (key !== '') {
// Style key should be case insensitive
key = key.toLowerCase();
this.styles[key] = value;
}
}, this);
Expand Down Expand Up @@ -497,6 +514,10 @@ StyleParser.prototype = {
* @return {string} JSX style key
*/
toJSXKey: function(key) {
// Don't capitalize -ms- prefix
if(/^-ms-/.test(key)) {
key = key.substr(1);
}
return hyphenToCamelCase(key);
},

Expand Down
60 changes: 60 additions & 0 deletions test/htmltojsx-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,42 @@ describe('htmltojsx', function() {
.toBe('<div style={{fontSize: \'12pt\'}}>Test</div>');
});

it('should convert vendor-prefix "style" attributes', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div style="-moz-hyphens: auto; -webkit-hyphens: auto">Test</div>').trim())
.toBe('<div style={{MozHyphens: \'auto\', WebkitHyphens: \'auto\'}}>Test</div>');
});

it('should convert uppercase vendor-prefix "style" attributes', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div style="-MOZ-HYPHENS: auto; -WEBKIT-HYPHENS: auto">Test</div>').trim())
.toBe('<div style={{MozHyphens: \'auto\', WebkitHyphens: \'auto\'}}>Test</div>');
});

it('should convert "style" attributes with vendor prefix-like strings in the middle and mixed case', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div style="myclass-MOZ-HYPHENS: auto; myclass-WEBKIT-HYPHENS: auto">Test</div>').trim())
.toBe('<div style={{myclassMozHyphens: \'auto\', myclassWebkitHyphens: \'auto\'}}>Test</div>');
});

it('should convert -ms- prefix "style" attributes', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div style="-ms-hyphens: auto">Test</div>').trim())
.toBe('<div style={{msHyphens: \'auto\'}}>Test</div>');
});

it('should convert "style" attributes with -ms- in the middle', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div style="myclass-ms-hyphens: auto">Test</div>').trim())
.toBe('<div style={{myclassMsHyphens: \'auto\'}}>Test</div>');
});

it('should convert uppercase "style" attributes', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div style="TEXT-ALIGN: center">Test</div>').trim())
.toBe('<div style={{textAlign: \'center\'}}>Test</div>');
});

it('should convert "class" attribute', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<div class="awesome">Test</div>').trim())
Expand All @@ -149,6 +185,30 @@ describe('htmltojsx', function() {
.toBe('<label htmlFor="potato">Test</label>');
});

it('should convert "maxlength" attribute to "maxLength"', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<input maxlength=2></input>').trim())
.toBe('<input maxLength={2} />');
});

it('should convert "http-equiv" attribute to "httpEquiv"', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<meta http-equiv="refresh">').trim())
.toBe('<meta httpEquiv="refresh" />');
});

it('should convert "accept-charset" attribute to "acceptCharset"', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<form accept-charset="UTF-8">Test</form>').trim())
.toBe('<form acceptCharset="UTF-8">Test</form>');
});

it('should convert "enctype" attribute to "encType"', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<form method="post" enctype="application/x-www-form-urlencoded">Test</form>').trim())
.toBe('<form method="post" encType="application/x-www-form-urlencoded">Test</form>');
});

it('should maintain value-less attributes', function() {
var converter = new HTMLtoJSX({ createClass: false });
expect(converter.convert('<input disabled>').trim())
Expand Down