Inheritance: IDocumentBuildContext
示例#1
0
 public TemplateModelTransformer(DocumentBuildContext context, TemplateCollection templateCollection, ApplyTemplateSettings settings, IDictionary <string, object> globals)
 {
     _context            = context ?? throw new ArgumentNullException(nameof(context));
     _templateCollection = templateCollection;
     _settings           = settings;
     _globalVariables    = globals;
 }
示例#2
0
 public TemplatePageLoader(IResourceFileReader reader, DocumentBuildContext context, int maxParallelism)
 {
     _reader             = reader;
     _maxParallelism     = maxParallelism;
     _rendererLoader     = new RendererLoader(reader, maxParallelism);
     _preprocessorLoader = new PreprocessorLoader(reader, context, maxParallelism);
 }
示例#3
0
        internal List <ManifestItem> Process(List <InternalManifestItem> manifest, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary <string, object> globals = null)
        {
            using (new LoggerPhaseScope("Apply Templates", true))
            {
                if (globals == null)
                {
                    globals = Tokens.ToDictionary(pair => pair.Key, pair => (object)pair.Value);
                }

                var documentTypes             = manifest.Select(s => s.DocumentType).Distinct();
                var notSupportedDocumentTypes = documentTypes.Where(s => s != "Resource" && _templateCollection[s] == null);
                if (notSupportedDocumentTypes.Any())
                {
                    Logger.LogWarning($"There is no template processing document type(s): {notSupportedDocumentTypes.ToDelimitedString()}");
                }
                Logger.LogInfo($"Applying templates to {manifest.Count} model(s)...");

                if (settings.Options.HasFlag(ApplyTemplateOptions.TransformDocument))
                {
                    var templatesInUse = documentTypes.Select(s => _templateCollection[s]).Where(s => s != null).ToList();
                    ProcessDependencies(settings.OutputFolder, templatesInUse);
                }
                else
                {
                    Logger.LogInfo("Dryrun, no template will be applied to the documents.");
                }

                var templateManifest = ProcessCore(manifest, context, settings, globals);
                return(templateManifest);
            }
        }
示例#4
0
 private void RegisterXRefSpec(DocumentBuildContext context, SaveResult result)
 {
     foreach (var spec in result.XRefSpecs)
     {
         if (!string.IsNullOrWhiteSpace(spec?.Uid))
         {
             XRefSpec xref;
             if (context.XRefSpecMap.TryGetValue(spec.Uid, out xref))
             {
                 Logger.LogWarning($"Uid({spec.Uid}) has already been defined in {((RelativePath)xref.Href).RemoveWorkingFolder()}.");
             }
             else
             {
                 context.XRefSpecMap[spec.Uid] = spec.ToReadOnly();
             }
         }
     }
     foreach (var spec in result.ExternalXRefSpecs)
     {
         if (!string.IsNullOrWhiteSpace(spec?.Uid))
         {
             context.ReportExternalXRefSpec(spec);
         }
     }
 }
示例#5
0
        internal List<ManifestItem> Process(List<InternalManifestItem> manifest, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary<string, object> globals = null)
        {
            using (new LoggerPhaseScope("Apply Templates", true))
            {
                if (globals == null)
                {
                    globals = Tokens.ToDictionary(pair => pair.Key, pair => (object)pair.Value);
                }

                var documentTypes = manifest.Select(s => s.DocumentType).Distinct();
                var notSupportedDocumentTypes = documentTypes.Where(s => s != "Resource" && _templateCollection[s] == null);
                if (notSupportedDocumentTypes.Any())
                {
                    Logger.LogWarning($"There is no template processing document type(s): {TypeForwardedToStringExtension.ToDelimitedString(notSupportedDocumentTypes)}");
                }
                Logger.LogInfo($"Applying templates to {manifest.Count} model(s)...");

                if (settings.Options.HasFlag(ApplyTemplateOptions.TransformDocument))
                {
                    var templatesInUse = documentTypes.Select(s => _templateCollection[s]).Where(s => s != null).ToList();
                    ProcessDependencies(settings.OutputFolder, templatesInUse);
                }
                else
                {
                    Logger.LogInfo("Dryrun, no template will be applied to the documents.");
                }

                var templateManifest = ProcessCore(manifest, context, settings, globals);
                return templateManifest;
            }
        }
示例#6
0
 private static void HandleUids(DocumentBuildContext context, SaveResult result)
 {
     if (result.LinkToUids.Count > 0)
     {
         context.XRef.UnionWith(result.LinkToUids.Where(s => s != null));
     }
 }
示例#7
0
 private void UpdateUidFileDependency(DocumentBuildContext context, List <HostService> hostServices)
 {
     foreach (var hostService in hostServices)
     {
         foreach (var m in hostService.Models)
         {
             if (m.Type == DocumentType.Overwrite)
             {
                 continue;
             }
             if (m.LinkToUids.Count != 0)
             {
                 context.DependencyGraph.ReportDependency(
                     ((RelativePath)m.OriginalFileAndType.File).GetPathFromWorkingFolder().ToString(),
                     GetFilesFromUids(context, m.LinkToUids));
             }
             if (m.LinkToFiles.Count != 0)
             {
                 context.DependencyGraph.ReportDependency(
                     ((RelativePath)m.OriginalFileAndType.File).GetPathFromWorkingFolder().ToString(),
                     m.LinkToFiles);
             }
         }
     }
 }
示例#8
0
 private void Prepare(
     DocumentBuildParameters parameters,
     DocumentBuildContext context,
     TemplateProcessor templateProcessor,
     string markdownServiceContextHash,
     out IHostServiceCreator hostServiceCreator,
     out PhaseProcessor phaseProcessor)
 {
     if (IntermediateFolder != null && parameters.ApplyTemplateSettings.TransformDocument)
     {
         context.IncrementalBuildContext = IncrementalBuildContext.Create(parameters, CurrentBuildInfo, LastBuildInfo, IntermediateFolder, markdownServiceContextHash);
         hostServiceCreator = new HostServiceCreatorWithIncremental(context);
         phaseProcessor     = new PhaseProcessor
         {
             Handlers =
             {
                 new PrebuildBuildPhaseHandler(context).WithIncremental(),
                 new PostbuildPhaseHandler(context,                       templateProcessor).WithIncremental(),
             }
         };
     }
     else
     {
         hostServiceCreator = new HostServiceCreator(context);
         phaseProcessor     = new PhaseProcessor
         {
             Handlers =
             {
                 new PrebuildBuildPhaseHandler(context),
                 new PostbuildPhaseHandler(context,     templateProcessor),
             }
         };
     }
 }
