// Hook: AfterPowerPoint // Replace simple tokens in slide text without losing the existing formatting. // // Walks every slide / shape / paragraph / portion and substitutes the tokens // {{JobName}}, {{OutputName}}, {{Today}}, and {{Region}} (the last from the // job parameters). Replacing at portion level preserves font and colour - // a naive TextFrame.Text = ... assignment would destroy that formatting. if (Presentation == null || Presentation.Slides.Count == 0) { AddWarning($"Presentation for '{OutputName}' is empty; nothing to substitute."); return; } var tokens = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["{{JobName}}"] = JobName ?? string.Empty, ["{{OutputName}}"] = OutputName ?? string.Empty, ["{{Today}}"] = $"{DateTime.Now:MMMM d, yyyy}", ["{{Region}}"] = Parameters.TryGetValue("Region", out var r) ? r : string.Empty, }; int replacements = 0; foreach (var slide in Presentation.Slides) { foreach (var shape in slide.Shapes) { var autoShape = shape as IAutoShape; if (autoShape?.TextFrame == null) continue; foreach (var paragraph in autoShape.TextFrame.Paragraphs) { foreach (var portion in paragraph.Portions) { var original = portion.Text ?? string.Empty; var updated = original; foreach (var kv in tokens) { if (updated.IndexOf(kv.Key, StringComparison.OrdinalIgnoreCase) >= 0) updated = updated.Replace(kv.Key, kv.Value); } if (original != updated) { portion.Text = updated; replacements++; } } } } } Logger.LogInformation($"Token substitution made {replacements} replacement(s) in '{OutputName}'.");