Skip to content

Commit

Permalink
Merge pull request #10 from browserslist/optimize
Browse files Browse the repository at this point in the history
Optimize
  • Loading branch information
dangreen committed May 1, 2019
2 parents 6f1327a + 0c7616a commit 06a61b1
Show file tree
Hide file tree
Showing 21 changed files with 529 additions and 181 deletions.
14 changes: 3 additions & 11 deletions examples/buildDemo.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ function renderUserAgentRegExp({
family,
sourceRegExpString,
regExpString,
resultVersion,
requestVersionsStrings
}, query) {
return `<li>
Expand All @@ -132,16 +131,9 @@ function renderUserAgentRegExp({
<tr>
<th>Source RegExp:</th><td><pre>${sourceRegExpString}</pre></td>
</tr>
${!resultVersion ? '' : `
<tr>
<th>Source RegExp version:</th><td>${resultVersion.join('.')}</td>
</tr>
`}
${resultVersion ? '' : `
<tr>
<th>Versioned RegExp:</th><td><pre>${regExpString}</pre></td>
</tr>
`}
<tr>
<th>Versioned RegExp:</th><td><pre>${regExpString}</pre></td>
</tr>
</table>
</li>`;
}
Expand Down
34 changes: 29 additions & 5 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
browserVersionsToRanges,
getRegExpsForBrowsers,
applyVersionsToRegExps,
optimizeAll,
joinVersionedBrowsersRegExps,
isAllVersion,
defaultOptions
Expand Down Expand Up @@ -124,16 +125,19 @@ if (verbose) {
const rangedBrowsers = browserVersionsToRanges(mergedBrowsers);
const sourceRegExps = getRegExpsForBrowsers(mergedBrowsers, options);
const regExps = applyVersionsToRegExps(sourceRegExps, rangedBrowsers, options);
const optimizedRegExps = optimizeAll(regExps);

console.log(
chalk.blue('\n> RegExps\n')
);

regExps.forEach(({
optimizedRegExps.forEach(({
family,
requestVersionsStrings,
sourceRegExp,
resultVersion,
resultFixedVersion,
resultMinVersion,
resultMaxVersion,
regExp
}) => {

Expand All @@ -151,8 +155,28 @@ if (verbose) {
regExpsTable.cell('Value', sourceRegExp);
regExpsTable.newRow();

regExpsTable.cell('Name', chalk.yellow('Source RegExp version:'));
regExpsTable.cell('Value', resultVersion && resultVersion.join('.'));
regExpsTable.cell('Name', chalk.yellow('Source RegExp fixed version:'));
regExpsTable.cell('Value', resultFixedVersion ? resultFixedVersion.join('.') : '...');
regExpsTable.newRow();

let regExpBrowsersVersion = '';

if (resultMinVersion) {
regExpBrowsersVersion = resultMinVersion.join('.');
} else {
regExpBrowsersVersion = '...';
}

regExpBrowsersVersion += ' - ';

if (resultMaxVersion) {
regExpBrowsersVersion += resultMaxVersion.join('.');
} else {
regExpBrowsersVersion += '...';
}

regExpsTable.cell('Name', chalk.yellow('Source RegExp browsers versions:'));
regExpsTable.cell('Value', regExpBrowsersVersion);
regExpsTable.newRow();

regExpsTable.cell('Name', chalk.yellow('Versioned RegExp:'));
Expand All @@ -162,7 +186,7 @@ if (verbose) {
console.log(`${regExpsTable.print()}\n`);
});

const regExpStr = joinVersionedBrowsersRegExps(regExps);
const regExpStr = joinVersionedBrowsersRegExps(optimizedRegExps);
const regExp = new RegExp(regExpStr);

console.log(regExp);
Expand Down
1 change: 1 addition & 0 deletions src/regexp/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './util';
export * from './optimize';
export * from './numberRay';
export * from './numberSegment';
export * from './numberRange';
Expand Down
112 changes: 3 additions & 109 deletions src/regexp/numbersPart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,117 +2,11 @@ import {
BRACED_NUMBER_PATTERN,
ESCAPE_SYMBOL,
getNumberPatternsCount,
regExpToString
regExpToString,
skipSquareBraces,
capturePostfix
} from './util';

/**
* Skip every char inside square braces.
* @param skip - Current skip state.
* @param prevChar - Previous char.
* @param char - Current char to check.
* @return Should skip this char or not.
*/
function skipSquareBraces(skip: boolean, prevChar: string, char: string) {

if (char === '['
&& prevChar !== ESCAPE_SYMBOL
) {
return true;
}

if (char === ']'
&& prevChar !== ESCAPE_SYMBOL
) {
return false;
}

return skip;
}

/**
* Get possible RegExp group postfix.
* @param regExpStr - Whole RegExp string.
* @param startFrom - Index to start capture.
* @return RegExp group postfix part.
*/
function capturePostfix(regExpStr: string, startFrom: number) {

let char = regExpStr[startFrom];

switch (char) {

case '+':
case '*':
case '?':
return char;

case '(': {

const nextChar = regExpStr[startFrom + 1];
const afterNextChar = regExpStr[startFrom + 2];

if (
nextChar !== '?'
|| afterNextChar !== '=' && afterNextChar !== '!'
) {
return '';
}

break;
}

case '{':
break;

default:
return '';
}

const regExpStrLength = regExpStr.length;
let prevChar = '';
let braceBalance = 0;
let skip = false;
let postfix = '';

for (let i = startFrom; i < regExpStrLength; i++) {

char = regExpStr[i];
prevChar = regExpStr[i - 1];
skip = skipSquareBraces(skip, prevChar, char);

if (!skip
&& prevChar !== ESCAPE_SYMBOL
&& (
char === '('
|| char === '{'
)
) {
braceBalance++;
}

if (braceBalance > 0) {
postfix += char;
}

if (!skip
&& prevChar !== ESCAPE_SYMBOL
&& braceBalance > 0
&& (
char === ')'
|| char === '}'
)
) {
braceBalance--;

if (braceBalance === 0) {
break;
}
}
}

return postfix;
}

/**
* Get from RegExp part with number patterns.
* @todo Optimize.
Expand Down
30 changes: 30 additions & 0 deletions src/regexp/optimize.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
optimize
} from './optimize';

describe('UserAgentRegExp', () => {

describe('optimize', () => {

it('should remove braces', () => {

expect(
optimize('(Family)foo(NotFamily)(bar)')
).toBe(
'FamilyfooNotFamilybar'
);

expect(
optimize('(Family)foo(NotFamily|bar)')
).toBe(
'Familyfoo(NotFamily|bar)'
);

expect(
optimize('(Family)(foo)?(?=NotFamily)')
).toBe(
'Family(foo)?(?=NotFamily)'
);
});
});
});
73 changes: 73 additions & 0 deletions src/regexp/optimize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {
BRACED_NUMBER_PATTERN,
ESCAPE_SYMBOL,
skipSquareBraces,
capturePostfix
} from './util';

export const OPTIMIZABLE_GROUP = /^\([\s\w\d_\-/!]+\)$/;

/**
* Optimize RegExp string: remove useless braces.
* @param regExpStr - RegExp string to optimize.
* @return Optimized RegExp string.
*/
export function optimize(regExpStr: string) {

const regExpStrLength = regExpStr.length;
let inGroup = false;
let skip = false;
let char = '';
let prevChar = '';
let postfix = '';
let groupAccum = '';
let optimizedRegExpStr = '';

for (let i = 0; i < regExpStrLength; i++) {

char = regExpStr[i];
prevChar = regExpStr[i - 1];
skip = skipSquareBraces(skip, prevChar, char);

if (!skip
&& prevChar !== ESCAPE_SYMBOL
&& char === '('
) {

if (inGroup) {
optimizedRegExpStr += groupAccum;
}

inGroup = true;
groupAccum = '';
}

if (inGroup) {
groupAccum += char;
} else {
optimizedRegExpStr += char;
}

if (!skip
&& prevChar !== ESCAPE_SYMBOL
&& char === ')'
&& inGroup
) {

inGroup = false;
postfix = capturePostfix(regExpStr, i + 1);
groupAccum += postfix;

if (groupAccum === BRACED_NUMBER_PATTERN
|| OPTIMIZABLE_GROUP.test(groupAccum)
) {
groupAccum = groupAccum.substr(1, groupAccum.length - 2);
}

optimizedRegExpStr += groupAccum;
i += postfix.length;
}
}

return optimizedRegExpStr;
}
Loading

0 comments on commit 06a61b1

Please sign in to comment.