示例#9
0
        private List <TemplateManifestItem> ProcessCore(List <ManifestItem> items, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary <string, object> globals)
        {
            var manifest = new ConcurrentBag <TemplateManifestItem>();
            var systemAttributeGenerator = new SystemMetadataGenerator(context);
            var transformer = new TemplateModelTransformer(context, _templateCollection, settings, globals);

            items.RunAll(
                item =>
            {
                var manifestItem = transformer.Transform(item);
                if (manifestItem.OutputFiles?.Count > 0)
                {
                    manifest.Add(manifestItem);
                }
            },
                context.MaxParallelism);

            var itemsToRemove = new List <string>();

            foreach (var duplicates in from m in manifest
                     from output in m.OutputFiles.Values
                     group m.OriginalFile by output into g
                     where g.Count() > 1
                     select g)
            {
                Logger.LogWarning($"Overwrite occurs while input files \"{string.Join(", ", duplicates)}\" writing to the same output file \"{duplicates.Key}\"");
                itemsToRemove.AddRange(duplicates.Skip(1));
            }

            return(manifest.Where(m => !itemsToRemove.Contains(m.OriginalFile)).ToList());
        }
示例#10
0
 public HostServiceCreatorWithIncremental(DocumentBuildContext context) : base(context)
 {
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     IncrementalContext = context.IncrementalBuildContext;
 }
 public HostServiceCreatorWithIncremental(DocumentBuildContext context) : base(context)
 {
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     IncrementalContext = context.IncrementalBuildContext;
 }
示例#12
0
        private Engine SetupEngine(ResourceCollection resourceCollection, TemplatePreprocessorResource scriptResource, DocumentBuildContext context)
        {
            var rootPath = (RelativePath)scriptResource.ResourceName;
            var engineCache = new Dictionary<string, Engine>();

            var utility = new TemplateUtility(context);
            _utilityObject = new
            {
                resolveSourceRelativePath = new Func<string, string, string>(utility.ResolveSourceRelativePath)
            };

            var engine = CreateDefaultEngine();

            var requireAction = new Func<string, object>(
                s =>
                {
                    if (!s.StartsWith(RequireRelativePathPrefix))
                    {
                        throw new ArgumentException($"Only relative path starting with `{RequireRelativePathPrefix}` is supported in require");
                    }
                    var relativePath = (RelativePath)s.Substring(RequireRelativePathPrefix.Length);
                    s = relativePath.BasedOn(rootPath);

                    var script = resourceCollection?.GetResource(s);
                    if (string.IsNullOrWhiteSpace(script))
                    {
                        return null;
                    }

                    Engine cachedEngine;
                    if (!engineCache.TryGetValue(s, out cachedEngine))
                    {
                        cachedEngine = CreateEngine(engine, RequireFuncVariableName);
                        engineCache[s] = cachedEngine;
                        cachedEngine.Execute(script);
                    }

                    return cachedEngine.GetValue(ExportsVariableName);
                });

            engine.SetValue(RequireFuncVariableName, requireAction);
            engineCache[rootPath] = engine;
            engine.Execute(scriptResource.Content);

            var value = engine.GetValue(ExportsVariableName);
            if (value.IsObject())
            {
                var exports = value.AsObject();
                GetOptionsFunc = GetFunc(GetOptionsFuncVariableName, exports);
                TransformModelFunc = GetFunc(TransformFuncVariableName, exports);
            }
            else
            {
                throw new InvalidPreprocessorException("Invalid 'exports' variable definition. 'exports' MUST be an object.");
            }

            return engine;
        }
示例#13
0
 private static List <HomepageInfo> GetHomepages(DocumentBuildContext context)
 {
     return((from s in context.GetTocInfo()
             where !string.IsNullOrEmpty(s.Homepage)
             select new HomepageInfo
     {
         Homepage = RelativePath.GetPathWithoutWorkingFolderChar(s.Homepage),
         TocPath = RelativePath.GetPathWithoutWorkingFolderChar(context.GetFilePath(s.TocFileKey))
     }).ToList());
 }
示例#14
0
 private static List <HomepageInfo> GetHomepages(DocumentBuildContext context)
 {
     return(context.GetTocInfo()
            .Where(s => !string.IsNullOrEmpty(s.Homepage))
            .Select(s => new HomepageInfo
     {
         Homepage = TypeForwardedToRelativePath.GetPathWithoutWorkingFolderChar(s.Homepage),
         TocPath = TypeForwardedToRelativePath.GetPathWithoutWorkingFolderChar(context.GetFilePath(s.TocFileKey))
     }).ToList());
 }
示例#15
0
 public TemplateJintPreprocessor(ResourceCollection resourceCollection, TemplatePreprocessorResource scriptResource, DocumentBuildContext context)
 {
     if (!string.IsNullOrWhiteSpace(scriptResource.Content))
     {
         _engine = SetupEngine(resourceCollection, scriptResource, context);
     }
     else
     {
         _engine = null;
     }
 }
示例#16
0
        private void SaveDependency(DocumentBuildContext context, DocumentBuildParameters parameters)
        {
            var vbi = _currentBuildInfo.Versions.Find(v => v.VersionName == parameters.VersionName);

            vbi.Dependency = Path.GetRandomFileName();
            using (var writer = File.CreateText(
                       Path.Combine(IntermediateFolder, vbi.Dependency)))
            {
                context.DependencyGraph.Save(writer);
            }
        }
示例#17
0
        public ManifestProcessor(List <ManifestItemWithContext> manifestWithContext, DocumentBuildContext context, TemplateProcessor templateProcessor)
        {
            _context             = context ?? throw new ArgumentNullException(nameof(context));
            _templateProcessor   = templateProcessor ?? throw new ArgumentNullException(nameof(templateProcessor));
            _manifestWithContext = manifestWithContext ?? throw new ArgumentNullException(nameof(manifestWithContext));

            // E.g. we can set TOC model to be globally shared by every data model
            // Make sure it is single thread
            _globalMetadata = _templateProcessor.Tokens?.ToDictionary(pair => pair.Key, pair => (object)pair.Value)
                              ?? new Dictionary <string, object>();
        }
示例#18
0
        /// <summary>
        /// TemplateName can be either file or folder
        /// 1. If TemplateName is file, it is considered as the default template
        /// 2. If TemplateName is a folder, files inside the folder is considered as the template, each file is named after {DocumentType}.{extension}
        /// </summary>
        /// <param name="templateName"></param>
        /// <param name="resourceProvider"></param>
        public TemplateProcessor(ResourceCollection resourceProvider, DocumentBuildContext context, int maxParallelism = 0)
        {
            if (maxParallelism <= 0)
            {
                maxParallelism = Environment.ProcessorCount;
            }

            _resourceProvider   = resourceProvider;
            _templateCollection = new TemplateCollection(resourceProvider, context, maxParallelism);
            Tokens = LoadTokenJson(resourceProvider) ?? new Dictionary <string, string>();
        }
