Guest User

Untitled

a guest
Oct 21st, 2017
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.04 KB | None | 0 0
  1. function isBlock(node) {
  2. if (node.nodeType !== Node.ELEMENT_NODE) return false;
  3. return /^(ADDRESS|ARTICLE|ASIDE|BLOCKQUOTE|CANVAS|DD|DIV|DL|DT|FIELDSET|FIGCAPTION|FIGURE|FOOTER|FORM|H1|H2|H3|H4|H5|H6|HEADER|HGROUP|HR|LI|MAIN|NAV|NOSCRIPT|OL|OUTPUT|P|PRE|SECTION|TABLE|TFOOT|UL|VIDEO)$/.test(node.nodeName);
  4. }
  5.  
  6. function createPseudoParagraph(node) {
  7. return { nodeName: "PSEUDO_PARAGRAPH", childNodes: [node] };
  8. }
  9.  
  10. function createBrBlock(nodes) {
  11. return { nodeName: "BR_BLOCK", childNodes: nodes };
  12. }
  13.  
  14. function getBoundingRect(node) {
  15. const rect = node.getBoundingClientRect();
  16. return {
  17. left: rect.left + window.pageXOffset,
  18. top: rect.top + window.pageYOffset,
  19. width: rect.width,
  20. height: rect.height,
  21. };
  22. }
  23.  
  24. function brbrTextToParagraphs(node) {
  25. // 空白、コメントを消す
  26. const nodes = [...node.childNodes || []].filter(n => {
  27. if (n.nodeType === Node.ELEMENT_NODE) return true;
  28. return n.nodeType === Node.TEXT_NODE && !!(n.nodeValue || "").trim();
  29. });
  30. // とりあえず普通のブロック要素と、PSEUDO_PARAGRAPH(text + インライン要素), BR_BLOCK(brが2個以上続いているやつ)に分割
  31. const paragraphs = [];
  32. let idx = 0;
  33. for (let i = 0; i < nodes.length; ++i) {
  34. const _node = nodes[i];
  35. if (_node.nodeName === "BR") {
  36. const ii = nodes.slice(i + 1).findIndex(n => n.nodeName !== "BR");
  37. if (ii === -1) {
  38. paragraphs.push(createBrBlock(nodes.slice(i)));
  39. break;
  40. } else if (ii > 0) {
  41. paragraphs.push(createBrBlock(nodes.slice(i, i + ii + 1)));
  42. idx += 2;
  43. i += ii;
  44. } else {
  45. if (!paragraphs[idx]) {
  46. paragraphs[idx] = createPseudoParagraph(_node);
  47. } else {
  48. paragraphs[idx].childNodes.push(_node);
  49. }
  50. }
  51. } else if (isBlock(_node)) {
  52. paragraphs.push(_node);
  53. idx += 2;
  54. } else {
  55. if (!paragraphs[idx]) {
  56. paragraphs[idx] = createPseudoParagraph(_node);
  57. } else {
  58. paragraphs[idx].childNodes.push(_node);
  59. }
  60. }
  61. }
  62. // 位置計算
  63. let rect = getBoundingRect(node);
  64. // まずは普通のブロック要素と、BR_BLOCKの箱を決定する
  65. for (let i = 0; i < paragraphs.length; ++i) {
  66. const _node = paragraphs[i];
  67. if (isBlock(_node)) {
  68. _node._rect = getBoundingRect(_node);
  69. } else if (_node.nodeName === "BR_BLOCK") {
  70. const first = getBoundingRect(_node.childNodes[0]);
  71. const last = getBoundingRect(_node.childNodes[_node.childNodes.length - 1]);
  72. const top = first.top + last.height;
  73. _node._rect = {
  74. left: first.left,
  75. top,
  76. width: 0,
  77. height: last.top + last.height - top,
  78. };
  79. }
  80. }
  81. // PSEUDO_PARAGRAPHの箱を前後関係から決定する
  82. for (let i = 0; i < paragraphs.length; ++i) {
  83. const _node = paragraphs[i];
  84. if (_node.nodeName !== "PSEUDO_PARAGRAPH" || _node.childNodes.every(x => x.nodeName === "BR")) continue;
  85. // top
  86. const first = _node.childNodes[0];
  87. let top = 0;
  88. if (first.nodeName === "BR") {
  89. _node.childNodes.shift();
  90. const r = getBoundingRect(first);
  91. top = r.top + r.height;
  92. } else if (first.nodeType !== Node.TEXT_NODE) {
  93. const r = getBoundingRect(first);
  94. top = r.top;
  95. } else {
  96. const prev = paragraphs[i - 1];
  97. top = prev ? prev._rect.top + prev._rect.height : rect.top;
  98. }
  99. // height
  100. const last = _node.childNodes[_node.childNodes.length - 1];
  101. let height = 0;
  102. if (last.nodeName === "BR") {
  103. _node.childNodes.pop();
  104. const r = getBoundingRect(last);
  105. height = r.top + r.height - top;
  106. } else if (last.nodeType !== Node.TEXT_NODE) {
  107. const r = getBoundingRect(last);
  108. height = r.top + r.height - top;
  109. } else {
  110. const next = paragraphs[i + 1];
  111. height = (next ? next._rect.top : rect.top + rect.height) - top;
  112. }
  113. _node._rect = {
  114. left: rect.left,
  115. width: rect.width,
  116. top,
  117. height,
  118. };
  119. }
  120. return paragraphs.filter(node => node.nodeType === Node.ELEMENT_NODE || !node.childNodes.every(x => x.nodeName === "BR"));
  121. }
Add Comment
Please, Sign In to add comment