internal ProcessResult Apply(List <Line> lines, string newLine, string?relativePath)
        {
            var  missingSnippets  = new List <MissingSnippet>();
            var  validationErrors = new List <ValidationError>();
            var  missingIncludes  = new List <MissingInclude>();
            var  usedSnippets     = new List <Snippet>();
            var  usedIncludes     = new List <Include>();
            var  builder          = new StringBuilder();
            Line?tocLine          = null;
            var  headerLines      = new List <Line>();

            for (var index = 0; index < lines.Count; index++)
            {
                var line = lines[index];

                if (validateContent)
                {
                    var errors = ContentValidation.Verify(line.Original).ToList();
                    if (errors.Any())
                    {
                        validationErrors.AddRange(errors.Select(error => new ValidationError(error.error, line.LineNumber, error.column, line.Path)));
                        continue;
                    }
                }

                if (includeProcessor.TryProcessInclude(lines, line, usedIncludes, index, missingIncludes))
                {
                    continue;
                }

                if (line.Current.StartsWith("#"))
                {
                    if (tocLine != null)
                    {
                        headerLines.Add(line);
                    }

                    continue;
                }

                if (line.Current == "toc")
                {
                    tocLine = line;
                    continue;
                }

                if (SnippetKeyReader.TryExtractKeyFromLine(line, out var key))
                {
                    builder.Clear();

                    void AppendLine(string s)
                    {
                        builder.Append(s);
                        builder.Append(newLine);
                    }

                    ProcessSnippetLine(AppendLine, missingSnippets, usedSnippets, key, line);
                    builder.TrimEnd();
                    line.Current = builder.ToString();
                }
            }

            if (writeHeader)
            {
                lines.Insert(0, new Line(HeaderWriter.WriteHeader(relativePath !, header, newLine), "", 0));
            }

            if (tocLine != null)
            {
                tocLine.Current = TocBuilder.BuildToc(headerLines, tocLevel, tocExcludes, newLine);
            }

            return(new ProcessResult(
                       missingSnippets: missingSnippets,
                       usedSnippets: usedSnippets.Distinct().ToList(),
                       usedIncludes: usedIncludes.Distinct().ToList(),
                       missingIncludes: missingIncludes,
                       validationErrors: validationErrors));
        }
        internal ProcessResult Apply(List <Line> lines, string newLine, string?relativePath)
        {
            var  missingSnippets  = new List <MissingSnippet>();
            var  validationErrors = new List <ValidationError>();
            var  missingIncludes  = new List <MissingInclude>();
            var  usedSnippets     = new List <Snippet>();
            var  usedIncludes     = new List <Include>();
            var  builder          = new StringBuilder();
            Line?tocLine          = null;

            void AppendLine(string s)
            {
                builder.Append(s);
                builder.Append(newLine);
            }

            var headerLines = new List <Line>();

            for (var index = 0; index < lines.Count; index++)
            {
                var line = lines[index];

                if (ValidateContent(relativePath, line, validationErrors))
                {
                    continue;
                }

                if (includeProcessor.TryProcessInclude(lines, line, usedIncludes, index, missingIncludes, relativePath))
                {
                    continue;
                }

                if (line.Current.StartsWith("#"))
                {
                    if (tocLine != null)
                    {
                        headerLines.Add(line);
                    }

                    continue;
                }

                if (line.Current == "toc")
                {
                    tocLine = line;
                    continue;
                }

                void AppendSnippet(string key1)
                {
                    builder.Clear();
                    ProcessSnippetLine(AppendLine, missingSnippets, usedSnippets, key1, relativePath, line);
                    builder.TrimEnd();
                    line.Current = builder.ToString();
                }

                if (SnippetKey.ExtractSnippet(line, out var key))
                {
                    AppendSnippet(key);
                    continue;
                }

                if (convention == DocumentConvention.SourceTransform)
                {
                    continue;
                }

                if (SnippetKey.ExtractStartCommentSnippet(line, out key))
                {
                    AppendSnippet(key);

                    index++;

                    lines.RemoveUntil(
                        index,
                        "<!-- endSnippet -->",
                        relativePath,
                        line);
                    continue;
                }

                if (line.Current == "<!-- toc -->")
                {
                    tocLine = line;

                    index++;

                    lines.RemoveUntil(index, "<!-- endToc -->", relativePath, line);

                    continue;
                }
            }

            if (writeHeader)
            {
                lines.Insert(0, new Line(HeaderWriter.WriteHeader(relativePath !, header, newLine), "", 0));
            }

            if (tocLine != null)
            {
                tocLine.Current = TocBuilder.BuildToc(headerLines, tocLevel, tocExcludes, newLine);
            }

            return(new ProcessResult(
                       missingSnippets: missingSnippets,
                       usedSnippets: usedSnippets.Distinct().ToList(),
                       usedIncludes: usedIncludes.Distinct().ToList(),
                       missingIncludes: missingIncludes,
                       validationErrors: validationErrors));
        }