gogocode-plugin-vue
Version:
132 lines (113 loc) • 5.46 kB
JavaScript
const scriptUtils = require('../utils/scriptUtils');
const _ = require('lodash');
function callSeq(scopedFilterList, arr, index) {
const item = arr[index];
const name = item.name;
const args = item.args;
if (index === arr.length - 1) {
return name;
}
const filterName = scopedFilterList.includes(name) ? `${name}_filter` : `$filters.${name}`;
return `${filterName}(${callSeq(scopedFilterList, arr, index + 1)}${args.length ? `, ${args.join(', ')}` : ''})`;
}
module.exports = function (ast, api) {
const $ = api.gogocode;
const vueAppName = 'window.$vueApp';
const isVueFile = ast.parseOptions && ast.parseOptions.language === 'vue';
const script = isVueFile ? ast.find('<script></script>') : ast;
const vueName = scriptUtils.getVueName();
// Vue.filter() => app.config.globalProperties.$filters
script.find(`${vueName}.filter($_$1, $_$2)`).each((filterAst) => {
const match = filterAst.match;
const filterName = match[1][0].value;
if (match[2]) {
const functionStr = match[2][0].value;
filterAst.replaceBy(
`(${vueAppName}.config.globalProperties.$filters || (${vueAppName}.config.globalProperties.$filters = {})).${filterName} = ${functionStr}`
);
}
});
const filter = script.find(`filters: { $_$1: $_$2 }`);
const scopedFilterList = [];
if (filter.length) {
const filterMatch = filter.match;
if (filterMatch[1] && filterMatch[1].length) {
for (let i = 0; i < filterMatch[1].length; ++i) {
const filterName = filterMatch[1][i].value;
const functionStr = filterMatch[2][i].value;
scopedFilterList.push(filterName);
if (functionStr.indexOf(filterName) === 0) {
scriptUtils.addMethod(
script,
`${functionStr.replace(new RegExp(`^${filterName}`), `${filterName}_filter`)}`
);
} else {
scriptUtils.addMethod(script, `${filterName}_filter: ${functionStr}`);
}
}
}
}
// 干掉原来的 filter
script.replace('{ $$$1, filters: { $$$2 } }', '{ $$$1 }');
// x | A | B | C => C(B(A(x)))
function converFilterExpression(filterExpression) {
const filterExpressionArr = filterExpression.split(' | ');
if (filterExpressionArr.length === 1) {
return filterExpression;
}
const matchArr = filterExpressionArr.map((e) => {
// A or B(x)
const expItem = e.trim();
// https://play.gogocode.io/#code/N4IglgdgDgrgLgYQPYBMCmIBcICGAKADwBoBPIgLyIHIBnKgShCJAHckAnAa2XSxADMYEAMZwwSCAAI47HBBr8OAWzz8wAGzQBJCIqKScUMPqRQxEmvUnAAOlMnCLcSQBJJAXgNGAdAHMk-o7odpIOTpI0SDDswmgekmqaOorekdGxIWHyzjg0zp4ueGkxaPrAYDQACuwBskqYCTjqNGgAvvSZjtnSJFBxnrlw3jhwMnhUaARQ7Gg0NOIQ3nC9aAyd4fwQAHI4Sv0GecOj7OOT07PzEt7CTZpo3hC7qx32XXkOtzt7NPGDR2MTKYzOYLYbsXwwPYQOB0ejeJSGPA4cEeAB8riR4LhvjQEDQsjgaDw9BeoRmcGiUk2XzQdladiY4Gg8AAMnJfHxln0aMJ2GAzIyABa5apoUZgfFYGQwUogGgwABGADUJSwACorTkzDCtIA
const expressionStatementAst = $(expItem, { isProgram: false });
const expressionType = expressionStatementAst.attr('expression.type') || 'Identifier';
if (expressionType === 'CallExpression') {
const args = (expressionStatementAst.attr('expression.arguments') || []).map((arg) =>
$(arg).generate()
);
const fnName = expressionStatementAst.attr('expression.callee.name') || '';
return {
name: fnName,
args,
};
} else {
return {
name: expItem,
args: [],
};
}
});
const newCallExpression = callSeq(scopedFilterList, _.reverse(matchArr), 0);
return newCallExpression;
}
if (isVueFile) {
const template = ast.find('<template></template>');
template.find('<$_$1>$_$2</$_$1>').each((node) => {
const nodes = _.get(node, 'match.[2].[0].node', []);
nodes.forEach((node) => {
const html = _.get(node, 'content.value.content', '');
if (node.nodeType === 'text' && html) {
const html = _.get(node, 'content.value.content');
const reg = /\{\{\s*(.*?)\s*\}\}/g;
const newHtml = html.replace(reg, (_mustacheHtml, innerExp) => {
const newCallExpression = converFilterExpression(innerExp);
const newMustacheHtml = `{{ ${newCallExpression} }}`;
return newMustacheHtml;
});
node.content.value.content = newHtml;
}
});
});
template.find('<$_$1></$_$1>').each((node) => {
const attrs = node.attr('content.attributes') || [];
attrs.forEach((attr) => {
const key = _.get(attr, 'key.content', '');
const value = _.get(attr, 'value.content', '');
if (key.indexOf('v-bind:') === 0 || key.indexOf(':') === 0) {
attr.value.content = converFilterExpression(value);
}
});
});
}
return ast;
};