-
-
Save developit/61d009284458ad4d757991e1756b7f41 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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