示例#19
0
        /// <summary>
        /// TemplateName can be either file or folder
        /// 1. If TemplateName is file, it is considered as the default template
        /// 2. If TemplateName is a folder, files inside the folder is considered as the template, each file is named after {DocumentType}.{extension}
        /// </summary>
        /// <param name="templateName"></param>
        /// <param name="resourceProvider"></param>
        public TemplateProcessor(ResourceCollection resourceProvider, DocumentBuildContext context, int maxParallelism = 0)
        {
            if (maxParallelism <= 0)
            {
                maxParallelism = Environment.ProcessorCount;
            }

            _resourceProvider = resourceProvider;
            _templateCollection = new TemplateCollection(resourceProvider, context, maxParallelism);
            Tokens = LoadTokenJson(resourceProvider) ?? new Dictionary<string, string>();
        }
示例#20
0
        public TemplateModelTransformer(DocumentBuildContext context, TemplateCollection templateCollection, ApplyTemplateSettings settings, IDictionary<string, object> globals)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            _context = context;
            _templateCollection = templateCollection;
            _settings = settings;
            _globalVariables = globals;
            _systemMetadataGenerator = new SystemMetadataGenerator(context);
        }
示例#21
0
        /// <summary>
        /// TemplateName can be either file or folder
        /// 1. If TemplateName is file, it is considered as the default template
        /// 2. If TemplateName is a folder, files inside the folder is considered as the template, each file is named after {DocumentType}.{extension}
        /// </summary>
        /// <param name="templateName"></param>
        /// <param name="resourceProvider"></param>
        public TemplateProcessor(ResourceFileReader resourceProvider, DocumentBuildContext context, int maxParallelism = 0)
        {
            if (maxParallelism <= 0)
            {
                maxParallelism = Environment.ProcessorCount;
            }

            _context            = context;
            _resourceProvider   = resourceProvider;
            _maxParallelism     = maxParallelism;
            _templateCollection = new TemplateCollection(resourceProvider, context, maxParallelism);
            Tokens = TemplateProcessorUtility.LoadTokens(resourceProvider) ?? new Dictionary <string, string>();
        }
        public TemplateModelTransformer(DocumentBuildContext context, TemplateCollection templateCollection, ApplyTemplateSettings settings, IDictionary <string, object> globals)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            _context                 = context;
            _templateCollection      = templateCollection;
            _settings                = settings;
            _globalVariables         = globals;
            _systemMetadataGenerator = new SystemMetadataGenerator(context);
        }
示例#23
0
        private void PrepareBuild(DocumentBuildContext context, IEnumerable <HostService> hostServices)
        {
            var incrementalContext = context.IncrementalBuildContext;
            var lbv = incrementalContext?.LastBuildVersionInfo;
            var cbv = incrementalContext?.CurrentBuildVersionInfo;

            if (ShouldTraceIncrementalInfo)
            {
                var ldg = lbv?.Dependency;
                var cdg = cbv.Dependency;
                if (ldg != null)
                {
                    // reregister dependency types from last dependency graph
                    using (new LoggerPhaseScope("RegisterDependencyTypeFromLastBuild", true))
                    {
                        cdg.RegisterDependencyType(ldg.DependencyTypes.Values);
                    }

                    // restore dependency graph from last dependency graph
                    using (new LoggerPhaseScope("ReportDependencyFromLastBuild", true))
                    {
                        cdg.ReportDependency(from r in ldg.ReportedBys
                                             from i in ldg.GetDependencyReportedBy(r)
                                             select i);
                    }
                }
            }
            foreach (var hostService in hostServices)
            {
                hostService.SourceFiles = context.AllSourceFiles;
                foreach (var m in hostService.Models)
                {
                    if (m.LocalPathFromRepoRoot == null)
                    {
                        m.LocalPathFromRepoRoot = TypeForwardedToStringExtension.ToDisplayPath(Path.Combine(m.BaseDir, m.File));
                    }
                    if (m.LocalPathFromRoot == null)
                    {
                        m.LocalPathFromRoot = TypeForwardedToStringExtension.ToDisplayPath(Path.Combine(m.BaseDir, m.File));
                    }
                }
                if (ShouldTraceIncrementalInfo)
                {
                    hostService.DependencyGraph = cbv.Dependency;
                    using (new LoggerPhaseScope("RegisterDependencyTypeFromProcessor", true))
                    {
                        RegisterDependencyType(hostService);
                    }
                }
            }
        }
示例#24
0
        private static FileModel Load(
            IDocumentProcessor processor,
            ImmutableDictionary <string, object> metadata,
            FileMetadata fileMetadata,
            FileAndType file,
            bool canProcessorIncremental,
            DocumentBuildContext context)
        {
            using (new LoggerFileScope(file.File))
            {
                Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Loading...");

                if (canProcessorIncremental)
                {
                    var incrementalContext = context.IncrementalBuildContext;
                    ChangeKindWithDependency ck;
                    string fileKey = ((TypeForwardedToRelativePath)file.File).GetPathFromWorkingFolder().ToString();
                    if (incrementalContext.ChangeDict.TryGetValue(fileKey, out ck))
                    {
                        Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}, ChangeType {ck}.");
                        if (ck == ChangeKindWithDependency.Deleted)
                        {
                            return(null);
                        }
                        if (ck == ChangeKindWithDependency.None)
                        {
                            Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Check incremental...");
                            if (processor.BuildSteps.Cast <ISupportIncrementalBuildStep>().All(step => step.CanIncrementalBuild(file)))
                            {
                                Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Skip build by incremental.");
                                return(null);
                            }
                            Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Incremental not available.");
                        }
                    }
                }

                var path = Path.Combine(file.BaseDir, file.File);
                metadata = ApplyFileMetadata(path, metadata, fileMetadata);
                try
                {
                    return(processor.Load(file, metadata));
                }
                catch (Exception)
                {
                    Logger.LogError($"Unable to load file: {file.File} via processor: {processor.Name}.");
                    throw;
                }
            }
        }
示例#25
0
 private static ManifestItem GetManifestItem(DocumentBuildContext context, FileModel model, SaveResult result)
 {
     return(new ManifestItem
     {
         DocumentType = result.DocumentType,
         ModelFile = result.ModelFile,
         ResourceFile = result.ResourceFile,
         Key = model.Key,
         // TODO: What is API doc's LocalPathToRepo? => defined in ManagedReferenceDocumentProcessor
         LocalPathFromRepoRoot = model.LocalPathFromRepoRoot,
         Model = model.ModelWithCache,
         InputFolder = model.OriginalFileAndType.BaseDir
     });
 }
示例#26
0
 private static InternalManifestItem GetManifestItem(DocumentBuildContext context, FileModel model, SaveResult result)
 {
     return(new InternalManifestItem
     {
         DocumentType = result.DocumentType,
         FileWithoutExtension = result.FileWithoutExtension,
         ResourceFile = result.ResourceFile,
         Key = model.Key,
         LocalPathFromRoot = model.LocalPathFromRoot,
         Model = model.ModelWithCache,
         InputFolder = model.OriginalFileAndType.BaseDir,
         Metadata = new Dictionary <string, object>((IDictionary <string, object>)model.ManifestProperties),
     });
 }
示例#27
0
        private ManifestItem HandleSaveResult(
            DocumentBuildContext context,
            HostService hostService,
            FileModel model,
            SaveResult result)
        {
            context.FileMap[model.Key] = ((RelativePath)model.File).GetPathFromWorkingFolder();
            DocumentException.RunAll(
                () => CheckFileLink(hostService, result),
                () => HandleUids(context, result),
                () => HandleToc(context, result),
                () => RegisterXRefSpec(context, result));

            return(GetManifestItem(context, model, result));
        }
示例#28
0
 private static ManifestItem GetManifestItem(DocumentBuildContext context, FileModel model, SaveResult result)
 {
     return(new ManifestItem
     {
         DocumentType = result.DocumentType,
         FileWithoutExtension = result.FileWithoutExtension,
         ResourceFile = result.ResourceFile,
         Key = model.Key,
         // TODO: What is API doc's LocalPathToRepo? => defined in ManagedReferenceDocumentProcessor
         LocalPathFromRepoRoot = model.LocalPathFromRepoRoot,
         Model = model.ModelWithCache,
         InputFolder = model.OriginalFileAndType.BaseDir,
         Metadata = new Dictionary <string, object>((IDictionary <string, object>)model.ManifestProperties),
     });
 }
示例#29
0
        private static void UpdateHostServicesPerchanges(DocumentBuildContext context, IEnumerable <HostService> hostServices)
        {
            var incrementalContext = context.IncrementalBuildContext;
            var cbv = incrementalContext.CurrentBuildVersionInfo;

            UpdateUidDependency(hostServices, context);
            if (incrementalContext.CanVersionIncremental)
            {
                var newChanges = incrementalContext.ExpandDependency(cbv.Dependency, d => true);
                Logger.LogDiagnostic($"After expanding dependency before postbuild, changes: {JsonUtility.Serialize(incrementalContext.ChangeDict)}");
                foreach (var hostService in hostServices)
                {
                    hostService.ReloadModelsPerIncrementalChanges(incrementalContext, newChanges, BuildPhase.PostBuild);
                }
            }
        }
示例#30
0
        /// <summary>
        /// Export xref map file.
        /// </summary>
        private static void ExportXRefMap(DocumentBuildParameters parameters, DocumentBuildContext context)
        {
            Logger.LogVerbose("Exporting xref map...");
            var xrefMap = new XRefMap();

            xrefMap.References =
                (from xref in context.XRefSpecMap.Values.AsParallel().WithDegreeOfParallelism(parameters.MaxParallelism)
                 select new XRefSpec(xref)
            {
                Href = ((RelativePath)context.FileMap[xref.Href]).RemoveWorkingFolder().ToString() + "#" + XRefDetails.GetHtmlId(xref.Uid),
            }).ToList();
            xrefMap.Sort();
            YamlUtility.Serialize(
                Path.Combine(parameters.OutputBaseDir, XRefMapFileName),
                xrefMap);
            Logger.LogInfo("XRef map exported.");
        }
示例#31
0
        public Template(string name, DocumentBuildContext context, TemplateRendererResource templateResource, TemplatePreprocessorResource scriptResource, ResourceCollection resourceCollection, int maxParallelism)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            Name = name;
            var templateInfo = GetTemplateInfo(Name);

            Extension    = templateInfo.Extension;
            Type         = templateInfo.DocumentType;
            TemplateType = templateInfo.TemplateType;
            _script      = scriptResource?.Content;
            if (!string.IsNullOrWhiteSpace(_script))
            {
                ScriptName        = Name + ".js";
                _preprocessorPool = ResourcePool.Create(() => CreatePreprocessor(resourceCollection, scriptResource, context), maxParallelism);
                try
                {
                    using (var preprocessor = _preprocessorPool.Rent())
                    {
                        ContainsGetOptions          = preprocessor.Resource.GetOptionsFunc != null;
                        ContainsModelTransformation = preprocessor.Resource.TransformModelFunc != null;
                    }
                }
                catch (Exception e)
                {
                    _preprocessorPool = null;
                    Logger.LogWarning($"{ScriptName} is not a valid template preprocessor, ignored: {e.Message}");
                }
            }

            if (!string.IsNullOrEmpty(templateResource?.Content) && resourceCollection != null)
            {
                _rendererPool            = ResourcePool.Create(() => CreateRenderer(resourceCollection, templateResource), maxParallelism);
                ContainsTemplateRenderer = true;
            }

            if (!ContainsGetOptions && !ContainsModelTransformation && !ContainsTemplateRenderer)
            {
                Logger.LogWarning($"Template {name} contains neither preprocessor to process model nor template to render model. Please check if the template is correctly defined. Allowed preprocessor functions are [exports.getOptions] and [exports.transform].");
            }

            Resources = ExtractDependentResources(Name);
        }
示例#32
0
文件: Template.cs 项目: vicancy/docfx
        public Template(string name, DocumentBuildContext context, TemplateRendererResource templateResource, TemplatePreprocessorResource scriptResource, ResourceCollection resourceCollection, int maxParallelism)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            Name = name;
            var templateInfo = GetTemplateInfo(Name);
            Extension = templateInfo.Extension;
            Type = templateInfo.DocumentType;
            TemplateType = templateInfo.TemplateType;
            _script = scriptResource?.Content;
            if (!string.IsNullOrWhiteSpace(_script))
            {
                ScriptName = Name + ".js";
                _preprocessorPool = ResourcePool.Create(() => CreatePreprocessor(resourceCollection, scriptResource, context), maxParallelism);
                try
                {
                    using (var preprocessor = _preprocessorPool.Rent())
                    {
                        ContainsGetOptions = preprocessor.Resource.GetOptionsFunc != null;
                        ContainsModelTransformation = preprocessor.Resource.TransformModelFunc != null;
                    }
                }
                catch (Exception e)
                {
                    _preprocessorPool = null;
                    Logger.LogWarning($"{ScriptName} is not a valid template preprocessor, ignored: {e.Message}");
                }
            }

            if (!string.IsNullOrEmpty(templateResource?.Content) && resourceCollection != null)
            {
                _rendererPool = ResourcePool.Create(() => CreateRenderer(resourceCollection, templateResource), maxParallelism);
                ContainsTemplateRenderer = true;
            }

            if (!ContainsGetOptions && !ContainsModelTransformation && !ContainsTemplateRenderer)
            {
                Logger.LogWarning($"Template {name} contains neither preprocessor to process model nor template to render model. Please check if the template is correctly defined. Allowed preprocessor functions are [exports.getOptions] and [exports.transform].");
            }

            Resources = ExtractDependentResources(Name);
        }
示例#33
0
 public ManifestProcessor(IEnumerable<HostService> hostServices, DocumentBuildContext context, TemplateProcessor templateProcessor)
 {
     if (hostServices == null)
     {
         throw new ArgumentNullException(nameof(hostServices));
     }
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     if (templateProcessor == null)
     {
         throw new ArgumentNullException(nameof(templateProcessor));
     }
     _context = context;
     _templateProcessor = templateProcessor;
     Init(hostServices);
 }
