public void Parse(DqParagraph paragraph) { var m = Regex.Matches(paragraph.Text, @"(?:табл(?:\.|иц[аые]|ице[ею]|іц[аы]|іца[йю]))\s+(\d+(\.\d+)*)", RegexOptions.IgnoreCase); if (m.Count == 0) { return; } var trimmedText = paragraph.Text.TrimStart(); if (m.Count == 1 && (m[0].Value.StartsWith("таблица", StringComparison.InvariantCultureIgnoreCase) || m[0].Value.StartsWith("табліца", StringComparison.InvariantCultureIgnoreCase)) && trimmedText.StartsWith(m[0].Value) && (trimmedText.Substring(m[0].Value.Length).TrimStart().Length == 0 || !char.IsLower(trimmedText.Substring(m[0].Value.Length).TrimStart().First()))) { paragraph.Meta.Structure.Add(new DqNumberedElement(paragraph, DqStructureElementType.TableDeclaration) { Number = m[0].Groups[1].Value }); } else { paragraph.Meta.Structure.Add(new DqNumberedElement(paragraph, DqStructureElementType.TableReference) { Number = m[0].Groups[1].Value }); } paragraph.Meta.Structure.AddRange(m.Cast <Match>().Skip(1).Select(mm => mm.Groups[1].Value).Select(t => new DqNumberedElement(paragraph, DqStructureElementType.TableReference) { Number = t })); }
public void Parse(DqParagraph paragraph) { var m = Regex.Matches(paragraph.Text, @"(?:рис(?:\.|унок|унк[аеу]|унком)|мал(?:\.|юнак|юнк[аеу]|юнкам))\s+(\d+(\.\d+)*)", RegexOptions.IgnoreCase); if (m.Count == 0) { return; } var trimmedText = paragraph.Text.TrimStart(); if (m.Count == 1 && (m[0].Value.StartsWith("рисунок", StringComparison.InvariantCultureIgnoreCase) || m[0].Value.StartsWith("малюнак", StringComparison.InvariantCultureIgnoreCase)) && trimmedText.StartsWith(m[0].Value)) { paragraph.Meta.Structure.Add(new DqNumberedElement(paragraph, DqStructureElementType.FigureDeclaration) { Number = m[0].Groups[1].Value }); } else { paragraph.Meta.Structure.Add(new DqNumberedElement(paragraph, DqStructureElementType.FigureReference) { Number = m[0].Groups[1].Value }); } paragraph.Meta.Structure.AddRange(m.Cast <Match>().Skip(1).Select(mm => mm.Groups[1].Value).Select(t => new DqSource(paragraph, DqStructureElementType.FigureReference) { Number = t })); }
public void Parse(DqParagraph paragraph, DqDocument dqDocument) { var m = Regex.Matches(paragraph.Text, @"[^]]\[(\d+)(?:,\s*c(?:тр)\.\d+)?\]", RegexOptions.IgnoreCase); if (m.Count != 0) { paragraph.Meta.Structure.AddRange(m.Cast <Match>().Select(mm => mm.Groups[1].Value).Select(t => new DqNumberedElement(paragraph, DqStructureElementType.SourceReference) { Number = t })); } var bibliographyPart = dqDocument.Structure.Bibliography; if (bibliographyPart == null || !bibliographyPart.Paragraphs.Contains(paragraph)) { return; } var match = Regex.Match(paragraph.Text, @"^\s*(\d+)", RegexOptions.IgnoreCase); if (!match.Success) { return; } paragraph.Meta.Structure.Add(new DqSource(paragraph, DqStructureElementType.SourceDeclaration) { Number = match.Groups[1].Value }); }
private static void UpdateCounters(DqParagraph paragraph, IList <int> counters) { for (var i = paragraph.Style.OutlineLevel + 1; i < 9; ++i) { counters[i] = 0; } counters[paragraph.Style.OutlineLevel]++; }
private string CalculateNumbers(DqParagraph paragraph, IReadOnlyList <int> counters) { var level = paragraph.Style.Numbering.Levels[paragraph.Style.OutlineLevel]; var numberText = level.Text; for (var i = 0; i <= paragraph.Style.OutlineLevel; i++) { numberText = numberText.Replace("%" + (i + 1), counters[i].ToString()); } return(numberText); }
private int GetLevel(DqParagraph paragraph) { if (paragraph.Style.OutlineLevel > 0) { return(paragraph.Style.OutlineLevel); } if (IsChapter(paragraph)) { return(0); } var numberPart = Regex.Match(paragraph.Text, @"^\s*\d+(\.\d+)*\s*[\D\S]", RegexOptions.IgnoreCase).Value; var m = Regex.Matches(numberPart, @"\b(\d+)\b", RegexOptions.IgnoreCase); return(m.Count == 0 ? 0 : m.Count - 1); }
private void AnalyzeMainPartParagraph(DqParagraph dqParagraph, DqDocument dqDocument) { if (string.IsNullOrWhiteSpace(dqParagraph.Text.Replace("{IMG}", "").Replace("{TBL}", "").Replace("{PageBreak}", ""))) { return; } if (dqParagraph.Meta.FigureDeclarations.Any()) { if (dqParagraph.Style.FontSize > Settings.Default.ExpectedFontSize) { dqParagraph.Meta.Errors.Add(new DqFontSizeError($"Неверный размер шрифта ({dqParagraph.Style.FontSize} пт). Подписи риcунков должны использовать шрифт не больше основного ({Settings.Default.ExpectedFontSize} пт).")); } } else if (dqParagraph.Meta.TableDeclarations.Any()) { if (dqParagraph.Style.FontSize > Settings.Default.ExpectedFontSize) { dqParagraph.Meta.Errors.Add(new DqFontSizeError($"Неверный размер шрифта ({dqParagraph.Style.FontSize} пт). Заголовки таблиц должны использовать шрифт не больше основного ({Settings.Default.ExpectedFontSize} пт).")); } } else if (dqParagraph.Meta.IsHeader) { if (dqParagraph.Style.FontSize < Settings.Default.ExpectedFontSize) { dqParagraph.Meta.Errors.Add(new DqFontSizeError($"Неверный размер шрифта ({dqParagraph.Style.FontSize} пт). Заголовки должны использовать шрифт не меньше основного ({Settings.Default.ExpectedFontSize} пт).")); } if (dqParagraph.GetPureText().Trim().EndsWith(".")) { dqParagraph.Meta.Errors.Add(new DqError($"В конце заголовков точка не ставится.")); } var number = Regex.Match(dqParagraph.GetPureText().TrimStart(), @"^((?:\d+\.)*\d+?)"); if (number.Success && number.Value.EndsWith(".")) { dqParagraph.Meta.Errors.Add(new DqError($"В конце номера (под)раздела точка не ставится.")); } } if (dqParagraph.Style.FontName != Settings.Default.ExpectedFontName) { dqParagraph.Meta.Errors.Add(new DqFontError($"Неверный шрифт ({dqParagraph.Style.FontName}). Иcпользуйте {Settings.Default.ExpectedFontName}.")); } if (dqParagraph.Meta.IsHeader) { if (dqParagraph.Style.Aligment == DqAligment.Center || dqParagraph.Style.Aligment == DqAligment.Right) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"Заголовки главной части должны быть выровнены по левому краю.")); } else if (dqParagraph.Style.Indent == 0) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"Отсутвует абзацный отступ.")); } } else if (dqParagraph.Meta.FigureDeclarations.Any()) { if (dqParagraph.Style.Aligment != DqAligment.Center) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"Подпись рисунка должна быть выровнена по центру.")); } else if (dqParagraph.Style.Indent != 0) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"При выравнивании по центру должен отсутвовать абзацный отступ.")); } } else if (dqParagraph.Meta.TableDeclarations.Any()) { if (dqParagraph.Style.Aligment == DqAligment.Center || dqParagraph.Style.Aligment == DqAligment.Right) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"Заголовок таблицы должен быть выровнен по левому краю.")); } else if (dqParagraph.Style.Indent != 0) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"Заголовок таблицы помещают без абзацного отступа.")); } } else if (!dqParagraph.Meta.IsHeader) { if (dqParagraph.Style.Indent == 0) { dqParagraph.Meta.Errors.Add(new DqAlignmentError($"Отсутствует абзацный отступ.")); } } if (dqParagraph.Style.SpacingBetweenLines != Settings.Default.ExpectedSpacingBetweenLines && !dqParagraph.Meta.IsHeader && !dqParagraph.Meta.FigureDeclarations.Any() && !dqParagraph.Meta.TableDeclarations.Any()) { dqParagraph.Meta.Errors.Add(new DqError($"Неверный междустрочный интервал ({dqParagraph.Style.SpacingBetweenLines}). Ожидается {Settings.Default.ExpectedSpacingBetweenLines}-ый интервал.")); } }
private bool IsNumbered(DqParagraph paragraph) => paragraph.Style.Numbering != null;
private void Analyze(DqParagraph dqParagraph) { var text = dqParagraph.GetPureText().Trim(); var isSite = text.Contains("http:") || text.Contains("https:"); var parts = Regex.Split(text, @"(\[Электронный ресурс\]|\[Electronic resource\])", RegexOptions.IgnoreCase); if (parts.Length == 1) { if (isSite) { dqParagraph.Meta.Errors.Add(new DqError($"Электронный ресурс имеет неверный формат.")); } return; } else { if (!isSite) { dqParagraph.Meta.Errors.Add(new DqError($"Не найдена ссылка на ресурс!")); return; } } var separator = parts[1]; if (separator != "[Электронный ресурс]" && separator != "[Electronic resource]") { dqParagraph.Meta.Errors.Add(new DqError($"Часть «{separator}» имеет неверный регистр.")); } var hasCyrillic = Regex.IsMatch(parts[0], @"\p{IsCyrillic}"); var hasLatin = Regex.IsMatch(parts[0], @"[a-zA-Z]"); var isRu = hasCyrillic; var isEn = hasLatin && !hasCyrillic; if (isRu) { if (string.Equals(separator, "[Electronic resource]", StringComparison.OrdinalIgnoreCase)) { dqParagraph.Meta.Errors.Add(new DqWarning($"Название электронного ресурса содержит кириллицу. Возможно, следует использовать «[Электронный ресурс]» вместо «{separator}».")); } } if (isEn) { if (string.Equals(separator, "[Электронный ресурс]", StringComparison.OrdinalIgnoreCase)) { dqParagraph.Meta.Errors.Add(new DqWarning($"Название электронного ресурса содержит только латиницу. Возможно, следует использовать «[Electronic resource]» вместо «{separator}».")); } } var yearMatch = Regex.Match(parts[2], @"\d{4}\s*(г\.?|год)"); if (yearMatch.Success) { dqParagraph.Meta.Errors.Add(new DqError($"При указании года слово «{yearMatch.Groups[1].Value}» не пишется.")); } var modeOfAccess = Regex.Match(parts[2], @"(Режим доступа\s*:\s*|Mode of access\s*:\s*)"); if (!modeOfAccess.Success) { dqParagraph.Meta.Errors.Add(new DqError($"Режим доступа не найден.")); return; } var dateOfAccess = Regex.Match(parts[2], @"(Дата доступа\s*:\s*|Date of access\s*:\s*)(\d{2}\.\d{2}\.\d{4})"); if (!dateOfAccess.Success) { dqParagraph.Meta.Errors.Add(new DqError($"Дата доступа не найдена.")); return; } if (!modeOfAccess.Groups[1].Value.Contains(" : ") || !dateOfAccess.Groups[1].Value.Contains(" : ")) { dqParagraph.Meta.Errors.Add(new DqError($"Перед и после двоеточия-разделителя ставится пробел («Режим доступа : », «Дата доступа : »)")); } }
public DqNumberedElement(DqParagraph paragraph, DqStructureElementType type) { Paragraph = paragraph; Type = type; }
public DqSource(DqParagraph paragraph, DqStructureElementType type) : base(paragraph, type) { }
private bool IsNumberedParagraph(DqParagraph paragraph) => IsChapter(paragraph) || Regex.IsMatch(paragraph.Text, @"^\d+(\.\d+)*\s*[\D\S]", RegexOptions.IgnoreCase);
private Token CreateToken(DqParagraph dqParagraph) => new Token(dqParagraph, GetLevel(dqParagraph));
private bool IsChapter(DqParagraph paragraph) => Regex.IsMatch(paragraph.Text, @"^\s*(Глава|Раздел|Часть|Падзел)\s*\d+(\s*[\D\S])?", RegexOptions.IgnoreCase);
public Token(DqParagraph paragraph, int level) { Paragraph = paragraph; Level = level; }