diff --git a/src/utils/lwcparser/fileutils/XmlFileProcessor.ts b/src/utils/lwcparser/fileutils/XmlFileProcessor.ts index 268c4c7..92caa5e 100644 --- a/src/utils/lwcparser/fileutils/XmlFileProcessor.ts +++ b/src/utils/lwcparser/fileutils/XmlFileProcessor.ts @@ -18,7 +18,7 @@ export class XmlFileProcessor implements FileProcessor { const filePath: string = file.location; const parser = new XmlParser(filePath); const fileDiffUtil = new FileDiffUtil(); - const fileContent: Map = parser.removeNode(XML_TAG_TO_REPLACE); + const fileContent: Map = parser.removeNode(XML_TAG_TO_REPLACE, namespace); if (fileContent) { const diff = fileDiffUtil.getFileDiff( file.name + file.ext, diff --git a/src/utils/lwcparser/jsParser/JavaScriptParser.ts b/src/utils/lwcparser/jsParser/JavaScriptParser.ts index 06acf9e..2c01148 100644 --- a/src/utils/lwcparser/jsParser/JavaScriptParser.ts +++ b/src/utils/lwcparser/jsParser/JavaScriptParser.ts @@ -4,30 +4,38 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable no-console */ import * as fs from 'fs'; -import * as parser from '@babel/parser'; +import { parse } from '@babel/parser'; import traverse from '@babel/traverse'; -import * as t from '@babel/types'; import { FileConstant } from '../fileutils/FileConstant'; const DEFAULT_NAMESPACE = 'c'; export class JavaScriptParser { // Function to replace strings in import declarations and write back to file - public replaceImportSource(filePath: string, oldSource: string): Map { + public replaceImportSource(filePath: string, oldSource: string): Map | null { const jsContentMap = new Map(); + // Read the JavaScript file const code = fs.readFileSync(filePath, 'utf-8'); + + // Skip processing if the file has specific markers or doesn't include the oldSource if (code.includes('Generated class DO NOT MODIFY') || !code.includes(oldSource + '/')) { return null; } + + // Store the original file content jsContentMap.set(FileConstant.BASE_CONTENT, code); - // Parse the code into an AST (Abstract Syntax Tree) - const ast = parser.parse(code, { + + // Parse the code into an AST + const ast = parse(code, { sourceType: 'module', // Specify that we are parsing an ES module - plugins: ['decorators'], // Include any relevant plugins if necessary (e.g., 'jsx', 'flow', etc.) + plugins: ['decorators'], // Include any relevant plugins if necessary }); - // Traverse the AST and modify import declarations + // Array to store replacement operations + const replacements: Array<{ original: string; updated: string }> = []; + + // Traverse the AST and identify import declarations traverse(ast, { ImportDeclaration(path) { const importSource = path.node.source.value; @@ -36,14 +44,20 @@ export class JavaScriptParser { if (importSource.includes(oldSource + '/')) { // Replace the old substring with the new substring const updatedSource = importSource.replace(oldSource, DEFAULT_NAMESPACE); - // Update the AST with the new source - path.node.source = t.stringLiteral(updatedSource); + replacements.push({ original: importSource, updated: updatedSource }); } }, }); - // jsContentMap.set(FileConstant.MODIFIED_CONTENT, generate(ast, {}, code).code); - jsContentMap.set(FileConstant.MODIFIED_CONTENT, code.replace(oldSource, DEFAULT_NAMESPACE)); - // return generate(ast, {}, code).code; + + // Apply replacements directly to the original code + let modifiedCode = code; + replacements.forEach(({ original, updated }) => { + const importRegex = new RegExp(`(["'])${original}(["'])`, 'g'); // Match the import string with quotes + modifiedCode = modifiedCode.replace(importRegex, `$1${updated}$2`); + }); + + // Store the modified content + jsContentMap.set(FileConstant.MODIFIED_CONTENT, modifiedCode); return jsContentMap; } diff --git a/src/utils/lwcparser/xmlParser/XmlParser.ts b/src/utils/lwcparser/xmlParser/XmlParser.ts index 35dbabb..4a82627 100644 --- a/src/utils/lwcparser/xmlParser/XmlParser.ts +++ b/src/utils/lwcparser/xmlParser/XmlParser.ts @@ -27,7 +27,7 @@ export class XmlParser { } } - public removeNode(tagName: string, index = 0): Map { + public removeNode(tagName: string, namespace: string, index = 0): Map { const xmlContentMap = new Map(); xmlContentMap.set(FileConstant.BASE_CONTENT, this.fileContent.replace('(/(<[^>]+?)/>/g', '$1 />')); if (!this.xmlDoc) { @@ -37,8 +37,13 @@ export class XmlParser { if (nodes.length > index) { const nodeToRemove = nodes[index]; - nodeToRemove.parentNode?.removeChild(nodeToRemove); - + if ( + nodeToRemove.firstChild != null && + nodeToRemove.firstChild.nodeValue != null && + nodeToRemove.firstChild.nodeValue.includes(namespace) + ) { + nodeToRemove.parentNode?.removeChild(nodeToRemove); + } const serializer = new XMLSerializer(); const xmlString: string = serializer.serializeToString(this.xmlDoc); xmlString.replace(/(<[^>]+?)\/>/g, '$1 />'); diff --git a/test/utils/lwc/parser/input/test.js b/test/utils/lwc/parser/input/test.js index 3cf515d..cf096e5 100644 --- a/test/utils/lwc/parser/input/test.js +++ b/test/utils/lwc/parser/input/test.js @@ -1,9 +1,14 @@ import { LightningElement, track, api } from 'lwc'; -import * as LABELS from './labels'; +import * as LABELS from 'vlocity_ins/labels'; import { cloneDeep } from 'runtime_omnistudio_common/lodash'; export default class TestInputJsFile extends LightningElement { labels = LABELS; + print() { + const test = 'vlocity_ins/testing'; + console.log(test); + } + @api set actionData(val) { if (val) { diff --git a/test/utils/lwc/parser/javascriptparser.test.ts b/test/utils/lwc/parser/javascriptparser.test.ts index ce9bfc1..0e6e975 100644 --- a/test/utils/lwc/parser/javascriptparser.test.ts +++ b/test/utils/lwc/parser/javascriptparser.test.ts @@ -34,7 +34,7 @@ describe('JavaScriptParser', () => { // Mock file reading readFileSyncStub.returns(mockFileContent); - parser.replaceImportSource(mockFilePath, 'oldSource'); + parser.replaceImportSource(mockFilePath, 'vlocity_ins'); // Assert that readFileSync was called with correct arguments expect(readFileSyncStub.calledWith(mockFilePath, 'utf-8')).to.be.false; @@ -42,7 +42,7 @@ describe('JavaScriptParser', () => { it('should replace import source correctly', () => { const mockFileContent = ` - import something from 'oldSource/module'; + import something from 'vlocity_ins/module'; `; // Mock file reading and writing diff --git a/test/utils/lwc/parser/xmlparser.test.ts b/test/utils/lwc/parser/xmlparser.test.ts index c3e8365..23270d6 100644 --- a/test/utils/lwc/parser/xmlparser.test.ts +++ b/test/utils/lwc/parser/xmlparser.test.ts @@ -12,13 +12,13 @@ describe('XmlParser', () => { }); it('should parse XML string into a Document object', () => { - const serializedXml = xmlParser.removeNode('runtimeNamespace').get('modified'); + const serializedXml = xmlParser.removeNode('runtimeNamespace', 'xyz').get('modified'); expect(serializedXml).contains(''); }); it('should remove the runtimeNamespace element correctly', () => { - const updatedXml = xmlParser.removeNode('runtimeNamespace'); + const updatedXml = xmlParser.removeNode('runtimeNamespace', 'xyz'); expect(updatedXml).not.contains(''); }); });