OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library trydart.htmlToText; | 5 library trydart.htmlToText; |
6 | 6 |
7 import 'dart:math' show | 7 import 'dart:math' show |
8 max; | 8 max; |
9 | 9 |
10 import 'dart:html'; | 10 import 'dart:html' show |
| 11 Element, |
| 12 Node, |
| 13 NodeFilter, |
| 14 Text, |
| 15 TreeWalker; |
| 16 |
| 17 import 'selection.dart' show |
| 18 TrySelection; |
11 | 19 |
12 /// Returns true if [node] is a block element, that is, not inline. | 20 /// Returns true if [node] is a block element, that is, not inline. |
13 bool isBlockElement(Node node) { | 21 bool isBlockElement(Node node) { |
14 if (node is! Element) return false; | 22 if (node is! Element) return false; |
15 Element element = node; | 23 Element element = node; |
16 return element.getComputedStyle().display != 'inline'; | 24 return element.getComputedStyle().display != 'inline'; |
17 } | 25 } |
18 | 26 |
19 /// Position [walker] at the last predecessor (that is, child of child of | 27 /// Position [walker] at the last predecessor (that is, child of child of |
20 /// child...) of [node]. The next call to walker.nextNode will return the first | 28 /// child...) of [node]. The next call to walker.nextNode will return the first |
21 /// node after [node]. | 29 /// node after [node]. |
22 void skip(Node node, TreeWalker walker) { | 30 void skip(Node node, TreeWalker walker) { |
23 if (walker.nextSibling() != null) { | 31 if (walker.nextSibling() != null) { |
24 walker.previousNode(); | 32 walker.previousNode(); |
25 return; | 33 return; |
26 } | 34 } |
27 for (Node current = walker.nextNode(); | 35 for (Node current = walker.nextNode(); |
28 current != null; | 36 current != null; |
29 current = walker.nextNode()) { | 37 current = walker.nextNode()) { |
30 if (!node.contains(current)) { | 38 if (!node.contains(current)) { |
31 walker.previousNode(); | 39 walker.previousNode(); |
32 return; | 40 return; |
33 } | 41 } |
34 } | 42 } |
35 } | 43 } |
36 | 44 |
37 /// Writes the text of [root] to [buffer]. Keeps track of [selection] and | 45 /// Writes the text of [root] to [buffer]. Keeps track of [selection] and |
38 /// returns the new anchorOffset from beginning of [buffer] or -1 if the | 46 /// returns the new anchorOffset from beginning of [buffer] or -1 if the |
39 /// selection isn't in [root]. | 47 /// selection isn't in [root]. |
40 int htmlToText(Node root, StringBuffer buffer, Selection selection) { | 48 int htmlToText(Node root, StringBuffer buffer, TrySelection selection) { |
41 int selectionOffset = -1; | 49 int selectionOffset = -1; |
42 TreeWalker walker = new TreeWalker(root, NodeFilter.SHOW_ALL); | 50 TreeWalker walker = new TreeWalker(root, NodeFilter.SHOW_ALL); |
43 | 51 |
44 for (Node node = root; node != null; node = walker.nextNode()) { | 52 for (Node node = root; node != null; node = walker.nextNode()) { |
45 switch (node.nodeType) { | 53 switch (node.nodeType) { |
46 case Node.CDATA_SECTION_NODE: | 54 case Node.CDATA_SECTION_NODE: |
47 case Node.TEXT_NODE: | 55 case Node.TEXT_NODE: |
48 if (selection.isCollapsed && selection.anchorNode == node) { | 56 if (selection.anchorNode == node) { |
49 selectionOffset = selection.anchorOffset + buffer.length; | 57 selectionOffset = selection.anchorOffset + buffer.length; |
50 } | 58 } |
51 Text text = node; | 59 Text text = node; |
52 buffer.write(text.data.replaceAll('\xA0', ' ')); | 60 buffer.write(text.data.replaceAll('\xA0', ' ')); |
53 break; | 61 break; |
54 | 62 |
55 default: | 63 default: |
56 if (node.nodeName == 'BR') { | 64 if (node.nodeName == 'BR') { |
57 buffer.write('\n'); | 65 buffer.write('\n'); |
58 } else if (node != root && isBlockElement(node)) { | 66 } else if (node != root && isBlockElement(node)) { |
59 selectionOffset = | 67 selectionOffset = |
60 max(selectionOffset, htmlToText(node, buffer, selection)); | 68 max(selectionOffset, htmlToText(node, buffer, selection)); |
61 skip(node, walker); | 69 skip(node, walker); |
62 } | 70 } |
63 break; | 71 break; |
64 } | 72 } |
65 } | 73 } |
66 | 74 |
67 if (isBlockElement(root)) { | 75 if (isBlockElement(root)) { |
68 buffer.write('\n'); | 76 buffer.write('\n'); |
69 } | 77 } |
70 | 78 |
71 return selectionOffset; | 79 return selectionOffset; |
72 } | 80 } |
OLD | NEW |