示例#34
0
 public ManifestProcessor(List <HostService> hostServices, DocumentBuildContext context, TemplateProcessor templateProcessor)
 {
     if (hostServices == null)
     {
         throw new ArgumentNullException(nameof(hostServices));
     }
     if (context == null)
     {
         throw new ArgumentNullException(nameof(context));
     }
     if (templateProcessor == null)
     {
         throw new ArgumentNullException(nameof(templateProcessor));
     }
     _context           = context;
     _templateProcessor = templateProcessor;
     Init(hostServices);
 }
示例#35
0
        private List <ManifestItem> ProcessCore(List <InternalManifestItem> items, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary <string, object> globals)
        {
            var manifest = new ConcurrentBag <ManifestItem>();
            var systemAttributeGenerator = new SystemMetadataGenerator(context);
            var transformer = new TemplateModelTransformer(context, _templateCollection, settings, globals);

            items.RunAll(
                item =>
            {
                var manifestItem = transformer.Transform(item);
                if (manifestItem.OutputFiles?.Count > 0)
                {
                    manifest.Add(manifestItem);
                }
            },
                context.MaxParallelism);
            return(manifest.ToList());
        }
示例#36
0
 private static IEnumerable <string> GetFilesFromUids(DocumentBuildContext context, IEnumerable <string> uids)
 {
     foreach (var uid in uids)
     {
         if (string.IsNullOrEmpty(uid))
         {
             continue;
         }
         XRefSpec spec;
         if (!context.XRefSpecMap.TryGetValue(uid, out spec))
         {
             continue;
         }
         if (spec.Href != null)
         {
             yield return(spec.Href);
         }
     }
 }
示例#37
0
        internal List <ManifestItem> Process(List <InternalManifestItem> manifest, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary <string, object> globals = null)
        {
            using (new LoggerPhaseScope("Apply Templates", LogLevel.Verbose))
            {
                if (globals == null)
                {
                    globals = Tokens.ToDictionary(pair => pair.Key, pair => (object)pair.Value);
                }
                if (settings == null)
                {
                    settings = context.ApplyTemplateSettings;
                }

                Logger.LogInfo($"Applying templates to {manifest.Count} model(s)...");
                var documentTypes = new HashSet <string>(manifest.Select(s => s.DocumentType));
                ProcessDependencies(documentTypes, settings);
                var templateManifest = ProcessCore(manifest, context, settings, globals);
                return(templateManifest);
            }
        }
示例#38
0
 private static void HandleToc(DocumentBuildContext context, SaveResult result)
 {
     if (result.TocMap?.Count > 0)
     {
         foreach (var toc in result.TocMap)
         {
             context.TocMap.AddOrUpdate(
                 toc.Key,
                 toc.Value,
                 (k, v) =>
             {
                 foreach (var item in toc.Value)
                 {
                     v.Add(item);
                 }
                 return(v);
             });
         }
     }
 }
示例#39
0
        internal List<ManifestItem> Process(List<InternalManifestItem> manifest, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary<string, object> globals = null)
        {
            using (new LoggerPhaseScope("Apply Templates", true))
            {
                if (globals == null)
                {
                    globals = Tokens.ToDictionary(pair => pair.Key, pair => (object)pair.Value);
                }
                if (settings == null)
                {
                    settings = context.ApplyTemplateSettings;
                }

                Logger.LogInfo($"Applying templates to {manifest.Count} model(s)...");
                var documentTypes = new HashSet<string>(manifest.Select(s => s.DocumentType));
                ProcessDependencies(documentTypes, settings);
                var templateManifest = ProcessCore(manifest, context, settings, globals);
                return templateManifest;
            }
        }
示例#40
0
        private void PrepareBuild(DocumentBuildContext context, IEnumerable<HostService> hostServices)
        {
            var incrementalContext = context.IncrementalBuildContext;
            var lbv = incrementalContext?.LastBuildVersionInfo;
            var cbv = incrementalContext?.CurrentBuildVersionInfo;
            if (ShouldTraceIncrementalInfo)
            {
                var ldg = lbv?.Dependency;
                var cdg = cbv.Dependency;
                if (ldg != null)
                {
                    // reregister dependency types from last dependency graph
                    using (new LoggerPhaseScope("RegisterDependencyTypeFromLastBuild", true))
                    {
                        cdg.RegisterDependencyType(ldg.DependencyTypes.Values);
                    }

                    // restore dependency graph from last dependency graph
                    using (new LoggerPhaseScope("ReportDependencyFromLastBuild", true))
                    {
                        cdg.ReportDependency(from r in ldg.ReportedBys
                                             from i in ldg.GetDependencyReportedBy(r)
                                             select i);
                    }
                }
            }
            foreach (var hostService in hostServices)
            {
                hostService.SourceFiles = context.AllSourceFiles;
                foreach (var m in hostService.Models)
                {
                    if (m.LocalPathFromRepoRoot == null)
                    {
                        m.LocalPathFromRepoRoot = TypeForwardedToStringExtension.ToDisplayPath(Path.Combine(m.BaseDir, m.File));
                    }
                    if (m.LocalPathFromRoot == null)
                    {
                        m.LocalPathFromRoot = TypeForwardedToStringExtension.ToDisplayPath(Path.Combine(m.BaseDir, m.File));
                    }
                }
                if (ShouldTraceIncrementalInfo)
                {
                    hostService.DependencyGraph = cbv.Dependency;
                    using (new LoggerPhaseScope("RegisterDependencyTypeFromProcessor", true))
                    {
                        RegisterDependencyType(hostService);
                    }
                }
            }
        }
示例#41
0
 private static void UpdateHostServicesPerchanges(DocumentBuildContext context, IEnumerable<HostService> hostServices)
 {
     var incrementalContext = context.IncrementalBuildContext;
     var cbv = incrementalContext.CurrentBuildVersionInfo;
     UpdateUidDependency(hostServices, context);
     if (incrementalContext.CanVersionIncremental)
     {
         var newChanges = incrementalContext.ExpandDependency(cbv.Dependency, d => true);
         Logger.LogDiagnostic($"After expanding dependency before postbuild, changes: {JsonUtility.Serialize(incrementalContext.ChangeDict)}");
         foreach (var hostService in hostServices)
         {
             hostService.ReloadModelsPerIncrementalChanges(incrementalContext, newChanges, BuildPhase.PostBuild);
         }
     }
 }
示例#42
0
        private InternalManifestItem HandleSaveResult(
            DocumentBuildContext context,
            HostService hostService,
            FileModel model,
            SaveResult result)
        {
            context.FileMap[model.Key] = ((TypeForwardedToRelativePath)model.File).GetPathFromWorkingFolder();
            DocumentException.RunAll(
                () => CheckFileLink(hostService, result),
                () => HandleUids(context, result),
                () => HandleToc(context, result),
                () => RegisterXRefSpec(context, result));

            return GetManifestItem(context, model, result);
        }
