2013-01-04 91 views
1

我正在一個Sharepoint網站上工作。我無法訪問Web部件代碼。我只能用JavaScript更改主頁面。JavaScript修復壞HTML標記

其中一個webpart有一個bug。它會將<img>更改爲SRC的值。

例如:

應該有

<img alt="img" src="http://www.apicture.png" style="margin:5px" /><br /><br /> 

,但有

<img alt="img" src="<a href="http://www.apicture.png">http://www.apicture.png</a>" style="margin:5px" /><br /><br /> 

我試圖匹配和替換,但innerHTML的打破了別人的腳本。

如何使用JavaScript修復我的問題?

編輯:

我的代碼:

var markup = document.documentElement.innerHTML; 
markup = markup.replace(/src=\".*?(http:\/\/[^\"]+)\"/g,'src=\"$1\"'); 
document.documentElement.innerHTML = markup; 

,但它打破了我的網頁。

+0

後這撥弄請 –

+0

的http:// jsfiddle.net/sancho/jKWgr/? – Sancho

+0

如果'src'包含未引號的雙引號,並且它本身被雙引號引起來,修復它將會很困難... –

回答

5

由於DOM已經被破壞,您需要退後一步並嘗試挽救HTML。

1)找到破碎元素的父母。雖然搜索&內部替換document.body.innerHTML可能會工作,you shouldn't really let regexes anywhere near large chunks of HTML。性能也是一個值得關注的問題,雖然較少。

<img alt="img" src="<a href="http://...將被瀏覽器解析爲源圖像「<a href=」。

使用jQuery,您可以簡單地要求$('img[src="<a href"]')獲取圖像。除IE < 8外,您可以使用querySelectorAll和相同的選擇器。如果您沒有jQuery,並且想要支持IE7,則需要使用getElementsByTagName進行手動過濾。

如果你真的很幸運,你可以通過getElementByID(或相應的jQuery)找到父母。

這是很容易的部分。


2)您的HTML沒有驗證,瀏覽器已經做了一些努力來解決它。你需要扭轉這個過程。預測瀏覽器操作是有問題的,但讓我們嘗試。

讓我們看到

瀏覽器做什麼這是Chrome和Firefox如何解決它:

<img src="&lt;a href=" http:="" www.test.com="" img="" image-20x20.png"="">http://www.test.com/img/image-20x20.png" style="margin:5px" /&gt; 

IE9排序中img屬性按字母順序innerHTML(O_0),不HTML - 跳過src中的<。 IE7-8另外從屬性剝離=""

圖像屬性很難打撈,但文本內容沒有受到傷害。無論如何可以看到的模式:

一切從<img開始,直到src=應該保留。不幸的是,在IE中,參數被重新排列,所以你必須保留不正確的標籤。 src="..."本身必須刪除。在現代瀏覽器中,所有的東西都是[不正確的],但是在IE中,正確的屬性可能會在那裏出現(反之亦然)。然後圖像標籤結束。

接下來的一切都是真正的URL,直到雙引號。從雙引號開始直到HTML轉義的/>是屬於圖像標籤的屬性。讓我們希望他們不包含HTML。 CSS很好(用於我們的目的)。


3)讓我們構建的正則表達式:開口IMG標籤的任何屬性(讓我們希望他們不包含HTML)(捕獲),該src屬性及其特定值(轉義或轉義)任何其他屬性(捕獲),標籤的結尾,URL(捕獲),一些更多的屬性(捕獲)和HTML轉義的結束標籤。

/<img([^>]*?)src="(?:<|\&lt\;)a href="([^>]*?)>([^"]+?)"(.*?)\/&gt;/gi 

您可能會感興趣how it's seen by RegexPal.com


它所應改爲:圖像與串接適當的屬性,並與打撈src。它可能是值得過濾的屬性,所以我們選擇一個回調替換。普通屬性只包含鍵中的單詞字符。更重要的是,普通屬性通常是非空字符串(IMG標籤沒有布爾屬性,unless you are using server-side maps)。這將匹配所有空屬性,但不是有效的屬性鍵:/\S+(?:="")?(?!=)/


下面是代碼:

//forEach, indexOf, map need shimming in IE<9 
//querySelectorAll cannot be reliably shimmed, so I'm not using that. 

//author: Jan Dvorak 
// https://stackoverflow.com/a/14157761/499214 

var images = document.getElementsByTagName("img"); 
var parents = []; 
[].forEach.call(images, function(i){ 
    if(
    /(?:<|\&lt\;)a href=/.test(i.getAttribute("src")) 
    && !~parents.indexOf(i.parentNode) 
){ 
    parents.push(i.parentNode) 
    } 
}) 

var re = /<img([^>]*?)src="(?:<|\&lt\;)a href="([^>]*?)>([^"]+?)"(.*?)\/&gt;/gi; 
parents.forEach(function(p){ 
    p.innerHTML = p.innerHTML.replace(
    re, 
    function(match, attr1, attr2, url, attr3){ 
     var attrs = [attr1, attr2, attr3].map(function(a){ 
     return a.replace(/\S+(?:="")?(?!=)/g,""); 
     }).join(" "); 
     return '<img '+attrs+' src="'+url+'" />'; 
    } 
); 
}); 

小提琴:http://jsfiddle.net/G2yj3/1/

+0

令人印象深刻的答案!我喜歡你如何評論你的代碼和添加作者信息;-) –

+0

你的代碼是非常令人印象深刻的。我試圖使用它,但我有一個錯誤。 IE和Chrome表示「forEach」具有空值或不是對象「>< – Sancho

+0

你是個瘋子。這樣的事情應該付出一些不錯的費用(我的意思是$!)。 +1 –

1

你可以使用正則表達式修復src屬性,但它不會修復整個頁面。原因是Web瀏覽器試圖解析這種不好的HTML,並在執行JS之前產生奇怪的輸出(額外的元素等)。由於您無法干擾HTML解析/呈現引擎,因此除了更改原始內容以解決此問題之外,沒有其他合理的方法。

+1

我已經在寫一個半合理的解決方案。 –

+0

@JanDvorak等不及要看到它 –

+0

@roXon享受。這很瘋狂,但它應該工作 –