1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

圧縮とか自己展開html

1
Posted at

つまり圧縮して自己展開するように作り変えます。今時のbrowserで普通に閲覧可能。programは以下の通り

<!doctype html><html><head>
<meta name=viewport content="width=device-width,initial-scale=1">
<title>sfxhtml</title>
<style>
*{color:snow;font-family:"MS Gothic",monospace;font-size:1em;margin:0}
html,body{overflow:hidden;height:100%}
input,select,label[id]{background:#848;border:1px solid #c6c;border-radius:4px;font-size:1em}
a{color:#acf;text-decoration:none}
a:hover,label:hover{color:#aff}
input,label,select{cursor:pointer;text-shadow:1px 1px #000}
input[type=file]{display:none}
#info{position:absolute;bottom:0;cursor:help;height:1.25em;text-align:left;width:100%;z-index:999}
#uform{width:100%;height:100%;background:#212;background:radial-gradient(circle at center center,#848,#212)}

/* drop area */
ol{border:2px dashed #caf;overflow:auto;background:rgba(48,32,48,.75);margin:0;position:absolute;top:1.4em;bottom:1.25em;left:0;right:0}
ol:empty:before{content:"Drop files here";display:block;text-align:center;position:relative;top:45%}
li{margin-bottom:3px}
.dover{background:#535}
.dpass{background:#323}
</style>
</head><body>
<form id=uform><div style="text-align:center">
	output<select id=op><option>raw<option>base64</select>
	charset<select id=ip><option>utf8<option value=866>ibm866<option value=l1>latin1<option value=l2>latin2<option value=l3>latin3<option value=l4>latin4<option>cyrillic<option>arabic<option>greek<option>hebrew<option>logical<option value=l6>latin6<option>iso-8859-13<option>iso-8859-14<option value=l9>iso-8859-15<option>iso-8859-16<option value=koi>koi8-r<option>koi8-u<option>mac<option>dos-874<option>cp1250<option>cp1251<option>cp1253<option value=l5>cp1254<option>cp1255<option>cp1256<option>cp1257<option>cp1258<option>x-mac-cyrillic<option>gbk<option>gb18030<option>hz-gb-2312<option>big5<option>euc-jp<option>iso-2022-jp<option>sjis<option>korean<option>iso-2022-kr<option>utf-16<option>utf-16be<option>x-user-defined<option>iso-2022-cn</select>
	<label id><input type=file multiple id=load>LOAD</label>
	<label id=save>Save</label>
	<label id=kill>kill</label>
	</div>
	<ol id=flist></ol>
</form>
<input type=button value="sfx html creater" id=info>
<script>
let g=a=>Uint8Array.from(a,a=>a.charCodeAt());
const H=[
	"<svg onload='",
	"fetch``.then(a=>a.arrayBuffer().then(a=>",
	"new Response(new Blob([",
	"a.slice(",,,
	')]).stream().pipeThrough(new DecompressionStream("deflate-raw"))).',
	"text",
	"().then(a=>write(","a","))",,"'>"],
//for rendering stopper
tag0=g('-->'),
tag1=g('</noscript>'),
tag2=g('</xmp>',g=a=>document.getElementById(a)),
info=g("info"),ol=g("flist"),lf=g("load"),
find=(P,A)=>{
	for(let M=P.length,N=A.length-M,i=0,j;i<=N;i+=j||1)
		for(j=0;A[i+j]===P[j];)if(++j===M)return 1
},
b64=A=>{
	var a=62,b=0,c,z=A.length,B=new Uint8Array((z*4+2)/3),C=new Uint8Array(64);
	for(C[a]=43;a;)C[--a]=a>51?a-4:a>25?a+71:a+65;
	for(C[63]=47;a<z;B[b++]=C[63&c])c=A[a++]<<16|A[a++]<<8|A[a++],B[b++]=C[c>>18],B[b++]=C[63&c>>12],B[b++]=C[63&c>>6];
	return new TextDecoder().decode(B)
},
worker=new Worker(`data:,
self.onmessage=async e=>{
	const{action,data}=e.data,z=data.length, s=new CompressionStream('deflate-raw'), w=s.writable.getWriter();
	new Response(s.readable).arrayBuffer().then(a=>postMessage({
		status:'success',
		result:new Uint8Array(a),
		inSize:z,
		outSize:a.byteLength
	}));
	//processing
	for(let a=0,b=Math.ceil(z<1e4?z/2:z<1e5?z/5:z<1e6?z/10:5e5);a<z;postMessage({status:'progress',p:a,ratio:(a/z*1e4|0)/100}))
		await w.write(data.subarray(a,a=Math.min(a+b,z)));
	await w.close()
}`);
ol.ondragover=function(e){
	this.className="dover";e.preventDefault();
	e.dataTransfer.dropEffect='copy'
};
ol.ondragleave=function(){this.className="dpass"};
ol.ondrop=lf.oninput=async function(e){
	e.preventDefault(e.stopPropagation());
	ol.className="dpass";
	var c=0,f=(e.dataTransfer||this).files,r,s=0,t=0,m=op.selectedIndex,cs=ip.value,st=new Date;
	for(e of f)t+=e.size;
	//write packed data
	let pf=r=>e.arrayBuffer().then(a=>{
		worker.postMessage({data:new Uint8Array(a)});
		worker.onmessage=f=>{
			let d=f.data;
			if(d.status==="progress")return info.value=info.style.width=((s+d.p)/t*1e4|0)/100+"%";
			let a=new Uint8Array(d.result),b=d.inSize,o=m?0:d.outSize,n=e.name.replace(/\.\w+$/,""),li=document.createElement("li"),O=H.slice();
			if(cs!="utf8")O[7]="arrayBuffer",O[9]='new TextDecoder("'+cs+'").decode(a)';
			if(m)O[1]="",O[3]="Uint8Array.from(atob`",O[4]=b64(a),O[5]="`,a=>a.charCodeAt()";
			else O[11]="))",O[13]=f=find(tag0,a)?find(tag1,a)?find(tag2,a)?"<plaintext hidden>":"<xmp hidden>":"<noscript>":"<!\--",O[4]=O.join``.length+f.length-1;
			s+=b,O=O.join``,c+=o+=O.length,li.innerHTML=`<a href=${URL.createObjectURL(new Blob(m?[O]:[O,a]))} download='${n}.gz.htm'>${n}.gz.htm</a> <input type=button value="${b+" -> "+o}">`;
			ol.appendChild(li);
			r(info.value=info.style.width=(s/t*1e4|0)/100+"%")
		}
	});
	for(e of f)await new Promise(pf);
	info.value=`${t+" -> "+c}(${(c/t*1e4|0)/100}%), ${new Date-st}ms`
};
// remove files
g("kill").onclick=function(){
	for(var e=ol.getElementsByTagName("a"),b=0,c;c=e[b++];)c.download&&URL.revokeObjectURL(c.href);
	if(b>1)info.value="removed all files",ol.innerHTML=""
};
// save files
g("save").onclick=function(){
	for(var b=ol.getElementsByTagName("a"),c=0,d;d=b[c++];)d.click();
	if(c<2)b=this,b.innerText="miss",setTimeout(function(){b.innerText="Save"},500)
}</script>

仕様

圧縮ではCompressionStream、展開ではDecompressionStream様を利用。入力されたhtmlは単一のsvg要素と圧縮文からなるhtmlに変換され、document.writeで展開文を書き出します。元と同じように描画されるとは限りません。
例えば、ふざけて <body onload="..."> を複数記述しているとか、非同期処理を多数搭載しているとか、そんなpageは動作が怪しいです。

説明書

  • output
    • raw

      圧縮文が無変換binary dataとなります

    • base64

      圧縮文がbase64変換されます。圧縮率劣化しますが安全

  • charset

    文字符号をここで指定した値として入力fileを読み込みます

  • LOAD

    file読み込み。複数選択可能

  • Save

    圧縮結果を全て保存

  • kill

    圧縮結果を全て破棄

  • Drop files here

    ここに複数fileをまとめて投下できます

参考文献

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?