Newer
Older
TriliumScripts / highlight_todotxt.js
0xRoM on 21 Mar 5 KB initial commit
  1. const TPL = `<div style="padding: 10px; border-top: 1px solid var(--main-border-color); contain: none;">
  2. <strong>Todo Highlighting Applied</strong>
  3. </div>`;
  4.  
  5. class MoodlogHighlighterWidget extends api.NoteContextAwareWidget {
  6. static get parentWidget() {
  7. //console.log("MDLG: Getting parent widget: center-pane");
  8. return 'center-pane';
  9. }
  10.  
  11. get position() {
  12. //console.log("MDLG: Setting position: 100");
  13. return 100;
  14. }
  15.  
  16. isEnabled() {
  17. const enabled = super.isEnabled()
  18. && this.note.type === 'text'
  19. && this.note.hasLabel('todotxt');
  20. //console.log(`MDLG: isEnabled: ${enabled}`);
  21. return enabled;
  22. }
  23.  
  24. doRender() {
  25. //console.log("MDLG: Rendering widget...");
  26. this.$widget = $(TPL);
  27. //console.log("MDLG: Widget rendered:", this.$widget);
  28. return this.$widget;
  29. }
  30.  
  31. async refreshWithNote(note) {
  32. //console.log("MDLG: Refreshing with note:", note);
  33. const { content } = await note.getNoteComplement();
  34. //console.log("MDLG: Note content fetched:", content);
  35.  
  36. // Check if content is fetched properly
  37. if (!content) {
  38. //console.log("MDLG: No content fetched. Exiting refresh.");
  39. return;
  40. }
  41.  
  42. const highlightedContent = this.applyHighlighting(content);
  43. //console.log("MDLG: Highlighted content:", highlightedContent);
  44.  
  45. if (highlightedContent !== content) {
  46. //console.log("MDLG: Updating note content with highlighted version");
  47.  
  48. // Use the setNoteContent function to update the note content
  49. try {
  50. await setNoteContent(note.noteId, highlightedContent);
  51. //console.log("MDLG: Content updated with highlighted version");
  52. } catch (error) {
  53. //console.error("MDLG: Error updating content:", error);
  54. }
  55. } else {
  56. //console.log("MDLG: No changes to content, skipping update.");
  57. }
  58. }
  59.  
  60.  
  61. applyHighlighting(content) {
  62. // Replace <br> with \n, then remove all other HTML tags
  63. const plainTextContent = content.replace(/<br\s*\/?\>/gi, '\n').replace(/<[^>]*>/g, ' ');
  64.  
  65. // Regular expressions for Todo.txt syntax
  66. const datePattern = /\b(0[1-9]|[12]\d|3[01])\/(0[1-9]|1[0-2])\/([1-2]\d{3})\b/g;
  67. const completedTaskPattern = /^\s*x\s+.*/g;
  68. const priorityPattern = /^(\s*\([A-E]\))\s+/;
  69. const projectPattern = /(?:\s|^)(\+\S+)/g;
  70. const contextPattern = /(?:\s|^)(@\S+)/g;
  71. const waitPattern = /\bWAIT\b/gi;
  72. const customAttributePattern = /(\s+[^\s:]+:[^\s:]+)+\s*$/g;
  73. function escapeHtml(str) {
  74. return str.replace(/[&<>"']/g, char => ({
  75. '&': '&amp;', '<': '&lt;', '>': '&gt;',
  76. '"': '&quot;', "'": '&#039;'
  77. })[char]);
  78. }
  79.  
  80. let highlightedLines = plainTextContent.split("\n").map(line => {
  81. // If line starts with 'x', make the whole line grey
  82. if (/^\s*x\s+/.test(line)) {
  83. return `<span style="color: grey;">${line}</span>`;
  84. }
  85. // Highlight priority with different colours based on level
  86. line = line.replace(priorityPattern, (match, priority) => {
  87. const level = priority.match(/[A-E]/)?.[0];
  88. const colors = {
  89. 'A': 'rgb(255, 0, 0)', // Red
  90. 'B': 'rgb(255, 102, 0)', // Orange
  91. 'C': 'rgb(255, 204, 0)', // Yellow
  92. 'D': 'rgb(0, 153, 255)', // Blue
  93. 'E': 'rgb(102, 204, 102)' // Green
  94. };
  95. const color = colors[level] || 'black';
  96. return `<span style="color: ${color}; font-weight: bold;">${escapeHtml(priority)}</span> `;
  97. });
  98. // Highlight date
  99. line = line.replace(datePattern, (match) => {
  100. return `<span style="color: rgb(188, 55, 237);">${escapeHtml(match)}</span>`;
  101. });
  102.  
  103. // Highlight project tags
  104. line = line.replace(projectPattern, (_, tag) => `<span style="color: rgb(224, 218, 36);"> ${escapeHtml(tag)}</span>`);
  105. // Highlight context tags
  106. line = line.replace(contextPattern, (_, tag) => `<span style="color: rgb(255, 165, 10);"> ${escapeHtml(tag)}</span>`);
  107. // Highlight WAIT command
  108. line = line.replace(waitPattern, `<span style="color: rgb(255, 69, 0);">WAIT</span>`);
  109. // Highlight custom attributes
  110. line = line.replace(customAttributePattern, `<span style="color: rgb(100, 149, 237);">$1</span>`);
  111. // Remove leading space (if any) from the beginning of the line, without affecting spaces before + or @
  112. line = line.replace(/^\s+/, '');
  113. return line.trim();
  114. });
  115.  
  116. return highlightedLines.join("<br>");
  117. }
  118.  
  119.  
  120.  
  121.  
  122.  
  123. async entitiesReloadedEvent({ loadResults }) {
  124. //console.log("MDLG: Entities reloaded event triggered");
  125. if (loadResults.isNoteContentReloaded(this.noteId)) {
  126. //console.log("MDLG: Note content reloaded, refreshing widget...");
  127. //this.refresh();
  128. } else {
  129. //console.log("MDLG: No content reload detected.");
  130. }
  131. }
  132.  
  133. }
  134.  
  135. console.log("TodoHighlight: Starting todotxt Highlighter Widget");
  136. module.exports = MoodlogHighlighterWidget;
  137.  
  138. function setNoteContent(noteId, content) {
  139. /*const noteElement = document.querySelector(`note-detail-readonly-text-content`);
  140.  
  141. if (noteElement) {
  142. noteElement.innerHTML = content; // Update the displayed content
  143. console.log(`MDLG: Updated note ${noteId} in the DOM.`);
  144. } else {
  145. console.warn(`MDLG: Note element with data-note-id='${noteId}' not found.`);
  146. }*/
  147. return api.runOnBackend((id, data) => api.getNote(id).setContent(data), [noteId, content]);
  148. }
Buy Me A Coffee