public void Execute(string path) { try { path = Path.GetFullPath(path); using (_console.CreateScope("Generating table of contents...")) { var updatedFilesCounter = 0; var elementParser = new DocsElementParser(); var headerParser = new HeaderParser(); var files = new MarkdownFileLocator(_fileSystem).GetFiles(path); foreach (var file in files) { var lines = _fileSystem.ReadFile(file.FullPath); var toc = elementParser.Parse(lines, "toc").SingleOrDefault(); if (toc == null) { continue; } updatedFilesCounter++; _console.WriteInfo($"Updating {file.RelativePath}"); var headers = headerParser.Parse(lines.Skip(toc.ElementLine)); lines.RemoveRange(toc.ElementLine, toc.ElementLines); var minLevel = headers.Min(x => x.Level); headers.ForEach(x => x.Level -= minLevel); var formatter = new LinkFormatter(); var tocContent = headers.Select(x => $"{Enumerable.Repeat(" ", x.Level).Join()}* {formatter.Format(x.Text)}"); lines.InsertRange(toc.ElementLine, new DocsElementWriter().Write(toc, tocContent)); _fileSystem.WriteFile(file.FullPath, lines); } _console.WriteInfo($"Updated {updatedFilesCounter} {(updatedFilesCounter == 1 ? "file" : "files")}."); } } catch (Exception exception) { _console.WriteError(exception.Message); } }
public void Execute(string path) { try { var srcPattern = @"^(?<uri>[^#]+)(#((id=(?<id>.+))|(lines=(?<from>\d+)((-(?<to>\d+))?)))?)?$"; var elementParser = new DocsElementParser(); var elementWriter = new DocsElementWriter(); using (_console.CreateScope("Importing samples...")) { var updatedFilesCounter = 0; foreach (var file in new MarkdownFileLocator(_fileSystem).GetFiles(path)) { var fileContent = _fileSystem.ReadFile(file.FullPath); var attributeOptions = new DocsElementParser.AttributeOptions { Required = new[] { "src" }, Optional = new[] { "language" } }; var samples = elementParser.Parse(fileContent, "sample", attributeOptions); if (!samples.Any()) { continue; } _console.WriteInfo($"Updating {file.RelativePath}"); foreach (var sample in samples.Reverse()) { var src = Regex.Match(sample.Attributes["src"], srcPattern); if (!src.Success) { _console.WriteError($" invalid src '{src}'."); continue; } var uri = src.Groups["uri"].Value; // todo - remote (http://...) uris if (uri.StartsWith(@"$/") || uri.StartsWith(@"$\")) { var rootDirectory = _settingsReader.GetSamplesDirectory(file.FullPath); uri = Path.Combine(rootDirectory, uri.Remove(0, 2)); } if (!Path.IsPathRooted(uri)) { var dir = Path.GetDirectoryName(file.FullPath); uri = Path.Combine(dir, uri); } if (!_fileSystem.FileExists(uri)) { _console.WriteError($" source not found ({uri})."); } var sampleContent = _fileSystem.ReadFile(uri); var idGroup = src.Groups["id"]; if (idGroup.Success) { // todo error handling var sampleElement = elementParser .Parse(sampleContent, "sample", new DocsElementParser.AttributeOptions { Required = new[] { "id" } }) .Single(x => x.Attributes["id"].Equals(idGroup.Value, StringComparison.OrdinalIgnoreCase)); sampleContent = sampleContent .Skip(sampleElement.ContentLine) .Take(sampleElement.ContentLines) .ToList(); } var fromGroup = src.Groups["from"]; if (fromGroup.Success) { // todo error handling, count/to to big/small var from = int.Parse(fromGroup.Value) - 1; var toGroup = src.Groups["to"]; var count = toGroup.Success ? int.Parse(toGroup.Value) - from : 1; sampleContent = sampleContent .Skip(from) .Take(count) .ToList(); } var language = sample.Attributes.TryGetValue("language", out var value) ? value : GetLanguage(uri); sampleContent.Insert(0, $"``` {language}".TrimEnd()); sampleContent.Add("```"); fileContent.RemoveRange(sample.ElementLine, sample.ElementLines); fileContent.InsertRange(sample.ElementLine, elementWriter.Write(sample, sampleContent)); } // todo only write file if its acually modified _fileSystem.WriteFile(file.FullPath, fileContent); updatedFilesCounter++; } _console.WriteInfo($"Updated {updatedFilesCounter} {(updatedFilesCounter == 1 ? "file" : "files")}."); } } catch (Exception exception) { _console.WriteError(exception.Message); } }