Skip to content

Commit

Permalink
Merge ee722b6 into 22b8126
Browse files Browse the repository at this point in the history
  • Loading branch information
JPeer264 committed Aug 9, 2020
2 parents 22b8126 + ee722b6 commit cd31dc0
Show file tree
Hide file tree
Showing 9 changed files with 439 additions and 0 deletions.
184 changes: 184 additions & 0 deletions __tests__/optimize/optimize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
import rcs from '../../lib';

beforeEach(() => {
rcs.cssVariablesLibrary.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
rcs.cssVariablesLibrary.reset();
rcs.keyframesLibrary.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
rcs.keyframesLibrary.reset();
rcs.selectorsLibrary.setAlphabet('#abcdefghijklmnopqrstuvwxyz');
rcs.selectorsLibrary.reset();
});

test('should ignore everything without selectors', () => {
const input = { };

rcs.mapping.load(input);
rcs.optimize();

expect(rcs.mapping.generate()).toEqual(input);
});

test('should ignore when no statistics are available', () => {
const input = {
selectors: {
'#test': 'a',
'.ca': 'a',
'.ba': 'b',
'.aa': 'c',
},
};

rcs.mapping.load(input);
rcs.optimize();

expect(rcs.mapping.generate()).toEqual(input);
});

test('should optimize without usageCount', () => {
rcs.mapping.load({
selectors: {
'#test': 'a',
'.ca': 'a',
'.ba': 'b',
'.aa': 'c',
},
});
rcs.statistics.load({
ids: {
unused: [],
usageCount: {
test: 2,
},
},
classes: {
unused: [],
usageCount: {
'my-selector': 2,
},
},
keyframes: {
unused: [],
usageCount: {},
},
cssVariables: {
unused: [],
usageCount: {},
},
});

rcs.optimize();

expect(rcs.mapping.generate()).toEqual({
selectors: {
'#test': 'a',
'.aa': 'c',
'.ba': 'b',
'.ca': 'a',
},
});
});

test('should optimize with usageCount', () => {
rcs.mapping.load({
selectors: {
'#test': 'a',
'.ca': 'a',
'.ba': 'b',
'.aa': 'c',
},
});
rcs.statistics.load({
ids: {
unused: [],
usageCount: {
test: 2,
},
},
classes: {
unused: [],
usageCount: {
ca: 3,
ba: 10,
},
},
keyframes: {
unused: [],
usageCount: {},
},
cssVariables: {
unused: [],
usageCount: {},
},
});

rcs.optimize();

expect(rcs.mapping.generate()).toEqual({
selectors: {
'#test': 'a',
'.aa': 'c',
'.ba': 'a',
'.ca': 'b',
},
});
});

test('should optimize everything', () => {
rcs.mapping.load({
selectors: {
'#a-first': 'a',
'#b-second': 'b',
'.a-first': 'a',
'.b-second': 'b',
'@a-first': 'a',
'@b-second': 'b',
'-a-first': 'a',
'-b-second': 'b',
},
});
rcs.statistics.load({
ids: {
unused: [],
usageCount: {
'a-first': 1,
'b-second': 3,
},
},
classes: {
unused: [],
usageCount: {
'a-first': 1,
'b-second': 3,
},
},
keyframes: {
unused: [],
usageCount: {
'a-first': 1,
'b-second': 3,
},
},
cssVariables: {
unused: [],
usageCount: {
'a-first': 1,
'b-second': 3,
},
},
});

rcs.optimize();

expect(rcs.mapping.generate()).toEqual({
selectors: {
'#a-first': 'b',
'#b-second': 'a',
'.a-first': 'b',
'.b-second': 'a',
'@a-first': 'b',
'@b-second': 'a',
'-a-first': 'b',
'-b-second': 'a',
},
});
});
38 changes: 38 additions & 0 deletions __tests__/optimize/separateMappingSelectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import separateMappingSelectors from '../../lib/optimize/separateMappingSelectors';

test('should do nothing', () => {
expect(separateMappingSelectors()).toEqual({
cssVariables: [],
keyframes: [],
classes: [],
ids: [],
});
});

test('should separate selectors correctly', () => {
expect(separateMappingSelectors({
'.test': 'a',
'#my-id': 'a',
'#my-other-id': 'b',
})).toEqual({
cssVariables: [],
keyframes: [],
classes: [['test', 'a']],
ids: [['my-id', 'a'], ['my-other-id', 'b']],
});
});

