Skip to content

Instantly share code, notes, and snippets.

@developit
Created May 28, 2020 03:18
Show Gist options
  • Save developit/61d009284458ad4d757991e1756b7f41 to your computer and use it in GitHub Desktop.
Save developit/61d009284458ad4d757991e1756b7f41 to your computer and use it in GitHub Desktop.
module.exports = {
create(context) {
return {
TaggedTemplateExpression(node) {
if (!isIdentifier(node.tag, 'html')) return;
const END_QUOTE = {
`'`: /^[^']*'/g,
`"`: /^[^"]*"/g
}
const matchers = [
['text', /[^<>"]*/, ['<', 'expression']],
['<', /^</g, ['tag name', 'expression', '/']],
['>', /^>/g],
['/', /^\//g, ['tag name', 'expression']],
['self-closing', /^\s*\/>/g, ['text']],
['tag name', /[a-z][a-z0-9-]*/gi],
['expression', /$/g, [advance]],
['attribute', /^\s+[a-z0-9_-$.]+/gi, ['attribute', 'self-closing']],
['attribute', /^\s+[a-z0-9_-$.]+=/gi, ['attribute value']],
['attribute value', /^(?:(['"])[^\1]*|[^\s'"]*)/gi, ['string', 'expression']],
['end attribute', ([quote]) => END_QUOTE[quote] || /^/g, ['attribute', 'self-closing']],
];
const m = matches.reduce((m, arr) => m.set(arr[0], [].concat(m.get(arr[0]), arr]), new Map());
let str;
let i = 0;
function advance() {
str = node.quasi.quasis[i++];
}
function next(...matches) {
for (let i=0; i<matches.length; i++) {
let matcher = m.get(matches[i]);
if (!Array.isArray(matcher)) matcher = [matcher];
for (let j=0; j<matcher.length; j++) {
let [name, reg] = matches[i];
if (typeof reg === 'function') reg = reg(match);
reg.lastIndex = index;
const result = reg.exec(str);
if (result) {
index = reg.lastIndex;
type = name;
match = result;
current = matches[i];
return result;
}
}
}
throw 'Expected one of: ' + matches.map(m => m[0]);
}
let index = 0;
let current;
let type;
let match;
advance();
next('text');
while (str) {
next(current[2]);
}
return true;
}
};
}
};
const is = (node, type) => node && node.type === type;
const isIdentifier = (node, name) => is(node, 'Identifier') && node.name === name;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment