Z̩̮̜͉̣͎͉̤͇͂̇͊̇̅̚ͅa̠͌̔l̨̢̞̘͉̟̰̱̭̜͍̙̣̬̂̿̌̐̾̾͂̍̽̓̓̇̄g̨̢̡̢̛͍̪̠̠̹̜̪̘̱͌̆̒̅̐ỏ̡̱̞̣̖̦̰̙͊́̋́̃̂̓̍̃

# T̡̨͈͇̟̼̱̤̹̠́͆̂̋̂̀̄̋́̚ö̴̮̬̙͎͈̳̯́̈́̄̿̔̿͌̀̈́̀̊͊͊̌̈̓̕ͅ i̷̢̛̖͈̗̇n̶̝͂̂̂v̸̹͈͍̮̰̺̰̯̬̀̋̎̃̅́̓o̸̢͈̪͍̦̫̬̪̬̞̫̗̅̑͊́̓͋̕̚k͉̣͆̄e̷̶̡̳̤̤͇̠̤̼̭̠̭͈̻͆̃́̒̂̊̇̂ ẗ̵̢̢̛͉̪͈̪̥̞̣̪̙́̈́̓̃̂̆̀h̨̗̻̰̱̳̅͂̎̇̽̃e̷̴̶̛̬̦̮̜̾̂̃͂̐̌̈́̄̾̈́̄̀̚̕ h͍̘̙̠̯̜̫̙̙̜̥͉̝̋͌̌́͋̽͋̉̂̊̄i̶̡̢̧̧̨̛̯̬̤̭͇͂́̏͂̐̋̈́̎̍̋̀̐̕v̸̡̢̛̤̫͇̹̱̗̮̻͈̳̄͆̓̄̾̀̋̀́̕ȩ͍̹͂-m̴̶̳̖̼̟̅̓ĭ̴̠̙̦̗͍̙̀̒͂͌ņ̵̵̨̼͇̖̥̉͂̓̌̀ḓ̛̛̗̠̰̞̫̗̘̗̖̖̎̈́̐́̈́̑ͅ ṟ̯̟̟̣͍͈̰̫͌̓̆̽̈́̆̀̊e͎̜̭̣̝̪͂̒̔̽̕p̸̧̡̨̛̛̤̦̹̩͉͎͈̬͍͈̞̈́̀̉̿̈̄̒̊̇̽̚ͅȓ̶̵̴̳̘̟͈̓e̬̟̝̎̍s̶̷̷̡̛̪̞͇̼̤̱̘̼̘̘͈̮̃̾̑̆̑̆̏̈ͅe̢̬̳͈͉̙̖̖̱̭͈̣̪̲̱͎̔̓̅̎͋̃͋̾̂ͅņ̸̷̶̷̸̻̱̻̹̻̥̹̟̭̘̟̟̣̟͊̔̏̔̀̐͆̋̚ͅt̶̵̢͍͈̳̱̬̫̯̣̾̂̆̓i̷̸̧̛̛̹̹̯̬̜̪̼͇̮̤̯̖̾̀̄̃͌̃̄̓̔̋̏n̴̛̩̗̦̟̖̣̒̓̈̒̓̏̇̈́̓̽̉͊̑͌́͋̚ͅͅg̛̬͉̳̗̈́ ċ̵̶̨̠̘̮̤̺̟̹̱̠̙̅̑̽̽̃̐́̀̅̃̾ḩ̤̖̮̖͈̣̘̺̱̍̎͋ȧ̸̴̴̡̨̢̧̘̩̥͉̣̰̝̘̪̠̖͉̐̋̇̏̊̚̕ͅö̵̩̼̰̣̟̱̳̞̖̪̗͎́̃́́̆̍̓͌̀̽̃̊̿s̸̼̱͇̿̍͊͊