test('should separate selectors, keyframes and cssVariables correctly', () => {
expect(separateMappingSelectors({
'.test': 'a',
'#my-id': 'a',
'#my-other-id': 'b',
'-my-var': 'a',
'@my-keyframe': 'a',
})).toEqual({
cssVariables: [['my-var', 'a']],
keyframes: [['my-keyframe', 'a']],
classes: [['test', 'a']],
ids: [['my-id', 'a'], ['my-other-id', 'b']],
});
});
62 changes: 62 additions & 0 deletions __tests__/optimize/sortSelectors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import sortSelectors from '../../lib/optimize/sortSelectors';

test('should ignore usage count for sorting', () => {
const result = sortSelectors(
['my-selector', 'should-be-here'],
{
unused: [],
usageCount: {
'not-available-selector': 14,
'my-selector': 2,
},
},
);

expect(result).toEqual(['my-selector', 'should-be-here']);
});

test('should optimize', () => {
const result = sortSelectors(
['short-selector', 'a-very-long-selector'],
{
unused: [],
usageCount: {
'short-selector': 14,
'a-very-long-selector': 2,
},
},
);

expect(result).toEqual(['short-selector', 'a-very-long-selector']);
});

test('sort by occurrence count', () => {
const result = sortSelectors(
['short-selector', 'a-very-long-selector'],
{
unused: [],
usageCount: {
'short-selector': 2,
'a-very-long-selector': 14,
},
},
);

expect(result).toEqual(['a-very-long-selector', 'short-selector']);
});

test('should sort three by occurrence coun', () => {
const result = sortSelectors(
['first-id', 'second-id', 'third-id'],
{
unused: [],
usageCount: {
'first-id': 25,
'second-id': 32,
'third-id': 29,
},
},
);

expect(result).toEqual(['second-id', 'third-id', 'first-id']);
});
2 changes: 2 additions & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as nameGenerator from './nameGenerator';
import selectorsLibrary from './selectorsLibrary';
import keyframesLibrary from './keyframesLibrary';
import cssVariablesLibrary from './cssVariablesLibrary';
import optimize from './optimize';

import generate from './mapping/generate';
import load from './mapping/load';
Expand Down Expand Up @@ -34,6 +35,7 @@ export default {
generate,
load,
},
optimize,
statistics: {
generate: generateStats,
load: loadStats,
Expand Down
3 changes: 3 additions & 0 deletions lib/optimize/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import optimize from './optimize';

export default optimize;
71 changes: 71 additions & 0 deletions lib/optimize/optimize.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import generateMapping from '../mapping/generate';
import generateStatistics from '../statistics/generate';
import { getStatistics } from '../statistics';
import loadMapping from '../mapping/load';
import selectorsLibrary from '../selectorsLibrary';
import keyframesLibrary from '../keyframesLibrary';
import cssVariablesLibrary from '../cssVariablesLibrary';
import separateMappingSelectors from './separateMappingSelectors';
import sortSelectors from './sortSelectors';

const optimize = (): void => {
const mapping = generateMapping();
const statistics = getStatistics();

if (!statistics) {
return;
}

// sorting
// renaming into new mapping
const separateMapping = separateMappingSelectors(mapping.selectors);
const optimizedMapping: { [key in keyof ReturnType<typeof generateStatistics>]?: string[] } = {};

// optimize each library
Object.entries(separateMapping).forEach(([key, selectors]) => {
const statisticsData = statistics[key as 'ids'];
const newSortedSelectors = sortSelectors(selectors.map(([s]) => s), statisticsData);

optimizedMapping[key as 'ids'] = newSortedSelectors;
});

// could be a cold start but
// reset everything just in case
selectorsLibrary.reset();
keyframesLibrary.reset();
cssVariablesLibrary.reset();

// fill libraries with optimized mapping
Object.entries(optimizedMapping).forEach(([key, selectors]) => {
if (!selectors) {
return;
}

switch (key) {
case 'ids':
selectors.forEach((selector) => selectorsLibrary.set(`#${selector}`));

break;

case 'keyframes':
selectors.forEach((selector) => keyframesLibrary.set(`@${selector}`));

break;

case 'cssVariables':
selectors.forEach((selector) => cssVariablesLibrary.set(`--${selector}`));

break;

case 'classes':
default:
selectors.forEach((selector) => selectorsLibrary.set(`.${selector}`));
}
});

// load with the same attribute selectors
// these cannot be optimized yet
loadMapping({ attributeSelectors: mapping.attributeSelectors });
};

export default optimize;
Loading

0 comments on commit cd31dc0

Please sign in to comment.