import { ExtendedRegex } from "../ExtendedRegex"; import { RegExpUtility } from "../RegExpUtility"; import { RegexReplacement, TextReplacement } from "./TextReplacement"; import { TextSelectionRange } from "./TextSelectionRange"; import { RegexStartEndSelector, TextSelector } from "./TextSelector"; export class TextReplacer { selector:TextSelector; replacements:TextReplacement[] = []; process( source:string ):string { let ranges = this.selector ? this.selector.select( source ) : [ TextSelectionRange.fromString( source ) ]; let replacedRanges:string[] = []; if ( this.selector ) { console.log( "RANGES", this.selector + "", ranges.map( r => r.start === 0 && r.length === source.length ? ( "complete source (" + source.length+ ")" ) : ( r.start + ":" + r.end ) ).join() ); } ranges.forEach( range => { let replacingSelection = range.get( source ); this.replacements.forEach( r => { replacingSelection = r.replace( replacingSelection ); } ); replacedRanges.push( replacingSelection ); } ); let replacedSource = TextSelectionRange.replaceRanges( source, ranges, replacedRanges ); return replacedSource; } setRegexStartEndSelection( start:RegExp, end:RegExp, inner:boolean = false ) { let regexSelector = new RegexStartEndSelector(); regexSelector.startRegex = start; regexSelector.endRegex = end; regexSelector.inner = inner; regexSelector.multiple = true; this.selector = regexSelector; } setOuterTagSelection( tag:string ) { this.setRegexStartEndSelection( new RegExp( `<${tag}` ), new RegExp( `<\\/${tag}>` ) ) } setInnerTagSelection( tag:string ) { this.setRegexStartEndSelection( new RegExp( `<${tag}` ), new RegExp( `<\\/${tag}>` ), true ) } addRegexReplacement( match:RegExp, replacement:string ) { let regexReplacement = new RegexReplacement(); regexReplacement.regex = match; regexReplacement.replacement = replacement; this.replacements.push( regexReplacement ); } static readonly attributeInnerRegExp = /()(\z)(<\/TAG>)/g; addTagAttributeToInnerTagReplacement( tag:string, attribute:string, innerTag:string ) { let regexSource = TextReplacer.attributeInnerRegExp.source.replace( /TAG/g, tag ); regexSource = regexSource.replace( /ATTRIBUTE/g, attribute ); let matcher = ExtendedRegex.create( regexSource ); console.log( "ATTRIBUTE TO INNER", matcher ); let replacement = `$1$3<${innerTag}>$2$4`; this.addRegexReplacement( matcher, replacement ); } addTagRenaming( oldTag:string, newTag:string ) { let matcher = RegExpUtility.createRegExp( /(<\/?)TAG/g, "TAG", oldTag ); let replacement = `$1${newTag}`; this.addRegexReplacement( matcher, replacement ); } static readonly removeAttributeREgex = /(<\P\z)ATTRIBUTE\s*=\s*".*"(\z>\z<\/\P>)/g; addAttributeRemoving( attribute:string) { let regexSource = TextReplacer.removeAttributeREgex.source.replace( /ATTRIBUTE/g, attribute ); let matcher = ExtendedRegex.create( regexSource ); let replacement = `$1 $2`; this.addRegexReplacement( matcher, replacement ); } static create( match:RegExp, replacement:string ) { let replacer = new TextReplacer(); replacer.addRegexReplacement( match, replacement ); return replacer; } static createInRegexSelection( match:RegExp, replacement:string, selectionStart:RegExp, selectionEnd:RegExp ) { let replacer = new TextReplacer(); replacer.setRegexStartEndSelection( selectionStart, selectionEnd ); replacer.addRegexReplacement( match, replacement ); return replacer; } static createInTag( match:RegExp, replacement:string, tag:string ) { let replacer = new TextReplacer(); replacer.setRegexStartEndSelection( new RegExp( `<${tag}` ), new RegExp( `<\\/${tag}>` ) ); replacer.addRegexReplacement( match, replacement ); return replacer; } }