wysiwygエディタについての学習13


## draft-jsを使ってみる続き

### エンティティを取得してメタデータを参照する

https://draftjs.org/docs/advanced-topics-entities.html

```js
const linkInstance = this.state.editorState.getCurrentContent().getEntity(entityKey)
console.log(linkInstance.getData())
```

### insertAtomicBlockって。。

なんでkeyを返さないのか。。
ランダム生成して返り値はEditorStateなので、追加した後でkeyを探すのが難しい。。

### insertAtomicBlockの実行後のkeyの取得

追加したエントリーとブロックが行方不明なので取得したい。

```test.js
let entityKey = entityKeys['MEDIA']
let newEditorState = AtomicBlockUtils.insertAtomicBlock(this.state.editorState, entityKey, 'MEDIA')
let currentContent = newEditorState.getCurrentContent()
let currentSelection = newEditorState.getSelection()
let selectionBefore = currentContent.getSelectionBefore()
console.warn('================== start ==================')
console.warn(currentSelection)
console.warn(currentSelection.getStartKey())
console.warn(currentSelection.getEndKey())
console.warn(currentSelection.getAnchorKey())
console.warn(currentSelection.getFocusKey())
console.warn(currentContent)
console.warn(selectionBefore)
console.warn(selectionBefore.getAnchorKey())
console.warn(selectionBefore.getFocusKey())
console.warn('================== end ==================')

this.onChange(newEditorState)
```

試してみるが、シンプルにkeyがとれない。
難しさとしては下記

* 返り値がない
* 追加する際に既存ブロックを分割して２ブロックにしてその隙間に追加するため、結果ブロックが二つ増える
	* あ、でもそもそもブロックの使いどころを間違ってる面はあるのかも。
	* 既存ブロックへのエンティティと文字列のセットを追加すればいいのかも。
	* あ、この辺の使い分け難しそう。。ブロックって何のためだっけ。
* 次のブロックを取得みたいな関数はない

アイディア

* entityの差分を見る
* blockの差分を見る
* 追加前のカーソル位置を取得しておいて、加算してそのカーソルのオフセットから取得
* 次のブロックを取得みたいなことができる関数を作る

最後のやつが便利かな。。

### ブロックの必要性と意義

デフォルトでは改行するたびにブロックが生成される。
１行で１ブロックという考え方なのだろうか。
これは、エンティティで表現してはいけないのか。
簡単にエンティティとブロックの相互変換ができるならばあまり困らないかもしれないが。。

ブロックって何のため？

https://draftjs.org/docs/api-reference-content-block.html#content

キャラクタメタデータの説明の、軽快に済ませられるという部分に対しては、
ブロックごとにエンティティなどを保持しているということも寄与しているのかどうか。。

### 概念の呼び方

ContentBlockをChromeのReactのデバッグアドオンで見ると、DraftEditorBlockとかになってる。
コンポーネント名かな。。若干混乱した。
ほかにもそんな感じのが多い。DraftEntityInstanceとか。
おそらく古い仕様をひきづってるんだろう。

### コンテンツブロックまわりの動きがよくわからない

下記のように初期データを作るとブロックが２つに分かれる。
まずこれがなぜかわかってない。

```test.js
const sampleMarkup =
  '<b>Bold text</b>, <i>Italic text</i><br/ ><br />' +
  '<a href="http://www.facebook.com">Example link</a>'
const blocksFromHTML = convertFromHTML(sampleMarkup)
const state = ContentState.createFromBlockArray(
  blocksFromHTML.contentBlocks,
  blocksFromHTML.entityMap
)
this.state = {
  editorState: EditorState.createWithContent(state, onlyHashTags),
}
```

これかな。。
`genFragment()`がタグの断片化をする際に、独自ロジックでブロック分けとかしてるのかな。

```convertFromHTMLToContentBlocks.js
// save the last block so we can use it later
lastBlock = nodeName;

// BR tags
if (nodeName === 'br') {
	if (lastLastBlock === 'br' && (!inBlock || getBlockTypeForTag(inBlock, lastList, blockRenderMap) === 'unstyled')) {
	  return { chunk: getBlockDividerChunk('unstyled', depth), entityMap };
	}
	return { chunk: getSoftNewlineChunk(), entityMap };
}
```

初期描画の時には、重複した分の<br>タグが<span>タグにされている。

```html
<span data-offset-key="aoomk-0-3"><span data-text="true">

</span></span>
```

エディタ上で改行したときには下記になっている。
こちらは`DraftModifier.splitBlock()`を実行しているような気がするけど、`<br>`を挿入している箇所がわからん。

```html
<br data-text="true">
```

`getSoftNewlineChunk()`の評価がおかしいのかな。

描画の方ではIE対応で分岐があった。

```js:DraftEditorTextNode.react.js.flow
// In IE, spans with <br> tags render as two newlines. By rendering a span
// with only a newline character, we can be sure to render a single line.
const useNewlineChar = UserAgent.isBrowser('IE <= 11');

/**
 * Check whether the node should be considered a newline.
 */
function isNewline(node: Element): boolean {
  return useNewlineChar ? node.textContent === '\n' : node.tagName === 'BR';
}

/**
 * Placeholder elements for empty text content.
 *
 * What is this `data-text` attribute, anyway? It turns out that we need to
 * put an attribute on the lowest-level text node in order to preserve correct
 * spellcheck handling. If the <span> is naked, Chrome and Safari may do
 * bizarre things to do the DOM -- split text nodes, create extra spans, etc.
 * If the <span> has an attribute, this appears not to happen.
 * See http://jsfiddle.net/9khdavod/ for the failure case, and
 * http://jsfiddle.net/7pg143f7/ for the fixed case.
 */
const NEWLINE_A = useNewlineChar ? <span key="A" data-text="true">{'\n'}</span> : <br key="A" data-text="true" />;

const NEWLINE_B = useNewlineChar ? <span key="B" data-text="true">{'\n'}</span> : <br key="B" data-text="true" />;
```

### エンティティを探し出すデコレータ

探すの面倒。。うまくいかない。。

https://draftjs.org/docs/v0-10-api-migration.html#content

```js
function findLinkEntities(contentBlock, callback, contentState) {
  contentBlock.findEntityRanges(
    (character) => {
      const entityKey = character.getEntity();
      return (
        entityKey !== null &&
        contentState.getEntity(entityKey).getType() === 'LINK'
      );
    },
    callback,
  );
};
```

## デバッグ

### スタックトレースをconsole.logに渡したい

https://blog.yuyat.jp/post/supress-stack-trace/
http://www.enhgo.com/code/sails-custom-blueprint/

### ソースマップからwebpack前の行数を復元

source-map-supportはうまくいかない。fsが競合かな。
babel-loaderやreact-hot-loaderとの兼ね合いも難しそうなので時間をかけてから挫折

https://blog.odoruinu.net/2016/08/12/how-to-correctly-source-map-stacktrace/
https://qiita.com/pirosikick/items/13280be87e33d1fa0e68
https://github.com/evanw/node-source-map-support

mozilla/source-mapがベースらしい

多段SourceMapの対応方法とライブラリ | Web Scratch
http://efcl.info/2014/09/03/multi-stage-sourcemap/

Source Mapを扱う関連ライブラリのまとめ | Web Scratch
http://efcl.info/2014/0622/res3933/

他のライブラリなどで、、Error出力後に変換できないかなと
これはよさそうだけどcoffeeだな

https://github.com/alinex/node-error

開発時に結合しているから面倒なのかな。。