@glimmer/syntax
Version:
126 lines (105 loc) • 11.3 kB
JavaScript
import { isKeyword } from './keywords';
import { preprocess } from './parser/tokenizer-event-handlers';
import traverse from './traversal/traverse';
/**
* Gets the correct Token from the Node based on it's type
*/
function tokensFromType(node, scopedTokens, options) {
if (node.type === 'PathExpression') {
if (node.head.type === 'AtHead' || node.head.type === 'ThisHead') {
return;
}
const possbleToken = node.head.name;
if (scopedTokens.indexOf(possbleToken) === -1) {
return possbleToken;
}
} else if (node.type === 'ElementNode') {
const {
tag
} = node;
const char = tag.charAt(0);
if (char === ':' || char === '@') {
return;
}
if (!options.includeHtmlElements && tag.indexOf('.') === -1 && tag.toLowerCase() === tag) {
return;
}
if (tag.substr(0, 5) === 'this.') {
return;
}
if (scopedTokens.indexOf(tag) !== -1) {
return;
}
return tag;
}
}
/**
* Adds tokens to the tokensSet based on their node.type
*/
function addTokens(tokensSet, node, scopedTokens, options) {
const maybeTokens = tokensFromType(node, scopedTokens, options);
(Array.isArray(maybeTokens) ? maybeTokens : [maybeTokens]).forEach(maybeToken => {
if (maybeToken !== undefined && maybeToken[0] !== '@') {
const maybeTokenFirstSegment = maybeToken.split('.')[0];
if (!scopedTokens.includes(maybeTokenFirstSegment)) {
tokensSet.add(maybeToken.split('.')[0]);
}
}
});
}
/**
* Parses and traverses a given handlebars html template to extract all template locals
* referenced that could possible come from the parent scope. Can exclude known keywords
* optionally.
*/
export function getTemplateLocals(html, options = {
includeHtmlElements: false,
includeKeywords: false
}) {
const ast = preprocess(html);
const tokensSet = new Set();
const scopedTokens = [];
traverse(ast, {
Block: {
enter({
blockParams
}) {
blockParams.forEach(param => {
scopedTokens.push(param);
});
},
exit({
blockParams
}) {
blockParams.forEach(() => {
scopedTokens.pop();
});
}
},
ElementNode: {
enter(node) {
node.blockParams.forEach(param => {
scopedTokens.push(param);
});
addTokens(tokensSet, node, scopedTokens, options);
},
exit({
blockParams
}) {
blockParams.forEach(() => {
scopedTokens.pop();
});
}
},
PathExpression(node) {
addTokens(tokensSet, node, scopedTokens, options);
}
});
let tokens = [];
tokensSet.forEach(s => tokens.push(s));
if (!(options === null || options === void 0 ? void 0 : options.includeKeywords)) {
tokens = tokens.filter(token => !isKeyword(token));
}
return tokens;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3N5bnRheC9saWIvZ2V0LXRlbXBsYXRlLWxvY2Fscy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxTQUFTLFNBQVQsUUFBMEIsWUFBMUI7QUFDQSxTQUFTLFVBQVQsUUFBMkIsbUNBQTNCO0FBQ0EsT0FBTyxRQUFQLE1BQXFCLHNCQUFyQjtBQVFBOzs7O0FBR0EsU0FBUyxjQUFULENBQ0UsSUFERixFQUVFLFlBRkYsRUFHRSxPQUhGLEVBR21DO0FBRWpDLE1BQUksSUFBSSxDQUFDLElBQUwsS0FBYyxnQkFBbEIsRUFBb0M7QUFDbEMsUUFBSSxJQUFJLENBQUMsSUFBTCxDQUFVLElBQVYsS0FBbUIsUUFBbkIsSUFBK0IsSUFBSSxDQUFDLElBQUwsQ0FBVSxJQUFWLEtBQW1CLFVBQXRELEVBQWtFO0FBQ2hFO0FBQ0Q7O0FBRUQsVUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUwsQ0FBVSxJQUEvQjs7QUFFQSxRQUFJLFlBQVksQ0FBQyxPQUFiLENBQXFCLFlBQXJCLE1BQXVDLENBQUMsQ0FBNUMsRUFBK0M7QUFDN0MsYUFBTyxZQUFQO0FBQ0Q7QUFDRixHQVZELE1BVU8sSUFBSSxJQUFJLENBQUMsSUFBTCxLQUFjLGFBQWxCLEVBQWlDO0FBQ3RDLFVBQU07QUFBRSxNQUFBO0FBQUYsUUFBVSxJQUFoQjtBQUVBLFVBQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxNQUFKLENBQVcsQ0FBWCxDQUFiOztBQUVBLFFBQUksSUFBSSxLQUFLLEdBQVQsSUFBZ0IsSUFBSSxLQUFLLEdBQTdCLEVBQWtDO0FBQ2hDO0FBQ0Q7O0FBRUQsUUFBSSxDQUFDLE9BQU8sQ0FBQyxtQkFBVCxJQUFnQyxHQUFHLENBQUMsT0FBSixDQUFZLEdBQVosTUFBcUIsQ0FBQyxDQUF0RCxJQUEyRCxHQUFHLENBQUMsV0FBSixPQUFzQixHQUFyRixFQUEwRjtBQUN4RjtBQUNEOztBQUVELFFBQUksR0FBRyxDQUFDLE1BQUosQ0FB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Q0FBekI7O0FBRUEsTUFBSSxFQUFDLE9BQU8sS0FBQSxJQUFQLElBQUEsT0FBTyxLQUFBLEtBQUEsQ0FBUCxHQUFPLEtBQUEsQ0FBUCxHQUFBLE9BQU8sQ0FBRSxlQUFWLENBQUosRUFBK0I7QUFDN0IsSUFBQSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQVAsQ0FBZSxLQUFELElBQVcsQ0FBQyxTQUFTLENBQUMsS0FBRCxDQUFuQyxDQUFUO0FBQ0Q7O0FBRUQsU0FBTyxNQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBpc0tleXdvcmQgfSBmcm9tICcuL2tleXdvcmRzJztcbmltcG9ydCB7IHByZXByb2Nlc3MgfSBmcm9tICcuL3BhcnNlci90b2tlbml6ZXItZXZlbnQtaGFuZGxlcnMnO1xuaW1wb3J0IHRyYXZlcnNlIGZyb20gJy4vdHJhdmVyc2FsL3RyYXZlcnNlJztcbmltcG9ydCAqIGFzIEFTVHYxIGZyb20gJy4vdjEvYXBpJztcblxuaW50ZXJmYWNlIEdldFRlbXBsYXRlTG9jYWxzT3B0aW9ucyB7XG4gIGluY2x1ZGVLZXl3b3Jkcz86IGJvb2xlYW47XG4gIGluY2x1ZGVIdG1sRWxlbWVudHM/OiBib29sZWFuO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGNvcnJlY3QgVG9rZW4gZnJvbSB0aGUgTm9kZSBiYXNlZCBvbiBpdCdzIHR5cGVcbiAqL1xuZnVuY3Rpb24gdG9rZW5zRnJvbVR5cGUoXG4gIG5vZGU6IEFTVHYxLk5vZGUsXG4gIHNjb3BlZFRva2Vuczogc3RyaW5nW10sXG4gIG9wdGlvbnM6IEdldFRlbXBsYXRlTG9jYWxzT3B0aW9uc1xuKTogc3RyaW5nIHwgdm9pZCB7XG4gIGlmIChub2RlLnR5cGUgPT09ICdQYXRoRXhwcmVzc2lvbicpIHtcbiAgICBpZiAobm9kZS5oZWFkLnR5cGUgPT09ICdBdEhlYWQnIHx8IG5vZGUuaGVhZC50eXBlID09PSAnVGhpc0hlYWQnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcG9zc2JsZVRva2VuID0gbm9kZS5oZWFkLm5hbWU7XG5cbiAgICBpZiAoc2NvcGVkVG9rZW5zLmluZGV4T2YocG9zc2JsZVRva2VuKSA9PT0gLTEpIHtcbiAgICAgIHJldHVybiBwb3NzYmxlVG9rZW47XG4gICAgfVxuICB9IGVsc2UgaWYgKG5vZGUudHlwZSA9PT0gJ0VsZW1lbnROb2RlJykge1xuICAgIGNvbnN0IHsgdGFnIH0gPSBub2RlO1xuXG4gICAgY29uc3QgY2hhciA9IHRhZy5jaGFyQXQoMCk7XG5cbiAgICBpZiAoY2hhciA9PT0gJzonIHx8IGNoYXIgPT09ICdAJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghb3B0aW9ucy5pbmNsdWRlSHRtbEVsZW1lbnRzICYmIHRhZy5pbmRleE9mKCcuJykgPT09IC0xICYmIHRhZy50b0xvd2VyQ2FzZSgpID09PSB0YWcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGFnLnN1YnN0cigwLCA1KSA9PT0gJ3RoaXMuJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmIChzY29wZWRUb2tlbnMuaW5kZXhPZih0YWcpICE9PSAtMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHJldHVybiB0YWc7XG4gIH1cbn1cblxuLyoqXG4gKiBBZGRzIHRva2VucyB0byB0aGUgdG9rZW5zU2V0IGJhc2VkIG9uIHRoZWlyIG5vZGUudHlwZVxuICovXG5mdW5jdGlvbiBhZGRUb2tlbnMoXG4gIHRva2Vuc1NldDogU2V0PHN0cmluZz4sXG4gIG5vZGU6IEFTVHYxLk5vZGUsXG4gIHNjb3BlZFRva2Vuczogc3RyaW5nW10sXG4gIG9wdGlvbnM6IEdldFRlbXBsYXRlTG9jYWxzT3B0aW9uc1xuKSB7XG4gIGNvbnN0IG1heWJlVG9rZW5zID0gdG9rZW5zRnJvbVR5cGUobm9kZSwgc2NvcGVkVG9rZW5zLCBvcHRpb25zKTtcblxuICAoQXJyYXkuaXNBcnJheShtYXliZVRva2VucykgPyBtYXliZVRva2VucyA6IFttYXliZVRva2Vuc10pLmZvckVhY2goKG1heWJlVG9rZW4pID0+IHtcbiAgICBpZiAobWF5YmVUb2tlbiAhPT0gdW5kZWZpbmVkICYmIG1heWJlVG9rZW5bMF0gIT09ICdAJykge1xuICAgICAgY29uc3QgbWF5YmVUb2tlbkZpcnN0U2VnbWVudCA9IG1heWJlVG9rZW4uc3BsaXQoJy4nKVswXTtcbiAgICAgIGlmICghc2NvcGVkVG9rZW5zLmluY2x1ZGVzKG1heWJlVG9rZW5GaXJzdFNlZ21lbnQpKSB7XG4gICAgICAgIHRva2Vuc1NldC5hZGQobWF5YmVUb2tlbi5zcGxpdCgnLicpWzBdKTtcbiAgICAgIH1cbiAgICB9XG4gIH0pO1xufVxuXG4vKipcbiAqIFBhcnNlcyBhbmQgdHJhdmVyc2VzIGEgZ2l2ZW4gaGFuZGxlYmFycyBodG1sIHRlbXBsYXRlIHRvIGV4dHJhY3QgYWxsIHRlbXBsYXRlIGxvY2Fsc1xuICogcmVmZXJlbmNlZCB0aGF0IGNvdWxkIHBvc3NpYmxlIGNvbWUgZnJvbSB0aGUgcGFyZW50IHNjb3BlLiBDYW4gZXhjbHVkZSBrbm93biBrZXl3b3Jkc1xuICogb3B0aW9uYWxseS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFRlbXBsYXRlTG9jYWxzKFxuICBodG1sOiBzdHJpbmcsXG4gIG9wdGlvbnM6IEdldFRlbXBsYXRlTG9jYWxzT3B0aW9ucyA9IHtcbiAgICBpbmNsdWRlSHRtbEVsZW1lbnRzOiBmYWxzZSxcbiAgICBpbmNsdWRlS2V5d29yZHM6IGZhbHNlLFxuICB9XG4pOiBzdHJpbmdbXSB7XG4gIGNvbnN0IGFzdCA9IHByZXByb2Nlc3MoaHRtbCk7XG4gIGNvbnN0IHRva2Vuc1NldCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCBzY29wZWRUb2tlbnM6IHN0cmluZ1tdID0gW107XG5cbiAgdHJhdmVyc2UoYXN0LCB7XG4gICAgQmxvY2s6IHtcbiAgICAgIGVudGVyKHsgYmxvY2tQYXJhbXMgfSkge1xuICAgICAgICBibG9ja1BhcmFtcy5mb3JFYWNoKChwYXJhbSkgPT4ge1xuICAgICAgICAgIHNjb3BlZFRva2Vucy5wdXNoKHBhcmFtKTtcbiAgICAgICAgfSk7XG4gICAgICB9LFxuXG4gICAgICBleGl0KHsgYmxvY2tQYXJhbXMgfSkge1xuICAgICAgICBibG9ja1BhcmFtcy5mb3JFYWNoKCgpID0+IHtcbiAgICAgICAgICBzY29wZWRUb2tlbnMucG9wKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9LFxuXG4gICAgRWxlbWVudE5vZGU6IHtcbiAgICAgIGVudGVyKG5vZGUpIHtcbiAgICAgICAgbm9kZS5ibG9ja1BhcmFtcy5mb3JFYWNoKChwYXJhbSkgPT4ge1xuICAgICAgICAgIHNjb3BlZFRva2Vucy5wdXNoKHBhcmFtKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGFkZFRva2Vucyh0b2tlbnNTZXQsIG5vZGUsIHNjb3BlZFRva2Vucywgb3B0aW9ucyk7XG4gICAgICB9LFxuXG4gICAgICBleGl0KHsgYmxvY2tQYXJhbXMgfSkge1xuICAgICAgICBibG9ja1BhcmFtcy5mb3JFYWNoKCgpID0+IHtcbiAgICAgICAgICBzY29wZWRUb2tlbnMucG9wKCk7XG4gICAgICAgIH0pO1xuICAgICAgfSxcbiAgICB9LFxuXG4gICAgUGF0aEV4cHJlc3Npb24obm9kZSkge1xuICAgICAgYWRkVG9rZW5zKHRva2Vuc1NldCwgbm9kZSwgc2NvcGVkVG9rZW5zLCBvcHRpb25zKTtcbiAgICB9LFxuICB9KTtcblxuICBsZXQgdG9rZW5zOiBzdHJpbmdbXSA9IFtdO1xuXG4gIHRva2Vuc1NldC5mb3JFYWNoKChzKSA9PiB0b2tlbnMucHVzaChzKSk7XG5cbiAgaWYgKCFvcHRpb25zPy5pbmNsdWRlS2V5d29yZHMpIHtcbiAgICB0b2tlbnMgPSB0b2tlbnMuZmlsdGVyKCh0b2tlbikgPT4gIWlzS2V5d29yZCh0b2tlbikpO1xuICB9XG5cbiAgcmV0dXJuIHRva2Vucztcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=