1// Copyright 2022 Google LLC 2 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6 7// http://www.apache.org/licenses/LICENSE-2.0 8 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License.import { exec } from 'child_process'; 14 15import DOM, { INewTag, IUpdateTag } from './DOMFuncs'; 16import { FileIO } from './FileIO'; 17import { IMigItem, IMigrationMap } from './migrationList'; 18 19export type TResultExistingEval = ['update' | 'duplicate', IUpdateTag] | void; 20export type TResultMissingEval = INewTag | void; 21 22interface IProcessXML { 23 attr?: string; 24 containerQuery?: string; 25 evalExistingEntry?: TEvalExistingEntry; 26 evalMissingEntry?: TEvalMissingEntry; 27 hidable?: boolean; 28 path: string; 29 step: number; 30 tagName: string; 31} 32 33export type TEvalExistingEntry = ( 34 attrname: string, 35 migItem: IMigItem, 36 qItem: Element 37) => TResultExistingEval; 38 39export type TEvalMissingEntry = (originalToken: string, migItem: IMigItem) => TResultMissingEval; 40 41export async function processQueriedEntries( 42 migrationMap: IMigrationMap, 43 { 44 attr = 'name', 45 containerQuery = '*', 46 evalExistingEntry, 47 path, 48 step, 49 tagName, 50 evalMissingEntry, 51 }: IProcessXML 52) { 53 const doc = await FileIO.loadXML(path); 54 55 const containerElement = 56 (containerQuery && doc.querySelector(containerQuery)) || doc.documentElement; 57 58 migrationMap.forEach((migItem, originalToken) => { 59 migItem.step[step] = 'ignore'; 60 61 const queryTiems = containerElement.querySelectorAll( 62 `${tagName}[${attr}="${originalToken}"]` 63 ); 64 65 if (evalMissingEntry) { 66 const addinOptions = evalMissingEntry(originalToken, migItem); 67 68 if (queryTiems.length == 0 && containerElement && addinOptions) { 69 DOM.addEntry(containerElement, addinOptions); 70 migItem.step[step] = 'add'; 71 return; 72 } 73 } 74 75 if (evalExistingEntry) 76 queryTiems.forEach((qEl) => { 77 const attrName = qEl.getAttribute(attr); 78 const migItem = migrationMap.get(attrName || ''); 79 80 if (!attrName || !migItem) return; 81 82 const updateOptions = evalExistingEntry(attrName, migItem, qEl); 83 84 if (!updateOptions) return; 85 86 const [processType, processOptions] = updateOptions; 87 88 switch (processType) { 89 case 'update': 90 if (DOM.updateElement(qEl, processOptions)) migItem.step[step] = 'update'; 91 break; 92 93 case 'duplicate': 94 if (DOM.duplicateEntryWithChange(qEl, processOptions)) 95 migItem.step[step] = 'duplicate'; 96 break; 97 } 98 }); 99 }); 100 101 await FileIO.saveFile(doc.documentElement.outerHTML, path); 102} 103