```js
[].concat(...[...document.all].map(e => [...e.childNodes])).filter(n => n.nodeType === Node.TEXT_NODE).map(n => n.textContent = n.textContent.replace(/([a-zA-Z])/g, (_, c) => c + [...Array(Math.floor(Math.random()*30))].map(() => String.fromCharCode(0x300 + Math.floor(Math.random()*79))).join('')))
```

Ç̵̶̶̡̛̱̘̤͉̘̹͈̳̝̝̽̆́̀̈́̾̍̅̎̑̌̿̚ͅȯ̷̳p̶͍̲͇̳̔̅̍̚y̴̸̵̢̡̭̖̩̫̘̼̦̬̓̿̇͋̉͊̓́́́̑̍ a̴̵̶̢̛̟̬̘͍̰̝̘͌̍̈́̉̔̂͋̊̑̍̽̚̕n̸̵̢̢̧̛̛̪̬̯̠̣̮̤̮̻͈͈̘͌͋́̓̏̀́̋d͇͎̝̜͈͇͂̋ p̄a̴̸̴̛͉̰̯̗̯̯͉̰̲͈̤̞̽͂̃̔̔̅̒͂̑́s̢̝̮̳̳̮̪̞̟̃̾̑̅̒́͊t̷̨̨̫̣͇̮̮͍̺̭̓̈̎̇̔̈́̆̒̌̕̕ĕ̢̢̡̤̗̟̫̄̀̚ t̶̸̢̥̘̫̮̹̤̉̑̀̀̽̔̑h̸̝̝̀͊̅e̵͇̖̞̹̅͊̄̋̄̐̑̑ c̼̞̠̯̜̹̺̱̖͈̙͎̔̈́̽̓̔́̄̾̋̾̓͊̅̾̔̚̚o̵̢̥̘͍̱̗͈͈̭̟͇̠̰̪̮̩̿̂̅͌̀̀͌̀̑̆̆d̡̡̳̣̪̦̩̟͉̝͇̬̼̺̖̫̏̈́̅̇̍́̓̎̋ͅͅe͉̦͆͂̉̔ a̛̺̥̜̤͈͍̠̠͍̣̳͌̍̊̉̎̑͌̇̊̾̽́̒̒̾̏b̸̶̭̙̥̥̱̫̮̜̌͌̋̿̍̓ò̵̸̻̟̰̗̯̥̭̈́̾͌͌̃̾̊̽̽́̑̉́v̳̗͊̄͊̓̔̅́ḙ t̴̶̵̡̧̮̯͍̟̝̭̲̮̰̰͇̺̪͊͋͋̓̽͆̽́̂́̂o̧̜̖̟̼̥͎̭̩̟̳͍̅̓̾̏̎̀̅̍̐͆̈͊͆ t̷͉̣̺̗̰̱̏͊̎̂̇̆ḩ̨̜͎̳̺̥̬͊́̇̒̾̐̏e̛͉̝̙̓̀̓̾̑̚ ȃ̵̡̢͎̖͈̬̾̓̃̓̋̊̏͆͆̆̋̿ḑ̡̩̦̬̬̻͎̏̑̍͋͆̊̽̊́̾̐̏̈̀̽̎̚d̸̨̼̭̥̮͉̯̥̬͈̦̦̠̯̺̮͆̏̄̄͊̽́̏̽̓̏̂̕r̙̤͊̔̀̾e̷̡̹̜̫͍̻̥̋͂̓́͋̍̆s̸̷̨̡͈̲̰̮͇̦̪̟̭͈̲̟̀͌̋͂̔͊̍̓̏̿̕s̆ b̴͍̰̖̹̉à̲̱̬ŕ̤̙̫͎̻̞̥̼̮̑͂ a̳͉̲̲̗̮̰̜̾̏̅̄͌̿̂̕n̸̸̛̦̹̥̺͈͈͂̂̎̌̈̒̀̔̽̏͂̆̍ͅd̗̀̉ ṗ̶̭̲̠̞͌̄r̸̷̨̡̨̛̺̫͎̞̤̣̭̠̞̣̼͊̀̅̓̈́̔̈́̚e̷̴̢̨̻̱̳̼̘̘̍̄́̓̽̒̔̽̃̍̓̄͌̒̏̆̀̚̚p̶̨̧̯̟̪̙͍̖̪̌̓̇̈́̐͋̅̕e̷̸̢̧̝̘̜̭̠̘̰̗̋̀̀̏͆̐̈́̌͆̌͆̏̕ͅņ̶̡̻̼̩̼̙̖̰̯̤͈͇̦̬̈́̂̒̀́͋̆̿͂͆̚d͆̉ͅ "j̺̙àv̴̖͍̀̿̽̏͆a̭͉̞͇͎̓͌̔͋s̸̢̢̡͎̲̯̙͈̳̱̟̹̱̤͎̏͂̅̄̒́̈̔̆̀ͅc̴̡̪̳͎̤̭̺̗̟͂̀̎́̏͆̒̈́ȓ̸̢̨̭͎̠̪̜̣̈͆̒͌͂͌̎͆͋ĩ̲̞̰̤́̄p͇̀̓͆́ţ̴̷̺̯̫̯̻̯̹̺̠̲͈͉̤̍̔̔̌͂̀̓́̂́͊́̕:", ẗ̷̢̯̮͇̗͈̦̫̮̼͆̔́̾h̖̰̲ȩ̛̝̥̘̯̠͉͂̊̓̚n̟̼̩͊̒̈ ṕr̴̨̦̭̦̪̺̟͊̃̂̑̾́̂́̆̀é̇s̷̨̪̤̮̟̗̿͂̐͌̈́̓̅s̵̛̭̤̩͎̦̳̠̘͈͍̜̒̏̽͂̃́̏̏̀ͅ Ě̸̦̱̙̭̠̯̬̂́́́̋̏̐̆̕ṅ̠̼̳̮̌̌͌̊̽̓ţ̷̶̡̨̛̩̰̜̪͇̫̘̯̱͈̙̯̜́̾͆̌̒̏̓̚ȩ̼̻͈͊̍̑̎ṟ̡̜̘̩͉͂̔̀̀̈́̐ k̵̡̲̮͉̣̲̜̰̺͎̺̲̒̅̓̓̿̐͂̊̂̌̋̉̀ͅe̸̵̯̣̥̣̝̒y̭̜̞̠̳̺͆̑̆͌.


