/** * Widget: Show highlighted text in the right pane * * By design there's no support for nonsensical or malformed constructs: * - For example, if there is a formula in the middle of the highlighted text, the two ends of the formula will be regarded as two entries */ import attributeService from "../services/attributes.js"; import RightPanelWidget from "./right_panel_widget.js"; import options from "../services/options.js"; import OnClickButtonWidget from "./buttons/onclick_button.js"; const TPL = `
`; export default class HighlightTextWidget extends RightPanelWidget { constructor() { super(); this.closeHltButton = new CloseHltButton(); this.child(this.closeHltButton); } get widgetTitle() { return "Highlighted Text"; } isEnabled() { return super.isEnabled() && this.note.type === 'text' && !this.noteContext.viewScope.highlightedTextTemporarilyHidden && this.noteContext.viewScope.viewMode === 'default'; } async doRenderBody() { this.$body.empty().append($(TPL)); this.$hlt = this.$body.find('.highlighted-text'); this.$body.find('.highlighted-text-widget').append(this.closeHltButton.render()); } async refreshWithNote(note) { /*The reason for adding highlightedTextTemporarilyHiddenPrevious is to record whether the previous state of the highlightedText is hidden or displayed, * and then let it be displayed/hidden at the initial time. * If there is no such value, when the right panel needs to display toc but not highlighttext, every time the note content is changed, * highlighttext Widget will appear and then close immediately, because getHlt function will consume time*/ if (this.noteContext.viewScope.highlightedTextTemporarilyHiddenPrevious == true) { this.toggleInt(true); } else { this.toggleInt(false); } const hltLabel = note.getLabel('hideHighlightWidget'); const optionsHlt = JSON.parse(options.get('highlightedText')); if (hltLabel?.value == "" || hltLabel?.value === "true" || optionsHlt == "") { this.toggleInt(false); this.triggerCommand("reEvaluateRightPaneVisibility"); return; } let $hlt = "", hltLiCount = -1; // Check for type text unconditionally in case alwaysShowWidget is set if (this.note.type === 'text') { const { content } = await note.getNoteComplement(); //hltColors/hltBgColors are the colors/background-color that appear in notes and in options ({ $hlt, hltLiCount } = await this.getHlt(content, optionsHlt)); } this.$hlt.html($hlt); if ([undefined, "false"].includes(hltLabel?.value) && hltLiCount > 0) { this.toggleInt(true); this.noteContext.viewScope.highlightedTextTemporarilyHiddenPrevious = true; } else { this.toggleInt(false); this.noteContext.viewScope.highlightedTextTemporarilyHiddenPrevious = false; } this.triggerCommand("reEvaluateRightPaneVisibility"); } /** * Builds a jquery table of helight text. */ getHlt(html, optionsHlt) { // element priority: span>i>strong>u // matches a span containing background-color const regex1 = /]*style\s*=\s*[^>]*background-color:[^>]*?>[\s\S]*?<\/span>/gi; // matches a span containing color const regex2 = /]*style\s*=\s*[^>]*[^-]color:[^>]*?>[\s\S]*?<\/span>/gi; // match italics const regex3 = /[\s\S]*?<\/i>/gi; // match bold const regex4 = /[\s\S]*?<\/strong>/gi; // match underline const regex5 = /[\s\S]*?<\/u>/g; // Possible values in optionsHlt: '["bold","italic","underline","color","bgColor"]' let findSubStr="", combinedRegexStr = ""; if (optionsHlt.indexOf("bgColor") >= 0){ findSubStr+=`,span[style*="background-color"]`; combinedRegexStr+=`|${regex1.source}`; } if (optionsHlt.indexOf("color") >= 0){ findSubStr+=`,span[style*="color"]`; combinedRegexStr+=`|${regex2.source}`; } if (optionsHlt.indexOf("italic") >= 0){ findSubStr+=`,i`; combinedRegexStr+=`|${regex3.source}`; } if (optionsHlt.indexOf("bold") >= 0){ findSubStr+=`,strong`; combinedRegexStr+=`|${regex4.source}`; } if (optionsHlt.indexOf("underline") >= 0){ findSubStr+=`,u`; combinedRegexStr+=`|${regex5.source}`; } findSubStr = findSubStr.substring(1) combinedRegexStr = `(` + combinedRegexStr.substring(1) + `)`; const combinedRegex = new RegExp(combinedRegexStr, 'gi'); let $hlt = $("