(fileContent, filePath)
| 147 | * code and a flag indicating if any changes were made. |
| 148 | */ |
| 149 | export function processFileContent(fileContent, filePath) { |
| 150 | // Optimization: a quick regex check is much faster than parsing every file. |
| 151 | if (!regexHtml.test(fileContent)) { |
| 152 | return { content: fileContent, hasChanges: false }; |
| 153 | } |
| 154 | |
| 155 | try { |
| 156 | const ast = acorn.parse(fileContent, {ecmaVersion: 'latest', sourceType: 'module'}); |
| 157 | addParentLinks(ast, null); |
| 158 | |
| 159 | let hasChanges = false; |
| 160 | |
| 161 | postOrderWalk(ast, (node) => { |
| 162 | if (node.type === 'TaggedTemplateExpression' && node.tag.type === 'Identifier' && node.tag.name === 'html') { |
| 163 | hasChanges = true; |
| 164 | |
| 165 | // As a quality-of-life feature, if a template is the return value of a method |
| 166 | // named `render`, we automatically rename the method to `createVdom`. |
| 167 | let current = node; |
| 168 | while (current.parent) { |
| 169 | const parent = current.parent; |
| 170 | if ((parent.type === 'MethodDefinition' || parent.type === 'Property') && parent.key.name === 'render') { |
| 171 | parent.key.name = 'createVdom'; |
| 172 | break; |
| 173 | } |
| 174 | current = parent; |
| 175 | } |
| 176 | |
| 177 | const templateLiteral = node.quasi; |
| 178 | const strings = templateLiteral.quasis.map(q => q.value.cooked); |
| 179 | const expressionCodeStrings = templateLiteral.expressions.map(exprNode => generate(exprNode)); |
| 180 | |
| 181 | const vdom = processHtmlTemplateLiteral(strings, expressionCodeStrings); |
| 182 | const vdomAst = jsonToAst(vdom); |
| 183 | |
| 184 | const parent = node.parent; |
| 185 | for (const key in parent) { |
| 186 | if (parent[key] === node) { |
| 187 | parent[key] = vdomAst; |
| 188 | return; |
| 189 | } |
| 190 | if (Array.isArray(parent[key])) { |
| 191 | const index = parent[key].indexOf(node); |
| 192 | if (index > -1) { |
| 193 | parent[key][index] = vdomAst; |
| 194 | return; |
| 195 | } |
| 196 | } |
| 197 | } |
| 198 | } |
| 199 | }); |
| 200 | |
| 201 | return { |
| 202 | content: hasChanges ? generate(ast) : fileContent, |
| 203 | hasChanges |
| 204 | }; |
| 205 | } catch (e) { |
| 206 | console.error(`Error processing HTML template in: ${filePath}`); |
no test coverage detected