示例#43
0
 private void UpdateContext(DocumentBuildContext context)
 {
     context.ResolveExternalXRefSpec();
 }
示例#44
0
文件: Template.cs 项目: vicancy/docfx
 private static ITemplatePreprocessor CreatePreprocessor(ResourceCollection resourceCollection, TemplatePreprocessorResource scriptResource, DocumentBuildContext context)
 {
     return new TemplateJintPreprocessor(resourceCollection, scriptResource, context);
 }
示例#45
0
 /// <summary>
 /// Export xref map file.
 /// </summary>
 private static string ExportXRefMap(DocumentBuildParameters parameters, DocumentBuildContext context)
 {
     Logger.LogVerbose("Exporting xref map...");
     var xrefMap = new XRefMap();
     xrefMap.References =
         (from xref in context.XRefSpecMap.Values.AsParallel().WithDegreeOfParallelism(parameters.MaxParallelism)
          select new XRefSpec(xref)
          {
              Href = ((RelativePath)context.FileMap[UriUtility.GetNonFragment(xref.Href)]).RemoveWorkingFolder() + UriUtility.GetFragment(xref.Href)
          }).ToList();
     xrefMap.Sort();
     string xrefMapFileNameWithVersion = string.IsNullOrEmpty(parameters.VersionName) ?
         XRefMapFileName :
         parameters.VersionName + "." + XRefMapFileName;
     YamlUtility.Serialize(
         Path.Combine(parameters.OutputBaseDir, xrefMapFileNameWithVersion),
         xrefMap,
         YamlMime.XRefMap);
     Logger.LogInfo("XRef map exported.");
     return xrefMapFileNameWithVersion;
 }
示例#46
0
        private IEnumerable<HostService> GetInnerContexts(
            DocumentBuildParameters parameters,
            IEnumerable<IDocumentProcessor> processors,
            TemplateProcessor templateProcessor,
            IMarkdownService markdownService,
            DocumentBuildContext context)
        {
            var k = from fileItem in (
                    from file in parameters.Files.EnumerateFiles()
                    from p in (from processor in processors
                               let priority = processor.GetProcessingPriority(file)
                               where priority != ProcessingPriority.NotSupported
                               group processor by priority into ps
                               orderby ps.Key descending
                               select ps.ToList()).FirstOrDefault() ?? new List<IDocumentProcessor> { null }
                    select new { file, p })
                    group fileItem by fileItem.p;

            var toHandleItems = k.Where(s => s.Key != null);
            var notToHandleItems = k.Where(s => s.Key == null);
            foreach (var item in notToHandleItems)
            {
                var sb = new StringBuilder();
                sb.AppendLine("Cannot handle following file:");
                foreach (var f in item)
                {
                    sb.Append("\t");
                    sb.AppendLine(f.file.File);
                }
                Logger.LogWarning(sb.ToString());
            }

            // todo : revert until PreProcessor ready
            foreach (var pair in (from processor in processors
                                  join item in toHandleItems on processor equals item.Key into g
                                  from item in g.DefaultIfEmpty()
                                  select new
                                  {
                                      processor,
                                      item,
                                  }).AsParallel().WithDegreeOfParallelism(parameters.MaxParallelism))
            {
                var incrementalContext = context.IncrementalBuildContext;
                var processorSupportIncremental = IsProcessorSupportIncremental(pair.processor);
                bool processorCanIncremental = processorSupportIncremental;
                if (processorSupportIncremental)
                {
                    incrementalContext.CreateProcessorInfo(pair.processor);
                    processorCanIncremental = incrementalContext.CanProcessorIncremental(pair.processor);
                }

                var hostService = new HostService(
                       parameters.Files.DefaultBaseDir,
                       pair.item == null
                            ? new FileModel[0]
                            : from file in pair.item
                              select Load(pair.processor, parameters.Metadata, parameters.FileMetadata, file.file, processorCanIncremental, context) into model
                              where model != null
                              select model)
                {
                    MarkdownService = markdownService,
                    Processor = pair.processor,
                    Template = templateProcessor,
                    Validators = MetadataValidators.ToImmutableList(),
                    ShouldTraceIncrementalInfo = processorSupportIncremental,
                    CanIncrementalBuild = processorCanIncremental,
                };

                if (ShouldTraceIncrementalInfo)
                {
                    using (new LoggerPhaseScope("ReportModelLoadInfo", true))
                    {
                        var allFiles = pair.item?.Select(f => f.file.File) ?? new string[0];
                        var loadedFiles = hostService.Models.Select(m => m.FileAndType.File);
                        incrementalContext.ReportModelLoadInfo(hostService, allFiles.Except(loadedFiles), null);
                        incrementalContext.ReportModelLoadInfo(hostService, loadedFiles, BuildPhase.PreBuild);
                    }
                }
                yield return hostService;
            }
        }
示例#47
0
 private void RegisterXRefSpec(DocumentBuildContext context, SaveResult result)
 {
     foreach (var spec in result.XRefSpecs)
     {
         if (!string.IsNullOrWhiteSpace(spec?.Uid))
         {
             XRefSpec xref;
             if (context.XRefSpecMap.TryGetValue(spec.Uid, out xref))
             {
                 Logger.LogWarning($"Uid({spec.Uid}) has already been defined in {((TypeForwardedToRelativePath)xref.Href).RemoveWorkingFolder()}.");
             }
             else
             {
                 context.RegisterInternalXrefSpec(spec);
             }
         }
     }
     foreach (var spec in result.ExternalXRefSpecs)
     {
         if (!string.IsNullOrWhiteSpace(spec?.Uid))
         {
             context.ReportExternalXRefSpec(spec);
         }
     }
 }
