Open theydy opened 3 years ago
const loaderUtils = require('loader-utils'); const formatSource = require('./formatSource.js'); module.exports = function (source) { try { const { // 模块所在的根目录 rootContext: rootPath, // 资源文件路径 resourcePath: filePath, } = this; /** * example: * rootPath: /home/xxx/project * filePath: /home/xxx/project/src/ooo/xxx.js * relativePath: src/ooo/xxx.js */ const relativePath = filePath.slice(rootPath.length + 1); const options = loaderUtils.getOptions(this); if ((options.exclude || []).length > 0) { const isSkip = options.exclude.some((path) => filePath.includes(path)); if (isSkip) { return source; } } const code = formatSource(source, relativePath); return code; } catch (error) { console.error('\nvue-dev-inspector compiler error', error); return source; } };
const compiler = require('@vue/compiler-dom'); function transform( ast, nodeList, options = { entry: (node, nodeList) => {}, out: (node, nodeList) => {}, } ) { const _traverse = (ast, options) => { options.entry && options.entry(ast, nodeList); ast.children && ast.children.map((node) => { _traverse(node, options); }); options.out && options.out(ast, nodeList); }; _traverse(ast, options); } function generator(nodeList, source) { let code = ''; // 如果 vue 文件中自定义块,必须写针对自定义块的 rule,否则 vue-loader 会报错,具体看 // https://theydy.github.io/notebook/vue/other.html#vue-loader-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%9D%97 let start = 0; for (let i = 0; i < nodeList.length; i++) { const node = nodeList[i]; code += source.slice(start, node.insertIndex); code += node.desc; if (i === nodeList.length - 1) { code += source.slice(node.insertIndex); } else { start = node.insertIndex; } } return code; } function vueDevInspectorLoader(source, relativePath) { const ast = compiler.parse(source); const template = ast.children.find((node) => node.tag === 'template'); // 如果没有 template 直接返回 if (!template) return source; const nodeList = []; transform(template, nodeList, { entry: (node, nodeList) => { if (!node.tag) return; const nodeStart = node.loc.start.offset; const hasProps = node.props && node.props.length; const insertIndex = !hasProps ? nodeStart + node.tag.length + 1 : node.props[node.props.length - 1].loc.end.offset; const target = { insertIndex, desc: ` data-inspector-line="${node.loc.start.line}" data-inspector-column="${node.loc.start.column}" data-inspector-relative-path="${relativePath}"`, }; nodeList.push(target); }, }); let code = generator(nodeList, source); return code; } module.exports = vueDevInspectorLoader;
vue-dev-inspector.js
formatSource.js