2013-09-06 4 views
2

로컬 .js 파일 및 2.0.3 jquery.min.js에 대한 태그를 포함하여 로컬 HTML 파일을 수정하려고합니다. 다음 코드에서 발췌 (전체 스크립트가 here입니다)입니다 :조건부 포함 <script> 태그가 jsdom

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

지금, 나는 두 번 스크립트를 실행하는 경우, 그것은 다시 HTML에서 이러한 링크가 모두 포함됩니다. 이 조건을 만들고 이미 존재하지 않는 경우에만 태그를 포함 할 수있는 방법이 있습니까?

답변

3

(. 내가 jsdom을 유지)

jsdom의 요점은 당신이 요소의 존재를 테스트 또는 요소를 삽입과 같은 일반 DOM 작업을 할 수있다, 내부 노드 . 그래서 저는 다음과 같이 할 것입니다 :

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 
+0

호기심에서 벗어남 : 외부에서 jsdom (data)의'window' 객체에 액세스하거나 콜백 함수에서만 액세스 할 수 있습니까? – pawel

+0

'document.parentWindow'는 찾고있는 표준 DOM API입니다. – Domenic

+0

그럼'if (typeof document.parentWindow.jQuery == "undefined")'도 잘 작동 할 수 있습니다. 맞습니까? – pawel

2

[편집 : 입니다. 아래 편집 참조]. jQuery가 이미 정의되어 있는지 확인하고 그렇지 않은 경우 스크립트를 포함하십시오.

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) { 
⋮ 

나는 그것을 테스트하지 않은,하지만 config.scripts가 빈 배열 인 경우 jsdom source code에 의해 판단하는 것이 scriptComplete 콜백을 불 수 있습니다.

EDIT : 귀하의 의견을 읽은 후에 나는 그것이 효과가 없을 것임을 깨달았습니다. jQuery을 확인하는 컨텍스트는 jsdom.envwindow 개체의 범위를 벗어납니다. jsdom은 유스 케이스가 임시 DOM에서 메모리 내 작업 일 가능성이 있으므로 추가 할 스크립트가 있는지 확인하지 않습니다.

수정 된 DOM을 유지하고 파일에서 다시 읽을 수 있고 이러한 중복 된 <scipt /> 요소를 추가하지 않고 다시 처리 할 수있는 경우 가장 쉬운 해결책은 파일을 작성하기 직전에이를 제거하는 것입니다.

/* 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; 
     } 
    }); 

이 행하기 전에 위의 중 하나를 추가 : 코드의 방법 $("head").append('<link ...으로

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

이이 링크를 여러 번 추가합니다. 당신은 그것의 존재를 확인해야합니다

if($('link[src$="stylesheets/test.css"]').length == 0) $("head").append('<link ... 
+0

위대한 해답입니다. 그러나'window'가 정의되지 않았다는 것에 불평합니다 :'ReferenceError : window is not defined'. 편집 : 아마도 우리는'jsdom.env'에 대한 콜백에서만 정의하기 때문일 것입니다. – mart1n

+0

또한,'jsdom.env'의 콜백이 실행될 때까지 스크립트를로드하지 않기 때문에 globalFromFixit 변수에 대한 검사가 작동하지 않습니다. 난 그냥 '데이터'문자열을 검색 할 수있을 것 같아요하지만 비싼 작업처럼 보인다. – mart1n

+0

@ mart1n 좋은 점. 편집을 참조하십시오. 혼란을 가져 미안합니다. – pawel