Exemplo n.º 1
0
        /// <summary>
        /// Resolve all script dependencies in the bound CQ document. Scripts that cotain a "data-
        /// location='head'" attribute will be moved to the head.
        /// </summary>
        ///
        /// <param name="doc">
        /// The document to resolve.
        /// </param>

        public void ResolveScriptDependencies(CQ doc)
        {
            string scriptSelector = "script[src][type='text/javascript'], link[type='text/css']";

            //+ (Options.HasFlag(ViewEngineOptions.ProcessAllScripts) ?
            //        "" : ".csquery-script")
            //        + "[src]";

            // Filter out non-relative paths (remote URLs)
            CQ scripts = doc[scriptSelector].Filter(item =>
            {
                return(!PathList.IsRemoteUrl(item.UrlSource()));
            });



            if (scripts.Length == 0)
            {
                return;
            }

            // move scripts to head as needed first

            var toMove = scripts.Filter("[data-location='head']");
            var head   = doc["head"];

            if (toMove.Length > 0)
            {
                foreach (var item in toMove)
                {
                    if (item.ParentNode != head)
                    {
                        head.Append(item);
                    }
                }
            }

            // resolve dependencies

            ScriptCollection coll = new ScriptCollection(LibraryPath, MapPath);

            coll.NoCache      = Options.HasFlag(ViewEngineOptions.NoCache);
            coll.IgnoreErrors = Options.HasFlag(ViewEngineOptions.IgnoreMissingScripts);

            // identify the insertion point for the script bundle
            var firstScriptEl = coll.AddFromCq(scripts);
            var firstScript   = firstScriptEl == null?
                                head.Children().First() :
                                    firstScriptEl.Cq();

            string           bundleUrl;
            List <ScriptRef> dependencies = coll.GetDependencies()
                                            .Where(item => !coll.Contains(item))
                                            .ToList();

            // find the first script with dependencies


            // Now add scripts directly for depenencies marked as NoCombine.

            foreach (var item in dependencies.Where(item => item.NoCombine))
            {
                firstScript.Before(GetScriptHtml(item.Path, item.ScriptHash));
            }

            // Before creating the bundle, remove any duplicates of the same script on the page



            bool hasBundle = Bundles.TryGetValue(coll, out bundleUrl);

            if (hasBundle)
            {
                // when nocache is set, we will regenerate the bundle, but not change the script ID. The v=
                // flag will be changed by BundleTable.
                if (Options.HasFlag(ViewEngineOptions.NoCache))
                {
                    string removeUrl = "~" + bundleUrl.Before("?");
                    BundleTable.Bundles.Remove(BundleTable.Bundles.GetBundleFor(removeUrl));
                    hasBundle = false;
                    ScriptID++;
                    //
                    //var bundleList = BundleTable.Bundles.ToList();
                    //BundleTable.Bundles.Clear();
                    //BundleTable.Bundles.ResetAll();
                    //BundleTable.EnableOptimizations = false;

                    //foreach (var oldBundle in bundleList)
                    //{
                    //    BundleTable.Bundles.Add(oldBundle);
                    //}
                }
            }
            else
            {
                ScriptID++;
            }

            if (!hasBundle)
            {
                string bundleAlias = "~/cqbundle" + ScriptID;
                var    bundle      = GetScriptBundle(bundleAlias);

                var activeDependencies = dependencies.Where(item => !item.NoCombine);
                foreach (var item in activeDependencies)
                {
                    bundle.Include(item.Path);
                }


                BundleTable.Bundles.Add(bundle);
                if (HttpContext.Current != null)
                {
                    bundleUrl = BundleTable.Bundles.ResolveBundleUrl(bundleAlias, true);
                }
                else
                {
                    bundleUrl = bundleAlias + "_no_http_context";
                }
                Bundles[coll] = bundleUrl;
            }

            var scriptPlaceholder = scripts.First();



            // add bundle after all noncombined scripts

            firstScript.Before(GetScriptHtml(bundleUrl));
        }
