JavaScriptからHTMLにアクセスするには、普通はdocumentオブジェクトを使うのですが、これで取得できるHTMLは既に他のJavaScriptによって汚されてしまったものである可能性があり、ブラウザが正規化してしまった結果であったりします。たとえばHTMLの文法チェックを行いたいと思っても、これでは無意味です。
そこで、ajax的に現在のページのHTMLソースを取ってきたらどうかと思いついて、簡単なスクリプトを作ってみました。それは造作なくできたんですが、これって画像とかの外部ファイルも同一サーバにあれば取ってきて埋め込めば、1ファイル化できるのではないかと考えました。で、できるできないでいえば、概ねできるんですけど、あんまり意味ないですねぇ。
※注意 IEで実行するとハングアップしてしまうので実行しないでください。
[
サンプルの実行]←クリックするとこのページの内容をひとまとめにしたソースを別ウインドウに表示します。
(function() {
var getdata = function(url, binaryflag) {
var xmlhttp;
try { xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) {
try { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } catch (err) {
xmlhttp = null;
};
};
if(!xmlhttp && typeof XMLHttpRequest != "undefined"){
xmlhttp = new XMLHttpRequest();
}
xmlhttp.open("GET", url, false);
if (binaryflag)
xmlhttp.overrideMimeType("text/plain; charset=x-user-defined");
xmlhttp.send(null);
return xmlhttp;
}
var base64 = function(data, binaryflag) {
var seed = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (data == null)
return "====";
var result = "";
var arr = getbytes(data, binaryflag);
var c = 0;
for (var i = 0; i < arr.length; i++) {
switch(i % 3) {
case 0: result += seed.charAt((arr[i]>>2)&0x3f);
c = (arr[i]&0x03)<<4;
break;
case 1: result += seed.charAt(c | ((arr[i]>>4)&0x0f));
c = (arr[i]&0x0f)<<2;
break;
case 2: result += seed.charAt(c | ((arr[i]>>6)&0x0f));
result += seed.charAt(arr[i]&0x3f);
c = 0;
break;
}
}
if (arr.length % 3 == 1) {
result += seed.charAt(c);
result += "==";
} else if (arr.length % 3 == 2) {
result += seed.charAt(c);
result += "=";
}
return result;
}
var getbytes = function(data, binaryflag) {
var result = [];
if (!binaryflag) {
for (var i = 0; i < data.length; i++) {
var c = data.charCodeAt(i);
if (c <= 0x7f) {
result.push(c);
} else if (c <= 0x07ff) {
result.push(((c >> 6) & 0x1F) | 0xC0);
result.push((c & 0x3F) | 0x80);
} else {
result.push(((c >> 12) & 0x0F) | 0xE0);
result.push(((c >> 6) & 0x3F) | 0x80);
result.push((c & 0x3F) | 0x80);
}
}
} else {
for (var i = 0; i < data.length; i++) {
result.push(data.charCodeAt(i) & 0xff);
}
}
return result;
};
var checkself = function(url) {
if (url.match(/^https?:\/\/([^\/]+).*/) && RegExp.$1 != location.host) {
return false;
} else {
return true;
}
};
var html = getdata(location.href).responseText;
html = html.replace(/<link[^>]*>/g, function() {
if (arguments[0].match(/rel="stylesheet"/i)) {
return arguments[0].replace(/(href=")([^"]*)(")/i, function() {
if (!checkself(arguments[2]))
return arguments[1] + arguments[2] + arguments[3];
var result = getdata(arguments[2]);
return arguments[1] + "data:" + result.getResponseHeader('content-type')
+ ";base64," + base64(result.responseText) + arguments[3];
});
} else if (arguments[0].match(/rel="shortcut icon"/i)) {
return arguments[0].replace(/(href=")([^"]*)(")/i, function() {
if (!checkself(arguments[2]))
return arguments[1] + arguments[2] + arguments[3];
var result = getdata(arguments[2], true);
return arguments[1] + "data:" + result.getResponseHeader('content-type')
+ ";base64," + base64(result.responseText, true) + arguments[3];
});
} else {
return arguments[0];
}
});
/* scriptは属性データに埋め込むとハングアップしてしまってマズいので、インラインにCDATAで埋め込む */
html = html.replace(/<script[^>]*>/g, function() {
if (arguments[0].match(/(src=")([^"]*)(")/i)) {
if (!checkself(RegExp.$2))
return arguments[0];
var result = getdata(RegExp.$2);
return arguments[0].replace(/src="[^"]*"/, '')
+ "<!--//--><![CDATA[//><!--\n"
+ result.responseText
+ "//--><!]]>";
} else {
return arguments[0];
}
});
html = html.replace(/<img[^>]*>/g, function() {
return arguments[0].replace(/(src=")([^"]*)(")/i, function() {
var u = RegExp.$2;
if (!checkself(u))
return arguments[0];
var result = getdata(arguments[2], true);
return arguments[1] + "data:" + result.getResponseHeader('content-type')
+ ";base64," + base64(result.responseText, true) + arguments[3];
});
});
var win = window.open("", "_blank");
if (win) {
win.document.write('<textarea id="textarea" style="border:none;width:100%;height:100%;"></textarea>');
win.document.close();
win.document.body.style.margin = 0;
win.document.body.style.overflow = 'hidden';
win.document.getElementById('textarea').value = html;
} else {
alert("ポップアップウインドウを許可する設定にしてください。");
}
})();