## 注意

実行には数秒くらいの時間が掛かります。
Googleの検索結果ページ等だと、何故かページのスタイルが崩壊してしまいます。
GitHubとかのページでやると良いでしょう。
(追記: スタイル等が崩壊するのは`<style>`や`<script>`の中身が変わるためのようです。こいつらもTextNodeなのか)

## 解説

ZalgoするJavaScript(ES6)ワンライナーです。
JavaScriptの闇がいくつか詰まっているので１つずつ説明しようと思います。

まずprettifyするとこんな感じ

```js
[].concat(...[...document.all].map(e => [...e.childNodes]))
  .filter(n => n.nodeType === Node.TEXT_NODE)
  .map(n =>
    n.textContent = n.textContent.replace(/([a-zA-Z])/g, (_, c) =>
      c + [...Array(Math.floor(Math.random()*30))].map(() =>
            String.fromCharCode(0x300 + Math.floor(Math.random()*79))
          ).join('')
    )
  )
```

### `[].concat(...arrayOfArrays)`

(編集しました。元は `Array.prototype.concat.apply([], arrayOfArrays)` としていましたが、ほぼ同じ意味です)

Array.flatMap をしたい時はこうするしかありません。 
ふざけんな

配列の配列(`arrayOfArrays`)を全て結合して１つの配列にします。

(追記: いつの間にか `Array.prototype.flatMap` が標準に入ってました)

今回は全てのelementに対してそれぞれのchildNodeの配列を取得するので、Nodeの配列の配列が出来ます。これを単なるNodeの配列にするわけです。

### `[...iterableObject]`

