abstract_highlighter.js 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import * as XpathUtil from '../common/xpath_util.js';
  2. import { addPrefix, Attribute } from '../enrich_mathml/enrich_attr.js';
  3. let counter = 0;
  4. export class AbstractHighlighter {
  5. constructor() {
  6. this.counter = counter++;
  7. this.ATTR = 'sre-highlight-' + this.counter.toString();
  8. this.color = null;
  9. this.mactionName = '';
  10. this.currentHighlights = [];
  11. }
  12. highlight(nodes) {
  13. this.currentHighlights.push(nodes.map((node) => {
  14. const info = this.highlightNode(node);
  15. this.setHighlighted(node);
  16. return info;
  17. }));
  18. }
  19. highlightAll(node) {
  20. const mactions = this.getMactionNodes(node);
  21. for (let i = 0, maction; (maction = mactions[i]); i++) {
  22. this.highlight([maction]);
  23. }
  24. }
  25. unhighlight() {
  26. const nodes = this.currentHighlights.pop();
  27. if (!nodes) {
  28. return;
  29. }
  30. nodes.forEach((highlight) => {
  31. if (this.isHighlighted(highlight.node)) {
  32. this.unhighlightNode(highlight);
  33. this.unsetHighlighted(highlight.node);
  34. }
  35. });
  36. }
  37. unhighlightAll() {
  38. while (this.currentHighlights.length > 0) {
  39. this.unhighlight();
  40. }
  41. }
  42. setColor(color) {
  43. this.color = color;
  44. }
  45. colorString() {
  46. return this.color.rgba();
  47. }
  48. addEvents(node, events) {
  49. const mactions = this.getMactionNodes(node);
  50. for (let i = 0, maction; (maction = mactions[i]); i++) {
  51. for (const [key, event] of Object.entries(events)) {
  52. maction.addEventListener(key, event);
  53. }
  54. }
  55. }
  56. getMactionNodes(node) {
  57. return Array.from(node.getElementsByClassName(this.mactionName));
  58. }
  59. isMactionNode(node) {
  60. const className = node.className || node.getAttribute('class');
  61. return className ? !!className.match(new RegExp(this.mactionName)) : false;
  62. }
  63. isHighlighted(node) {
  64. return node.hasAttribute(this.ATTR);
  65. }
  66. setHighlighted(node) {
  67. node.setAttribute(this.ATTR, 'true');
  68. }
  69. unsetHighlighted(node) {
  70. node.removeAttribute(this.ATTR);
  71. }
  72. colorizeAll(node) {
  73. XpathUtil.updateEvaluator(node);
  74. const allNodes = XpathUtil.evalXPath(`.//*[@${Attribute.ID}]`, node);
  75. allNodes.forEach((x) => this.colorize(x));
  76. }
  77. uncolorizeAll(node) {
  78. const allNodes = XpathUtil.evalXPath(`.//*[@${Attribute.ID}]`, node);
  79. allNodes.forEach((x) => this.uncolorize(x));
  80. }
  81. colorize(node) {
  82. const fore = addPrefix('foreground');
  83. if (node.hasAttribute(fore)) {
  84. node.setAttribute(fore + '-old', node.style.color);
  85. node.style.color = node.getAttribute(fore);
  86. }
  87. }
  88. uncolorize(node) {
  89. const fore = addPrefix('foreground') + '-old';
  90. if (node.hasAttribute(fore)) {
  91. node.style.color = node.getAttribute(fore);
  92. }
  93. }
  94. }