htmlに生のbinary dataを埋め込むっぽい方法

生のbinaryと言うからにはBase64に変換するような生ぬるい方法ではない。**ほぼ**そのまま埋め込むのだ。ほぼとは何ぞ? と思う読者もいるだろう。1つだけ除外しなければならない文字が存在するのだ。それがUnicode番号13、復帰文字という奴だ。
厄介な事にhtmlに記述される文字の中でも復帰文字はUnicode番号10として認識されてしまう。環境にもよるかもしれないが、少なくともWindows Google Chrome、JavaScriptでは `innerText、innerHTML、textContent` で得られる値は10である。そのため別の文字に変換した上でescape文字と組にしなければならない。当然だがescape文字自身もescape文字と組にしなければならない。
単純に `\` でescapeすれば良いという話ではない。そもそもJavaScriptのように `\r` と書いても復帰文字が自動召喚されるわけではない(まあJavaScript側でそういう風に処理すればいいのだが…)。
escape文字に適任なのはbinary data中で最も出現数が少ない文字である。その方が膨張率が小さくて済む。
さて、下らないかもしれない前置きはこの辺にして本題とやらに話をにすり替えていこう。

:::note warn
制約
こんな馬鹿げた事をする為にはmeta要素で `charset=l1` (latin1、iso-8859-1等と同義)を設定しなければならない。UTF8などという符号化法式を選択する余地はないのだ!
:::
## html中のどこに仕込むか?
さすがにどこでもいいというわけにはいかない。a要素やp要素では意味不明な文字列がだらだらと丸出しになる。おまけに連続する空白類も1文字分扱いだ。要素内の`<!-- -->`の区間の文字は全て無視される始末。これらを考慮すると候補は限られる。
* style
偶然cssとして解釈されるbinary dataに直面するかもしれない。その対策として `type="text/plain"` を設定すれば良い
* script
`type="text/plain"` を設定する
* noscript
特に欠点が無いかも
* textarea
開始tag直後と閉じtag直前の改行が無視される問題がある。加えて**数値文字参照と文字実体参照**の対策は非常に面倒
* xmp
廃止された要素。それを無視すれば使い勝手が良い。`<xmp hidden>...</xmp>`などと記述すれば中身は隠蔽される…かも
* plaintext
廃止された要素。最強っぽいけどhtml最後の要素にする必要がある
* title
`innerText`と`textContent`で取得できるが**数値文字参照と文字実体参照**の対策が面倒。しかも`title`がめちゃくちゃになる
* comment(`<!-- -->`)
comment要素自体の取得が面倒。多分間接的にしかできない。取得できないBrowserも存在する。`<a id=a></a><!--binary-->`などと記述し、`a.nextSibling`で取得可能で、その中身(binary string)を取得するにも`textContent`一択である。昔は`innerText`か`innerHTML`で取得できたような気がする…(曖昧)。 
comment要素とは異なるが、`<a id=a><!--binary--></a>`と記述すれば`a.innerHTML`で`<--`と`-->`も含めた文字列を取得できる。できなかった時代もあったような気がするが記憶が曖昧。

plaintext以外はbinary data中に閉じtagと認識できる羅列が見つかったら破綻する。その対策として閉じtagとみなせる羅列の途中にescape文字を仕込む。

:::note warn
html編集にはBinary Editor
文字番号0のLatin1文字は普通の文書編集programでは消えていたり別文字に変換されている可能性がある。安全を期するためにもBinary Editorで編集する事を勧める
:::
## 復元処理
latin1の文書の中でも文字番号128～159(130,143,144,146,158以外)の扱いは特殊である。この連中は `charCodeAt` で得られる値が変態じみている。詳細は以下の表の通り。
<table><tr><th>latin1<th>取得値<th>latin1<th>取得値<th>latin1<th>取得値<tr><td>128<td>376<td>138<td>8226<td>150<td>8240<tr><td>129<td>382<td>139<td>8221<td>151<td>710<tr><td>131<td>339<td>140<td>8220<td>152<td>8225<tr><td>132<td>8250<td>141<td>8217<td>153<td>8224<tr><td>133<td>353<td>142<td>8216<td>154<td>8230<tr><td>134<td>8482<td>145<td>381<td>155<td>8222<tr><td>135<td>732<td>147<td>338<td>156<td>402<tr><td>136<td>8212<td>148<td>8249<td>157<td>8218<tr><td>137<td>8211<td>149<td>352<td>159<td>8364</table>

これらのひねくれ者的な文字に対しては、文字番号通りの値を得るための特殊な処理が必要だ。例えば以下のようになる。
```js
A=Uint8Array.form(L1txt,(c,i)=>(i=c.charCodeAt()%65533)>>8?129+' \x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C \x8E  \x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C \x9E\x9F'.indexOf(c):i)

```
` \x82\x83...\x9E\x9F` の部分は実際には生のLatin1文字でいいのだが、便宜上このように記述。`%65533`とは何者か? `charCodeAt`は文字番号0のLatin1文字を65533だ! などと豪語しておられるのだ。その誤解を解くためのまじないである。
連想配列で紐付ける古典的な手法もある。以下の例では`noscript`要素の中身をbinaryに変換して取得している。
```html
<noscript id=s>abc	ABC
!"#$%\~:;</noscript>
<script>
function L1toBin(L1txt){
	var a=256,z=L1txt.length,h={__proto__:null},A=new Uint8Array(z);
	for(;a;)h["\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f".charAt(h[String.fromCharCode(--a)]=a)]=a^128;
	for(;a<z;)A[a]=h[L1txt.charAt(a++)];
	return A
}
A=L1toBin(s.innerText)
</script>
```
これも`\x80\x81...\x9e\x9f`の部分は生のLatin1文字列であり、128 bytesとなる。え? `charAt`は古臭いって? そう、今時は`[]`で位置を指定できるのだが、古風にこだわってみた。
7行目も今時は以下のように書き換えられる。
```js
for(z of L1txt)A[a++]=h[z];
```
## 裏技
実は閉じtag、`<!-- -->`、復帰文字、escape文字等といったものを考慮せず埋め込む方法がある。htmlをpng形式の画像として再読み込みすればいいのだ。少し特殊でやや複雑な方法であり、制約もある。
htmlの先頭にpngの頭情報を埋め込み、続いて画像本体、htmlのcanvas要素とimg要素を埋め込む。png画像本体は埋め込みたい任意のbinaryから構築する。
img要素のonload属性でアレコレ処理すると、任意のbinary情報を取得できるって寸法だ。実用例として[zpng](https://codegolf.github.io/zpng/)がある