public void Process(DocumentBuildContext context, string outputDirectory) { var baseDirectory = context.BuildOutputFolder; if (string.IsNullOrEmpty(outputDirectory)) outputDirectory = Environment.CurrentDirectory; if (string.IsNullOrEmpty(baseDirectory)) baseDirectory = Environment.CurrentDirectory; if (!Directory.Exists(outputDirectory)) Directory.CreateDirectory(outputDirectory); // 1. Copy dependent files with path relative to the base output directory ProcessDependencies(outputDirectory); Dictionary<string, HashSet<string>> unProcessedType = new Dictionary<string, HashSet<string>>(StringComparer.OrdinalIgnoreCase); Dictionary<string, string> extMapping = new Dictionary<string, string>(); // 2. Get extension for each item foreach (var item in context.Manifest) { if (item.ModelFile == null) throw new ArgumentNullException("Model file path must be specified!"); if (item.DocumentType == null) throw new ArgumentNullException($"Document type is not allowed to be NULL for ${item.ModelFile}!"); // NOTE: Resource is not supported for applying templates if (item.DocumentType.Equals("Resource", StringComparison.OrdinalIgnoreCase)) continue; var templates = _templates[item.DocumentType]; // Get default template extension if (templates == null || templates.Count == 0) { HashSet<string> unProcessedFiles; if (unProcessedType.TryGetValue(item.DocumentType, out unProcessedFiles)) { unProcessedFiles.Add(item.ModelFile); } else { unProcessedType[item.DocumentType] = new HashSet<string>(FilePathComparer.OSPlatformSensitiveComparer) { item.ModelFile }; } } else { var defaultTemplate = templates.FirstOrDefault(s => s.IsPrimary) ?? templates[0]; string key = ((RelativePath)item.OriginalFile).GetPathFromWorkingFolder(); string value; if (context.FileMap.TryGetValue(key, out value)) { context.FileMap[key] = Path.ChangeExtension(value, defaultTemplate.Extension); extMapping[key] = defaultTemplate.Extension; } else { Logger.Log(LogLevel.Warning, $"{key} is not found in .filemap"); } } } //update internal XrefMap if (context.XRefSpecMap != null) { foreach (var pair in context.XRefSpecMap) { string ext; if (extMapping.TryGetValue(pair.Value.Href, out ext)) { pair.Value.Href = Path.ChangeExtension(pair.Value.Href, ext); } } } if (unProcessedType.Count > 0) { StringBuilder sb = new StringBuilder("There is no template processing:"); foreach (var type in unProcessedType) { sb.AppendLine($"- Document type: \"{type.Key}\""); sb.AppendLine($"- Files:"); foreach (var file in type.Value) { sb.AppendLine($" -\"{file}\""); } } Logger.Log(LogLevel.Warning, sb.ToString());// not processed but copied to '{modelOutputPath}'"); } List<TemplateManifestItem> manifest = new List<TemplateManifestItem>(); // 3. Process every model and save to output directory foreach (var item in context.Manifest) { var manifestItem = new TemplateManifestItem { DocumentType = item.DocumentType, OriginalFile = item.LocalPathFromRepoRoot, OutputFiles = new Dictionary<string, string>() }; try { var templates = _templates[item.DocumentType]; // 1. process model if (templates == null) { // TODO: what if template to transform the type is not found? DO NOTHING? // CopyFile(modelFile, modelOutputPath); } else { var modelFile = Path.Combine(baseDirectory, item.ModelFile); var systemAttrs = new SystemAttributes(context, item, TemplateProcessor.Language); foreach (var template in templates) { var extension = template.Extension; string outputFile = Path.ChangeExtension(item.ModelFile, extension); string outputPath = Path.Combine(outputDirectory ?? string.Empty, outputFile); var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); var transformed = template.Transform(modelFile, systemAttrs); if (!string.IsNullOrWhiteSpace(transformed)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { TranformHtml(context, transformed, item.ModelFile, outputPath); } else { File.WriteAllText(outputPath, transformed, Encoding.UTF8); } Logger.Log(LogLevel.Verbose, $"Transformed model \"{item.ModelFile}\" to \"{outputPath}\"."); } else { // TODO: WHAT to do if is transformed to empty string? STILL creat empty file? Logger.Log(LogLevel.Warning, $"Model \"{item.ModelFile}\" is transformed to empty string with template \"{template.Name}\""); File.WriteAllText(outputPath, string.Empty); } manifestItem.OutputFiles.Add(extension, outputFile); } } // 2. process resource if (item.ResourceFile != null) { manifestItem.OutputFiles.Add("resource", item.ResourceFile); PathUtility.CopyFile(Path.Combine(baseDirectory, item.ResourceFile), Path.Combine(outputDirectory, item.ResourceFile), true); } } catch (Exception e) { Logger.Log(LogLevel.Warning, $"Unable to transform {item.ModelFile}: {e.Message}. Ignored."); } manifest.Add(manifestItem); } // Save manifest var manifestPath = Path.Combine(outputDirectory, ManifestFileName); JsonUtility.Serialize(manifestPath, manifest); Logger.Log(LogLevel.Verbose, $"Manifest file saved to {manifestPath}."); }
public static TemplateManifestItem Transform(DocumentBuildContext context, ManifestItem item, TemplateCollection templateCollection, string outputDirectory, bool exportMetadata, Func <string, string> metadataFilePathProvider) { var baseDirectory = context.BuildOutputFolder ?? string.Empty; var manifestItem = new TemplateManifestItem { DocumentType = item.DocumentType, OriginalFile = item.LocalPathFromRepoRoot, OutputFiles = new Dictionary <string, string>() }; if (templateCollection == null || templateCollection.Count == 0) { return(manifestItem); } try { var model = item.Model?.Content; var templates = templateCollection[item.DocumentType]; // 1. process model if (templates == null) { // Logger.LogWarning($"There is no template processing {item.DocumentType} document \"{item.LocalPathFromRepoRoot}\""); } else { var modelFile = Path.Combine(baseDirectory, item.ModelFile); var systemAttrs = new SystemAttributes(context, item, TemplateProcessor.Language); foreach (var template in templates) { var extension = template.Extension; string outputFile = Path.ChangeExtension(item.ModelFile, extension); string outputPath = Path.Combine(outputDirectory ?? string.Empty, outputFile); var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) { Directory.CreateDirectory(dir); } string transformed; if (model == null) { // TODO: remove // currently keep to pass UT transformed = template.Transform(item.ModelFile, systemAttrs); } else { var result = template.TransformModel(model, systemAttrs); if (exportMetadata) { if (metadataFilePathProvider == null) { throw new ArgumentNullException(nameof(metadataFilePathProvider)); } JsonUtility.Serialize(metadataFilePathProvider(outputPath), result.Model); } transformed = result.Result; } if (!string.IsNullOrWhiteSpace(transformed)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { TranformHtml(context, transformed, item.ModelFile, outputPath); } else { File.WriteAllText(outputPath, transformed, Encoding.UTF8); } Logger.Log(LogLevel.Verbose, $"Transformed model \"{item.ModelFile}\" to \"{outputPath}\"."); } else { // TODO: WHAT to do if is transformed to empty string? STILL creat empty file? Logger.LogWarning($"Model \"{item.ModelFile}\" is transformed to empty string with template \"{template.Name}\""); File.WriteAllText(outputPath, string.Empty); } manifestItem.OutputFiles.Add(extension, outputFile); } } // 2. process resource if (item.ResourceFile != null) { PathUtility.CopyFile(Path.Combine(baseDirectory, item.ResourceFile), Path.Combine(outputDirectory, item.ResourceFile), true); manifestItem.OutputFiles.Add("resource", item.ResourceFile); } } catch (Exception e) { Logger.LogWarning($"Unable to transform {item.ModelFile}: {e.Message}. Ignored."); } return(manifestItem); }
public static TemplateManifestItem Transform(DocumentBuildContext context, ManifestItem item, TemplateCollection templateCollection, string outputDirectory, bool exportMetadata, Func<string, string> metadataFilePathProvider) { var baseDirectory = context.BuildOutputFolder ?? string.Empty; var manifestItem = new TemplateManifestItem { DocumentType = item.DocumentType, OriginalFile = item.LocalPathFromRepoRoot, OutputFiles = new Dictionary<string, string>() }; if (templateCollection == null || templateCollection.Count == 0) { return manifestItem; } try { var model = item.Model?.Content; var templates = templateCollection[item.DocumentType]; // 1. process model if (templates == null) { // Logger.LogWarning($"There is no template processing {item.DocumentType} document \"{item.LocalPathFromRepoRoot}\""); } else { var modelFile = Path.Combine(baseDirectory, item.ModelFile); var systemAttrs = new SystemAttributes(context, item, TemplateProcessor.Language); foreach (var template in templates) { var extension = template.Extension; string outputFile = Path.ChangeExtension(item.ModelFile, extension); string outputPath = Path.Combine(outputDirectory ?? string.Empty, outputFile); var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); string transformed; if (model == null) { // TODO: remove // currently keep to pass UT transformed = template.Transform(item.ModelFile, systemAttrs); } else { var result = template.TransformModel(model, systemAttrs); if (exportMetadata) { if (metadataFilePathProvider == null) { throw new ArgumentNullException(nameof(metadataFilePathProvider)); } JsonUtility.Serialize(metadataFilePathProvider(outputPath), result.Model); } transformed = result.Result; } if (!string.IsNullOrWhiteSpace(transformed)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { TranformHtml(context, transformed, item.ModelFile, outputPath); } else { File.WriteAllText(outputPath, transformed, Encoding.UTF8); } Logger.Log(LogLevel.Verbose, $"Transformed model \"{item.ModelFile}\" to \"{outputPath}\"."); } else { // TODO: WHAT to do if is transformed to empty string? STILL creat empty file? Logger.LogWarning($"Model \"{item.ModelFile}\" is transformed to empty string with template \"{template.Name}\""); File.WriteAllText(outputPath, string.Empty); } manifestItem.OutputFiles.Add(extension, outputFile); } } // 2. process resource if (item.ResourceFile != null) { PathUtility.CopyFile(Path.Combine(baseDirectory, item.ResourceFile), Path.Combine(outputDirectory, item.ResourceFile), true); manifestItem.OutputFiles.Add("resource", item.ResourceFile); } } catch (Exception e) { Logger.LogWarning($"Unable to transform {item.ModelFile}: {e.Message}. Ignored."); } return manifestItem; }
private TemplateManifestItem TransformItem(ManifestItem item, IDocumentBuildContext context, ApplyTemplateSettings settings) { if (settings.Options.HasFlag(ApplyTemplateOptions.ExportRawModel)) { ExportModel(item.Model.Content, item.ModelFile, settings.RawModelExportSettings); } if (item.Model == null || item.Model.Content == null) { throw new ArgumentNullException("Content for item.Model should not be null!"); } var manifestItem = new TemplateManifestItem { DocumentType = item.DocumentType, OriginalFile = item.LocalPathFromRepoRoot, OutputFiles = new Dictionary <string, string>() }; var outputDirectory = settings.OutputFolder ?? Environment.CurrentDirectory; if (!IsEmpty) { HashSet <string> missingUids = new HashSet <string>(); // Must convert to JObject first as we leverage JsonProperty as the property name for the model var model = ConvertToObjectHelper.ConvertStrongTypeToJObject(item.Model.Content); var templates = Templates[item.DocumentType]; // 1. process model if (templates != null) { var systemAttrs = new SystemAttributes(context, item, TemplateProcessor.Language); foreach (var template in templates) { var extension = template.Extension; string outputFile = Path.ChangeExtension(item.ModelFile, extension); string outputPath = Path.Combine(outputDirectory, outputFile); var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) { Directory.CreateDirectory(dir); } object viewModel = null; try { viewModel = template.TransformModel(model, systemAttrs, _global); } catch (Exception e) { // save raw model for further investigation: var exportSettings = ApplyTemplateSettings.RawModelExportSettingsForDebug; var rawModelPath = ExportModel(item.Model, item.ModelFile, exportSettings); throw new DocumentException($"Error transforming model \"{rawModelPath}\" generated from \"{item.LocalPathFromRepoRoot}\" using \"{template.ScriptName}\": {e.Message}"); } string result; try { result = template.Transform(viewModel); } catch (Exception e) { // save view model for further investigation: var exportSettings = ApplyTemplateSettings.ViewModelExportSettingsForDebug; var viewModelPath = ExportModel(viewModel, outputFile, exportSettings); throw new DocumentException($"Error applying template \"{template.Name}\" to view model \"{viewModelPath}\" generated from \"{item.LocalPathFromRepoRoot}\": {e.Message}"); } if (settings.Options.HasFlag(ApplyTemplateOptions.ExportViewModel)) { ExportModel(viewModel, outputFile, settings.ViewModelExportSettings); } if (settings.Options.HasFlag(ApplyTemplateOptions.TransformDocument)) { if (string.IsNullOrWhiteSpace(result)) { // TODO: WHAT to do if is transformed to empty string? STILL creat empty file? Logger.LogWarning($"Model \"{item.ModelFile}\" is transformed to empty string with template \"{template.Name}\""); File.WriteAllText(outputPath, string.Empty); } else { TransformDocument(result, extension, context, outputPath, item.ModelFile, missingUids); Logger.Log(LogLevel.Verbose, $"Transformed model \"{item.LocalPathFromRepoRoot}\" to \"{outputPath}\"."); } manifestItem.OutputFiles.Add(extension, outputFile); } } } if (missingUids.Count > 0) { var uids = string.Join(", ", missingUids.Select(s => $"\"{s}\"")); Logger.LogWarning($"Unable to resolve cross-reference {uids} for \"{manifestItem.OriginalFile.ToDisplayPath()}\""); } } // 2. process resource if (item.ResourceFile != null) { // Resource file has already been processed in its plugin manifestItem.OutputFiles.Add("resource", item.ResourceFile); } return(manifestItem); }
public void Process(DocumentBuildContext context, string outputDirectory) { var baseDirectory = context.BuildOutputFolder; if (string.IsNullOrEmpty(outputDirectory)) { outputDirectory = Environment.CurrentDirectory; } if (string.IsNullOrEmpty(baseDirectory)) { baseDirectory = Environment.CurrentDirectory; } if (!Directory.Exists(outputDirectory)) { Directory.CreateDirectory(outputDirectory); } // 1. Copy dependent files with path relative to the base output directory ProcessDependencies(outputDirectory); Dictionary <string, HashSet <string> > unProcessedType = new Dictionary <string, HashSet <string> >(StringComparer.OrdinalIgnoreCase); Dictionary <string, string> extMapping = new Dictionary <string, string>(); // 2. Get extension for each item foreach (var item in context.Manifest) { if (item.ModelFile == null) { throw new ArgumentNullException("Model file path must be specified!"); } if (item.DocumentType == null) { throw new ArgumentNullException($"Document type is not allowed to be NULL for ${item.ModelFile}!"); } // NOTE: Resource is not supported for applying templates if (item.DocumentType.Equals("Resource", StringComparison.OrdinalIgnoreCase)) { continue; } var templates = _templates[item.DocumentType]; // Get default template extension if (templates == null || templates.Count == 0) { HashSet <string> unProcessedFiles; if (unProcessedType.TryGetValue(item.DocumentType, out unProcessedFiles)) { unProcessedFiles.Add(item.ModelFile); } else { unProcessedType[item.DocumentType] = new HashSet <string>(FilePathComparer.OSPlatformSensitiveComparer) { item.ModelFile }; } } else { var defaultTemplate = templates.FirstOrDefault(s => s.IsPrimary) ?? templates[0]; string key = ((RelativePath)item.OriginalFile).GetPathFromWorkingFolder(); string value; if (context.FileMap.TryGetValue(key, out value)) { context.FileMap[key] = Path.ChangeExtension(value, defaultTemplate.Extension); extMapping[key] = defaultTemplate.Extension; } else { Logger.Log(LogLevel.Warning, $"{key} is not found in .filemap"); } } } //update internal XrefMap if (context.XRefSpecMap != null) { foreach (var pair in context.XRefSpecMap) { string ext; if (extMapping.TryGetValue(pair.Value.Href, out ext)) { pair.Value.Href = Path.ChangeExtension(pair.Value.Href, ext); } } } if (unProcessedType.Count > 0) { StringBuilder sb = new StringBuilder("There is no template processing:"); foreach (var type in unProcessedType) { sb.AppendLine($"- Document type: \"{type.Key}\""); sb.AppendLine($"- Files:"); foreach (var file in type.Value) { sb.AppendLine($" -\"{file}\""); } } Logger.Log(LogLevel.Warning, sb.ToString());// not processed but copied to '{modelOutputPath}'"); } List <TemplateManifestItem> manifest = new List <TemplateManifestItem>(); // 3. Process every model and save to output directory foreach (var item in context.Manifest) { var manifestItem = new TemplateManifestItem { DocumentType = item.DocumentType, OriginalFile = item.LocalPathFromRepoRoot, OutputFiles = new Dictionary <string, string>() }; try { var templates = _templates[item.DocumentType]; // 1. process model if (templates == null) { // TODO: what if template to transform the type is not found? DO NOTHING? // CopyFile(modelFile, modelOutputPath); } else { var modelFile = Path.Combine(baseDirectory, item.ModelFile); var systemAttrs = new SystemAttributes(context, item, TemplateProcessor.Language); foreach (var template in templates) { var extension = template.Extension; string outputFile = Path.ChangeExtension(item.ModelFile, extension); string outputPath = Path.Combine(outputDirectory ?? string.Empty, outputFile); var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) { Directory.CreateDirectory(dir); } var transformed = template.Transform(modelFile, systemAttrs); if (!string.IsNullOrWhiteSpace(transformed)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { TranformHtml(context, transformed, item.ModelFile, outputPath); } else { File.WriteAllText(outputPath, transformed, Encoding.UTF8); } Logger.Log(LogLevel.Verbose, $"Transformed model \"{item.ModelFile}\" to \"{outputPath}\"."); } else { // TODO: WHAT to do if is transformed to empty string? STILL creat empty file? Logger.Log(LogLevel.Warning, $"Model \"{item.ModelFile}\" is transformed to empty string with template \"{template.Name}\""); File.WriteAllText(outputPath, string.Empty); } manifestItem.OutputFiles.Add(extension, outputFile); } } // 2. process resource if (item.ResourceFile != null) { manifestItem.OutputFiles.Add("resource", item.ResourceFile); PathUtility.CopyFile(Path.Combine(baseDirectory, item.ResourceFile), Path.Combine(outputDirectory, item.ResourceFile), true); } } catch (Exception e) { Logger.Log(LogLevel.Warning, $"Unable to transform {item.ModelFile}: {e.Message}. Ignored."); } manifest.Add(manifestItem); } // Save manifest var manifestPath = Path.Combine(outputDirectory, ManifestFileName); JsonUtility.Serialize(manifestPath, manifest); Logger.Log(LogLevel.Verbose, $"Manifest file saved to {manifestPath}."); }
// TODO: change to use IDocumentBuildContext public static TemplateManifestItem Transform(DocumentBuildContext context, ManifestItem item, TemplateCollection templateCollection, string outputDirectory, bool exportMetadata, Func<string, string> metadataFilePathProvider) { if (item.Model == null || item.Model.Content == null) throw new ArgumentNullException("Content for item.Model should not be null!"); var baseDirectory = context.BuildOutputFolder ?? string.Empty; var manifestItem = new TemplateManifestItem { DocumentType = item.DocumentType, OriginalFile = item.LocalPathFromRepoRoot, OutputFiles = new Dictionary<string, string>() }; HashSet<string> missingUids = new HashSet<string>(); if (templateCollection == null || templateCollection.Count == 0) { return manifestItem; } try { var model = item.Model.Content; var templates = templateCollection[item.DocumentType]; // 1. process model if (templates == null) { // Logger.LogWarning($"There is no template processing {item.DocumentType} document \"{item.LocalPathFromRepoRoot}\""); } else { var systemAttrs = new SystemAttributes(context, item, TemplateProcessor.Language); foreach (var template in templates) { var extension = template.Extension; string outputFile = Path.ChangeExtension(item.ModelFile, extension); string outputPath = Path.Combine(outputDirectory ?? string.Empty, outputFile); var dir = Path.GetDirectoryName(outputPath); if (!string.IsNullOrEmpty(dir)) Directory.CreateDirectory(dir); string transformed; var result = template.TransformModel(model, systemAttrs); if (exportMetadata) { if (metadataFilePathProvider == null) { throw new ArgumentNullException(nameof(metadataFilePathProvider)); } JsonUtility.Serialize(metadataFilePathProvider(outputPath), result.Model); } transformed = result.Result; if (!string.IsNullOrWhiteSpace(transformed)) { if (extension.Equals(".html", StringComparison.OrdinalIgnoreCase)) { try { TranformHtml(context, transformed, item.ModelFile, outputPath); } catch (AggregateException e) { e.Handle(s => { var xrefExcetpion = s as CrossReferenceNotResolvedException; if (xrefExcetpion != null) { missingUids.Add(xrefExcetpion.UidRawText); return true; } else { return false; } }); } } else { File.WriteAllText(outputPath, transformed, Encoding.UTF8); } Logger.Log(LogLevel.Verbose, $"Transformed model \"{item.ModelFile}\" to \"{outputPath}\"."); } else { // TODO: WHAT to do if is transformed to empty string? STILL creat empty file? Logger.LogWarning($"Model \"{item.ModelFile}\" is transformed to empty string with template \"{template.Name}\""); File.WriteAllText(outputPath, string.Empty); } manifestItem.OutputFiles.Add(extension, outputFile); } } // 2. process resource if (item.ResourceFile != null) { PathUtility.CopyFile(Path.Combine(baseDirectory, item.ResourceFile), Path.Combine(outputDirectory, item.ResourceFile), true); manifestItem.OutputFiles.Add("resource", item.ResourceFile); } } catch (Exception e) { Logger.LogError($"Unable to transform {item.ModelFile}: {e.Message}. Ignored."); throw; } if (missingUids.Count > 0) { var uids = string.Join(", ", missingUids.Select(s => $"\"{s}\"")); Logger.LogWarning($"Unable to resolve cross-reference {uids} for \"{manifestItem.OriginalFile.ToDisplayPath()}\""); } return manifestItem; }