示例#48
0
        private Manifest BuildCore(DocumentBuildParameters parameters)
        {
            using (new LoggerPhaseScope(PhaseName, true))
            {
                Logger.LogInfo($"Max parallelism is {parameters.MaxParallelism}.");
                Directory.CreateDirectory(parameters.OutputBaseDir);
                var context = new DocumentBuildContext(
                    Path.Combine(Directory.GetCurrentDirectory(), parameters.OutputBaseDir),
                    parameters.Files.EnumerateFiles(),
                    parameters.ExternalReferencePackages,
                    parameters.XRefMaps,
                    parameters.MaxParallelism,
                    parameters.Files.DefaultBaseDir);
                if (ShouldTraceIncrementalInfo)
                {
                    context.IncrementalBuildContext = IncrementalBuildContext.Create(parameters, CurrentBuildInfo, LastBuildInfo, IntermediateFolder);
                    Logger.RegisterListener(context.IncrementalBuildContext.CurrentBuildVersionInfo.BuildMessage.GetListener());
                    if (context.IncrementalBuildContext.CanVersionIncremental)
                    {
                        context.IncrementalBuildContext.LoadChanges();
                        Logger.LogVerbose($"Before expanding dependency before build, changes: {JsonUtility.Serialize(context.IncrementalBuildContext.ChangeDict, Formatting.Indented)}");
                        var dependencyGraph = context.IncrementalBuildContext.LastBuildVersionInfo.Dependency;
                        context.IncrementalBuildContext.ExpandDependency(dependencyGraph, d => dependencyGraph.DependencyTypes[d.Type].Phase == BuildPhase.Build || dependencyGraph.DependencyTypes[d.Type].TriggerBuild);
                        Logger.LogVerbose($"After expanding dependency before build, changes: {JsonUtility.Serialize(context.IncrementalBuildContext.ChangeDict, Formatting.Indented)}");
                    }
                }

                Logger.LogVerbose("Start building document...");

                // Start building document...
                List<HostService> hostServices = null;
                try
                {
                    using (var templateProcessor = parameters.TemplateManager?.GetTemplateProcessor(context, parameters.MaxParallelism) ?? TemplateProcessor.DefaultProcessor)
                    {
                        IMarkdownService markdownService;
                        using (new LoggerPhaseScope("CreateMarkdownService", true))
                        {
                            markdownService = CreateMarkdownService(parameters, templateProcessor.Tokens.ToImmutableDictionary());
                        }

                        using (new LoggerPhaseScope("Load", true))
                        {
                            hostServices = GetInnerContexts(parameters, Processors, templateProcessor, markdownService, context).ToList();
                        }

                        var manifest = BuildCore(hostServices, context, parameters.VersionName).ToList();

                        // Use manifest from now on
                        using (new LoggerPhaseScope("UpdateContext", true))
                        {
                            UpdateContext(context);
                        }

                        // Run getOptions from Template
                        using (new LoggerPhaseScope("FeedOptions", true))
                        {
                            FeedOptions(manifest, context);
                        }

                        // Template can feed back xref map, actually, the anchor # location can only be determined in template
                        using (new LoggerPhaseScope("FeedXRefMap", true))
                        {
                            FeedXRefMap(manifest, context);
                        }

                        using (new LoggerPhaseScope("UpdateHref", true))
                        {
                            UpdateHref(manifest, context);
                        }

                        // Afterwards, m.Item.Model.Content is always IDictionary
                        using (new LoggerPhaseScope("ApplySystemMetadata", true))
                        {
                            ApplySystemMetadata(manifest, context);
                        }

                        // Register global variables after href are all updated
                        IDictionary<string, object> globalVariables;
                        using (new LoggerPhaseScope("FeedGlobalVariables", true))
                        {
                            globalVariables = FeedGlobalVariables(templateProcessor.Tokens, manifest, context);
                        }

                        // processor to add global variable to the model
                        foreach (var m in templateProcessor.Process(manifest.Select(s => s.Item).ToList(), context, parameters.ApplyTemplateSettings, globalVariables))
                        {
                            context.ManifestItems.Add(m);
                        }
                        return new Manifest
                        {
                            Files = context.ManifestItems.ToList(),
                            Homepages = GetHomepages(context),
                            XRefMap = ExportXRefMap(parameters, context),
                            SourceBasePath = TypeForwardedToStringExtension.ToNormalizedPath(EnvironmentContext.BaseDirectory)
                        };
                    }
                }
                finally
                {
                    if (hostServices != null)
                    {
                        foreach (var item in hostServices)
                        {
                            Cleanup(item);
                            item.Dispose();
                        }
                    }
                }
            }
        }
示例#49
0
        private static FileModel Load(
            IDocumentProcessor processor,
            ImmutableDictionary<string, object> metadata,
            FileMetadata fileMetadata,
            FileAndType file,
            bool canProcessorIncremental,
            DocumentBuildContext context)
        {
            using (new LoggerFileScope(file.File))
            {
                Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Loading...");

                if (canProcessorIncremental)
                {
                    var incrementalContext = context.IncrementalBuildContext;
                    ChangeKindWithDependency ck;
                    string fileKey = ((TypeForwardedToRelativePath)file.File).GetPathFromWorkingFolder().ToString();
                    if (incrementalContext.ChangeDict.TryGetValue(fileKey, out ck))
                    {
                        Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}, ChangeType {ck}.");
                        if (ck == ChangeKindWithDependency.Deleted)
                        {
                            return null;
                        }
                        if (ck == ChangeKindWithDependency.None)
                        {
                            Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Check incremental...");
                            if (processor.BuildSteps.Cast<ISupportIncrementalBuildStep>().All(step => step.CanIncrementalBuild(file)))
                            {
                                Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Skip build by incremental.");
                                return null;
                            }
                            Logger.LogDiagnostic($"Processor {processor.Name}, File {file.FullPath}: Incremental not available.");
                        }
                    }
                }

                var path = Path.Combine(file.BaseDir, file.File);
                metadata = ApplyFileMetadata(path, metadata, fileMetadata);
                try
                {
                    return processor.Load(file, metadata);
                }
                catch (Exception)
                {
                    Logger.LogError($"Unable to load file: {file.File} via processor: {processor.Name}.");
                    throw;
                }
            }
        }
示例#50
0
 private static void HandleToc(DocumentBuildContext context, SaveResult result)
 {
     if (result.TocMap?.Count > 0)
     {
         foreach (var toc in result.TocMap)
         {
             HashSet<string> list;
             if (context.TocMap.TryGetValue(toc.Key, out list))
             {
                 foreach (var item in toc.Value)
                 {
                     list.Add(item);
                 }
             }
             else
             {
                 context.TocMap[toc.Key] = toc.Value;
             }
         }
     }
 }
示例#51
0
 private void BuildCore(PhaseProcessor phaseProcessor, List<HostService> hostServices, DocumentBuildContext context)
 {
     try
     {
         phaseProcessor.Process(hostServices, context.MaxParallelism);
     }
     catch (BuildCacheException e)
     {
         var message = $"Build cache was corrupted, please try force rebuild `build --force` or clear the cache files in the path: {IntermediateFolder}. Detail error: {e.Message}.";
         Logger.LogError(message);
         throw new DocfxException(message, e);
     }
 }
示例#52
0
 private void Prepare(
     DocumentBuildParameters parameters,
     DocumentBuildContext context,
     TemplateProcessor templateProcessor,
     string markdownServiceContextHash,
     out IHostServiceCreator hostServiceCreator,
     out PhaseProcessor phaseProcessor)
 {
     if (IntermediateFolder != null && parameters.ApplyTemplateSettings.TransformDocument)
     {
         context.IncrementalBuildContext = IncrementalBuildContext.Create(parameters, CurrentBuildInfo, LastBuildInfo, IntermediateFolder, markdownServiceContextHash);
         hostServiceCreator = new HostServiceCreatorWithIncremental(context);
         phaseProcessor = new PhaseProcessor
         {
             Handlers =
                             {
                                 new PrebuildBuildPhaseHandler(context).WithIncremental(),
                                 new PostbuildPhaseHandler(context, templateProcessor).WithIncremental(),
                             }
         };
     }
     else
     {
         hostServiceCreator = new HostServiceCreator(context);
         phaseProcessor = new PhaseProcessor
         {
             Handlers =
                             {
                                 new PrebuildBuildPhaseHandler(context),
                                 new PostbuildPhaseHandler(context, templateProcessor),
                             }
         };
     }
 }
