namespace QWERTYkez.WordProcessor; internal static class Extension { public static void SwapBottomRight(this PageMargin margin) { if (margin.Right is { } r) { margin.Right = margin.Bottom is not null ? new((uint)margin.Bottom.Value) : null; margin.Bottom = new((int)r.Value); } else if(margin.Bottom is { } b) { margin.Bottom = null; margin.Right = new((uint)b.Value); } } public static void SwapValues(this PageSize size) { if (size.Width is { } w) { size.Width = size.Height is not null ? new(size.Height.Value) : null; size.Height = new(w.Value); } else if (size.Height is { } h) { size.Height = null; size.Width = new(h.Value); } } /// /// Возвращает индекс указанного элемента в коллекции. /// /// Коллекция элементов. /// Элемент для поиска. /// Индекс элемента, или -1, если элемент не найден. public static int IndexOf(this OpenXmlElementList list, OpenXmlElement element) { if (list == null || element == null) return -1; for (int i = 0; i < list.Count; i++) { if (list[i] == element) return i; } return -1; } /// /// Извлекает свойства шрифта (FontProps) из Run, содержащего указанный текст в параграфе. /// public static FontProps? ExtractFontProps(this Paragraph paragraph, string searchText) { if (paragraph is null || string.IsNullOrEmpty(searchText)) return null; var runs = paragraph.Descendants().ToList(); if (runs.Count == 0) return null; // Собираем полный текст параграфа и позиции каждого Run для анализа var runInfos = new List<(Run Run, int Start, int End, string Text)>(); int currentPosition = 0; foreach (var run in runs) { var runText = GetRunText(run); if (!string.IsNullOrEmpty(runText)) { runInfos.Add((run, currentPosition, currentPosition + runText.Length, runText)); currentPosition += runText.Length; } } // Ищем Run, который содержит искомый текст (регистронезависимо) foreach (var (run, start, end, text) in runInfos) { // Проверяем, содержится ли искомый текст в этом Run if (text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase) >= 0) return FontPropsExtractor.CreateFontPropsFromRun(run, paragraph); } // Если точное вхождение не найдено, ищем пересечение текста var fullText = string.Concat(runInfos.Select(r => r.Text)); int textIndex = fullText.IndexOf(searchText, StringComparison.OrdinalIgnoreCase); if (textIndex >= 0) { // Находим первый Run, который пересекается с найденным текстом var intersectingRun = runInfos.FirstOrDefault(r => r.Start <= textIndex && r.End > textIndex); if (intersectingRun.Run is not null) return FontPropsExtractor.CreateFontPropsFromRun(intersectingRun.Run, paragraph); } return null; // Не удалось найти подходящий Run } /// /// Вспомогательный метод для получения текста из Run. /// static string GetRunText(Run run) { if (run is null) return string.Empty; var sb = new StringBuilder(); foreach (var text in run.Elements()) { sb.Append(text.Text ?? string.Empty); } return sb.ToString(); } }