Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

refactor(*): separate jqLite/compile/sce camelCasing logic #15249

Closed
wants to merge 1 commit into from

Conversation

mgol
Copy link
Member

@mgol mgol commented Oct 12, 2016

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
Refactor

What is the current behavior? (You can also link to an open issue here)
jqLite's camelCasing logic converts not only dashes but also underscores & colons; it also collapses multiple dashes etc.

What is the new behavior (if this is a feature change)?
jqLite's camelCasing logic is separated from the one used in compile/sce and more strict, making jqLite more similar to the jQuery behavior. This is also needed to make the new planned data key camelCasing work like in jQuery 3.

Does this PR introduce a breaking change?
Yes.

Please check if the PR fulfills these requirements

Other information:

jqLite needs camelCase for it's css method; it should only convert one dash
followed by a lowercase letter to an uppercase one; it shouldn't touch
underscores, colons or collapse multiple dashes into one. This is behavior
of jQuery 3 as well.

This commit separates jqLite camelCasing from the $compile one (and $sce but
that's an internal-only use). The $compile version should behave as before.

Also, jqLite's css camelCasing logic was put in a separate function and
refactored: now the properties starting from an uppercase letter are used by
default (i.e. Webkit, not webkit) and the only exception is for the -ms- prefix
that is converted to ms, not Ms. This makes the logic clearer as we're just
always changing a dash followed by a lowercase letter by an uppercase one; this
is also how it works in jQuery.

Ref #15126
Fix #7744

@@ -136,22 +136,31 @@ JQLite._data = function(node) {
function jqNextId() { return ++jqId; }


var SPECIAL_CHARS_REGEXP = /([:\-_]+(.))/g;
var MOZ_HACK_REGEXP = /^moz([A-Z])/;
var DASH_LOWERCASE_REGEXP = /-([a-z])/g;
Copy link
Member

@gkalpak gkalpak Oct 12, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should match [A-Z] as well.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't. That's the whole point of this change!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I even wrote some tests to ensure that's not getting converted. ;)

@@ -27,6 +27,13 @@ var SCE_CONTEXTS = {

// Helper functions follow.

var UNDERSCORE_LOWERCASE_REGEXP = /_([a-z])/g;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too, I wonder what might break by only matching lowercase letters.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing. ;) This is a purely internal function, only used to iterate once through a few constant strings during the initialization.

});

it('should not convert slashes followed by a non-letter', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slashes --> dashes (?)

@mgol
Copy link
Member Author

mgol commented Oct 12, 2016

I updated the commit message, adding a breaking change info.

expect(a.style.fooBar).toBe('bar');
});

it('should covert dash-separated strings to camelCase', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

covert -> convert

expect(a.style['foo:bar_baz']).toBe('baz');
});

it('should covert leading dashes followed by a lowercase letter', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

covert -> convert


jqA.css('foo-42- -a-B', 'foo');

expect(a.style['foo-42- A-B']).toBe('foo');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a crazy case. Do we really care that this is what it does?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't expect keys exactly like that to be used in practice but this string tests the fact that only -[a-z] gets converted pretty well. I can split it into separate cases if you prefer but I thought one string should suffice.

expect(a.style['foo-42- A-B']).toBe('foo');
});

it('should covert the -ms- prefix to ms instead of Ms', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

covert -> convert

expect(kebabToCamel('foo-42- -a-B')).toBe('foo-42- A-B');
});

it('should not covert browser specific css properties in a special way', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

covert -> convert

expect(kebabToCamel('foo:bar_baz')).toBe('foo:bar_baz');
});

it('should covert leading dashes followed by a lowercase letter', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

covert -> convert

@mgol
Copy link
Member Author

mgol commented Oct 12, 2016

Typos fixed.

@mgol
Copy link
Member Author

mgol commented Oct 12, 2016

@petebacondarwin Should it be fix instead of refactor as well? This is aligning with jQuery amongst other things.

@mgol
Copy link
Member Author

mgol commented Oct 12, 2016

I tweaked the commit message (see the first commit).

@petebacondarwin does that look OK?

@petebacondarwin
Copy link
Contributor

Better!

jqLite needs camelCase for it's css method; it should only convert one dash
followed by a lowercase letter to an uppercase one; it shouldn't touch
underscores, colons or collapse multiple dashes into one. This is behavior
of jQuery 3 as well.

This commit separates jqLite camelCasing from the $compile one (and $sce but
that's an internal-only use). The $compile version should behave as before.

Also, jqLite's css camelCasing logic was put in a separate function and
refactored: now the properties starting from an uppercase letter are used by
default (i.e. Webkit, not webkit) and the only exception is for the -ms- prefix
that is converted to ms, not Ms. This makes the logic clearer as we're just
always changing a dash followed by a lowercase letter by an uppercase one; this
is also how it works in jQuery.

Ref angular#15126
Fix angular#7744

BREAKING CHANGE: before, when Angular was used without jQuery, the key passed
to the css method was more heavily camelCased; now only a single (!) hyphen
followed by a lowercase letter is getting transformed. This also affects APIs
that rely on the css method, like ngStyle.

If you use Angular with jQuery, it already behaved in this way so no changes
are needed on your part.

To migrate the code follow the example below:

Before:

HTML:

// All five versions used to be equivalent.
<div ng-style={background_color: 'blue'}></div>
<div ng-style={'background:color': 'blue'}></div>
<div ng-style={'background-color': 'blue'}></div>
<div ng-style={'background--color': 'blue'}></div>
<div ng-style={backgroundColor: 'blue'}></div>

JS:

// All five versions used to be equivalent.
elem.css('background_color', 'blue');
elem.css('background:color', 'blue');
elem.css('background-color', 'blue');
elem.css('background--color', 'blue');
elem.css('backgroundColor', 'blue');

// All five versions used to be equivalent.
var bgColor = elem.css('background_color');
var bgColor = elem.css('background:color');
var bgColor = elem.css('background-color');
var bgColor = elem.css('background--color');
var bgColor = elem.css('backgroundColor');

After:

HTML:

// Previous five versions are no longer equivalent but these two still are.
<div ng-style={'background-color': 'blue'}></div>
<div ng-style={backgroundColor: 'blue'}></div>

JS:

// Previous five versions are no longer equivalent but these two still are.
elem.css('background-color', 'blue');
elem.css('backgroundColor', 'blue');

// Previous five versions are no longer equivalent but these two still are.
var bgColor = elem.css('background-color');
var bgColor = elem.css('backgroundColor');
@petebacondarwin
Copy link
Contributor

Landed via #15238

@mgol mgol deleted the camelCase branch October 13, 2016 07:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ngStyle ignores properties with underscore only when jQuery is installed
4 participants