Exemplo n.º 2
0
        /// <summary>
        /// Resolve all script dependencies in the bound CQ document. Scripts that cotain a "data-
        /// location='head'" attribute will be moved to the head.
        /// </summary>
        ///
        /// <param name="doc">
        /// The document to resolve.
        /// </param>

        public void ResolveScriptDependencies(CQ doc)
        {
            string scriptSelector = "script[src][type='text/javascript'], script[src]:not([type]), link[type='text/css']";

            CQ scripts = doc[scriptSelector];

            if (scripts.Length == 0)
            {
                return;
            }

            // move scripts first
            // TODO: Optimize using a query caching mechanism so

            foreach (var item in scripts.Filter("[data-moveto]"))
            {
                var target = doc.Select(item["data-moveto"]);
                if (target.Length > 0)
                {
                    target.First().Append(item);
                    item.RemoveAttribute("data-moveto");
                }
            }


            // resolve dependencies

            ScriptCollection coll = new ScriptCollection(ScriptEnvironment);

            coll.Options = Options;

            // identify the insertion point for the script bundle. AddFromCq returns the first script with dependencies,
            // so scripts should be added right before that one. Otherwise they should be added
            // at the end of head.

            var firstScriptEl = coll.AddFromCq(scripts);
            CQ  firstScript   = null;

            if (firstScriptEl != null)
            {
                firstScript = firstScriptEl.Cq();
            }

            string           bundleUrl;
            List <ScriptRef> dependencies = coll.GetDependencies()
                                            .Where(item => !coll.Contains(item))
                                            .ToList();

            // Now add scripts directly for dependencies marked as NoCombine.


            var inlineScripts = Options.HasFlag(ViewEngineOptions.NoBundle) ?
                                dependencies :
                                dependencies.Where(item => item.NoCombine);


            foreach (var item in inlineScripts)
            {
                var script = GetScriptHtml(item.Path, item.ScriptHash);
                if (firstScript != null)
                {
                    firstScript.Before(script);
                }
                else
                {
                    firstScript = script;
                    doc["body"].Append(script);
                }
            }

            // Before creating the bundle, remove any duplicates of the same script on the page


            if (!Options.HasFlag(ViewEngineOptions.NoBundle))
            {
                bool hasBundle = Bundles.TryGetValue(coll, out bundleUrl);

                if (hasBundle)
                {
                    // when nocache is set, we will regenerate the bundle, but not change the script ID. The v=
                    // flag will be changed by BundleTable.

                    if (Options.HasFlag(ViewEngineOptions.NoCache))
                    {
                        string removeUrl = "~" + bundleUrl.Before("?");
                        BundleTable.Bundles.Remove(BundleTable.Bundles.GetBundleFor(removeUrl));
                        hasBundle = false;
                        ScriptID++;

                        // this code attempts to un-cache the bundle, it doesn't work.
                        // leaving it here until some permanent solution is found as a reminder
                        //
                        // http://stackoverflow.com/questions/12317391/how-to-force-bundlecollection-to-flush-cached-script-bundles-in-mvc4
                        //
                        //var bundleList = BundleTable.Bundles.ToList();
                        //BundleTable.Bundles.Clear();
                        //BundleTable.Bundles.ResetAll();
                        //BundleTable.EnableOptimizations = false;

                        //foreach (var oldBundle in bundleList)
                        //{
                        //    BundleTable.Bundles.Add(oldBundle);
                        //}
                    }
                }
                else
                {
                    ScriptID++;
                }

                if (!hasBundle)
                {
                    var activeDependencies = dependencies.Where(item => !item.NoCombine).ToList();
                    if (activeDependencies.Count > 0)
                    {
                        string bundleAlias = "~/cqbundle" + ScriptID;
                        var    bundle      = GetScriptBundle(bundleAlias);



                        foreach (var item in activeDependencies)
                        {
                            bundle.Include(item.Path);
                        }


                        BundleTable.Bundles.Add(bundle);
                        if (HttpContext.Current != null)
                        {
                            bundleUrl = BundleTable.Bundles.ResolveBundleUrl(bundleAlias, true);
                        }
                        else
                        {
                            bundleUrl = bundleAlias + "_no_http_context";
                        }
                        Bundles[coll] = bundleUrl;
                    }
                }

                var scriptPlaceholder = scripts.First();



                // add bundle after all noncombined scripts
                if (!String.IsNullOrEmpty(bundleUrl))
                {
                    firstScript.Before(GetScriptHtml(bundleUrl));
                }
            }
        }