/// <summary> /// Writes the output of a local file to the stream /// </summary> /// <param name="sw"></param> /// <param name="fi"></param> /// <param name="type"></param> /// <param name="origUrl"></param> /// <param name="http"></param> protected virtual CompositeFileDefinition WriteFileToStream(StreamWriter sw, FileInfo fi, ClientDependencyType type, string origUrl, HttpContextBase http) { if (fi is null) { throw new ArgumentNullException(nameof(fi)); } if (!PathHelper.TryGetFileExtension(origUrl, out var ext1)) { throw new InvalidOperationException($"Could not get extension from file name {origUrl}"); } if (!fi.Extension.Equals(ext1, StringComparison.InvariantCultureIgnoreCase)) { throw new InvalidOperationException("The file extensions for the resolved file and the original URL do not match"); } //get a writer for the file, first check if there's a specific file writer //then check for an extension writer. var writer = FileWriters.GetWriterForFile(origUrl); if (writer is DefaultFileWriter) { writer = FileWriters.GetWriterForExtension(fi.Extension); if (writer == null) { return(null); } } return(writer.WriteToStream(this, sw, fi, type, origUrl, http) ? new CompositeFileDefinition(origUrl, true) : null); }
public static void RegisterRoutes(RouteCollection routes, string versionSpecificNamespace) { routes.MapRoute( name: "Criteria resources", url: "App_Plugins/UmbracoPersonalisationGroups/GetResourceForCriteria/{criteriaAlias}/{fileName}", defaults: new { controller = "Resource", action = "GetResourceForCriteria" }, namespaces: new[] { CommonNamespace }); routes.MapRoute( name: "Core resources", url: "App_Plugins/UmbracoPersonalisationGroups/GetResource/{fileName}", defaults: new { controller = "Resource", action = "GetResource" }, namespaces: new[] { CommonNamespace }); routes.MapRoute( name: "Criteria methods", url: "App_Plugins/UmbracoPersonalisationGroups/Criteria/{action}", defaults: new { controller = "Criteria", action = "Index" }, namespaces: new[] { CommonNamespace }); routes.MapRoute( name: "Geo location methods", url: "App_Plugins/UmbracoPersonalisationGroups/GeoLocation/{action}", defaults: new { controller = "GeoLocation", action = "Index" }, namespaces: new[] { CommonNamespace }); routes.MapRoute( name: "Member methods", url: "App_Plugins/UmbracoPersonalisationGroups/Member/{action}", defaults: new { controller = "Member", action = "Index" }, namespaces: new[] { versionSpecificNamespace }); // Add the virtual file writer for the extension type. FileWriters.AddWriterForExtension(AppConstants.ResourceExtension, new EmbeddedResourceWriter()); }
/// <inheritdoc/> protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { // Register custom routes. RouteBuilder.RegisterRoutes(RouteTable.Routes); // Ensure client dependency can find the embedded resources. FileWriters.AddWriterForExtension(EmbeddedResourceConstants.ResourceExtension, new EmbeddedResourceWriter()); }
private static void Main(string[] args) { Console.WriteLine("Publisher Subscriber Project!"); var pub = new FileWriters(); var sub1 = new DisplayService("1", pub); pub.RaiseInsertMessageEvent("This is Message", "TheFile"); }
protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); //an extension method to replace the default razor view engine with the CDF view engine // instead of using the cdf module since this is only for mvc ViewEngines.Engines.ReplaceEngine <FixedRazorViewEngine>(new CdfRazorViewEngine()); FileWriters.AddWriterForExtension(".nu", new EmbeddedResourceWriter()); }
public void DisplayService_ShouldSetId_WhenConstructed(string id) { //Given var pub = new FileWriters(); var service = new DisplayService(id, pub); //When pub.RaiseInsertMessageEvent("Message", "file"); //Then service.Id().Should().Be(id); }
public void Event_ShouldBeRaised_WhenDoSomethingIsCalled() { //Given var pub = new FileWriters(); //When //Then using (IMonitor <FileWriters> monitoredSubject = pub.Monitor()) { pub.RaiseInsertMessageEvent("This Is Message", "text"); monitoredSubject.Should().Raise("RaiseCustomEvent"); } }
/// <summary> /// Writes a given path to the stream /// </summary> /// <param name="type"></param> /// <param name="path">The path could be a local url or an absolute url</param> /// <param name="context"></param> /// <param name="sw"></param> /// <returns>If successful returns a CompositeFileDefinition, otherwise returns null</returns> public CompositeFileDefinition WritePathToStream(ClientDependencyType type, string path, HttpContextBase context, StreamWriter sw) { CompositeFileDefinition def = null; if (!string.IsNullOrEmpty(path)) { try { var fi = new FileInfo(context.Server.MapPath(path)); //all config based extensions and all extensions registered by file writers var fileBasedExtensions = ClientDependencySettings.Instance.FileBasedDependencyExtensionList .Union(FileWriters.GetRegisteredExtensions()); if (fileBasedExtensions.Contains(fi.Extension.ToUpper())) { //if the file doesn't exist, then we'll assume it is a URI external request def = !fi.Exists ? WriteFileToStream(sw, path, type, context) //external request : WriteFileToStream(sw, fi, type, path, context); //internal request } else { //if it's not a file based dependency, try to get the request output. def = WriteFileToStream(sw, path, type, context); } } catch (Exception ex) { if (ex is NotSupportedException || ex is ArgumentException || ex is HttpException) { //could not parse the string into a fileinfo or couldn't mappath, so we assume it is a URI def = WriteFileToStream(sw, path, type, context); } else { //if this fails, log the exception, but continue ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. EXCEPTION: {1}", path, ex.Message), ex); } } } if (type == ClientDependencyType.Javascript) { sw.Write(";;;"); //write semicolons in case the js isn't formatted correctly. This also helps for debugging. } return(def); }
public void FileWriterWritesToTestFile() { //Given var pub = new FileWriters(); var sub = new DisplayService("id", pub); pub.RaiseInsertMessageEvent("This is Message", "text"); //When var text = File.ReadAllText(@"../../../../text.txt"); //Then text.Should().NotBeEmpty(); }
/// <summary> /// Writes the output of a local file to the stream /// </summary> /// <param name="sw"></param> /// <param name="fi"></param> /// <param name="type"></param> /// <param name="origUrl"></param> /// <param name="http"></param> protected virtual CompositeFileDefinition WriteFileToStream(StreamWriter sw, FileInfo fi, ClientDependencyType type, string origUrl, HttpContextBase http) { //get a writer for the file, first check if there's a specific file writer //then check for an extension writer. var writer = FileWriters.GetWriterForFile(origUrl); if (writer is DefaultFileWriter) { writer = FileWriters.GetWriterForExtension(fi.Extension); } return(writer.WriteToStream(this, sw, fi, type, origUrl, http) ? new CompositeFileDefinition(origUrl, true) : null); }
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { base.ApplicationStarted(umbracoApplication, applicationContext); RouteTable .Routes .MapRoute( name: "nuPickersShared", url: EmbeddedResource.ROOT_URL.TrimStart("~/") + "{folder}/{file}", defaults: new { controller = "EmbeddedResource", action = "GetSharedResource" }, namespaces: new[] { "nuPickers.EmbeddedResource" }); FileWriters.AddWriterForExtension(EmbeddedResource.FILE_EXTENSION, new EmbeddedResourceVirtualFileWriter()); }
protected bool CanProcessLocally(HttpContextBase context, string filePath, out IVirtualFileWriter virtualFileWriter) { //First check if there's any virtual file providers that can handle this var writer = FileWriters.GetVirtualWriterForFile(filePath); if (writer == null) { var ext = Path.GetExtension(filePath); writer = FileWriters.GetVirtualWriterForExtension(ext); } if (writer != null) { virtualFileWriter = writer; return(writer.FileProvider.FileExists(filePath)); } //can process if it exists locally virtualFileWriter = null; return(File.Exists(context.Server.MapPath(filePath))); }
/// <summary> /// The main startup method /// </summary> private void Startup() { foreach (var embeddedResourceItem in EmbeddedResourceService.GetEmbeddedResourceItems()) { // register with mvc RouteTable .Routes .MapRoute( name: "EmbeddedResource" + Guid.NewGuid().ToString(), url: embeddedResourceItem.ResourceUrl.TrimStart("~/"), // forward slash always expected defaults: new { controller = "EmbeddedResource", action = "GetEmbeddedResource", url = embeddedResourceItem.ResourceUrl }, namespaces: new[] { "Our.Umbraco.EmbeddedResource" }); // register with client depenedency FileWriters.AddWriterForFile(embeddedResourceItem.ResourceUrl.TrimStart('~'), new EmbeddedResourceVirtualFileWriter()); } }
/// <summary> /// This will check if there's a file writer for the file extension of the file path and if that file physically exists in the website /// </summary> /// <param name="context"></param> /// <param name="filePath"></param> /// <param name="virtualFileWriter"></param> /// <returns></returns> protected bool CanProcessLocally(HttpContextBase context, string filePath, out IVirtualFileWriter virtualFileWriter) { //First check if there's any virtual file providers that can handle this var writer = FileWriters.GetVirtualWriterForFile(filePath); if (writer == null) { if (!PathHelper.TryGetFileExtension(filePath, out var ext)) { virtualFileWriter = null; return(false); } writer = FileWriters.GetVirtualWriterForExtension(ext); } if (writer != null) { virtualFileWriter = writer; try { return(writer.FileProvider.FileExists(filePath)); } catch (Exception) { return(false); } } //can process if it exists locally virtualFileWriter = null; if (!PathHelper.TryMapPath(filePath, context, out var mappedPath)) { return(false); } return(File.Exists(mappedPath)); }
/// <summary> /// Writes a given path to the stream /// </summary> /// <param name="type"></param> /// <param name="path">The path could be a local url or an absolute url</param> /// <param name="context"></param> /// <param name="sw"></param> /// <returns>If successful returns a CompositeFileDefinition, otherwise returns null</returns> public CompositeFileDefinition WritePathToStream(ClientDependencyType type, string path, HttpContextBase context, StreamWriter sw) { CompositeFileDefinition def = null; if (!string.IsNullOrEmpty(path)) { try { var fi = new FileInfo(context.Server.MapPath(path)); //all config based extensions and all extensions registered by file writers var fileBasedExtensions = ClientDependencySettings.Instance.FileBasedDependencyExtensionList .Union(FileWriters.GetRegisteredExtensions()); if (fileBasedExtensions.Contains(fi.Extension.ToUpper())) { //if the file doesn't exist, then we'll assume it is a URI external request def = !fi.Exists ? WriteFileToStream(sw, path, type, context) //external request : WriteFileToStream(sw, fi, type, path, context); //internal request } else { //if it's not a file based dependency, try to get the request output. def = WriteFileToStream(sw, path, type, context); } } catch (Exception ex) { if (ex is NotSupportedException || ex is ArgumentException || ex is HttpException) { //could not parse the string into a fileinfo or couldn't mappath, so we assume it is a URI //before we try to load it by URI, we want to check if the URI is a local request, we'll try to detect if it is and // then try to load it from the file system, if the file isn't there then we'll continue trying to load it via the URI. Uri uri; if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out uri) && uri.IsLocalUri(context)) { var localPath = uri.PathAndQuery; var fi = new FileInfo(context.Server.MapPath(localPath)); if (fi.Exists) { try { WriteFileToStream(sw, fi, type, path, context); //internal request } catch (Exception ex1) { ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. EXCEPTION: {1}", path, ex1.Message), ex1); } } } def = WriteFileToStream(sw, path, type, context); } else { //if this fails, log the exception, but continue ClientDependencySettings.Instance.Logger.Error(string.Format("Could not load file contents from {0}. EXCEPTION: {1}", path, ex.Message), ex); } } } if (type == ClientDependencyType.Javascript) { sw.Write(";;;"); //write semicolons in case the js isn't formatted correctly. This also helps for debugging. } return(def); }
public static void Initialize() { //register the less writer. FileWriters.AddWriterForExtension(".sass", new SassWriter()); FileWriters.AddWriterForExtension(".scss", new SassWriter()); }
/// <summary> /// Because we can have both internal and external dependencies rendered, we need to stagger the script tag output... if they are external, we need to stop the compressing/combining /// and write out the external dependency, then resume the compressing/combining handler. /// </summary> /// <param name="dependencies"></param> /// <param name="http"></param> /// <param name="builder"></param> /// <param name="renderCompositeFiles"></param> /// <param name="renderSingle"></param> protected void WriteStaggeredDependencies( IEnumerable <IClientDependencyFile> dependencies, HttpContextBase http, StringBuilder builder, Func <IEnumerable <IClientDependencyFile>, HttpContextBase, IDictionary <string, string>, string> renderCompositeFiles, Func <string, IDictionary <string, string>, string> renderSingle) { //This action will stagger the output based on whether or not the html attribute declarations are the same for each dependency Action <IEnumerable <IClientDependencyFile> > staggerOnDifferentAttributes = (list) => { var sameAttributes = new List <IClientDependencyFile>(); var currHtmlAttr = GetHtmlAttributes(list.ElementAt(0)); foreach (var c in list) { if (!currHtmlAttr.IsEqualTo(GetHtmlAttributes(c))) { //if the attributes are different we need to stagger if (sameAttributes.Any()) { //render the current buffer builder.Append(renderCompositeFiles(sameAttributes, http, currHtmlAttr)); //clear the buffer sameAttributes.Clear(); } } //add the item to the buffer and set the current html attributes sameAttributes.Add(c); currHtmlAttr = GetHtmlAttributes(c); } //if there's anything in the buffer then write the remaining if (sameAttributes.Any()) { builder.Append(renderCompositeFiles(sameAttributes, http, currHtmlAttr)); } }; var fileBasedExtensions = ClientDependencySettings.Instance.FileBasedDependencyExtensionList .Union(FileWriters.GetRegisteredExtensions()) .ToArray(); var currNonRemoteFiles = new List <IClientDependencyFile>(); foreach (var f in dependencies) { // if it is an external resource OR // if it is a non-standard JS/CSS resource (i.e. a server request) // then we need to break the sequence // unless it has been explicitely required that the dependency be bundled if (!http.IsAbsolutePath(f.FilePath) && !fileBasedExtensions.Contains(Path.GetExtension(f.FilePath).ToUpper()) //now check for external resources || (http.IsAbsolutePath(f.FilePath) //remote dependencies aren't local && !new Uri(f.FilePath, UriKind.RelativeOrAbsolute).IsLocalUri(http) // not required to be bundled && !f.ForceBundle)) { //we've encountered an external dependency, so we need to break the sequence and restart it after //we output the raw script tag if (currNonRemoteFiles.Count > 0) { //render the current buffer staggerOnDifferentAttributes(currNonRemoteFiles); //clear the buffer currNonRemoteFiles.Clear(); } //write out the single script tag builder.Append(renderSingle(f.FilePath, GetHtmlAttributes(f))); } else { //its a normal registration, add to the buffer currNonRemoteFiles.Add(f); } } //now check if there's anything in the buffer to render if (currNonRemoteFiles.Count > 0) { //render the current buffer staggerOnDifferentAttributes(currNonRemoteFiles); } }
/// <summary> /// Writes a given path to the stream /// </summary> /// <param name="type"></param> /// <param name="path">The path could be a local url or an absolute url</param> /// <param name="context"></param> /// <param name="sw"></param> /// <returns>If successful returns a CompositeFileDefinition, otherwise returns null</returns> public CompositeFileDefinition WritePathToStream(ClientDependencyType type, string path, HttpContextBase context, StreamWriter sw) { path = path.Trim(); if (string.IsNullOrEmpty(path) || !PathHelper.TryGetFileExtension(path, out var extension)) { return(null); } CompositeFileDefinition def = null; //all config based extensions and all extensions registered by file writers var fileBasedExtensions = ClientDependencySettings.Instance.FileBasedDependencyExtensionList .Union(FileWriters.GetRegisteredExtensions()) .ToList(); try { if (fileBasedExtensions.Contains(extension, StringComparer.InvariantCultureIgnoreCase)) { if (CanProcessLocally(context, path, out IVirtualFileWriter virtualWriter)) { //internal request if (virtualWriter != null) { var vf = virtualWriter.FileProvider.GetFile(path); def = WriteVirtualFileToStream(sw, vf, virtualWriter, type, context); } else { if (PathHelper.TryGetFileInfo(path, context, out var fi)) { def = WriteFileToStream(sw, fi, type, path, context); } } } else { //Before we try to load it by URI, we want to check if the URI is a local file request. //We can try to detect if it is and try to load it from the file system. //If the file isn't local and doesn't exist then we'll continue trying to load it via the URI. //NOTE: At this stage we've already validated that the file type is based on the file types registered with CDF. if (Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out Uri uri)) { if (uri.IsLocalUri(context)) { //extract the path of the request and ensure it starts with the virtual path marker (~/) so that the file //can only be looked up local to this website. var absPath = uri.AbsolutePath.EnsureStartsWith("/").EnsureStartsWith("~"); if (PathHelper.TryGetFileInfo(absPath, context, out var fi)) { //Re-validate the extension since URIs and file names can parse differently extension = fi.Extension; if (fileBasedExtensions.Contains(extension, StringComparer.InvariantCultureIgnoreCase)) { def = WriteFileToStream(sw, fi, type, path, context); } } } else { //external request to a file based dependency def = WriteFileToStream(sw, path, type, context); } } } } else { //if it's not a file based dependency, try to get the request output. def = WriteFileToStream(sw, path, type, context); } } catch (Exception ex) { //if this fails, log the exception, but continue ClientDependencySettings.Instance.Logger.Error($"Could not load file contents from {path}. EXCEPTION: {ex.Message}", ex); } if (def == null) { return(null); } if (type == ClientDependencyType.Javascript) { sw.Write(";;;"); //write semicolons in case the js isn't formatted correctly. This also helps for debugging. } return(def); }
/// <summary> /// Because we can have both internal and external dependencies rendered, we need to stagger the script tag output... if they are external, we need to stop the compressing/combining /// and write out the external dependency, then resume the compressing/combining handler. /// </summary> /// <param name="dependencies"></param> /// <param name="http"></param> /// <param name="builder"></param> /// <param name="renderCompositeFiles"></param> /// <param name="renderSingle"></param> protected void WriteStaggeredDependencies( IEnumerable <IClientDependencyFile> dependencies, HttpContextBase http, StringBuilder builder, Func <IEnumerable <IClientDependencyFile>, HttpContextBase, IDictionary <string, string>, string> renderCompositeFiles, Func <string, IDictionary <string, string>, string> renderSingle) { var fileBasedExtensions = ClientDependencySettings.Instance.FileBasedDependencyExtensionList .Union(FileWriters.GetRegisteredExtensions()) .ToArray(); var currNonRemoteFiles = new List <IClientDependencyFile>(); foreach (var f in dependencies) { //need to parse out the request's extensions and remove query strings //need to force non-bundled lines for items with query parameters or a hash value. var extension = f.FilePath.Contains('?') || f.FilePath.Contains('#') ? "" : Path.GetExtension(f.FilePath); var stringExt = ""; #if !Net35 if (!string.IsNullOrWhiteSpace(extension)) #else if (!string.IsNullOrEmpty(extension)) #endif { stringExt = extension.ToUpper().Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries)[0]; } //if this is a protocol-relative/protocol-less uri, then we need to add the protocol for the remaining // logic to work properly if (f.FilePath.StartsWith("//")) { f.FilePath = Regex.Replace(f.FilePath, @"^\/\/", http.Request.Url.GetLeftPart(UriPartial.Scheme)); } // if it is an external resource OR // if it is a non-standard JS/CSS resource (i.e. a server request) // then we need to break the sequence // unless it has been explicitely required that the dependency be bundled if ((!http.IsAbsolutePath(f.FilePath) && !fileBasedExtensions.Contains(stringExt)) //now check for external resources || (http.IsAbsolutePath(f.FilePath) //remote dependencies aren't local && !new Uri(f.FilePath, UriKind.RelativeOrAbsolute).IsLocalUri(http) // not required to be bundled && !f.ForceBundle)) { //we've encountered an external dependency, so we need to break the sequence and restart it after //we output the raw script tag if (currNonRemoteFiles.Count > 0) { //render the current buffer StaggerOnDifferentAttributes(http, builder, currNonRemoteFiles, renderCompositeFiles); //clear the buffer currNonRemoteFiles.Clear(); } //write out the single script tag builder.Append(renderSingle(f.FilePath, GetHtmlAttributes(f))); } else { //its a normal registration, add to the buffer currNonRemoteFiles.Add(f); } } //now check if there's anything in the buffer to render if (currNonRemoteFiles.Count > 0) { //render the current buffer StaggerOnDifferentAttributes(http, builder, currNonRemoteFiles, renderCompositeFiles); } }
protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext) { base.ApplicationStarted(umbracoApplication, applicationContext); RouteBuilder.BuildRoutes(RouteTable.Routes); FileWriters.AddWriterForExtension(".nu", new EmbeddedResourceWriter()); }
public static void Initialize() { //register the less writer. FileWriters.AddWriterForExtension(".coffee", new CoffeeWriter()); }
public static void Initialize() { //register the less writer. FileWriters.AddWriterForExtension(".ts", new TypeScriptWriter()); }