From 86861f6ec36b6015c20dd0b4529b627fc8f92667 Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Wed, 31 May 2023 18:32:33 +0800
Subject: [PATCH 01/10] Show highlighted text in the left pane
---
src/public/app/layouts/desktop_layout.js | 2 +
src/public/app/widgets/highlighted_text.js | 267 ++++++++++++++++++
.../widgets/type_widgets/content_widget.js | 2 +
.../options/text_notes/highlighted_text.js | 90 ++++++
src/routes/api/options.js | 2 +
src/services/options_init.js | 2 +
6 files changed, 365 insertions(+)
create mode 100644 src/public/app/widgets/highlighted_text.js
create mode 100644 src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js
index 17dcc99a7..3a9ec2930 100644
--- a/src/public/app/layouts/desktop_layout.js
+++ b/src/public/app/layouts/desktop_layout.js
@@ -44,6 +44,7 @@ import BacklinksWidget from "../widgets/floating_buttons/zpetne_odkazy.js";
import SharedInfoWidget from "../widgets/shared_info.js";
import FindWidget from "../widgets/find.js";
import TocWidget from "../widgets/toc.js";
+import HltWidget from "../widgets/highlighted_text.js";
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
import AboutDialog from "../widgets/dialogs/about.js";
import HelpDialog from "../widgets/dialogs/help.js";
@@ -181,6 +182,7 @@ export default class DesktopLayout {
)
.child(new RightPaneContainer()
.child(new TocWidget())
+ .child(new HltWidget())
.child(...this.customWidgets.get('right-pane'))
)
)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
new file mode 100644
index 000000000..3dbfc9b5c
--- /dev/null
+++ b/src/public/app/widgets/highlighted_text.js
@@ -0,0 +1,267 @@
+/**
+ * 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 HltWidget 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.hltTemporarilyHidden
+ && this.noteContext.viewScope.viewMode === 'default';
+ }
+
+ async doRenderBody() {
+ this.$body.empty().append($(TPL));
+ this.$hlt = this.$body.find('.hlt');
+ this.$body.find('.hlt-widget').append(this.closeHltButton.render());
+ }
+
+ async refreshWithNote(note) {
+ const hltLabel = note.getLabel('hlt');
+
+ if (hltLabel?.value === 'hide') {
+ this.toggleInt(false);
+ this.triggerCommand("reEvaluateRightPaneVisibility");
+ return;
+ }
+
+ let $hlt = "", hltColors = [], hltBgColors = [];
+
+ let optionsHltColors = JSON.parse(options.get('highlightedTextColors'));
+ let optionsHltBgColors = JSON.parse(options.get('highlightedTextBgColors'));
+ // 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, hltColors, hltBgColors } = await this.getHlt(content, optionsHltColors, optionsHltBgColors));
+ }
+ this.$hlt.html($hlt);
+ this.toggleInt(
+ ["", "show"].includes(hltLabel?.value)
+ || hltColors!=""
+ || hltBgColors!=""
+ );
+
+ this.triggerCommand("reEvaluateRightPaneVisibility");
+ }
+ //Converts color values in RGB, RGBA, or HSL format to hexadecimal format, removing transparency
+ colorToHex(color) {
+ function rgbToHex(rgb) {
+ // Converts color values in RGB or RGBA format to hexadecimal format
+ var rgba = rgb.match(/\d+/g);
+ var r = parseInt(rgba[0]);
+ var g = parseInt(rgba[1]);
+ var b = parseInt(rgba[2]);
+ var hex = "#";
+ hex += (r < 16 ? "0" : "") + r.toString(16);
+ hex += (g < 16 ? "0" : "") + g.toString(16);
+ hex += (b < 16 ? "0" : "") + b.toString(16);
+ return hex;
+ }
+
+ function hslToHex(hsl) {
+ // Convert color values in HSL format to RGB format and then to hexadecimal format
+ var hslValues = hsl.match(/\d+(\.\d+)?/g);
+ var h = parseFloat(hslValues[0]) / 360;
+ var s = parseFloat(hslValues[1]) / 100;
+ var l = parseFloat(hslValues[2]) / 100;
+ var r, g, b;
+
+ if (s === 0) {
+ r = g = b = l; // achromatic
+ } else {
+ function hueToRgb(p, q, t) {
+ if (t < 0) t += 1;
+ if (t > 1) t -= 1;
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
+ if (t < 1 / 2) return q;
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
+ return p;
+ }
+
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = hueToRgb(p, q, h + 1 / 3);
+ g = hueToRgb(p, q, h);
+ b = hueToRgb(p, q, h - 1 / 3);
+ }
+
+ var hex = "#";
+ hex += (Math.round(r * 255) < 16 ? "0" : "") + Math.round(r * 255).toString(16);
+ hex += (Math.round(g * 255) < 16 ? "0" : "") + Math.round(g * 255).toString(16);
+ hex += (Math.round(b * 255) < 16 ? "0" : "") + Math.round(b * 255).toString(16);
+ return hex;
+ }
+ if (color.indexOf("rgb") !== -1) {
+ return rgbToHex(color);
+ } else if (color.indexOf("hsl") !== -1) {
+ return hslToHex(color);
+ } else {
+ return "";
+ }
+ }
+ // Determine whether the highlighted color is in the options, avoid errors caused by errors in color conversion,
+ // and the error of each value is acceptable within 2
+ hexIsInOptionHexs(targetColor, optionColors){
+ for (let i = 0; i < optionColors.length; i++) {
+ if (Math.abs(parseInt(optionColors[i].slice(1, 3), 16) - parseInt(targetColor.slice(1, 3), 16)) > 2) { continue; }
+ if (Math.abs(parseInt(optionColors[i].slice(3, 5), 16) - parseInt(targetColor.slice(3, 5), 16)) > 2) { continue; }
+ if (Math.abs(parseInt(optionColors[i].slice(5, 7), 16) - parseInt(targetColor.slice(5, 7), 16)) > 2) { continue; }
+ return true;
+ }
+ return false;
+ }
+ /**
+ * Builds a jquery table of helight text.
+ */
+ getHlt(html, optionsHltColors, optionsHltBgColors) {
+ const hltBCs = $(html).find(`span[style*="background-color"],span[style*="color"]`)
+ const $hlt = $("");
+ let hltColors = [];
+ let hltBgColors = [];
+ for (let hltIndex = 0; hltIndex');
+
+ if (color != "") {
+ var hexColor = this.colorToHex(color);
+ if (this.hexIsInOptionHexs(hexColor,optionsHltColors)) {
+ $li.html(hltText)
+ hltColors.push(hexColor);
+ liDisplay=true;
+ }
+ }
+ if (bgColor != "") {
+ var hexBgColor = this.colorToHex(bgColor);
+ if (this.hexIsInOptionHexs(hexBgColor,optionsHltBgColors)) {
+ //When you need to add a background color, in order to make the display more comfortable, change the background color to transparent
+ $li.html(hltText.css("background-color", hexBgColor+"80"))
+ hltBgColors.push(hexBgColor);
+ liDisplay=true;
+ }
+ }
+ if(!liDisplay){
+ $li.css("display","none");
+ }
+ //The font color and background color may be nested or adjacent to each other. At this time, connect the front and back li to avoid interruption
+ if(hltIndex!=0 && hltBCs[hltIndex-1].nextSibling ===hltBCs[hltIndex] && $hlt.children().last().css("display")!="none"){
+ $hlt.children().last().append($li.html());
+ }else{
+ $li.on("click", () => this.jumpToHlt(hltIndex));
+ $hlt.append($li);
+ }
+
+ };
+ return {
+ $hlt,
+ hltColors,
+ hltBgColors
+ };
+ }
+
+ async jumpToHlt(hltIndex) {
+ const isReadOnly = await this.noteContext.isReadOnly();
+ if (isReadOnly) {
+ const $container = await this.noteContext.getContentElement();
+ const hltElement = $container.find(`span[style*="background-color"],span[style*="color"]`)[hltIndex];
+
+ if (hltElement != null) {
+ hltElement.scrollIntoView({ behavior: "smooth", block: "center" });
+ }
+ } else {
+ const textEditor = await this.noteContext.getTextEditor();
+ $(textEditor.editing.view.domRoots.values().next().value).find(`span[style*="background-color"],span[style*="color"]`)[hltIndex].scrollIntoView({
+ behavior: "smooth", block: "center"
+ });
+ }
+ }
+
+ async closeHltCommand() {
+ this.noteContext.viewScope.hltTemporarilyHidden = 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 === 'hlt')
+ && attributeService.isAffecting(attr, this.note))) {
+ await this.refresh();
+ }
+ }
+}
+
+
+class CloseHltButton extends OnClickButtonWidget {
+ constructor() {
+ super();
+
+ this.icon("bx-x")
+ .title("Close HLT")
+ .titlePlacement("bottom")
+ .onClick((widget, e) => {
+ e.stopPropagation();
+
+ widget.triggerCommand("closeHlt");
+ })
+ .class("icon-action close-hlt");
+ }
+}
diff --git a/src/public/app/widgets/type_widgets/content_widget.js b/src/public/app/widgets/type_widgets/content_widget.js
index 967c996e5..f7a4846bd 100644
--- a/src/public/app/widgets/type_widgets/content_widget.js
+++ b/src/public/app/widgets/type_widgets/content_widget.js
@@ -7,6 +7,7 @@ import MaxContentWidthOptions from "./options/appearance/max_content_width.js";
import KeyboardShortcutsOptions from "./options/shortcuts.js";
import HeadingStyleOptions from "./options/text_notes/heading_style.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 VimKeyBindingsOptions from "./options/code_notes/vim_key_bindings.js";
import WrapLinesOptions from "./options/code_notes/wrap_lines.js";
@@ -61,6 +62,7 @@ const CONTENT_WIDGETS = {
_optionsTextNotes: [
HeadingStyleOptions,
TableOfContentsOptions,
+ HighlightedTextOptions,
TextAutoReadOnlySizeOptions
],
_optionsCodeNotes: [
diff --git a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
new file mode 100644
index 000000000..7fc2ce825
--- /dev/null
+++ b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
@@ -0,0 +1,90 @@
+import OptionsWidget from "../options_widget.js";
+
+const TPL = `
+
+
+
Highlighted Text
+
+ Displays highlighted text in the left pane. You can customize the highlighted text displayed in the left pane:
+ Text color:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Background color:
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`;
-export default class HltWidget extends RightPanelWidget {
+export default class HighlightTextWidget extends RightPanelWidget {
constructor() {
super();
@@ -59,20 +59,20 @@ export default class HltWidget extends RightPanelWidget {
isEnabled() {
return super.isEnabled()
&& this.note.type === 'text'
- && !this.noteContext.viewScope.hltTemporarilyHidden
+ && !this.noteContext.viewScope.highlightedTextTemporarilyHidden
&& this.noteContext.viewScope.viewMode === 'default';
}
async doRenderBody() {
this.$body.empty().append($(TPL));
- this.$hlt = this.$body.find('.hlt');
- this.$body.find('.hlt-widget').append(this.closeHltButton.render());
+ this.$hlt = this.$body.find('.highlighted-text');
+ this.$body.find('.highlighted-text-widget').append(this.closeHltButton.render());
}
async refreshWithNote(note) {
- const hltLabel = note.getLabel('hlt');
+ const hltLabel = note.getLabel('hideHighlightWidget');
- if (hltLabel?.value === 'hide') {
+ if (hltLabel?.value=="" || hltLabel?.value=== "true") {
this.toggleInt(false);
this.triggerCommand("reEvaluateRightPaneVisibility");
return;
@@ -90,7 +90,7 @@ export default class HltWidget extends RightPanelWidget {
}
this.$hlt.html($hlt);
this.toggleInt(
- ["", "show"].includes(hltLabel?.value)
+ [undefined, "false"].includes(hltLabel?.value)
|| hltColors!=""
|| hltBgColors!=""
);
@@ -200,7 +200,7 @@ export default class HltWidget extends RightPanelWidget {
$li.css("display","none");
}
//The font color and background color may be nested or adjacent to each other. At this time, connect the front and back li to avoid interruption
- if(hltIndex!=0 && hltBCs[hltIndex-1].nextSibling ===hltBCs[hltIndex] && $hlt.children().last().css("display")!="none"){
+ if(hltIndex!=0 && hltBCs[hltIndex-1].nextSibling === hltBCs[hltIndex] && $hlt.children().last().css("display")!="none"){
$hlt.children().last().append($li.html());
}else{
$li.on("click", () => this.jumpToHlt(hltIndex));
@@ -233,7 +233,7 @@ export default class HltWidget extends RightPanelWidget {
}
async closeHltCommand() {
- this.noteContext.viewScope.hltTemporarilyHidden = true;
+ this.noteContext.viewScope.highlightedTextTemporarilyHidden = true;
await this.refresh();
this.triggerCommand('reEvaluateRightPaneVisibility');
}
@@ -255,13 +255,13 @@ class CloseHltButton extends OnClickButtonWidget {
super();
this.icon("bx-x")
- .title("Close HLT")
+ .title("Close HighlightTextWidget")
.titlePlacement("bottom")
.onClick((widget, e) => {
e.stopPropagation();
widget.triggerCommand("closeHlt");
})
- .class("icon-action close-hlt");
+ .class("icon-action close-highlighted-text");
}
}
diff --git a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
index 7fc2ce825..ec884959a 100644
--- a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
+++ b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
@@ -1,67 +1,64 @@
import OptionsWidget from "../options_widget.js";
const TPL = `
-
+
Highlighted Text
- Displays highlighted text in the left pane. You can customize the highlighted text displayed in the left pane:
+ Displays highlighted text in the right panel. You can customize the highlighted text displayed in the right panel:
Text color:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Background color:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
`;
export default class HighlightedTextOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
- this.$hltColors = this.$widget.find(".hlt-color");
+ this.$hltColors = this.$widget.find(".highlighted-text-color");
this.$hltColors.on('change', () => {
- const hltColorVals=this.$widget.find('input.hlt-color[type="checkbox"]:checked').map(function() {
+ const hltColorVals=this.$widget.find('input.highlighted-text-color[type="checkbox"]:checked').map(function() {
return this.value;
}).get();
this.updateOption('highlightedTextColors', JSON.stringify(hltColorVals));
});
- this.$hltBgColors = this.$widget.find(".hlt-background-color");
+ this.$hltBgColors = this.$widget.find(".highlighted-text-background-color");
this.$hltBgColors.on('change', () =>{
- const hltBgColorVals=this.$widget.find('input.hlt-background-color[type="checkbox"]:checked').map(function() {
+ const hltBgColorVals=this.$widget.find('input.highlighted-text-background-color[type="checkbox"]:checked').map(function() {
return this.value;
}).get();
this.updateOption('highlightedTextBgColors', JSON.stringify(hltBgColorVals));
@@ -72,14 +69,14 @@ export default class HighlightedTextOptions extends OptionsWidget {
async optionsLoaded(options) {
const hltColorVals=JSON.parse(options.highlightedTextColors);
const hltBgColorVals=JSON.parse(options.highlightedTextBgColors);
- this.$widget.find('input.hlt-color[type="checkbox"]').each(function () {
+ this.$widget.find('input.highlighted-text-color[type="checkbox"]').each(function () {
if ($.inArray($(this).val(), hltColorVals) !== -1) {
$(this).prop("checked", true);
} else {
$(this).prop("checked", false);
}
});
- this.$widget.find('input.hlt-background-color[type="checkbox"]').each(function () {
+ this.$widget.find('input.highlighted-text-background-color[type="checkbox"]').each(function () {
if ($.inArray($(this).val(), hltBgColorVals) !== -1) {
$(this).prop("checked", true);
} else {
From 92d5aeae41ea384c1b0249bd70721481bf7b4dfc Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Wed, 31 May 2023 22:34:24 +0800
Subject: [PATCH 03/10] Show highlighted text in the right panel
---
src/public/app/widgets/highlighted_text.js | 11 ++--
.../options/text_notes/highlighted_text.js | 62 +++++++++----------
src/services/options_init.js | 4 +-
3 files changed, 40 insertions(+), 37 deletions(-)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
index 43bc377ce..c9f3ef08c 100644
--- a/src/public/app/widgets/highlighted_text.js
+++ b/src/public/app/widgets/highlighted_text.js
@@ -82,11 +82,14 @@ export default class HighlightTextWidget extends RightPanelWidget {
let optionsHltColors = JSON.parse(options.get('highlightedTextColors'));
let optionsHltBgColors = JSON.parse(options.get('highlightedTextBgColors'));
+ const colorToValDic={"Dark": "#000000", "Dim grey": "#4d4d4d", "Grey": "#999999", "Light grey": "#e6e6e6", "White": "#ffffff", "Red": "#e64c4c", "Orange": "#e6994c", "Yellow": "#e6e64c", "Light green": "#99e64c", "Green": "#4ce64c", "Aquamarine": "#4ce699", "Turquoise": "#4ce6e6", "Light blue": "#4c99e6", "Blue": "#4c4ce6", "Purple": "#994ce6"}
+ const optionsHltColorsVal = optionsHltColors.map(color => colorToValDic[color]);
+ const optionsHltBgColorsVal = optionsHltBgColors.map(color => colorToValDic[color]);
// 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, hltColors, hltBgColors } = await this.getHlt(content, optionsHltColors, optionsHltBgColors));
+ ({ $hlt, hltColors, hltBgColors } = await this.getHlt(content, optionsHltColorsVal, optionsHltBgColorsVal));
}
this.$hlt.html($hlt);
this.toggleInt(
@@ -167,7 +170,7 @@ export default class HighlightTextWidget extends RightPanelWidget {
/**
* Builds a jquery table of helight text.
*/
- getHlt(html, optionsHltColors, optionsHltBgColors) {
+ getHlt(html, optionsHltColorsVal, optionsHltBgColorsVal) {
const hltBCs = $(html).find(`span[style*="background-color"],span[style*="color"]`)
const $hlt = $("");
let hltColors = [];
@@ -181,7 +184,7 @@ export default class HighlightTextWidget extends RightPanelWidget {
if (color != "") {
var hexColor = this.colorToHex(color);
- if (this.hexIsInOptionHexs(hexColor,optionsHltColors)) {
+ if (this.hexIsInOptionHexs(hexColor,optionsHltColorsVal)) {
$li.html(hltText)
hltColors.push(hexColor);
liDisplay=true;
@@ -189,7 +192,7 @@ export default class HighlightTextWidget extends RightPanelWidget {
}
if (bgColor != "") {
var hexBgColor = this.colorToHex(bgColor);
- if (this.hexIsInOptionHexs(hexBgColor,optionsHltBgColors)) {
+ if (this.hexIsInOptionHexs(hexBgColor,optionsHltBgColorsVal)) {
//When you need to add a background color, in order to make the display more comfortable, change the background color to transparent
$li.html(hltText.css("background-color", hexBgColor+"80"))
hltBgColors.push(hexBgColor);
diff --git a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
index ec884959a..d5c284d94 100644
--- a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
+++ b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
@@ -3,7 +3,7 @@ import OptionsWidget from "../options_widget.js";
const TPL = `
Highlighted Text
- Displays highlighted text in the right panel. You can customize the highlighted text displayed in the right panel:
+ You can customize the highlighted text displayed in the right panel:
Text color:
-
+
@@ -28,7 +28,7 @@ const TPL = `
Background color:
-
+
From 0a66809bf0ca8aabe4af5426b1bc6eaa68098dd9 Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Thu, 1 Jun 2023 20:38:55 +0800
Subject: [PATCH 05/10] Not show when nothing is checked in the options
---
src/public/app/widgets/highlighted_text.js | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
index 1182c6fc2..b6ced3124 100644
--- a/src/public/app/widgets/highlighted_text.js
+++ b/src/public/app/widgets/highlighted_text.js
@@ -81,16 +81,16 @@ export default class HighlightTextWidget extends RightPanelWidget {
}
const hltLabel = note.getLabel('hideHighlightWidget');
- if (hltLabel?.value == "" || hltLabel?.value === "true") {
+ let optionsHltColors = JSON.parse(options.get('highlightedTextColors'));
+ let optionsHltBgColors = JSON.parse(options.get('highlightedTextBgColors'));
+
+ if (hltLabel?.value == "" || hltLabel?.value === "true" || (optionsHltColors=="" && optionsHltBgColors=="")) {
this.toggleInt(false);
this.triggerCommand("reEvaluateRightPaneVisibility");
return;
}
let $hlt = "", hltLiCount = -1;
-
- let optionsHltColors = JSON.parse(options.get('highlightedTextColors'));
- let optionsHltBgColors = JSON.parse(options.get('highlightedTextBgColors'));
//Obtained by `textEditor.config.get('fontColor.colors'), but this command can only be used in edit mode, so it is directly saved here
const colorToValDic = { "Black": "hsl(0,0%,0%)", "Dim grey": "hsl(0,0%,30%)", "Grey": "hsl(0,0%,60%)", "Light grey": "hsl(0,0%,90%)", "White": "hsl(0,0%,100%)", "Red": "hsl(0,75%,60%)", "Orange": "hsl(30,75%,60%)", "Yellow": "hsl(60,75%,60%)", "Light green": "hsl(90,75%,60%)", "Green": "hsl(120,75%,60%)", "Aquamarine": "hsl(150,75%,60%)", "Turquoise": "hsl(180,75%,60%)", "Light blue": "hsl(210,75%,60%)", "Blue": "hsl(240,75%,60%)", "Purple": "hsl(270,75%,60%)" }
const optionsHltColorsVal = optionsHltColors.map(color => colorToValDic[color]);
From 1413756d0095d6b8384f297d78e1b35a9590de44 Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Sat, 3 Jun 2023 11:55:50 +0800
Subject: [PATCH 06/10] Show highlighted text in right panel
---
src/public/app/widgets/highlighted_text.js | 168 ++++++++++--------
.../options/text_notes/highlighted_text.js | 83 ++-------
src/routes/api/options.js | 3 +-
src/services/options_init.js | 3 +-
4 files changed, 113 insertions(+), 144 deletions(-)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
index b6ced3124..f13bdc6b8 100644
--- a/src/public/app/widgets/highlighted_text.js
+++ b/src/public/app/widgets/highlighted_text.js
@@ -81,25 +81,20 @@ export default class HighlightTextWidget extends RightPanelWidget {
}
const hltLabel = note.getLabel('hideHighlightWidget');
- let optionsHltColors = JSON.parse(options.get('highlightedTextColors'));
- let optionsHltBgColors = JSON.parse(options.get('highlightedTextBgColors'));
+ const optionsHlt = JSON.parse(options.get('highlightedText'));
- if (hltLabel?.value == "" || hltLabel?.value === "true" || (optionsHltColors=="" && optionsHltBgColors=="")) {
+ if (hltLabel?.value == "" || hltLabel?.value === "true" || optionsHlt == "") {
this.toggleInt(false);
this.triggerCommand("reEvaluateRightPaneVisibility");
return;
}
let $hlt = "", hltLiCount = -1;
- //Obtained by `textEditor.config.get('fontColor.colors'), but this command can only be used in edit mode, so it is directly saved here
- const colorToValDic = { "Black": "hsl(0,0%,0%)", "Dim grey": "hsl(0,0%,30%)", "Grey": "hsl(0,0%,60%)", "Light grey": "hsl(0,0%,90%)", "White": "hsl(0,0%,100%)", "Red": "hsl(0,75%,60%)", "Orange": "hsl(30,75%,60%)", "Yellow": "hsl(60,75%,60%)", "Light green": "hsl(90,75%,60%)", "Green": "hsl(120,75%,60%)", "Aquamarine": "hsl(150,75%,60%)", "Turquoise": "hsl(180,75%,60%)", "Light blue": "hsl(210,75%,60%)", "Blue": "hsl(240,75%,60%)", "Purple": "hsl(270,75%,60%)" }
- const optionsHltColorsVal = optionsHltColors.map(color => colorToValDic[color]);
- const optionsHltBgColorsVal = optionsHltBgColors.map(color => colorToValDic[color]);
// 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, optionsHltColorsVal, optionsHltBgColorsVal));
+ ({ $hlt, hltLiCount } = await this.getHlt(content, optionsHlt));
}
this.$hlt.html($hlt);
if ([undefined, "false"].includes(hltLabel?.value) && hltLiCount > 0) {
@@ -110,90 +105,115 @@ export default class HighlightTextWidget extends RightPanelWidget {
this.noteContext.viewScope.highlightedTextTemporarilyHiddenPrevious = false;
}
-
this.triggerCommand("reEvaluateRightPaneVisibility");
}
/**
* Builds a jquery table of helight text.
*/
- getHlt(html, optionsHltColorsVal, optionsHltBgColorsVal) {
- const hltTagsRegex = /]*(?:background-color|color):[^;>]+;[^>]*>(.*?)<\/span>/gi;
- let prevEndIndex = -1;
- let prevLiDisplay = false;
- const $hlt = $("");
- let hltLiCount = 0;
- for (let match = null, hltIndex = 0; ((match = hltTagsRegex.exec(html)) !== null); hltIndex++) {
- var spanHtml = match[0];
- const styleString = match[0].match(/style="(.*?)"/)[1];
- const text = match[1];
- const startIndex = match.index;
- const endIndex = hltTagsRegex.lastIndex - 1;
- var $li = $('
');
-
- const styles = styleString
- .split(';')
- .filter(item => item.includes('background-color') || item.includes('color'))
- .map(item => item.trim());
-
- for (let stylesIndex = 0; stylesIndex < styles.length; stylesIndex++) {
- var [color, colorVal] = styles[stylesIndex].split(':');
- colorVal = colorVal.replace(/\s+/g, '');
- if (color == "color" && optionsHltColorsVal.indexOf(colorVal) >= 0) {
- $li.html(spanHtml)
- hltLiCount++;
-
- }
- else if (color == "background-color" && optionsHltBgColorsVal.indexOf(colorVal) >= 0) {
-
- //When you need to add a background color, in order to make the display more comfortable, change the background color to Translucent
- const spanHtmlRegex = /background-color:\s*(hsl|rgb)\((\d{1,3}),(\d{1,3}%?),(\d{1,3}%?)\)/i;
- let spanHtmlMatch = spanHtml.match(spanHtmlRegex);
- if (spanHtmlMatch && spanHtmlMatch.length > 4) {
- let newColorValue = `${spanHtmlMatch[1]}a(${spanHtmlMatch[2]},${spanHtmlMatch[3]},${spanHtmlMatch[4]},0.5)`;
- spanHtml = spanHtml.replace(spanHtmlRegex, `background-color: ${newColorValue}`);
- }
- $li.html(spanHtml)
- hltLiCount++;
-
- } else {
- $li.css("display", "none");
- }
- }
- if ($li.css("display")!="none"){
- if (prevEndIndex != -1 && startIndex === prevEndIndex + 1 && prevLiDisplay == true) {
- $hlt.children().last().append($li.html());
- } else {
- if ($li.text().trim() == "") { $li.css("display", "none"); }
- $li.on("click", () => this.jumpToHlt(hltIndex));
- $hlt.append($li);
- }
- }
-
- prevEndIndex = endIndex;
- prevLiDisplay = $li.css("display")!="none";
+ 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');
+ var $hlt = $("");
+ var hltLiCount = 0;
+ let prevEndIndex = -1;
+ for (let match = null, hltIndex = 0; ((match = combinedRegex.exec(html)) !== null); hltIndex++) {
+ var subHtml = match[0];
+ const startIndex = match.index;
+ const endIndex = combinedRegex.lastIndex;
+ hltLiCount++;
+ if (prevEndIndex != -1 && startIndex === prevEndIndex) {
+ $hlt.children().last().append(subHtml);
+ } else {
+ var $li = $('
');
+ $li.html(subHtml);
+ if ($li.text().trim() == "") { $li.css("display", "none"); }
+ $li.on("click", () => this.jumpToHlt(findSubStr,hltIndex));
+ $hlt.append($li);
+ }
+ prevEndIndex = endIndex;
+ }
+
return {
$hlt,
hltLiCount
};
}
-
- async jumpToHlt(hltIndex) {
+ async jumpToHlt(findSubStr,hltIndex) {
const isReadOnly = await this.noteContext.isReadOnly();
+ let targetElement;
if (isReadOnly) {
const $container = await this.noteContext.getContentElement();
- const hltElement = $container.find(`span[style*="background-color"],span[style*="color"]`)[hltIndex];
-
- if (hltElement != null) {
- hltElement.scrollIntoView({ behavior: "smooth", block: "center" });
- }
+ 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();
- $(textEditor.editing.view.domRoots.values().next().value).find(`span[style*="background-color"],span[style*="color"]`)[hltIndex].scrollIntoView({
- behavior: "smooth", block: "center"
- });
+ 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() {
diff --git a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
index 8af3503f8..90a47b616 100644
--- a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
+++ b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
@@ -1,83 +1,34 @@
import OptionsWidget from "../options_widget.js";
const TPL = `
-
-
+
Highlighted Text
-
- You can customize the highlighted text displayed in the right panel:
- Text color:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Background color:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+ You can customize the highlighted text displayed in the right panel:
+
+
+
+
+
+
.toc li {
cursor: pointer;
+ text-align: justify;
+ text-justify: distribute;
+ word-wrap: break-word;
+ hyphens: auto;
}
.toc li:hover {
From 446c41d020f0df9647af491c5b24e3e20e87631e Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Sat, 3 Jun 2023 17:00:15 +0800
Subject: [PATCH 08/10] Show highlighted text in right panel
---
src/public/app/layouts/desktop_layout.js | 4 ++--
src/public/app/widgets/highlighted_text.js | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/public/app/layouts/desktop_layout.js b/src/public/app/layouts/desktop_layout.js
index 0125e4ed1..17d569c4c 100644
--- a/src/public/app/layouts/desktop_layout.js
+++ b/src/public/app/layouts/desktop_layout.js
@@ -44,7 +44,7 @@ import BacklinksWidget from "../widgets/floating_buttons/zpetne_odkazy.js";
import SharedInfoWidget from "../widgets/shared_info.js";
import FindWidget from "../widgets/find.js";
import TocWidget from "../widgets/toc.js";
-import HighlightTextWidget from "../widgets/highlighted_text.js";
+import HighlightedTextWidget from "../widgets/highlighted_text.js";
import BulkActionsDialog from "../widgets/dialogs/bulk_actions.js";
import AboutDialog from "../widgets/dialogs/about.js";
import HelpDialog from "../widgets/dialogs/help.js";
@@ -182,7 +182,7 @@ export default class DesktopLayout {
)
.child(new RightPaneContainer()
.child(new TocWidget())
- .child(new HighlightTextWidget())
+ .child(new HighlightedTextWidget())
.child(...this.customWidgets.get('right-pane'))
)
)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
index f39e7c696..2ddecce88 100644
--- a/src/public/app/widgets/highlighted_text.js
+++ b/src/public/app/widgets/highlighted_text.js
@@ -46,7 +46,7 @@ const TPL = `
`;
-export default class HighlightTextWidget extends RightPanelWidget {
+export default class HighlightedTextWidget extends RightPanelWidget {
constructor() {
super();
@@ -242,7 +242,7 @@ class CloseHltButton extends OnClickButtonWidget {
super();
this.icon("bx-x")
- .title("Close HighlightTextWidget")
+ .title("Close HighlightedTextWidget")
.titlePlacement("bottom")
.onClick((widget, e) => {
e.stopPropagation();
From 3e3d7aa4d7e6cebadf7ec7083c11715e50c89992 Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Sat, 3 Jun 2023 17:12:06 +0800
Subject: [PATCH 09/10] Show highlighted text in right panel
---
src/public/app/widgets/highlighted_text.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
index 2ddecce88..b22697994 100644
--- a/src/public/app/widgets/highlighted_text.js
+++ b/src/public/app/widgets/highlighted_text.js
@@ -95,7 +95,6 @@ export default class HighlightedTextWidget extends RightPanelWidget {
// 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);
From 8852e8e531062dcf92f30cb1ea8da57e3ac2502e Mon Sep 17 00:00:00 2001
From: SiriusXT <1160925501@qq.com>
Date: Sun, 4 Jun 2023 16:02:30 +0800
Subject: [PATCH 10/10] Show highlighted text in right panel
---
src/public/app/widgets/highlighted_text.js | 14 ++++++++------
src/public/app/widgets/toc.js | 8 ++++----
.../options/text_notes/highlighted_text.js | 2 +-
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/src/public/app/widgets/highlighted_text.js b/src/public/app/widgets/highlighted_text.js
index b22697994..daced39d4 100644
--- a/src/public/app/widgets/highlighted_text.js
+++ b/src/public/app/widgets/highlighted_text.js
@@ -72,11 +72,11 @@ export default class HighlightedTextWidget extends RightPanelWidget {
}
async refreshWithNote(note) {
- /*The reason for adding highlightedTextTemporarilyHiddenPrevious is to record whether the previous state of the highlightedText is hidden or displayed,
+ /*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.highlightedTextTemporarilyHiddenPrevious == true) {
+ if (this.noteContext.viewScope.highlightedTextPreviousVisible == true) {
this.toggleInt(true);
} else {
this.toggleInt(false);
@@ -100,20 +100,19 @@ export default class HighlightedTextWidget extends RightPanelWidget {
this.$hlt.html($hlt);
if ([undefined, "false"].includes(hltLabel?.value) && hltLiCount > 0) {
this.toggleInt(true);
- this.noteContext.viewScope.highlightedTextTemporarilyHiddenPrevious = true;
+ this.noteContext.viewScope.highlightedTextPreviousVisible = true;
} else {
this.toggleInt(false);
- this.noteContext.viewScope.highlightedTextTemporarilyHiddenPrevious = false;
+ this.noteContext.viewScope.highlightedTextPreviousVisible = false;
}
this.triggerCommand("reEvaluateRightPaneVisibility");
}
/**
- * Builds a jquery table of helight text.
+ * Builds a 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
@@ -125,6 +124,7 @@ export default class HighlightedTextWidget extends RightPanelWidget {
// match underline
const regex5 = /[\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"]`;
@@ -157,8 +157,10 @@ export default class HighlightedTextWidget extends RightPanelWidget {
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.html(subHtml);
diff --git a/src/public/app/widgets/toc.js b/src/public/app/widgets/toc.js
index 43ecb8f2d..8d66b3294 100644
--- a/src/public/app/widgets/toc.js
+++ b/src/public/app/widgets/toc.js
@@ -84,11 +84,11 @@ export default class TocWidget extends RightPanelWidget {
}
async refreshWithNote(note) {
- /*The reason for adding tocTemporarilyHiddenPrevious is to record whether the previous state of the toc is hidden or displayed,
+ /*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.tocTemporarilyHiddenPrevious ==true){
+ if (this.noteContext.viewScope.tocPreviousVisible ==true){
this.toggleInt(true);
}else{
this.toggleInt(false);
@@ -112,10 +112,10 @@ export default class TocWidget extends RightPanelWidget {
this.$toc.html($toc);
if (["", "show"].includes(tocLabel?.value) || headingCount >= options.getInt('minTocHeadings')){
this.toggleInt(true);
- this.noteContext.viewScope.tocTemporarilyHiddenPrevious=true;
+ this.noteContext.viewScope.tocPreviousVisible=true;
}else{
this.toggleInt(false);
- this.noteContext.viewScope.tocTemporarilyHiddenPrevious=false;
+ this.noteContext.viewScope.tocPreviousVisible=false;
}
this.triggerCommand("reEvaluateRightPaneVisibility");
diff --git a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
index 90a47b616..4f96999cc 100644
--- a/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
+++ b/src/public/app/widgets/type_widgets/options/text_notes/highlighted_text.js
@@ -16,7 +16,7 @@ const TPL = `
export default class HighlightedTextOptions extends OptionsWidget {
doRender() {
this.$widget = $(TPL);
- this.$hlt = this.$widget.find(".highlighted-text-check");
+ 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;