/// <summary> /// TODO: extract to base class together with class ApplyOverrideDocument /// </summary> /// <param name="models"></param> /// <param name="host"></param> private void ApplyOverrides(ImmutableList <FileModel> models, IHostService host) { foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var od = ms.Where(m => m.Type == DocumentType.Override).ToList(); var articles = ms.Except(od).ToList(); if (articles.Count == 0 || od.Count == 0) { continue; } if (od.Count > 1) { var uidDefinitions = od[0].Uids.Where(u => u.Name == uid); var errorMessage = string.Join(",", uidDefinitions.Select(s => $"\"{s.File}\" Line {s.Line}")); throw new DocumentException($"UID \"{uid}\" is defined in multiple places: {errorMessage}. Only one overwrite document is allowed per particular UID."); } var ovm = ((List <RestApiItemViewModel>)od[0].Content).Single(vm => vm.Uid == uid); foreach ( var pair in from model in articles from item in new RestApiItemViewModel[] { (RestApiItemViewModel)model.Content }.Concat(((RestApiItemViewModel)model.Content).Children) where item.Uid == uid select new { model, item }) { var vm = pair.item; Merger.Merge(ref vm, ovm); vm.Metadata = MergeMetadata(vm.Metadata, ovm.Metadata); ((HashSet <string>)pair.model.Properties.LinkToUids).UnionWith((HashSet <string>)od[0].Properties.LinkToUids); ((HashSet <string>)pair.model.Properties.LinkToFiles).UnionWith((HashSet <string>)od[0].Properties.LinkToFiles); } } }
private void FillCore(PageViewModel model, IHostService host) { if (model.References == null || model.References.Count == 0) { return; } foreach (var r in model.References) { var m = host.LookupByUid(r.Uid).Find(x => x.Type == DocumentType.Article); if (m == null) { continue; } var page = (PageViewModel)m.Content; var item = page.Items.Find(x => x.Uid == r.Uid); if (item == null) { continue; } r.Summary = item.Summary; r.Type = item.Type; r.Syntax = item.Syntax; r.Platform = item.Platform; } }
private void FillCore(PageViewModel model, IHostService host, string file) { TraceSourceInfo(model, file); if (model.References == null || model.References.Count == 0) { return; } foreach (var r in model.References) { var m = host.LookupByUid(r.Uid).Find(x => x.Type == DocumentType.Article); if (m == null) { SourceInfo i; if (_items.TryGetValue(r.Uid, out i)) { FillContent(r, i); } continue; } var page = (PageViewModel)m.Content; var item = page.Items.Find(x => x.Uid == r.Uid); if (item == null) { continue; } FillContent(r, item); } }
private void ApplyOverrides(ImmutableList<FileModel> models, IHostService host) { foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var od = ms.SingleOrDefault(m => m.Type == DocumentType.Override); if (od != null) { var ovm = ((List<ItemViewModel>)od.Content).Single(vm => vm.Uid == uid); foreach ( var pair in from model in ms where model.Type == DocumentType.Article from item in ((PageViewModel)model.Content).Items where item.Uid == uid select new { model, item }) { var vm = pair.item; // todo : fix file path Merger.Merge(ref vm, ovm); ((HashSet<string>)pair.model.Properties.LinkToUids).UnionWith((HashSet<string>)od.Properties.LinkToUids); ((HashSet<string>)pair.model.Properties.LinkToFiles).UnionWith((HashSet<string>)od.Properties.LinkToFiles); } } } }
private void FillCore(PageViewModel model, IHostService host) { if (model.References == null || model.References.Count == 0) { return; } foreach (var r in model.References) { var m = host.LookupByUid(r.Uid).Find(x => x.Type == DocumentType.Article); if (m == null) { continue; } var page = (PageViewModel)m.Content; var item = page.Items.Find(x => x.Uid == r.Uid); if (item == null) { continue; } r.Additional["summary"] = item.Summary; r.Additional["type"] = item.Type; r.Additional["syntax"] = item.Syntax; r.Additional["platform"] = item.Platform; } }
private void ApplyOverrides(ImmutableList <FileModel> models, IHostService host) { foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var od = ms.SingleOrDefault(m => m.Type == DocumentType.Override); if (od != null) { var ovm = ((List <ItemViewModel>)od.Content).Single(vm => vm.Uid == uid); foreach ( var pair in from model in ms where model.Type == DocumentType.Article from item in ((PageViewModel)model.Content).Items where item.Uid == uid select new { model, item }) { var vm = pair.item; // todo : fix file path Merger.Merge(ref vm, ovm); ((HashSet <string>)pair.model.Properties.LinkToUids).UnionWith((HashSet <string>)od.Properties.LinkToUids); ((HashSet <string>)pair.model.Properties.LinkToFiles).UnionWith((HashSet <string>)od.Properties.LinkToFiles); } } } }
public void Build(FileModel model, IHostService host) { if (model.Type == DocumentType.Article) { var contents = (IDictionary <string, object>)model.Content; if (contents.ContainsKey("related-topics")) { var newLinks = new List <Link>(); var topics = (string)contents["related-topics"]; if (topics != null) { foreach (var topic in topics.Split(',')) { var found = host.LookupByUid(topic.Trim()); if (found != null && found.Count > 0) { var top = found[0]; var topContents = (IDictionary <string, object>)top.Content; var url = (string)topContents["path"]; url = url.Substring(0, url.Length - 3); // cut off .md newLinks.Add(new Link() { Title = (string)topContents["title"], Url = $"/{url}.html" }); } } AddLinksDivToContents(contents, "related-topics", newLinks); } } if (contents.ContainsKey("links")) { var linkList = (List <object>)contents["links"]; if (linkList != null) { var newLinks = new List <Link>(); foreach (string mdLink in linkList) { var m = Regex.Match(mdLink, @"\[([^\]]+)\]\(([^\)]+)\)"); if (m.Success) { newLinks.Add(new Link() { Title = m.Groups[1].Value, Url = m.Groups[2].Value }); } } AddLinksDivToContents(contents, "links", newLinks); } } model.Content = contents; } }
protected virtual void ApplyOverwrites(ImmutableList <FileModel> models, IHostService host) { foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var od = ms.Where(m => m.Type == DocumentType.Overwrite).ToList(); var articles = ms.Except(od).ToList(); if (articles.Count == 0 || od.Count == 0) { continue; } ApplyOverwrite(host, od, uid, articles); } }
private void ApplyOverwrites(ImmutableList <FileModel> models, IHostService host) { foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var od = ms.Where(m => m.Type == DocumentType.Overwrite).ToList(); var articles = ms.Except(od).ToList(); if (articles.Count == 0 || od.Count == 0) { continue; } // Multiple UID in overwrite documents is allowed now var ovms = (from fm in od.Distinct() from content in GetItemsFromOverwriteDocument(fm, uid, host) select new { model = content, fileModel = fm }).ToList(); if (ovms.Count == 0) { continue; } // 1. merge all the overwrite document into one overwrite view model var ovm = ovms.Skip(1).Aggregate(ovms[0].model, (accum, item) => Merge(accum, item.model, item.fileModel)); // 2. apply the view model to articles matching the uid foreach ( var pair in from model in articles from item in GetItemsToOverwrite(model, uid, host) select new { model, item }) { var vm = pair.item; Merge(vm, ovm, ovms[0].fileModel); ((HashSet <string>)pair.model.Properties.LinkToUids).UnionWith((HashSet <string>)od[0].Properties.LinkToUids); ((HashSet <string>)pair.model.Properties.LinkToFiles).UnionWith((HashSet <string>)od[0].Properties.LinkToFiles); } } }
public override IEnumerable <FileModel> Prebuild(ImmutableList <FileModel> models, IHostService host) { host.LogInfo("Merging platform..."); var processedUid = new HashSet <string>(); var merged = models.RunAll(m => { if (m.Type != DocumentType.Article) { return(m); } if (m.Uids.Length == 0) { host.LogWarning("Unknown model without uid.", file: m.File); return(m); } var mainUid = m.Uids[0].Name; if (processedUid.Contains(mainUid)) { return(null); } var sameTopics = host.LookupByUid(mainUid); if (sameTopics.Count == 1) { return(m); } processedUid.Add(mainUid); var vm = (PageViewModel)m.Content; m.Content = MergeCore( mainUid, m, from topic in sameTopics where topic != m where topic.Type == DocumentType.Article select topic, host); return(m); }); host.LogInfo("Platform merged."); return(from p in merged where p != null select p); }
public override IEnumerable<FileModel> Prebuild(ImmutableList<FileModel> models, IHostService host) { host.LogInfo("Merging platform..."); var processedUid = new HashSet<string>(); var merged = models.RunAll(m => { if (m.Type != DocumentType.Article) { return m; } if (m.Uids.Length == 0) { host.LogWarning("Unknown model without uid.", file: m.File); return m; } var mainUid = m.Uids[0]; if (processedUid.Contains(mainUid)) { return null; } var sameTopics = host.LookupByUid(mainUid); if (sameTopics.Count == 1) { return m; } processedUid.Add(mainUid); var vm = (PageViewModel)m.Content; m.Content = MergeCore( mainUid, m, from topic in sameTopics where topic != m where topic.Type == DocumentType.Article select topic, host); return m; }); host.LogInfo("Platform merged."); return from p in merged where p != null select p; }
public override void Postbuild(ImmutableList <FileModel> models, IHostService host) { var schemaProcessor = new SchemaProcessor(new MergeTypeInterpreter()); foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var od = ms.Where(m => m.Type == DocumentType.Overwrite).ToList(); var articles = ms.Except(od).ToList(); if (articles.Count == 0 || od.Count == 0) { continue; } if (articles.Count > 1) { throw new DocumentException($"{uid} is defined in multiple articles {articles.Select(s => s.LocalPathFromRoot).ToDelimitedString()}"); } var model = articles[0]; var uids = model.Properties.Uids; model.Content = schemaProcessor.Process(model.Content, model.Properties.Schema, new ProcessContext(host, model)); } }
private void ApplyOverwriteToModel(OverwriteApplier overwriteApplier, string uid, IHostService host) { var ms = host.LookupByUid(uid); var ods = ms.Where(m => m.Type == DocumentType.Overwrite).ToList(); var articles = ms.Except(ods).ToList(); if (articles.Count == 0 || ods.Count == 0) { return; } if (articles.Count > 1) { throw new DocumentException($"{uid} is defined in multiple articles {articles.Select(s => s.LocalPathFromRoot).ToDelimitedString()}"); } var model = articles[0]; var schema = model.Properties.Schema as DocumentSchema; using (new LoggerFileScope(model.LocalPathFromRoot)) { var uidDefiniton = model.Uids.Where(s => s.Name == uid).ToList(); if (uidDefiniton.Count == 0) { throw new DocfxException($"Unable to find UidDefinition for Uid {uid}"); } try { foreach (var ud in uidDefiniton) { var jsonPointer = new JsonPointer(ud.Path).GetParentPointer(); var schemaForCurrentUid = jsonPointer.FindSchema(schema); var source = jsonPointer.GetValue(model.Content); foreach (var od in ods) { using (new LoggerFileScope(od.LocalPathFromRoot)) { foreach (var fm in ((IEnumerable <OverwriteDocumentModel>)od.Content).Where(s => s.Uid == uid)) { // Suppose that BuildOverwriteWithSchema do the validation of the overwrite object var overwriteObject = overwriteApplier.BuildOverwriteWithSchema(od, fm, schemaForCurrentUid); overwriteApplier.MergeContentWithOverwrite(ref source, overwriteObject, ud.Name, string.Empty, schemaForCurrentUid); model.LinkToUids = model.LinkToUids.Union(od.LinkToUids); model.LinkToFiles = model.LinkToFiles.Union(od.LinkToFiles); model.FileLinkSources = model.FileLinkSources.Merge(od.FileLinkSources); model.UidLinkSources = model.UidLinkSources.Merge(od.UidLinkSources); } } } } // 1. Validate schema after the merge // TODO: Issue exists - however unable to identify which overwrite document the issue is from ((SchemaDrivenDocumentProcessor)host.Processor).SchemaValidator.Validate(model.Content); // 2. Re-export xrefspec after the merge overwriteApplier.UpdateXrefSpec(model, schema); } catch (DocumentException e) { // Log error here to preserve file info Logger.LogError(e.Message); throw; } } }
public override void Postbuild(ImmutableList<FileModel> models, IHostService host) { foreach (var uid in host.GetAllUids()) { var ms = host.LookupByUid(uid); var ods = ms.Where(m => m.Type == DocumentType.Overwrite).ToList(); var articles = ms.Except(ods).ToList(); if (articles.Count == 0 || ods.Count == 0) { continue; } if (articles.Count > 1) { throw new DocumentException($"{uid} is defined in multiple articles {articles.Select(s => s.LocalPathFromRoot).ToDelimitedString()}"); } var model = articles[0]; var schema = model.Properties.Schema as DocumentSchema; using (new LoggerFileScope(model.LocalPathFromRoot)) { var uidDefiniton = model.Uids.Where(s => s.Name == uid).ToList(); if (uidDefiniton.Count == 0) { throw new DocfxException($"Unable to find UidDefinition for Uid {uid}"); } foreach (var ud in uidDefiniton) { var jsonPointer = new JsonPointer(ud.Path).GetParentPointer(); var schemaForCurrentUid = jsonPointer.FindSchema(schema); var source = jsonPointer.GetValue(model.Content); foreach (var od in ods) { using (new LoggerFileScope(od.LocalPathFromRoot)) { foreach (var fm in ((IEnumerable<OverwriteDocumentModel>)od.Content).Where(s => s.Uid == uid)) { // Suppose that BuildOverwriteWithSchema do the validation of the overwrite object var overwriteObject = BuildOverwriteWithSchema(od, fm, host, schemaForCurrentUid); _merger.Merge(ref source, overwriteObject, ud.Name, string.Empty, schemaForCurrentUid); model.LinkToUids = model.LinkToUids.Union(od.LinkToUids); model.LinkToFiles = model.LinkToFiles.Union(od.LinkToFiles); model.FileLinkSources = model.FileLinkSources.Merge(od.FileLinkSources); model.UidLinkSources = model.UidLinkSources.Merge(od.UidLinkSources); } } } } // 1. Validate schema after the merge ((SchemaDrivenDocumentProcessor)host.Processor).SchemaValidator.Validate(model.Content); // 2. Re-export xrefspec after the merge var context = new ProcessContext(host, model); _xrefSpecUpdater.Process(model.Content, schema, context); UpdateXRefSpecs((List<XRefSpec>)model.Properties.XRefSpecs, context.XRefSpecs); UpdateXRefSpecs((List<XRefSpec>)model.Properties.ExternalXRefSpecs, context.ExternalXRefSpecs); } } }