Skip to content

Commit

Permalink
Optimize kebabify (#207)
Browse files Browse the repository at this point in the history
* Optimize kebabify

By passing a function to replace, we can do the uppercase to lowercase
conversion at the same time. This is pretty much the exact example that
MDN gives, with the only difference being that we aren't checking
against the offset here to avoid adding "-" at the beginning of the
string:

  https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Using_an_inline_function_that_modifies_the_matched_characters

In my profiling, this seems to make kebabify 50% faster (50ms -> 25ms).

* Collapse kebabify into kebabifyStyleName

Now that we've simplified kebabify, there really isn't much value in
having it be in its own function like this. Moving it into
kebabifyStyleName to simplify and optimize.

* Add tests for kebabifyStyleName

My refactoring caused test coverage to drop, so I decided to add some
unit tests here. They pass before and after my refactoring.

* Replace ms- to -ms- regex with logic

This avoids an often-unnecessary regex run, which makes this function
run a little faster. I first went with str.slice, but benchmarking
showed that to be 18% slower than bracket access.
  • Loading branch information
lencioni authored and xymostech committed Mar 6, 2017
1 parent a7d2aff commit 5d36d56
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 4 deletions.
11 changes: 8 additions & 3 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,15 @@ export const flattenDeep = (list /* : any[] */) /* : any[] */ =>
list.reduce((memo, x) => memo.concat(Array.isArray(x) ? flattenDeep(x) : x), []);

const UPPERCASE_RE = /([A-Z])/g;
const MS_RE = /^ms-/;
const UPPERCASE_RE_TO_KEBAB = (match /* : string */) /* : string */ => `-${match.toLowerCase()}`;

const kebabify = (string /* : string */) /* : string */ => string.replace(UPPERCASE_RE, '-$1').toLowerCase();
export const kebabifyStyleName = (string /* : string */) /* : string */ => kebabify(string).replace(MS_RE, '-ms-');
export const kebabifyStyleName = (string /* : string */) /* : string */ => {
const result = string.replace(UPPERCASE_RE, UPPERCASE_RE_TO_KEBAB);
if (result[0] === 'm' && result[1] === 's' && result[2] === '-') {
return `-${result}`;
}
return result;
};

const isNotObject = (
x/* : ObjectMap | any */
Expand Down
17 changes: 16 additions & 1 deletion tests/util_test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {assert} from 'chai';

import {flattenDeep, recursiveMerge} from '../src/util.js';
import {flattenDeep, kebabifyStyleName, recursiveMerge} from '../src/util.js';

describe('Utils', () => {
describe('flattenDeep', () => {
Expand Down Expand Up @@ -66,4 +66,19 @@ describe('Utils', () => {
});
});
});

describe('kebabifyStyleName', () => {
it('kebabifies camelCase', () => {
assert.equal(kebabifyStyleName('fooBarBaz'), 'foo-bar-baz');
});
it('kebabifies PascalCase', () => {
assert.equal(kebabifyStyleName('FooBarBaz'), '-foo-bar-baz');
});
it('does not force -webkit-', () => {
assert.equal(kebabifyStyleName('webkitFooBarBaz'), 'webkit-foo-bar-baz');
});
it('forces -ms-', () => {
assert.equal(kebabifyStyleName('msFooBarBaz'), '-ms-foo-bar-baz');
});
});
});

0 comments on commit 5d36d56

Please sign in to comment.