回答編集履歴

1

実装案を追記

2017/03/26 03:51

投稿

think49
think49

スコア18162

test CHANGED
@@ -2,17 +2,35 @@
2
2
 
3
3
 
4
4
 
5
- 技術的には可能ですが、要件だけ出して「教えてください」といえる難易度の問題ではないように思います。
5
+ 技術的には可能ですが、要件だけ出して「教えてください」といえる難易度の問題ではないように思います。
6
6
 
7
7
 
8
8
 
9
- - `<span>あいう</span><span>えお</span>` に対して検索語「あいうえお」がマッチしなければならない(MUST)
9
+ 1. `<span>あいう</span><span>えお</span>` に対して検索語「あいうえお」がマッチしなければならない(MUST)
10
10
 
11
- - `<span>あいう</span><span>えお</span>` に対して検索語「うえ」がマッチしなければならない(MUST)
11
+ 2. `<span>あいう</span><span>えお</span>` に対して検索語「うえ」がマッチしなければならない(MUST)
12
12
 
13
- - `<span title="すくりぷと">Script</span>` に対して検索語「すくりぷと」がマッチしてはならない(MUST NOT)
13
+ 3. `<span title="すくりぷと">Script</span>` に対して検索語「すくりぷと」がマッチしてはならない(MUST NOT)
14
14
 
15
- - `<h1>サンプル</h1><p>これはテストです。</p>` に対して「検索語「サンプルこれはテストです。」がマッチしてはならない(MUST NOT)
15
+ 4. `<h1>サンプル</h1><p>これはテストです。</p>` に対して「検索語「サンプルこれはテストです。」がマッチしてはならない(MUST NOT)
16
+
17
+
18
+
19
+ 上記例題は次のDOMを出力する事を期待します。
20
+
21
+
22
+
23
+ 1. `<span><mark class="highlight">あいう</mark></span><span><mark class="highlight">えお</mark></span>` もしくは `<mark class="highlight"><span>あいう</span><span>えお</span></mark>`
24
+
25
+ 2. `<span>あい<mark class="highlight">う</mark></span><span><mark class="highlight">え</mark>お</span>`
26
+
27
+ 3. マッチしない
28
+
29
+ 4. マッチしない
30
+
31
+
32
+
33
+ ※1. は後者がすっきりしていますが、2. の処理を入れることを踏まえると前者の方がコードを書きやすいかもしれません。
16
34
 
17
35
 
18
36
 
@@ -20,17 +38,29 @@
20
38
 
21
39
 
22
40
 
23
- 正規表現でタグの対応関係、インラインボックスのタグだけ抽出する実装は複雑化するので DOM API で実装するのが無難だと思います。
41
+ 正規表現でタグの対応関係、インラインボックスのタグだけ抽出する実装は複雑化してしまいます。
42
+
43
+ 以下にDOM API で実装する手順を書きます。
24
44
 
25
45
 
26
46
 
27
- 1. `document.evaluate` で検索語の1文字目となるテキストノードを検索
47
+ 1. `document.evaluate` で検索語の1文字目となるテキストノードを検索(参考: https://teratail.com/questions/31198)
28
48
 
29
49
  2. テキストノード内の文字列を1文字ずつ検索し、テキストノード内に検索語の前方一致語区を発見したら、`createElement` で mark 要素を生成し、`appendChild` でテキストノードを挿入後に `replaceChild` で置換する
30
50
 
31
- 3. テキストノード内に検索語が部分一致で見つかったら処理を終了し、前方一致で見つかったら {parentNode` の `computedStyle` の `display` プロパティが `inline` もしくは `inline^bloxk` の場合に 4. の処理へ進み、そうでないなら終了する
51
+ 3. テキストノード内に検索語が部分一致で見つかったら処理を終了し、前方一致で見つかったら 4. へ進
32
52
 
53
+ 4. `element.parentNode` で親要素を参照し、`computedStyle` の `display` プロパティが `inline` もしくは `inline-block` の場合に 5. へ進み、そうでないなら終了する
54
+
55
+ 5. `element.nextSibling` が存在しないなら 4.へ戻り、存在するなら `element.nextSibling` を参照して 6. へ進む
56
+
33
- 4. ...
57
+ 6. `element.nodeType` がテキストノードならまだマッチしていない検索語を対象にして 3. へ戻り、要素ノードなら 7. へ進む
58
+
59
+ 7. `element.firstChild` の `nodeType` がテキストノードになるまで `firstChild` を参照し続け、テキストノードを発見したら 6. へ戻り、 `firstChild` が `null` になるまで参照し続けたら終了する
60
+
61
+
62
+
63
+ コメントノードの読み飛ばし等、細かな例外処理はありますが、大まかにはこんな流れで実装可能だと思います。
34
64
 
35
65
 
36
66