Skip to content

Commit

Permalink
Fix filter importing with glob pattern in URLs
Browse files Browse the repository at this point in the history
There was a problem with importing URLs containing glob patterns which
are also used for node and selector filtering.

Fixes #158
  • Loading branch information
maoberlehner committed Dec 9, 2017
1 parent 0c66916 commit 0a24256
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,40 +7,84 @@ describe(`parseNodeFilters()`, () => {
expect(typeof parseNodeFilters).toBe(`function`);
});

test(`It should return an empty array if no filters were found.`, () => {
test(`It should return an empty array if there is no filter divider.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();

const urlWithoutFilters = `style.scss`;

const nodeFilters = parseNodeFilters(urlWithoutFilters);
const expectedResult: any[] = [];

expect(nodeFilters).toEqual(expectedResult);
});

test(`It should return an empty array if no filters were found.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();
const urlWithoutFilters = `{ .some-thing } from style.scss`;

const nodeFilters = parseNodeFilters(urlWithoutFilters);
const expectedResult: any[] = [];

expect(nodeFilters).toEqual(expectedResult);
});

test(`It should return node filters from URL.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();

const urlWithFilters = `[at-rules, mixins] from style.scss`;

const nodeFilters = parseNodeFilters(urlWithFilters);
const expectedResult = [
`at-rules`,
`mixins`,
];

expect(nodeFilters).toEqual(expectedResult);
});

test(`It should ignore brackets used in a glob pattern.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();
const urlWithGlobPattern = `[!_]style.scss`;

const nodeFilters = parseNodeFilters(urlWithGlobPattern);
const expectedResult: any[] = [];

expect(nodeFilters).toEqual(expectedResult);
});

test(`It should return node filters from URL with glob pattern.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();
const urlWithFilters = `[at-rules, mixins] from [!_]style.scss`;

const nodeFilters = parseNodeFilters(urlWithFilters);
const expectedResult = [
`at-rules`,
`mixins`,
];

expect(nodeFilters).toEqual(expectedResult);
});

test(`It should return node filters when filter contains \`from\`.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();
const urlWithFilters = `[at-rules, mixins, from] from style.scss`;

const nodeFilters = parseNodeFilters(urlWithFilters);
const expectedResult = [
`at-rules`,
`mixins`,
`from`,
];

expect(nodeFilters).toEqual(expectedResult);
});

test(`It should trim empty filter from multi line URL.`, () => {
const parseNodeFilters = parseNodeFiltersFactory();

const urlWithFilters = `[
at-rules,
mixins,
] from style.scss`;
const nodeFilters = parseNodeFilters(urlWithFilters);

const nodeFilters = parseNodeFilters(urlWithFilters);
const expectedResult = [
`at-rules`,
`mixins`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import { IFilterParser } from '../interfaces/IFilterParser';

export function parseNodeFiltersFactory(): IFilterParser {
return (url: string) => {
const filterDivider = /[\n\r\s]+from[\n\r\s]+/;

if (!filterDivider.test(url)) {
return [];
}

const nodeFiltersMatch = url
.split(filterDivider)[0]
.replace(/{.*?\/.*?\/.*?}/, ``)
.match(/\[([\s\S]*)\]/);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,26 @@ describe(`parseSelectorFilters()`, () => {
expect(typeof parseSelectorFilters).toBe(`function`);
});

test(`It should return an empty array if there is no filter divider.`, () => {
const parseSelectorFilters = parseSelectorFiltersFactory(
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);
const urlWithoutFilters = `style.scss`;

const selectorFilters = parseSelectorFilters(urlWithoutFilters);
const expectedResult: any[] = [];

expect(selectorFilters).toEqual(expectedResult);
});

test(`It should return an empty array if no filters were found.`, () => {
const parseSelectorFilters = parseSelectorFiltersFactory(
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);
const urlWithoutFilters = `[some-thing] from style.scss`;

const urlWithoutFilters = `style.scss`;
const selectorFilters = parseSelectorFilters(urlWithoutFilters);
const expectedResult: any[] = [];

Expand All @@ -45,8 +58,8 @@ describe(`parseSelectorFilters()`, () => {
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);

const urlWithFilters = `{ .btn, .btn-alert } from style.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult = [
{
Expand All @@ -67,8 +80,8 @@ describe(`parseSelectorFilters()`, () => {
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);

const urlWithFilters = `{ .btn as .button, .btn-alert as .button-alert } from style.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult = [
{
Expand All @@ -84,13 +97,74 @@ describe(`parseSelectorFilters()`, () => {
expect(selectorFilters).toEqual(expectedResult);
});

test(`It should handle special characters.`, () => {
test(`It should ignore curly brackets used in a glob pattern.`, () => {
const parseSelectorFilters = parseSelectorFiltersFactory(
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);
const urlWithFilters = `style{1}.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult: any[] = [];

expect(selectorFilters).toEqual(expectedResult);
});

test(`It should return selector filters from URL with glob pattern.`, () => {
const parseSelectorFilters = parseSelectorFiltersFactory(
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);
const urlWithFilters = `{ .btn, .btn-alert } from style{1}.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult = [
{
replacement: undefined,
selector: `.btn`,
},
{
replacement: undefined,
selector: `.btn-alert`,
},
];

expect(selectorFilters).toEqual(expectedResult);
});

test(`It should return selector filters when filter contains \`from\`.`, () => {
const parseSelectorFilters = parseSelectorFiltersFactory(
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);
const urlWithFilters = `{ .btn, .btn-alert, .from } from style.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult = [
{
replacement: undefined,
selector: `.btn`,
},
{
replacement: undefined,
selector: `.btn-alert`,
},
{
replacement: undefined,
selector: `.from`,
},
];

expect(selectorFilters).toEqual(expectedResult);
});

test(`It should handle special characters.`, () => {
const parseSelectorFilters = parseSelectorFiltersFactory(
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);
const urlWithFilters = `{ .btn@m as .button@m } from style.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult = [
{
Expand All @@ -107,8 +181,8 @@ describe(`parseSelectorFilters()`, () => {
dependencies.processRawSelectorFilters,
dependencies.splitSelectorFilter,
);

const urlWithFilters = `{ /^\\.btn(.*)/i as .button$1 } from style.scss`;

const selectorFilters = parseSelectorFilters(urlWithFilters);
const expectedResult = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ export function parseSelectorFiltersFactory(
splitSelectorFilter: ISplitSelectorFilter,
): IParseSelectorFilters {
return (url: string) => {
const selectorFiltersMatch = url.match(/{([\s\S]*)}/);
const filterDivider = /[\n\r\s]+from[\n\r\s]+/;

if (!filterDivider.test(url)) {
return [];
}

const selectorFiltersMatch = url
.split(filterDivider)[0]
.match(/{([\s\S]*)}/);

if (!selectorFiltersMatch) {
return [];
Expand Down

0 comments on commit 0a24256

Please sign in to comment.