mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	Merge pull request #3988 from SiriusXT/Highlighted-Text
Show highlighted text in the right pane
This commit is contained in:
		
						commit
						eff3e1df85
					
				@ -44,6 +44,7 @@ import BacklinksWidget from "../widgets/floating_buttons/zpetne_odkazy.js";
 | 
				
			|||||||
import SharedInfoWidget from "../widgets/shared_info.js";
 | 
					import SharedInfoWidget from "../widgets/shared_info.js";
 | 
				
			||||||
import FindWidget from "../widgets/find.js";
 | 
					import FindWidget from "../widgets/find.js";
 | 
				
			||||||
import TocWidget from "../widgets/toc.js";
 | 
					import TocWidget from "../widgets/toc.js";
 | 
				
			||||||
 | 
					import HighlightedTextWidget from "../widgets/highlighted_text.js";
 | 
				
			||||||
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
 | 
					import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
 | 
				
			||||||
import AboutDialog from "../widgets/dialogs/about.js";
 | 
					import AboutDialog from "../widgets/dialogs/about.js";
 | 
				
			||||||
import HelpDialog from "../widgets/dialogs/help.js";
 | 
					import HelpDialog from "../widgets/dialogs/help.js";
 | 
				
			||||||
@ -184,6 +185,7 @@ export default class DesktopLayout {
 | 
				
			|||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    .child(new RightPaneContainer()
 | 
					                    .child(new RightPaneContainer()
 | 
				
			||||||
                        .child(new TocWidget())
 | 
					                        .child(new TocWidget())
 | 
				
			||||||
 | 
					                        .child(new HighlightedTextWidget())
 | 
				
			||||||
                        .child(...this.customWidgets.get('right-pane'))
 | 
					                        .child(...this.customWidgets.get('right-pane'))
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										255
									
								
								src/public/app/widgets/highlighted_text.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										255
									
								
								src/public/app/widgets/highlighted_text.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,255 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * 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 = `<div class="highlighted-text-widget">
 | 
				
			||||||
 | 
					    <style>
 | 
				
			||||||
 | 
					        .highlighted-text-widget {
 | 
				
			||||||
 | 
					            padding: 10px;
 | 
				
			||||||
 | 
					            contain: none; 
 | 
				
			||||||
 | 
					            overflow: auto;
 | 
				
			||||||
 | 
					            position: relative;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        .highlighted-text > ol {
 | 
				
			||||||
 | 
					            padding-left: 20px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        .highlighted-text li {
 | 
				
			||||||
 | 
					            cursor: pointer;
 | 
				
			||||||
 | 
					            margin-bottom: 3px;
 | 
				
			||||||
 | 
					            text-align: justify;
 | 
				
			||||||
 | 
					            text-justify: distribute;
 | 
				
			||||||
 | 
					            word-wrap: break-word;
 | 
				
			||||||
 | 
					            hyphens: auto;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        .highlighted-text li:hover {
 | 
				
			||||||
 | 
					            font-weight: bold;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        .close-highlighted-text {
 | 
				
			||||||
 | 
					            position: absolute;
 | 
				
			||||||
 | 
					            top: 2px;
 | 
				
			||||||
 | 
					            right: 2px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <span class="highlighted-text"></span>
 | 
				
			||||||
 | 
					</div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class HighlightedTextWidget 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 highlightedTextPreviousVisible 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.highlightedTextPreviousVisible == 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();
 | 
				
			||||||
 | 
					            ({ $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.highlightedTextPreviousVisible = true;
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            this.toggleInt(false);
 | 
				
			||||||
 | 
					            this.noteContext.viewScope.highlightedTextPreviousVisible = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.triggerCommand("reEvaluateRightPaneVisibility");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Builds a table of helight text.      
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    getHlt(html, optionsHlt) {
 | 
				
			||||||
 | 
					        // matches a span containing background-color
 | 
				
			||||||
 | 
					        const regex1 = /<span[^>]*style\s*=\s*[^>]*background-color:[^>]*?>[\s\S]*?<\/span>/gi; 
 | 
				
			||||||
 | 
					        // matches a span containing color
 | 
				
			||||||
 | 
					        const regex2 = /<span[^>]*style\s*=\s*[^>]*[^-]color:[^>]*?>[\s\S]*?<\/span>/gi;
 | 
				
			||||||
 | 
					        // match italics
 | 
				
			||||||
 | 
					        const regex3 = /<i>[\s\S]*?<\/i>/gi;
 | 
				
			||||||
 | 
					        // match bold
 | 
				
			||||||
 | 
					        const regex4 = /<strong>[\s\S]*?<\/strong>/gi;
 | 
				
			||||||
 | 
					        // match underline
 | 
				
			||||||
 | 
					        const regex5 = /<u>[\s\S]*?<\/u>/g;
 | 
				
			||||||
 | 
					        // Possible values in optionsHlt: '["bold","italic","underline","color","bgColor"]'
 | 
				
			||||||
 | 
					        // element priority: span>i>strong>u
 | 
				
			||||||
 | 
					        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 = $("<ol>");
 | 
				
			||||||
 | 
					        let prevEndIndex = -1, hltLiCount = 0;
 | 
				
			||||||
 | 
					        for (let match = null, hltIndex=0; ((match = combinedRegex.exec(html)) !== null); hltIndex++) {
 | 
				
			||||||
 | 
					            var subHtml = match[0];
 | 
				
			||||||
 | 
					            const startIndex = match.index;
 | 
				
			||||||
 | 
					            const endIndex = combinedRegex.lastIndex;
 | 
				
			||||||
 | 
					            if (prevEndIndex != -1 && startIndex === prevEndIndex) {
 | 
				
			||||||
 | 
					                //If the previous element is connected to this element in HTML, then concatenate them into one.
 | 
				
			||||||
 | 
					                $hlt.children().last().append(subHtml);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                //hide li if its text content is empty
 | 
				
			||||||
 | 
					                if ([...subHtml.matchAll(/(?<=^|>)[^><]+?(?=<|$)/g)].map(matchTmp => matchTmp[0]).join('').trim() != ""){
 | 
				
			||||||
 | 
					                    var $li = $('<li>');
 | 
				
			||||||
 | 
					                    $li.html(subHtml);
 | 
				
			||||||
 | 
					                    $li.on("click", () => this.jumpToHlt(findSubStr,hltIndex));
 | 
				
			||||||
 | 
					                    $hlt.append($li);
 | 
				
			||||||
 | 
					                    hltLiCount++;
 | 
				
			||||||
 | 
					                }else{
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            prevEndIndex = endIndex;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return {
 | 
				
			||||||
 | 
					            $hlt,
 | 
				
			||||||
 | 
					            hltLiCount
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    async jumpToHlt(findSubStr,hltIndex) {
 | 
				
			||||||
 | 
					        const isReadOnly = await this.noteContext.isReadOnly();
 | 
				
			||||||
 | 
					        let targetElement;
 | 
				
			||||||
 | 
					        if (isReadOnly) {
 | 
				
			||||||
 | 
					            const $container = await this.noteContext.getContentElement();
 | 
				
			||||||
 | 
					            targetElement=$container.find(findSubStr).filter(function() {
 | 
				
			||||||
 | 
					                if (findSubStr.indexOf("color")>=0 &&  findSubStr.indexOf("background-color")<0){
 | 
				
			||||||
 | 
					                    let color = this.style.color;
 | 
				
			||||||
 | 
					                    return $(this).prop('tagName')=="SPAN" && color==""?false:true;
 | 
				
			||||||
 | 
					                }else{
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }                
 | 
				
			||||||
 | 
					            }).filter(function() {
 | 
				
			||||||
 | 
					                return $(this).parent(findSubStr).length === 0 
 | 
				
			||||||
 | 
					                && $(this).parent().parent(findSubStr).length === 0
 | 
				
			||||||
 | 
					                && $(this).parent().parent().parent(findSubStr).length === 0
 | 
				
			||||||
 | 
					                && $(this).parent().parent().parent().parent(findSubStr).length === 0;
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            const textEditor = await this.noteContext.getTextEditor();
 | 
				
			||||||
 | 
					            targetElement=$(textEditor.editing.view.domRoots.values().next().value).find(findSubStr).filter(function() {
 | 
				
			||||||
 | 
					                // When finding span[style*="color"] but not looking for span[style*="background-color"], 
 | 
				
			||||||
 | 
					                // the background-color error will be regarded as color, so it needs to be filtered
 | 
				
			||||||
 | 
					                if (findSubStr.indexOf("color")>=0 &&  findSubStr.indexOf("background-color")<0){
 | 
				
			||||||
 | 
					                    let color = this.style.color;
 | 
				
			||||||
 | 
					                    return $(this).prop('tagName')=="SPAN" && color==""?false:true;
 | 
				
			||||||
 | 
					                }else{
 | 
				
			||||||
 | 
					                    return true;
 | 
				
			||||||
 | 
					                }                
 | 
				
			||||||
 | 
					            }).filter(function() {
 | 
				
			||||||
 | 
					                //Need to filter out the child elements of the element that has been found
 | 
				
			||||||
 | 
					                return $(this).parent(findSubStr).length === 0 
 | 
				
			||||||
 | 
					                && $(this).parent().parent(findSubStr).length === 0
 | 
				
			||||||
 | 
					                && $(this).parent().parent().parent(findSubStr).length === 0
 | 
				
			||||||
 | 
					                && $(this).parent().parent().parent().parent(findSubStr).length === 0;
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        targetElement[hltIndex].scrollIntoView({
 | 
				
			||||||
 | 
					            behavior: "smooth", block: "center"
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async closeHltCommand() {
 | 
				
			||||||
 | 
					        this.noteContext.viewScope.highlightedTextTemporarilyHidden = true;
 | 
				
			||||||
 | 
					        await this.refresh();
 | 
				
			||||||
 | 
					        this.triggerCommand('reEvaluateRightPaneVisibility');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async entitiesReloadedEvent({ loadResults }) {
 | 
				
			||||||
 | 
					        if (loadResults.isNoteContentReloaded(this.noteId)) {
 | 
				
			||||||
 | 
					            await this.refresh();
 | 
				
			||||||
 | 
					        } else if (loadResults.getAttributes().find(attr => attr.type === 'label'
 | 
				
			||||||
 | 
					            && (attr.name.toLowerCase().includes('readonly') || attr.name === 'hideHighlightWidget')
 | 
				
			||||||
 | 
					            && attributeService.isAffecting(attr, this.note))) {
 | 
				
			||||||
 | 
					            await this.refresh();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class CloseHltButton extends OnClickButtonWidget {
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        this.icon("bx-x")
 | 
				
			||||||
 | 
					            .title("Close HighlightedTextWidget")
 | 
				
			||||||
 | 
					            .titlePlacement("bottom")
 | 
				
			||||||
 | 
					            .onClick((widget, e) => {
 | 
				
			||||||
 | 
					                e.stopPropagation();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                widget.triggerCommand("closeHlt");
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .class("icon-action close-highlighted-text");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -38,6 +38,10 @@ const TPL = `<div class="toc-widget">
 | 
				
			|||||||
        
 | 
					        
 | 
				
			||||||
        .toc li {
 | 
					        .toc li {
 | 
				
			||||||
            cursor: pointer;
 | 
					            cursor: pointer;
 | 
				
			||||||
 | 
					            text-align: justify;
 | 
				
			||||||
 | 
					            text-justify: distribute;
 | 
				
			||||||
 | 
					            word-wrap: break-word;
 | 
				
			||||||
 | 
					            hyphens: auto;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        .toc li:hover {
 | 
					        .toc li:hover {
 | 
				
			||||||
@ -80,6 +84,16 @@ export default class TocWidget extends RightPanelWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async refreshWithNote(note) {
 | 
					    async refreshWithNote(note) {
 | 
				
			||||||
 | 
					        /*The reason for adding tocPreviousVisible is to record whether the previous state of the toc 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 highlighttext but not toc, every time the note content is changed, 
 | 
				
			||||||
 | 
					        * toc will appear and then close immediately, because getToc(html) function will consume time*/
 | 
				
			||||||
 | 
					        if (this.noteContext.viewScope.tocPreviousVisible ==true){
 | 
				
			||||||
 | 
					            this.toggleInt(true);
 | 
				
			||||||
 | 
					        }else{
 | 
				
			||||||
 | 
					            this.toggleInt(false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const tocLabel = note.getLabel('toc');
 | 
					        const tocLabel = note.getLabel('toc');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (tocLabel?.value === 'hide') {
 | 
					        if (tocLabel?.value === 'hide') {
 | 
				
			||||||
@ -96,10 +110,13 @@ export default class TocWidget extends RightPanelWidget {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.$toc.html($toc);
 | 
					        this.$toc.html($toc);
 | 
				
			||||||
        this.toggleInt(
 | 
					        if (["", "show"].includes(tocLabel?.value) || headingCount >= options.getInt('minTocHeadings')){
 | 
				
			||||||
            ["", "show"].includes(tocLabel?.value)
 | 
					            this.toggleInt(true);
 | 
				
			||||||
            || headingCount >= options.getInt('minTocHeadings')
 | 
					            this.noteContext.viewScope.tocPreviousVisible=true;  
 | 
				
			||||||
        );
 | 
					        }else{
 | 
				
			||||||
 | 
					            this.toggleInt(false);
 | 
				
			||||||
 | 
					            this.noteContext.viewScope.tocPreviousVisible=false;  
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.triggerCommand("reEvaluateRightPaneVisibility");
 | 
					        this.triggerCommand("reEvaluateRightPaneVisibility");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@ import MaxContentWidthOptions from "./options/appearance/max_content_width.js";
 | 
				
			|||||||
import KeyboardShortcutsOptions from "./options/shortcuts.js";
 | 
					import KeyboardShortcutsOptions from "./options/shortcuts.js";
 | 
				
			||||||
import HeadingStyleOptions from "./options/text_notes/heading_style.js";
 | 
					import HeadingStyleOptions from "./options/text_notes/heading_style.js";
 | 
				
			||||||
import TableOfContentsOptions from "./options/text_notes/table_of_contents.js";
 | 
					import TableOfContentsOptions from "./options/text_notes/table_of_contents.js";
 | 
				
			||||||
 | 
					import HighlightedTextOptions from "./options/text_notes/highlighted_text.js";
 | 
				
			||||||
import TextAutoReadOnlySizeOptions from "./options/text_notes/text_auto_read_only_size.js";
 | 
					import TextAutoReadOnlySizeOptions from "./options/text_notes/text_auto_read_only_size.js";
 | 
				
			||||||
import VimKeyBindingsOptions from "./options/code_notes/vim_key_bindings.js";
 | 
					import VimKeyBindingsOptions from "./options/code_notes/vim_key_bindings.js";
 | 
				
			||||||
import WrapLinesOptions from "./options/code_notes/wrap_lines.js";
 | 
					import WrapLinesOptions from "./options/code_notes/wrap_lines.js";
 | 
				
			||||||
@ -61,6 +62,7 @@ const CONTENT_WIDGETS = {
 | 
				
			|||||||
    _optionsTextNotes: [
 | 
					    _optionsTextNotes: [
 | 
				
			||||||
        HeadingStyleOptions,
 | 
					        HeadingStyleOptions,
 | 
				
			||||||
        TableOfContentsOptions,
 | 
					        TableOfContentsOptions,
 | 
				
			||||||
 | 
					        HighlightedTextOptions,
 | 
				
			||||||
        TextAutoReadOnlySizeOptions
 | 
					        TextAutoReadOnlySizeOptions
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    _optionsCodeNotes: [
 | 
					    _optionsCodeNotes: [
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					import OptionsWidget from "../options_widget.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const TPL = `
 | 
				
			||||||
 | 
					<div class="options-section">
 | 
				
			||||||
 | 
					    <h4>Highlighted Text</h4>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    You can customize the highlighted text displayed in the right panel:<br>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<label><input type="checkbox" class="highlighted-text-check" value="bold"> Bold font  </label>
 | 
				
			||||||
 | 
					<label><input type="checkbox" class="highlighted-text-check" value="italic"> Italic font  </label>
 | 
				
			||||||
 | 
					<label><input type="checkbox" class="highlighted-text-check" value="underline"> Underlined font  </label>
 | 
				
			||||||
 | 
					<label><input type="checkbox" class="highlighted-text-check" value="color"> Font with color  </label>
 | 
				
			||||||
 | 
					<label><input type="checkbox" class="highlighted-text-check" value="bgColor"> Font with background color  </label>
 | 
				
			||||||
 | 
					</div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class HighlightedTextOptions extends OptionsWidget {
 | 
				
			||||||
 | 
					    doRender() {
 | 
				
			||||||
 | 
					        this.$widget = $(TPL);
 | 
				
			||||||
 | 
					        this.$hlt = this.$widget.find("input.highlighted-text-check");
 | 
				
			||||||
 | 
					        this.$hlt.on('change', () => {
 | 
				
			||||||
 | 
					            const hltVals=this.$widget.find('input.highlighted-text-check[type="checkbox"]:checked').map(function() {
 | 
				
			||||||
 | 
					                return this.value;
 | 
				
			||||||
 | 
					              }).get();
 | 
				
			||||||
 | 
					            this.updateOption('highlightedText', JSON.stringify(hltVals));
 | 
				
			||||||
 | 
					            });        
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async optionsLoaded(options) {
 | 
				
			||||||
 | 
					        const hltVals=JSON.parse(options.highlightedText);
 | 
				
			||||||
 | 
					        this.$widget.find('input.highlighted-text-check[type="checkbox"]').each(function () {
 | 
				
			||||||
 | 
					            if ($.inArray($(this).val(), hltVals) !== -1) {
 | 
				
			||||||
 | 
					                    $(this).prop("checked", true);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                    $(this).prop("checked", false);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -60,6 +60,7 @@ const ALLOWED_OPTIONS = new Set([
 | 
				
			|||||||
    'compressImages',
 | 
					    'compressImages',
 | 
				
			||||||
    'downloadImagesAutomatically',
 | 
					    'downloadImagesAutomatically',
 | 
				
			||||||
    'minTocHeadings',
 | 
					    'minTocHeadings',
 | 
				
			||||||
 | 
					    'highlightedText',
 | 
				
			||||||
    'checkForUpdates',
 | 
					    'checkForUpdates',
 | 
				
			||||||
    'disableTray',
 | 
					    'disableTray',
 | 
				
			||||||
    'customSearchEngineName',
 | 
					    'customSearchEngineName',
 | 
				
			||||||
 | 
				
			|||||||
@ -87,6 +87,7 @@ const defaultOptions = [
 | 
				
			|||||||
    { name: 'compressImages', value: 'true', isSynced: true },
 | 
					    { name: 'compressImages', value: 'true', isSynced: true },
 | 
				
			||||||
    { name: 'downloadImagesAutomatically', value: 'true', isSynced: true },
 | 
					    { name: 'downloadImagesAutomatically', value: 'true', isSynced: true },
 | 
				
			||||||
    { name: 'minTocHeadings', value: '5', isSynced: true },
 | 
					    { name: 'minTocHeadings', value: '5', isSynced: true },
 | 
				
			||||||
 | 
					    { name: 'highlightedText', value: '["bold","italic","underline","color","bgColor"]', isSynced: true },
 | 
				
			||||||
    { name: 'checkForUpdates', value: 'true', isSynced: true },
 | 
					    { name: 'checkForUpdates', value: 'true', isSynced: true },
 | 
				
			||||||
    { name: 'disableTray', value: 'false', isSynced: false },
 | 
					    { name: 'disableTray', value: 'false', isSynced: false },
 | 
				
			||||||
    { name: 'customSearchEngineName', value: 'Duckduckgo', isSynced: false },
 | 
					    { name: 'customSearchEngineName', value: 'Duckduckgo', isSynced: false },
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user