library-ts/browser/text/replacing/TextReplacer.ts

134 lines
4.2 KiB
TypeScript
Raw Permalink Normal View History

2025-03-08 08:16:54 +00:00
import { ExtendedRegex } from "../ExtendedRegex";
2025-03-08 12:22:18 +00:00
import { RegExpUtility } from "../RegExpUtitlity";
2025-03-08 08:16:54 +00:00
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 = /(<TAG\zATTRIBUTE\s*=\s*"(.*)"\z>)(\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</${innerTag}>$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 );
2025-03-08 12:22:18 +00:00
2025-03-08 08:16:54 +00:00
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;
}
}