private void BuildCore(FileModel model, IHostService host) { var markdownService = (MarkdigMarkdownService)model.MarkdownFragmentsModel.Properties.MarkdigMarkdownService; var overwriteDocumentModelCreater = new OverwriteDocumentModelCreater(model.MarkdownFragmentsModel.OriginalFileAndType.File); var overwriteApplier = new OverwriteApplier(host, OverwriteModelType.MarkdownFragments); var schema = model.Properties.Schema as DocumentSchema; List <OverwriteDocumentModel> overwriteDocumentModels; // 1. string => AST(MarkdownDocument) var ast = markdownService.Parse((string)model.MarkdownFragmentsModel.Content, model.MarkdownFragmentsModel.OriginalFileAndType.File); // 2 AST(MarkdownDocument) => MarkdownFragmentModel var fragments = new MarkdownFragmentsCreater().Create(ast).ToList(); // 3. MarkdownFragmentModel => OverwriteDocument overwriteDocumentModels = fragments.Select(overwriteDocumentModelCreater.Create).ToList(); model.MarkdownFragmentsModel.Content = overwriteDocumentModels; // Validate here as OverwriteDocumentModelCreater already filtered some invalid cases, e.g. duplicated H2 ValidateWithSchema(fragments, model); // 4. Apply schema to OverwriteDocument, and merge with skeyleton YAML object foreach (var overwriteDocumentModel in overwriteDocumentModels) { var uidDefinitons = model.Uids.Where(s => s.Name == overwriteDocumentModel.Uid).ToList(); if (uidDefinitons.Count == 0) { Logger.LogWarning( $"Unable to find UidDefinition for Uid: { overwriteDocumentModel.Uid}", code: WarningCodes.Overwrite.InvalidMarkdownFragments); continue; } if (uidDefinitons.Count > 1) { Logger.LogWarning($"There are more than one UidDefinitions found for Uid {overwriteDocumentModel.Uid} in lines {string.Join(", ", uidDefinitons.Select(uid => uid.Line).ToList())}"); } var ud = uidDefinitons[0]; var jsonPointer = new JsonPointer(ud.Path).GetParentPointer(); var schemaForCurrentUid = jsonPointer.FindSchema(schema); var source = jsonPointer.GetValue(model.Content); var overwriteObject = overwriteApplier.BuildOverwriteWithSchema(model.MarkdownFragmentsModel, overwriteDocumentModel, schema); overwriteApplier.MergeContentWithOverwrite(ref source, overwriteObject, ud.Name, string.Empty, schemaForCurrentUid); } // 5. Validate schema after the merge using (new LoggerFileScope(model.LocalPathFromRoot)) { ((SchemaDrivenDocumentProcessor)host.Processor).SchemaValidator.Validate(model.Content); } // 6. Re-export xrefspec after the merge overwriteApplier.UpdateXrefSpec(model, schema); model.LinkToUids = model.LinkToUids.Union(model.MarkdownFragmentsModel.LinkToUids); model.LinkToFiles = model.LinkToFiles.Union(model.MarkdownFragmentsModel.LinkToFiles); model.FileLinkSources = model.FileLinkSources.Merge(model.MarkdownFragmentsModel.FileLinkSources); model.UidLinkSources = model.UidLinkSources.Merge(model.MarkdownFragmentsModel.UidLinkSources); model.MarkdownFragmentsModel.Content = overwriteDocumentModels; }
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); } } }