示例#53
0
 public TemplateUtility(DocumentBuildContext context)
 {
     _context = context;
 }
示例#54
0
        private Manifest BuildCore(DocumentBuildParameters parameters)
        {
            using (new LoggerPhaseScope(PhaseName, true))
            {
                Logger.LogInfo($"Max parallelism is {parameters.MaxParallelism}.");
                Directory.CreateDirectory(parameters.OutputBaseDir);

                var context = new DocumentBuildContext(
                    Path.Combine(Directory.GetCurrentDirectory(), parameters.OutputBaseDir),
                    parameters.Files.EnumerateFiles(),
                    parameters.ExternalReferencePackages,
                    parameters.XRefMaps,
                    parameters.MaxParallelism,
                    parameters.Files.DefaultBaseDir,
                    parameters.VersionName,
                    parameters.ApplyTemplateSettings,
                    parameters.RootTocPath);

                Logger.LogVerbose("Start building document...");

                // Start building document...
                List<HostService> hostServices = null;
                IHostServiceCreator hostServiceCreator = null;
                PhaseProcessor phaseProcessor = null;
                try
                {
                    using (var templateProcessor = parameters.TemplateManager?.GetTemplateProcessor(context, parameters.MaxParallelism) ?? TemplateProcessor.DefaultProcessor)
                    {
                        using (new LoggerPhaseScope("Prepare", true))
                        {
                            if (MarkdownService == null)
                            {
                                MarkdownService = CreateMarkdownService(parameters, templateProcessor.Tokens.ToImmutableDictionary());
                            }
                            Prepare(
                                parameters,
                                context,
                                templateProcessor,
                                (MarkdownService as IHasIncrementalContext)?.GetIncrementalContextHash(),
                                out hostServiceCreator,
                                out phaseProcessor);
                        }
                        using (new LoggerPhaseScope("Load", true))
                        {
                            hostServices = GetInnerContexts(parameters, Processors, templateProcessor, hostServiceCreator).ToList();
                        }

                        BuildCore(phaseProcessor, hostServices, context);

                        return new Manifest
                        {
                            Files = context.ManifestItems.ToList(),
                            Homepages = GetHomepages(context),
                            XRefMap = ExportXRefMap(parameters, context),
                            SourceBasePath = StringExtension.ToNormalizedPath(EnvironmentContext.BaseDirectory)
                        };
                    }
                }
                finally
                {
                    if (hostServices != null)
                    {
                        foreach (var item in hostServices)
                        {
                            Cleanup(item);
                            item.Dispose();
                        }
                    }
                }
            }
        }
示例#55
0
 private static InternalManifestItem GetManifestItem(DocumentBuildContext context, FileModel model, SaveResult result)
 {
     return new InternalManifestItem
     {
         DocumentType = result.DocumentType,
         FileWithoutExtension = result.FileWithoutExtension,
         ResourceFile = result.ResourceFile,
         Key = model.Key,
         LocalPathFromRoot = model.LocalPathFromRoot,
         Model = model.ModelWithCache,
         InputFolder = model.OriginalFileAndType.BaseDir,
         Metadata = new Dictionary<string, object>((IDictionary<string, object>)model.ManifestProperties),
     };
 }
示例#56
0
 public TemplateProcessor GetTemplateProcessor(DocumentBuildContext context, int maxParallelism)
 {
     return new TemplateProcessor(CreateTemplateResource(_templates), context, maxParallelism);
 }
示例#57
0
        private IEnumerable<ManifestItemWithContext> ExportManifest(HostService hostService, DocumentBuildContext context)
        {
            var manifestItems = new List<ManifestItemWithContext>();
            using (new LoggerPhaseScope("Save", true))
            {
                hostService.Models.RunAll(m =>
                {
                    if (m.Type != DocumentType.Overwrite)
                    {
                        using (new LoggerFileScope(m.LocalPathFromRoot))
                        {
                            Logger.LogDiagnostic($"Processor {hostService.Processor.Name}: Saving...");
                            m.BaseDir = context.BuildOutputFolder;
                            if (m.FileAndType.SourceDir != m.FileAndType.DestinationDir)
                            {
                                m.File = (TypeForwardedToRelativePath)m.FileAndType.DestinationDir + (((TypeForwardedToRelativePath)m.File) - (TypeForwardedToRelativePath)m.FileAndType.SourceDir);
                            }
                            var result = hostService.Processor.Save(m);
                            if (result != null)
                            {
                                string extension = string.Empty;
                                if (hostService.Template != null)
                                {
                                    if (hostService.Template.TryGetFileExtension(result.DocumentType, out extension))
                                    {
                                        m.File = result.FileWithoutExtension + extension;
                                    }
                                }

                                var item = HandleSaveResult(context, hostService, m, result);
                                item.Extension = extension;

                                manifestItems.Add(new ManifestItemWithContext(item, m, hostService.Processor, hostService.Template?.GetTemplateBundle(result.DocumentType)));
                            }
                        }
                    }
                });
            }
            return manifestItems;
        }
示例#58
0
 private static List<HomepageInfo> GetHomepages(DocumentBuildContext context)
 {
     return context.GetTocInfo()
         .Where(s => !string.IsNullOrEmpty(s.Homepage))
         .Select(s => new HomepageInfo
         {
             Homepage = RelativePath.GetPathWithoutWorkingFolderChar(s.Homepage),
             TocPath = RelativePath.GetPathWithoutWorkingFolderChar(context.GetFilePath(s.TocFileKey))
         }).ToList();
 }
示例#59
0
        private List<ManifestItem> ProcessCore(List<InternalManifestItem> items, DocumentBuildContext context, ApplyTemplateSettings settings, IDictionary<string, object> globals)
        {
            var manifest = new ConcurrentBag<ManifestItem>();
            var systemAttributeGenerator = new SystemMetadataGenerator(context);
            var transformer = new TemplateModelTransformer(context, _templateCollection, settings, globals);
            items.RunAll(
                item =>
                {
                    using (new LoggerFileScope(item.LocalPathFromRoot))
                    {
                        var manifestItem = transformer.Transform(item);
                        if (manifestItem.OutputFiles?.Count > 0)
                        {
                            manifest.Add(manifestItem);
                        }
                    }
                },
                context.MaxParallelism);
            return manifest.ToList();

        }
示例#60
0
 private static void HandleUids(DocumentBuildContext context, SaveResult result)
 {
     if (result.LinkToUids.Count > 0)
     {
         context.XRef.UnionWith(result.LinkToUids.Where(s => s != null));
     }
 }