I'm trying to modify a local HTML file by including tags for a local .js file and 2.0.3 jquery.min.js. Here is an excerpt from the code (entire script is here):

 jsdom.env(
  data,
  ["//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js", "../javascripts/fixit.js"],
  function (errors, window) {
    var $ = window.jQuery;
⋮

Now, if I run the script twice, it includes both of these links in the HTML again. Is there a way to make this conditional and include the tags only if they are not already present?

有帮助吗?

解决方案

(I maintain jsdom.)

The whole point of jsdom is you can do normal DOM operations, like testing for an element's presence or inserting an element, inside Node. So I would do something like this:

var jsdom = require("jsdom").jsdom;

var document = jsdom(data);

if (!document.head.querySelector("script[src$='2.0.3/jquery.min.js']")) {
    var script = document.createElement("script");
    script.src = "//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js";
    document.head.appendChild(script);
}

// Same for ../javascripts/fixit.js

其他提示

[Edit: it's wrong. See edit below]. Check if jQuery is already defined, include scripts if not.

var scripts = [], undef;
if(typeof window.jQuery === typeof undef){
    scripts = ["//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js", "../javascripts/fixit.js"];
}

jsdom.env(
  data,
  scripts,
  function (errors, window) {
⋮

I haven't tested it, but judging by jsdom source code it'll fire scriptComplete callback if config.scripts is an empty array.

EDIT: after reading your comments I've realized it's not going to work. The context in which I check for jQuery is outside of the scope of jsdom.env's window object. And jsdom doesn't check for the existence of scripts you want to append as its use case is probably in-memory operations on temporary DOM.

So if you need to persist the modified DOM and be able to re-read it from file and process again without adding these duplicate <scipt /> elements the easiest solution would be to get rid of them just before writing the file.

/* if you don't want to save the document with <script> elements at all */
Array.prototype.slice.call( document.scripts ) // convert document.scripts to regular Array
.forEach( 
    function( script ){ 
      /* you probably want to check if script.src matches jQuery or whatever,
       * e.g. if( script.src.indexOf('jquery.min.js' > -1 ){
       */
       script.parentNode.removeChild( script ); 
 });


/* alternatively if you want to have each <script> exactly one (remove duplicates) */
var srcs = {};
Array.prototype.slice.call( document.scripts ) // convert document.scripts to regular Array
  .forEach( 
     function( script ){ 
        if( srcs[ scipt.src ] ){
           script.parentNode.removeChild( script );
        }
        else {
           srcs[ script.src ] = 1;
        }
  });

Add one of the above before this line:

var output = window.document.doctype + window.document.innerHTML;

By the way $("head").append('<link ... in your code will add this link multiple times as well. You should check for its existence:

if( $('link[src$="stylesheets/test.css"]').length == 0 ) $("head").append('<link ...
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top