private Engine SetupEngine(IResourceFileReader resourceCollection, ResourceInfo scriptResource, DocumentBuildContext context) { var rootPath = (RelativePath)scriptResource.Path; var engineCache = new Dictionary <string, Engine>(); var utility = new TemplateUtility(context); _utilityObject = new { resolveSourceRelativePath = new Func <string, string, string>(utility.ResolveSourceRelativePath), getHrefFromRoot = new Func <string, string, string>(utility.GetHrefFromRoot), markup = new Func <string, string, string>(utility.Markup), }; var engine = CreateDefaultEngine(); var requireAction = new Func <string, object>( s => { if (!s.StartsWith(RequireRelativePathPrefix, StringComparison.Ordinal)) { 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); } if (!engineCache.TryGetValue(s, out Engine cachedEngine)) { cachedEngine = CreateEngine(engine, RequireFuncVariableName); engineCache[s] = cachedEngine; cachedEngine.Execute(script, new ParserOptions { Source = s }); } 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); _transformFunc = GetFunc(TransformFuncVariableName, exports); } else { throw new InvalidPreprocessorException("Invalid 'exports' variable definition. 'exports' MUST be an object."); } return(engine); }