`document.all` とか `element.childNodes` とかはただの`Iterable`であって`Array`ではないため、 `map` が出来ません。
そのため、上記のような spread operator (`...`) を配列リテラルに使うことで無理やりArrayにします。

### ページ内の全てのTextNodeを取得する

まとめると、以下でページ内の全てのTextNodeを取得することが出来ることになります。

```js
[].concat(...[...document.all].map(e => [...e.childNodes]))
  .filter(n => n.nodeType === Node.TEXT_NODE)
```

### `[...Array(n)]`

例えば、 `Array(10).forEach(() => console.log('foo'))` としても何も出力されません(`forEach`を`map`に変えても同じ)。
`Array.prototype.forEach` も `Array.prototype.map` も、値がまだ代入されていないインデックスに対してはcallbackは呼び出されないのです。

一方で、`[...Array(10)].forEach(() => console.log('foo'))` とすると "foo" が10回出力されます。
これは、 `Array.apply` に 
10個の`undefined` が引数として渡された結果
 `length`が`10`のものがargumentsとして渡された結果、0から9までのindexに　`undefined` が代入されたことになるからです。


(ここの解釈はちょっと合ってるか怪しい...)

### Combining character

http://www.unicode.org/charts/PDF/U0300.pdf

Unicodeには実にいろんな文字があります。
上記の U0300-U036F の範囲の文字は Combining character といって、直前の文字の上や下や真ん中にくっついてしまいます。
２文字以上の combining character が続くと、全ての combining character が前の文字にくっついて、上や下にズラーッと並んでしまいます。

スペースや日本語等の文字にはくっつかず、横に続いてしまうため、今回のスクリプトではアルファベットだけにくっつけるようにしています。
また、私の環境だと□になってしまったりしたので上記の文字のうち一部のみを使用しています。

## おまけ

特定の文字列だけ変換したいことってありますよね。この記事を書くときとか。

```js
'Any string here'.replace(/([a-zA-Z])/g, (_, c) => c + [...Array(Math.floor(Math.random()*30))].map(() => String.fromCharCode(0x300 + Math.floor(Math.random()*79))).join(''))
```


H̸̘̖̲̙̊̅̉̓̓̈́̏͋̕ȩ̨̡͈̰̟̹̝̒́̈̔̏̓̑̾ ẃ̶̷̨̢̢͎̟̦̺̗̥̗̘̓̓h̾ơ͈̯̭̝̞̊̃̎̉͊̾̾͆̂͂̚ W̸̶̷̢̟̲̙̮̫̭̫̾̇̆͌̆a̵̢̛̻̩̩̦̟͎̜͈̭͎̙̼͂̐̃̏̐̈́̇̇̚ī̤̫̘̈̑ṭ̸̢̛̟̰̖̝̬͎̥̝̀̏̅̎̇͋̀̈́̐̈́̓̎̑̂̓̚s̶̵̱̘̦̍͊ B̧̫̦̫̮̤̻̖̌̓e̷̛̳̮̺̤̳͎̮̳̲̐̎̔̋ͅh̶̹͍i̿̎̔̀ͅǹ̷͍̦̭̮̜̖̱̈̂̓̒͂̂ḑ̸̺̪̞̪̜̗̰̜̻̗̓̒̒̈́̍͊̏̄̉̒̍̾̽̌́̕ T̵̡̛̪̩̙̜́̌̅̃͂̏̾ḩ̸̞͈̞̯̥̣̹̩̫̤͂̇̀̀̾̇̆̔̽̎͊͆̄̾̂̚e̵̩̬͈̙̍̆͌̐ W̵̡̠̣̩̳̪͉̰̮̪̭̘̣̐́̈́̇̌͌̎́̐̂̎ͅa̡̢̩̯̘͎̻̺̹̞̔͊̽͋̏̐l̷̷̢̢̧̢̛̙̖̤̗̲̠̫̠̹̋̇̇́̚ĺ̴̵̴̸̻̗̬̪̙̠̥̘̙̙̆̃̋̉̑͌͌̾̄͆̚ͅ