Skip to content

Instantly share code, notes, and snippets.

@drzhbe
Created June 27, 2018 14:09
Show Gist options
  • Save drzhbe/4c0e3b9c3c4bfaec4da81db48b0888d2 to your computer and use it in GitHub Desktop.
Save drzhbe/4c0e3b9c3c4bfaec4da81db48b0888d2 to your computer and use it in GitHub Desktop.
function translateSelector(original){
let result = original.replace(simpleRe, (match, value) => {
return replace(match, value);
}).replace(attributeRe, (match, op, value) => {
switch (op) {
case '=':
console.log('=', match, value)
return replace(match, value);
case '^=':
console.log('^=', match, value)
return replaceStartsWith(match, value);
case '$=':
return replaceEndsWith(match, value);
case '*=':
return replaceContains(match, value);
default:
return match;
}
}).replace(/\s/g, '');
return result;
}
const replace = (match, value) => changeMap[value]
? match.replace(value, changeMap[value])
: match;
const replaceStartsWith = (match, value) => {
const key = Object.keys(changeMap).find(key => key.startsWith(value));
return key
? match.replace(value, changeMap[key]).replace('^=', '=') + ',' + match
: match;
};
const replaceEndsWith = (match, value) => {
const key = Object.keys(changeMap).find(key => key.endsWith(value));
return key
? match.replace(value, changeMap[key]).replace('$=', '=') + ',' + match
: match;
};
const replaceContains = (match, value) => {
const keys = Object.keys(changeMap).filter(key => key.indexOf(value) !== -1);
const change = keys
.map(key => match.replace(value, changeMap[key]).replace('*=', '='))
.join(',');
return change
? change + ',' + match
: match;
};
const lookup = (attribute) => {
return {
id: {
'id1': '__id1__',
'id2': '__id2__',
'id3': '__id3__',
'id4': '__id4__',
'id5': '__id5__'
},
class: {
'class1': '__class1__',
'class2': '__class2__',
'class3': '__class3__',
'class4': '__class4__',
'class5': '__class5__',
'foo': 'bar',
'first': 'last',
'fire': 'erif'
}
}[attribute]
};
// captures 1 group: value of selector
const simpleRe = /(?:\#|\.)(\w*)/g;
// captures 2 groups: operation and value of selector
const attributeRe = /\w*?\[(?:class|id)(=|\^=|\$=|\*=)'(\w*)']/g;
const changeMap = Object.assign(lookup('id'), lookup('class'));
describe('QuerySelector', function () {
describe('basic', function () {
it('should replace single id/class', function () {
expect(translateSelector('#id1')).toEqual('#__id1__');
expect(translateSelector('#id2')).toEqual('#__id2__');
expect(translateSelector('#id3')).toEqual('#__id3__');
expect(translateSelector('#id4')).toEqual('#__id4__');
expect(translateSelector('.class5')).toEqual('.__class5__');
});
it('should replace multiple ids and classes', function () {
expect(translateSelector('#id5, #id4, #id3, #id2, #id1')).toEqual('#__id5__,#__id4__,#__id3__,#__id2__,#__id1__');
expect(translateSelector('.class5#id4')).toEqual('.__class5__#__id4__');
expect(translateSelector('.class5#id4 > #id3')).toEqual('.__class5__#__id4__>#__id3__');
expect(translateSelector('#id6.class6 > #id3')).toEqual('#id6.class6>#__id3__');
});
});
describe('attributes', function () {
it('should replace a single id/class', function () {
expect(translateSelector(`div[id='id4']`)).toEqual(`div[id='__id4__']`);
expect(translateSelector(`div[class='class5']`)).toEqual(`div[class='__class5__']`);
});
it('should replace multiple attributes', function () {
expect(translateSelector(`div[id='id4'][class='class5']`)).toEqual(`div[id='__id4__'][class='__class5__']`);
expect(translateSelector(`div[class='class5'][id='id4']`)).toEqual(`div[class='__class5__'][id='__id4__']`);
expect(translateSelector(`div.class1[class='class5'].class2[id='id4'].class3`)).toEqual(`div.__class1__[class='__class5__'].__class2__[id='__id4__'].__class3__`);
});
it('should not replace an unsupported attribute', function () {
expect(translateSelector(`div[idz='id4']`)).toEqual(`div[idz='id4']`);
expect(translateSelector(`div[classz='class5']`)).toEqual(`div[classz='class5']`);
});
});
describe('complex attribute values', function () {
it('should support begins with...', function () {
expect(translateSelector(`div[class^='fo']`)).toEqual(
"div[class='bar']," +
"div[class^='fo']");
});
it('should support end with...', function () {
expect(translateSelector(`div[class$='o']`)).toEqual(
"div[class='bar']," +
"div[class$='o']");
});
it('should support contains...', function () {
expect(translateSelector(`div[class*='ir']`)).toEqual(
"div[class='last']," +
"div[class='erif']," +
"div[class*='ir']");
});
it.only('should replace multiple attributes', function () {
expect(translateSelector(`div[class^='fo'][class='class5']`)).toEqual(
"div[class='__class5__'][class='bar']," +
"div[class='__class5__'][class^='fo']");
expect(translateSelector(`div[class^='f'][class='class5']`)).toEqual(
"div[class='__class5__'][class='bar']," +
"div[class='__class5__'][class='last']," +
"div[class='__class5__'][class='erif']," +
"div[class='__class5__'][class^='f']");
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment