/// <summary> /// Populates a <see cref="ListViewItem"/> with information from <paramref name="file"/>. /// </summary> /// <param name="lvi">The listview item to fill with data.</param> /// <param name="file">The file information.</param> private void PopulateListViewItem(ListViewItem lvi, OutputFileInfo file) { lvi.Tag = file; if (this.ProjectOutput != null && this.ProjectOutput.ProjectInfo.IsExcluded(file.SourceFile)) { lvi.ForeColor = Color.Gray; lvi.ImageIndex = this.GetFileImageIndex("$excluded"); } else { lvi.ForeColor = this.listView1.ForeColor; lvi.ImageIndex = this.GetFileImageIndex(file.Extension); } int i = 0; this.PopulateListViewItem(lvi, i++, file.Name); this.PopulateListViewItem(lvi, i++, file.Modified.ToString("yyyy-MM-dd HH:mm:ss")); this.PopulateListViewItem(lvi, i++, file.Type); this.PopulateListViewItem(lvi, i++, file.Size.ToHumanReadableSize()); this.PopulateListViewItem(lvi, i++, !string.IsNullOrEmpty(file.SourceFile) ? System.IO.Path.GetFileName(file.SourceFile) : string.Empty); this.PopulateListViewItem(lvi, i++, file.SourceFile); this.PopulateListViewItem(lvi, i++); }
private void TransformDocument(string result, string extension, IDocumentBuildContext context, string destFilePath, ManifestItem manifestItem, out List <XRefDetails> unresolvedXRefs) { Task <byte[]> hashTask; unresolvedXRefs = new List <XRefDetails>(); using (var stream = EnvironmentContext.FileAbstractLayer.Create(destFilePath).WithMd5Hash(out hashTask)) using (var sw = new StreamWriter(stream)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { TransformHtml(context, result, manifestItem.SourceRelativePath, destFilePath, sw, out unresolvedXRefs); } else { sw.Write(result); } } var ofi = new OutputFileInfo { RelativePath = destFilePath, LinkToPath = GetLinkToPath(destFilePath), Hash = Convert.ToBase64String(hashTask.Result) }; manifestItem.OutputFiles.Add(extension, ofi); }
/// <summary> /// Creates a new <see cref="ListViewItem"/> and populates it with file information. /// </summary> /// <param name="file">The file data to populate the listview item with.</param> private void PopulateListViewItem(OutputFileInfo file) { var lvi = new ListViewItem(); this.PopulateListViewItem(lvi, file); this.listView1.Items.Add(lvi); }
private void TransformDocument(string result, string extension, IDocumentBuildContext context, string destFilePath, HashSet <string> missingUids, ManifestItem manifestItem) { Task <byte[]> hashTask; using (var stream = EnvironmentContext.FileAbstractLayer.Create(destFilePath).WithMd5Hash(out hashTask)) using (var sw = new StreamWriter(stream)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { try { TransformHtml(context, result, manifestItem.SourceRelativePath, destFilePath, sw); } catch (AggregateException e) { e.Handle(s => { var xrefExcetpion = s as CrossReferenceNotResolvedException; if (xrefExcetpion != null) { missingUids.Add(xrefExcetpion.UidRawText); return(true); } else { return(false); } }); } } else { sw.Write(result); } } var ofi = new OutputFileInfo { RelativePath = destFilePath, LinkToPath = GetLinkToPath(destFilePath), Hash = Convert.ToBase64String(hashTask.Result) }; manifestItem.OutputFiles.Add(extension, ofi); }
/// <summary> /// Must guarantee thread safety /// </summary> /// <param name="item"></param> /// <returns></returns> internal ManifestItem Transform(InternalManifestItem item) { if (item.Model == null || item.Model.Content == null) { throw new ArgumentNullException("Content for item.Model should not be null!"); } var model = ConvertObjectToDictionary(item.Model.Content); model = AppendGlobalMetadata(model); if (_settings.Options.HasFlag(ApplyTemplateOptions.ExportRawModel)) { ExportModel(model, item.FileWithoutExtension, _settings.RawModelExportSettings); } var manifestItem = new ManifestItem { DocumentType = item.DocumentType, SourceRelativePath = item.LocalPathFromRoot, Metadata = item.Metadata, Version = _context.VersionName, }; var outputDirectory = _settings.OutputFolder ?? Directory.GetCurrentDirectory(); // 1. process resource if (item.ResourceFile != null) { // Resource file has already been processed in its plugin var ofi = new OutputFileInfo { RelativePath = item.ResourceFile, LinkToPath = GetLinkToPath(item.ResourceFile), }; manifestItem.OutputFiles.Add("resource", ofi); } // 2. process model var templateBundle = _templateCollection[item.DocumentType]; if (templateBundle == null) { return(manifestItem); } HashSet <string> missingUids = new HashSet <string>(); // Must convert to JObject first as we leverage JsonProperty as the property name for the model foreach (var template in templateBundle.Templates) { if (!template.ContainsTemplateRenderer) { continue; } try { var extension = template.Extension; string outputFile = item.FileWithoutExtension + extension; object viewModel = null; try { viewModel = template.TransformModel(model); } catch (Exception e) { string message; if (_settings.DebugMode) { // save raw model for further investigation: var rawModelPath = ExportModel(model, item.FileWithoutExtension, _settings.RawModelExportSettingsForDebug); message = $"Error transforming model \"{rawModelPath}\" generated from \"{item.LocalPathFromRoot}\" using \"{template.ScriptName}\". {e.Message}"; } else { message = $"Error transforming model generated from \"{item.LocalPathFromRoot}\" using \"{template.ScriptName}\". To get the detailed raw model, please run docfx with debug mode --debug. {e.Message} "; } Logger.LogError(message); throw new DocumentException(message, e); } string result; try { result = template.Transform(viewModel); } catch (Exception e) { string message; if (_settings.DebugMode) { // save view model for further investigation: var viewModelPath = ExportModel(viewModel, outputFile, _settings.ViewModelExportSettingsForDebug); message = $"Error applying template \"{template.Name}\" to view model \"{viewModelPath}\" generated from \"{item.LocalPathFromRoot}\". {e.Message}"; } else { message = $"Error applying template \"{template.Name}\" generated from \"{item.LocalPathFromRoot}\". To get the detailed view model, please run docfx with debug mode --debug. {e.Message}"; } Logger.LogError(message); throw new DocumentException(message, e); } if (_settings.Options.HasFlag(ApplyTemplateOptions.ExportViewModel)) { ExportModel(viewModel, outputFile, _settings.ViewModelExportSettings); } if (_settings.Options.HasFlag(ApplyTemplateOptions.TransformDocument)) { if (string.IsNullOrWhiteSpace(result)) { string message; if (_settings.DebugMode) { var viewModelPath = ExportModel(viewModel, outputFile, _settings.ViewModelExportSettingsForDebug); message = $"Model \"{viewModelPath}\" is transformed to empty string with template \"{template.Name}\""; } else { message = $"Model is transformed to empty string with template \"{template.Name}\". To get the detailed view model, please run docfx with debug mode --debug"; } Logger.LogWarning(message); } TransformDocument(result ?? string.Empty, extension, _context, outputFile, missingUids, manifestItem); Logger.LogDiagnostic($"Transformed model \"{item.LocalPathFromRoot}\" to \"{outputFile}\"."); } } catch (PathTooLongException e) { var message = $"Error processing {item.LocalPathFromRoot}: {e.Message}"; throw new PathTooLongException(message, e); } } if (missingUids.Count > 0) { var uids = string.Join(", ", missingUids.Select(s => $"\"{s}\"")); Logger.LogWarning($"Invalid cross reference {uids}.", null, item.LocalPathFromRoot); } return(manifestItem); }
public void TestIndexDotJsonWithNonEnglishCharacters() { var rawHtml = @" <!DOCTYPE html> <html> <head> <meta charset=""utf-8""> <title>This is title in head metadata</title> </head> <body> <h1> This is Title </h1> <p class='data-searchable'> Hello World, Microsoft </p> <article> <h1> This is article title </h1> docfx can do anything... and it supports non-english characters like these: ãâáà êé í õôó Типы шрифтов 人物 文字 </article> </body> </html> "; // prepares temp folder and file for testing purposes // ExtractSearchIndex should probably be refactored so we can test it without depending on the filesystem var tempTestFolder = "temp_test_folder"; if (Directory.Exists(tempTestFolder)) { Directory.Delete(tempTestFolder, true); } Directory.CreateDirectory(tempTestFolder); File.WriteAllText(Path.Combine(tempTestFolder, "index.html"), rawHtml, new UTF8Encoding(false)); // prepares fake manifest object var outputFileInfo = new OutputFileInfo(); outputFileInfo.RelativePath = "index.html"; var manifestItem = new ManifestItem(); manifestItem.OutputFiles.Add(".html", outputFileInfo); var manifest = new Manifest(); manifest.Files.Add(manifestItem); // process the fake manifest, using tempTestFolder as the output folder _extractor.Process(manifest, tempTestFolder); var expectedIndexJSON = @"{ ""index.html"": { ""href"": ""index.html"", ""title"": ""This is title in head metadata"", ""keywords"": ""Hello World, Microsoft This is article title docfx can do anything... and it supports non-english characters like these: ãâáà êé í õôó Типы шрифтов 人物 文字"" } }"; var actualIndexJSON = File.ReadAllText(Path.Combine(tempTestFolder, "index.json"), Encoding.UTF8); Assert.Equal(expectedIndexJSON, actualIndexJSON); }