import {Utility} from '../Utility'; import {FileSystemInstance, IFile} from "../File"; import {MapType, ParsingStrategy} from "./ParsingStrategy"; import {SortType} from "@kirinnee/core"; export class InverseInlineFlagResolver implements ParsingStrategy { MapType: MapType = MapType.FLAG; Target: string = "flags"; private util: Utility; private readonly comments: string[]; constructor(util: Utility, comments: string[] = []) { this.util = util; this.comments = [""].concat(comments).Sort(SortType.Descending, (s: string) => s.length); } Count(wFlag: object, files: FileSystemInstance[], map: Map, ignoreFile: boolean): Map { let keys: string[] = this.util.FlattenFlagObject(wFlag).MapKey((s: string) => this.ModifyFlagKeys(s)).Keys(); files.Each((f: FileSystemInstance) => { keys.Each((s: string) => { let num = ignoreFile ? 0 : f.sourceAbsolutePath.Count(s); let key = s.Omit(1).Skip(6); if (f["content"] != null && !f["binary"]) { let file: IFile = f as IFile; num += file.content.Count(s); } if (!map.has(key)) { map.set(key, num); } else { map.set(key, map.get(key)! + num); } }); }); return map; } CountPossibleUnaccountedFlags(files: FileSystemInstance[]): string[] { let flag = /flag!~[^~]*~/g; return files .Where(f => f["content"] != null && !f["binary"]) .Map(f => (f as IFile).content .LineBreak() .Map(s => s.Match(flag).Map(s => `${s}:${f.relativePath}`)) .Flatten() ) .Flatten() .concat( files.Map((f: FileSystemInstance) => f.destinationAbsolutePath.Match(flag)).Flatten() ) as string[]; } /** * The flag object to make decisions * @param wFlag flag object * @param files file streams` * @constructor */ ResolveFiles(wFlag: object, files: FileSystemInstance[]): FileSystemInstance[] { //Changes it to search term after flattening the configuration file let map: Map = this.util .FlattenFlagObject(wFlag) .MapKey(this.ModifyFlagKeys) .MapValue((v: boolean) => !v); return files .Where((f: FileSystemInstance) => this.ShouldStay(map, f.relativePath)) .Map((f: FileSystemInstance) => this.RemoveFlagSignature(map, f)); } ResolveContents(wFlag: object, files: FileSystemInstance[]): FileSystemInstance[] { let map: Map = this.util .FlattenFlagObject(wFlag) .MapKey(this.ModifyFlagKeys) .MapValue((v: boolean) => !v); return files.Map((f: FileSystemInstance) => this.ResolveFileContent(map, f)); } ModifyFlagKeys(input: string): string { return 'flag!~' + input + '~'; } /** * Check if target file should stay base on flag map * @param map flag map * @param checkTarget file path * @constructor */ ShouldStay(map: Map, checkTarget: string) { return map.Where((k: string, v: boolean) => !checkTarget.includes(k) || v).size === map.size; } // noinspection JSMethodCanBeStatic /** * Removes the injected code signature from files and directories * @param map key value pair of what to remove * @param f the file to remove from * @constructor */ RemoveFlagSignature(map: Map, f: FileSystemInstance): FileSystemInstance { f.destinationAbsolutePath = f.destinationAbsolutePath.Without(map.Arr().Map((s: [string, boolean]) => s["0"])); return f; }; ResolveFileContent(map: Map, f: FileSystemInstance): FileSystemInstance { if (f['content'] != null && !f["binary"]) { let file: IFile = f as IFile; file.content = file.content .LineBreak() .Where((s: string) => this.ShouldStay(map, s)) .Map((s: string) => s.Without(this.RemoveArray(map))) .join("\n"); return file; } return f; } private RemoveArray(map: Map): string[] { let nestedArr: string[][] = this.comments.Map((c: string) => map.Keys().Map((k: string) => c + k)); return nestedArr.Flatten(); } }