Merge remote-tracking branch 'origin/develop' into feature/native_window_buttons

; Conflicts:
;	src/public/stylesheets/theme-next.css
This commit is contained in:
Elian Doran
2024-12-06 21:23:49 +02:00
23 changed files with 680 additions and 96 deletions
BIN
View File
Binary file not shown.
+2 -2
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8 -3
View File
@@ -258,9 +258,14 @@ function goToLinkExt(evt, hrefLink, $link) {
} else {
// Enable protocols supported by CKEditor 5 to be clickable.
// Refer to `allowedProtocols` in https://github.com/TriliumNext/trilium-ckeditor5/blob/main/packages/ckeditor5-build-balloon-block/src/ckeditor.ts.
// Adding `:` to these links might be safer.
const otherAllowedProtocols = ['mailto:', 'tel:', 'sms:', 'sftp:', 'smb:', 'slack:', 'zotero:'];
if (otherAllowedProtocols.some(protocol => hrefLink.toLowerCase().startsWith(protocol))){
// And be consistent with `allowedSchemes` in `src\services\html_sanitizer.ts`
const allowedSchemes = [
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero'
];
if (allowedSchemes.some(protocol => hrefLink.toLowerCase().startsWith(protocol+':'))){
window.open(hrefLink, '_blank');
}
}
+16 -3
View File
@@ -273,10 +273,23 @@ async function getNoteTitleWithPathAsSuffix(notePath) {
.append($('<span class="note-title">').text(title));
if (path.length > 0) {
$titleWithPath
.append($('<span class="note-path">').text(` (${path.join(' / ')})`));
}
const $notePath = $('<span class="note-path">');
$notePath.append($(`<span class="path-bracket"> (</span>)`));
for (let segmentIndex = 0; segmentIndex < path.length; segmentIndex++) {
$notePath.append($(`<span>`).text(path[segmentIndex]));
if (segmentIndex < path.length - 1) {
$notePath.append($(`<span class="path-delimiter">`).text(" / "));
}
}
$notePath.append($(`<span class="path-bracket">)</span>)`));
$titleWithPath.append($notePath);
}
return $titleWithPath;
}
+4 -4
View File
@@ -33,21 +33,21 @@ const DROPDOWN_TPL = `
<div class="calendar-header">
<div class="calendar-month-selector">
<button class="calendar-btn bx bx-left-arrow-alt" data-calendar-toggle="previous"></button>
<button class="calendar-btn bx bx-chevron-left" data-calendar-toggle="previous"></button>
<select data-calendar-input="month">
${Object.entries(MONTHS).map(([i, month]) => `<option value=${i}>${month}</option>`)}
</select>
<button class="calendar-btn bx bx-right-arrow-alt" data-calendar-toggle="next"></button>
<button class="calendar-btn bx bx-chevron-right" data-calendar-toggle="next"></button>
</div>
<div class="calendar-year-selector">
<button class="calendar-btn bx bx-left-arrow-alt" data-calendar-toggle="previousYear"></button>
<button class="calendar-btn bx bx-chevron-left" data-calendar-toggle="previousYear"></button>
<input type="number" min="1900" max="2999" step="1" data-calendar-input="year" />
<button class="calendar-btn bx bx-right-arrow-alt" data-calendar-toggle="nextYear"></button>
<button class="calendar-btn bx bx-chevron-right" data-calendar-toggle="nextYear"></button>
</div>
</div>
+1 -1
View File
@@ -49,7 +49,7 @@ const TPL = `
<div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="export-subtree-format" value="html">
${t('export.format_html')}
${t('export.format_html_zip')}
</label>
</div>
+119 -8
View File
@@ -28,6 +28,51 @@ const TPL = `<div class="note-map-widget" style="position: relative;">
font-size: 130%;
padding: 1px 10px 1px 10px;
}
/* Style Ui Element to Drag Nodes */
.fixnodes-type-switcher {
position: absolute;
top: 10px;
left: 45%;
z-index: 10; /* should be below dropdown (note actions) */
border-radius:0.2rem;
}
/* Start of styling the slider */
input[type="range"] {
/* removing default appearance */
-webkit-appearance: none;
appearance: none;
margin-left: 15px;
width:50%
}
/* Changing slider tracker */
input[type="range"]::-webkit-slider-runnable-track {
height: 6px;
background: #ccc;
border-radius: 16px;
}
/* Changing Slider Thumb*/
input[type="range"]::-webkit-slider-thumb {
/* removing default appearance */
-webkit-appearance: none;
appearance: none;
/* creating a custom design */
height: 15px;
width: 15px;
margin-top:-4px;
background-color: #661822;
border-radius: 50%;
/* End of styling the slider */
</style>
<div class="btn-group btn-group-sm map-type-switcher" role="group">
@@ -35,6 +80,14 @@ const TPL = `<div class="note-map-widget" style="position: relative;">
<button type="button" class="btn bx bx-sitemap" title="${t("note-map.button-tree-map")}" data-type="tree"></button>
</div>
<! UI for dragging Notes and link force >
<div class=" btn-group-sm fixnodes-type-switcher" role="group">
<button type="button" class="btn bx bx-expand" title="Fixation" data-type="moveable"></button>
<input type="range" class=" slider" min="1" title="Link distance" max="100" value="40" >
</div>
<div class="style-resolver"></div>
<div class="note-map-container"></div>
@@ -43,7 +96,7 @@ const TPL = `<div class="note-map-widget" style="position: relative;">
export default class NoteMapWidget extends NoteContextAwareWidget {
constructor(widgetMode) {
super();
this.fixNodes = false; // needed to save the status of the UI element. Is set later in the code
this.widgetMode = widgetMode; // 'type' or 'ribbon'
}
@@ -64,6 +117,13 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
await attributeService.setLabel(this.noteId, 'mapType', type);
});
// Reading the status of the Drag nodes Ui element. Changing it´s color when activated. Reading Force value of the link distance.
this.$widget.find('.fixnodes-type-switcher').on('click', async event => {
this.fixNodes = !this.fixNodes;
event.target.style.backgroundColor = this.fixNodes ? '#661822' : 'transparent';
});
super.doRender();
}
@@ -92,13 +152,61 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH);
//variables for the hover effekt. We have to save the neighbours of a hovered node in a set. Also we need to save the links as well as the hovered node itself
let hoverNode = null;
const highlightLinks = new Set();
const neighbours = new Set();
this.graph = ForceGraph()(this.$container[0])
.width(this.$container.width())
.height(this.$container.height())
.onZoom(zoom => this.setZoomLevel(zoom.k))
.d3AlphaDecay(0.01)
.d3VelocityDecay(0.08)
.nodeCanvasObject((node, ctx) => this.paintNode(node, this.getColorForNode(node), ctx))
//Code to fixate nodes when dragged
.onNodeDragEnd(node => {
if (this.fixNodes) {
node.fx = node.x;
node.fy = node.y;
} else {
node.fx = null;
node.fy = null;
}
})
//check if hovered and set the hovernode variable, saving the hovered node object into it. Clear links variable everytime you hover. Without clearing links will stay highlighted
.onNodeHover(node => {
hoverNode = node || null;
highlightLinks.clear();
})
// set link width to immitate a highlight effekt. Checking the condition if any links are saved in the previous defined set highlightlinks
.linkWidth(link => (highlightLinks.has(link) ? 3 : 0.4))
.linkColor(link => (highlightLinks.has(link) ? 'white' : this.css.mutedTextColor))
.linkDirectionalArrowLength(4)
.linkDirectionalArrowRelPos(0.95)
// main code for highlighting hovered nodes and neighbours. here we "style" the nodes. the nodes are rendered several hundred times per second.
.nodeCanvasObject((node, ctx) => {
if (hoverNode == node) { //paint only hovered node
this.paintNode(node, '#661822', ctx);
neighbours.clear(); //clearing neighbours or the effect would be maintained after hovering is over
for (const link of data.links) { //check if node is part of a link in the canvas, if so add it´s neighbours and related links to the previous defined variables to paint the nodes
if (link.source.id == node.id || link.target.id == node.id) {
neighbours.add(link.source);
neighbours.add(link.target);
highlightLinks.add(link);
neighbours.delete(node);
}
}
} else if (neighbours.has(node) && hoverNode != null) { //paint neighbours
this.paintNode(node, '#9d6363', ctx);
} else {
this.paintNode(node, this.getColorForNode(node), ctx); //paint rest of nodes in canvas
}
})
.nodePointerAreaPaint((node, ctx) => this.paintNode(node, this.getColorForNode(node), ctx))
.nodePointerAreaPaint((node, color, ctx) => {
ctx.fillStyle = color;
@@ -109,10 +217,6 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
.nodeLabel(node => esc(node.name))
.maxZoom(7)
.warmupTicks(30)
.linkDirectionalArrowLength(5)
.linkDirectionalArrowRelPos(1)
.linkWidth(1)
.linkColor(() => this.css.mutedTextColor)
.onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id))
.onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, e));
@@ -130,8 +234,15 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
const magnifiedRatio = Math.pow(nodeLinkRatio, 1.5);
const charge = -20 / magnifiedRatio;
const boundedCharge = Math.min(-3, charge);
let distancevalue = 40; // default value for the link force of the nodes
this.$widget.find('.fixnodes-type-switcher input').on('change', async e => {
distancevalue = e.target.closest('input').value;
this.graph.d3Force('link').distance(distancevalue);
this.renderData(data);
});
this.graph.d3Force('link').distance(40);
this.graph.d3Force('center').strength(0.2);
this.graph.d3Force('charge').strength(boundedCharge);
this.graph.d3Force('charge').distanceMax(1000);
@@ -201,7 +312,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget {
ctx.fillStyle = color;
ctx.beginPath();
ctx.arc(x, y, size, 0, 2 * Math.PI, false);
ctx.arc(x, y, size*0.8, 0, 2 * Math.PI, false);
ctx.fill();
const toRender = this.zoomLevel > 2
+1 -1
View File
@@ -43,7 +43,7 @@ export default class NoteWrapperWidget extends FlexContainer {
}
this.$widget.toggleClass("full-content-width",
['image', 'mermaid', 'book', 'render', 'canvas', 'webView'].includes(note.type)
['image', 'mermaid', 'book', 'render', 'canvas', 'webView', 'mindMap'].includes(note.type)
|| !!note?.isLabelTruthy('fullContentWidth')
);
@@ -146,7 +146,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
async createPromotedAttributeCell(definitionAttr, valueAttr, valueName) {
const definition = definitionAttr.getDefinition();
const id = `value-${this.noteId}-${definitionAttr.position}`;
const id = `value-${valueAttr.attributeId}`;
const $input = $("<input>")
.prop("tabindex", 200 + definitionAttr.position)
+28 -13
View File
@@ -139,13 +139,14 @@ const TAB_ROW_TPL = `
overflow: hidden;
pointer-events: all;
color: var(--inactive-tab-text-color);
background-color: var(--inactive-tab-background-color);
--tab-background-color: var(--workspace-tab-background-color);
background-color: var(--tab-background-color, var(--inactive-tab-background-color));
}
.tab-row-widget .note-tab[active] .note-tab-wrapper {
font-weight: bold;
color: var(--active-tab-text-color);
background-color : var(--active-tab-background-color);
background-color : var(--tab-background-color, var(--active-tab-background-color));
}
.tab-row-widget .note-tab[is-mini] .note-tab-wrapper {
@@ -189,11 +190,11 @@ const TAB_ROW_TPL = `
}
.tab-row-widget .note-tab:hover .note-tab-wrapper {
background-color: var(--inactive-tab-hover-background-color);
background-color: var(--tab-background-color, var(--inactive-tab-hover-background-color));
}
.tab-row-widget .note-tab[active]:hover .note-tab-wrapper {
background-color: var(--active-tab-hover-background-color);
background-color: var(--tab-background-color, var(--active-tab-hover-background-color));
}
.tab-row-widget .note-tab .note-tab-close:hover {
@@ -243,6 +244,9 @@ const TAB_ROW_TPL = `
export default class TabRowWidget extends BasicWidget {
doRender() {
this.$widget = $(TAB_ROW_TPL);
const documentStyle = window.getComputedStyle(document.documentElement);
this.showNoteIcons = (documentStyle.getPropertyValue("--tab-note-icons") === "true");
this.draggabillies = [];
@@ -667,18 +671,18 @@ export default class TabRowWidget extends BasicWidget {
}
}
let noteIcon = "";
if (noteContext) {
const hoistedNote = froca.getNoteFromCache(noteContext.hoistedNoteId);
if (hoistedNote) {
$tab.find('.note-tab-icon')
.removeClass()
.addClass("note-tab-icon")
.addClass(hoistedNote.getWorkspaceIconClass());
$tab.find('.note-tab-wrapper').css("background", hoistedNote.getWorkspaceTabBackgroundColor());
}
else {
$tab.find('.note-tab-wrapper')
.css("--workspace-tab-background-color", hoistedNote.getWorkspaceTabBackgroundColor());
if (!this.showNoteIcons) {
noteIcon = hoistedNote.getWorkspaceIconClass();
}
} else {
$tab.find('.note-tab-wrapper').removeAttr("style");
}
}
@@ -688,7 +692,7 @@ export default class TabRowWidget extends BasicWidget {
if (!note) {
this.updateTitle($tab, t('tab_row.new_tab'));
return;
}
}
const title = await noteContext.getNavigationTitle();
this.updateTitle($tab, title);
@@ -696,6 +700,17 @@ export default class TabRowWidget extends BasicWidget {
$tab.addClass(note.getCssClass());
$tab.addClass(utils.getNoteTypeClass(note.type));
$tab.addClass(utils.getMimeTypeClass(note.mime));
if (this.showNoteIcons) {
noteIcon = note.getIcon();
}
if (noteIcon) {
$tab.find('.note-tab-icon')
.removeClass()
.addClass("note-tab-icon")
.addClass(noteIcon);
}
}
async entitiesReloadedEvent({loadResults}) {
@@ -54,7 +54,7 @@ const TPL = `
cursor: text !important;
}
.note-detail-editable-text *:not(figure,.include-note):first-child {
.note-detail-editable-text *:not(figure, .include-note, hr):first-child {
margin-top: 0 !important;
}
+5 -1
View File
@@ -509,7 +509,11 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th
.tooltip {
font-size: var(--main-font-size) !important;
z-index: calc(var(--ck-z-panel) - 1) !important;
/*
TODO: Investigate the purpose of this
z-index: calc(var(--ck-z-panel) - 1) !important;
*/
z-index: 3000;
}
.tooltip-trigger {
+479 -46
View File
@@ -40,7 +40,7 @@
--launcher-pane-size: 58px;
--launcher-pane-horizontal-size: 54px;
--launcher-pane-horizontal-icon-size: 20px;
--launcher-pane-horizontal-icon-size: 20px;
--launcher-pane-button-margin: 6px;
--launcher-pane-button-gap: 3px;
@@ -55,6 +55,15 @@
--menu-item-icon-vert-offset: 0;
--more-accented-background-color: var(--card-background-hover-color);
--timeline-left-gap: 20px;
--timeline-right-gap: 20px;
--timeline-bullet-size: 10px;
--timeline-bullet-vertical-pos: .75em;
--timeline-connector-size: 4px;
/* Theme capabilities */
--tab-note-icons: true;
}
/*
@@ -135,11 +144,14 @@
--launcher-pane-background-color: #e8e8e8;
--launcher-pane-horizontal-background-color: #fafafa;
--launcher-pane-horizontal-border-color: rgba(0, 0, 0, 0.1);
--launcher-pane-text-color: #000000bd;
--launcher-pane-button-hover-color: black;
--launcher-pane-button-hover-background: white;
--launcher-pane-button-hover-shadow: 4px 4px 4px rgba(0, 0, 0, .075);
--sync-status-error-pulse-color: #ff5528;
--root-background: var(--left-pane-background-color);
--gutter-color: transparent;
@@ -169,10 +181,9 @@
--scrollbar-border-color: #ddd;
--scrollbar-background-color: #ddd;
--tooltip-background-color: #f8f8f8;
--link-color: blue;
--mermaid-theme: default;
--mermaid-theme: default;
--code-block-box-shadow: 4px 4px 8px rgba(0, 0, 0, 0.1), 0px 0px 2px rgba(0, 0, 0, 0.2);
@@ -182,6 +193,21 @@
--card-border-color: #eaeaea;
--card-shadow-color: rgba(0, 0, 0, 0.1);
--card-box-shadow: 0 0 12px var(--card-shadow-color);
--calendar-color: var(--menu-text-color);
--calendar-weekday-labels-color: var(--muted-text-color);
--calendar-day-hover-color: var(--hover-item-text-color);
--calendar-day-hover-background: var(--active-item-background-color);
--calendar-day-highlight-background: #80808024;
--timeline-bullet-color: #a5a5a5;
--timeline-bullet-hover-color: black;
--timeline-connector-color: #f1f1f1;
--timeline-connector-active-color: #ddd;
--tooltip-background-color: rgba(255, 255, 255, 0.85);
--tooltip-foreground-color: #000000ba;
--tooltip-shadow-color: rgba(0, 0, 0, .15);
}
/*
@@ -195,8 +221,8 @@
--main-background-color: #333;
--main-text-color: #ccc;
--main-border-color: #454545;
--subtle-border-color: rgba(0, 0, 0, 0.3);
--dropdown-border-color: #555;
--subtle-border-color: #313131;
--dropdown-border-color: #292929;
--dropdown-shadow-opacity: .6;
--dropdown-item-icon-destructive-color: #de6e5b;
--disabled-tooltip-icon-color: #7fd2ef;
@@ -268,11 +294,14 @@
--launcher-pane-background-color: #1a1a1a;
--launcher-pane-horizontal-background-color: #282828;
--launcher-pane-horizontal-border-color: rgb(22, 22, 22);
--launcher-pane-text-color: #909090;
--launcher-pane-button-hover-color: #ffffff;
--launcher-pane-button-hover-background: #ffffff1c;
--launcher-pane-button-hover-shadow: 4px 4px 4px rgba(0, 0, 0, .2);
--sync-status-error-pulse-color: #f47871;
--root-background: var(--left-pane-background-color);
--gutter-color: transparent;
@@ -296,7 +325,6 @@
--scrollbar-border-color: #666;
--scrollbar-background-color: #333;
--tooltip-background-color: #333;
--link-color: lightskyblue;
--mermaid-theme: dark;
@@ -308,6 +336,21 @@
--card-background-press-color: #464646;
--card-border-color: #222222;
--card-box-shadow: 0 0 12px rgba(0, 0, 0, 0.15);
--calendar-color: var(--menu-text-color);
--calendar-weekday-labels-color: var(--muted-text-color);
--calendar-day-hover-color: var(--hover-item-text-color);
--calendar-day-hover-background: var(--active-item-background-color);
--calendar-day-highlight-background: #8080805a;
--timeline-bullet-color: gray;
--timeline-bullet-hover-color: white;
--timeline-connector-color: #464646;
--timeline-connector-active-color: #545454;
--tooltip-background-color: rgba(67, 67, 67, 0.86);
--tooltip-foreground-color: #ffffffeb;
--tooltip-shadow-color: rgba(0, 0, 0, 0.4);
}
body ::-webkit-calendar-picker-indicator {
@@ -377,6 +420,18 @@ body.layout-horizontal {
border-right: 2px solid var(--left-pane-collapsed-border-color);
}
/*
* Global menu
*/
.global-menu div.zoom-buttons a {
border: unset;
}
.global-menu div.zoom-buttons a.bx {
color: var(--menu-text-color) !important;
}
/*
* Launcher pane
*/
@@ -392,7 +447,7 @@ body.layout-horizontal > .horizontal {
#launcher-pane.horizontal {
height: var(--launcher-pane-size) !important;
border-bottom: 1px solid var(--subtle-border-color);
border-bottom: 1px solid var(--launcher-pane-horizontal-border-color);
}
#launcher-pane .launcher-button,
@@ -431,6 +486,33 @@ body.layout-horizontal > .horizontal {
box-shadow 100ms ease-in;
}
#launcher-pane div.launcher-button {
display: flex;
justify-content: center;
align-items: center;
}
#launcher-pane .sync-status .sync-status-icon {
top: 3px;
}
#launcher-pane .sync-status-icon:not(.sync-status-in-progress):hover {
background: unset;
}
@keyframes sync-status-pulse {
from {
color: currentColor
} to {
color: var(--pulse-color);
}
}
#launcher-pane .sync-status-disconnected-with-changes {
--pulse-color: var(--sync-status-error-pulse-color);
animation: sync-status-pulse 1s ease-in-out alternate-reverse infinite;
}
#launcher-pane.horizontal .launcher-button {
font-size: var(--launcher-pane-horizontal-icon-size);
}
@@ -439,13 +521,25 @@ body.layout-horizontal > .horizontal {
--hover-item-background-color: transparent;
}
/*
* Left pane
*/
.tooltip .tooltip-arrow {
display: none;
}
/* Search Box */
.tooltip .tooltip-inner {
padding: 6px 10px !important;
box-shadow: -1px -1px 2px var(--tooltip-shadow-color),
2px 2px 8px var(--tooltip-shadow-color) !important;
border: unset !important;
border-radius: 6px;
backdrop-filter: blur(5px);
color: var(--tooltip-foreground-color) !important;
}
#left-pane .quick-search {
/*
* Search Box
*/
div.quick-search {
--padding-top: 8px;
--padding-left: 8px;
--padding-right: 8px;
@@ -459,7 +553,7 @@ body.layout-horizontal > .horizontal {
padding: var(--padding-top) var(--padding-right) var(--padding-bottom) var(--padding-left);
}
#left-pane .quick-search::before {
div.quick-search::before {
/* The background rectangle of the search box */
position: absolute;
content: "";
@@ -474,34 +568,34 @@ body.layout-horizontal > .horizontal {
transition: background-color 200ms ease-in;
}
#left-pane .quick-search:hover:before {
div.quick-search:hover:before {
/* Hovered search box background rectangle */
background: var(--quick-search-hover-background);
transition: background-color 75ms ease-out;
}
#left-pane .quick-search:focus-within:before {
div.quick-search:focus-within:before {
/* Focused search box background rectangle */
border-color: var(--quick-search-focus-border);
background: var(--quick-search-focus-background);
transition: background-color 100ms ease-out;
}
#left-pane .quick-search input {
padding-left: 15px;
box-shadow: unset;
background: transparent;
div.quick-search input {
padding-left: 15px !important;
box-shadow: unset !important;
background: transparent !important;
}
#left-pane .quick-search input::placeholder {
div.quick-search input::placeholder {
color: var(--quick-search-color);
}
#left-pane .quick-search:focus-within input {
div.quick-search:focus-within input {
color: var(--quick-search-focus-color) !important;
}
#left-pane .quick-search .search-button {
div.quick-search .search-button {
display: flex;
align-items: center;
justify-content: center;
@@ -514,27 +608,30 @@ body.layout-horizontal > .horizontal {
transition: background-color 200ms ease-in !important;
}
#left-pane .quick-search .search-button:active {
div.quick-search .search-button:active {
transform: scale(.85);
}
#left-pane .quick-search:focus-within:has(input:not(:placeholder-shown)) .search-button {
div.quick-search:focus-within:has(input:not(:placeholder-shown)) .search-button {
/* Matches when the input has a value and the focus is inside the search box */
background: var(--left-pane-item-action-button-background) !important;
color: var(--left-pane-item-action-button-color) !important;
transition: background-color 500ms ease-out !important;
}
html body #left-pane .quick-search:focus-within .search-button:hover,
#left-pane .quick-search .search-button.show {
html body .quick-search:focus-within .search-button:hover,
div.quick-search .search-button.show {
/* Hover state */
background: var(--left-pane-item-action-button-hover-background) !important;
color: var(--left-pane-item-action-button-color) !important;
transition: background-color 100ms ease-out !important;
}
/* Tree */
/*
* Left pane
*/
/* Tree */
#left-pane .tree-actions {
/* TODO: relocate instead of hiding */
@@ -706,7 +803,7 @@ body.layout-horizontal .tab-row-container:after {
left: 0;
right: 0;
height: 1px;
background: var(--subtle-border-color);
border-bottom: 1px solid var(--launcher-pane-horizontal-border-color);
}
body.layout-vertical.electron.platform-darwin .tab-row-container {
@@ -728,6 +825,17 @@ body.layout-horizontal .tab-row-widget-container {
overflow: hidden;
}
#root-widget.horizontal-layout .tab-row-widget .note-tab .note-tab-wrapper {
border: 1px solid transparent;
border-bottom-color: transparent;
box-shadow: unset;
}
#root-widget.horizontal-layout .tab-row-widget .note-tab[active] .note-tab-wrapper {
border: 1px solid var(--launcher-pane-horizontal-border-color);
border-bottom-color: transparent;
}
.tab-row-widget .note-tab .note-tab-wrapper {
height: var(--tab-height) !important;
transition: background 75ms ease-in,
@@ -743,6 +851,20 @@ body.layout-horizontal .tab-row-widget .note-tab .note-tab-wrapper {
border-bottom-right-radius: 0;
}
.note-tab .note-tab-wrapper {
--tab-background-color: initial !important;
}
.note-tab .note-tab-wrapper::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
height: 3px;
background-color: var(--workspace-tab-background-color);
}
.tab-row-widget .note-tab:nth-child(1) {
transform: translate3d(var(--tab-first-item-horiz-offset), 0, 0);
}
@@ -850,11 +972,14 @@ body.layout-horizontal .tab-row-widget .note-tab .note-tab-wrapper {
*/
#center-pane {
border-radius: var(--center-pane-border-radius) 0 0 0;
padding-top: 2px;
background: var(--main-background-color);
}
.vertical-layout #center-pane {
border-radius: var(--center-pane-border-radius) 0 0 0;
}
/*
* Ribbon & note header
*/
@@ -979,6 +1104,216 @@ html body .dropdown-item.disabled {
color: var(--menu-item-arrow-color) !important;
}
/*
* Calendar
*/
.calendar-dropdown-widget {
padding: 12px;
color: var(--calendar-color);
}
.calendar-dropdown-widget .calendar-header {
padding: 8px 0 20px 0;
}
.calendar-dropdown-widget .calendar-header input[type="number"] {
appearance: textfield !important;
}
.calendar-dropdown-widget .calendar-header input[type="number"]::-webkit-outer-spin-button,
.calendar-dropdown-widget .calendar-header input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.calendar-dropdown-widget .calendar-header input,
.calendar-dropdown-widget .calendar-header select {
/* TODO: Provide styling for background and states */
border: unset;
text-align: center;
font-size: 1.4em;
font-weight: 300;
}
.calendar-dropdown-widget .calendar-week span {
font-size: .85em;
font-weight: 500;
color: var(--calendar-weekday-labels-color);
}
.calendar-dropdown-widget .calendar-body {
font-size: .9em;
}
.calendar-dropdown-widget .calendar-body a {
background: transparent;
color: var(--calendar-color);
}
.calendar-dropdown-widget .calendar-body a.calendar-date-exists {
position: relative;
text-decoration: none !important;
}
.calendar-dropdown-widget .calendar-body a.calendar-date-exists:not(:hover)::before {
--vertical-margin: 13%;
--horiz-margin: 18%;
content: "";
position: absolute;
top: var(--vertical-margin);
right: var(--horiz-margin);
bottom: var(--vertical-margin);
left: var(--horiz-margin);
border-radius: 6px;
background: var(--calendar-day-highlight-background);
z-index: -1;
}
body .calendar-dropdown-widget .calendar-body a:hover {
border-radius: 6px;
background: var(--calendar-day-hover-background);
color: var(--calendar-day-hover-color) !important;
}
/*
* Note tooltip
*/
.tooltip .tooltip-inner:has(.note-tooltip-content) {
border-radius: 8px;
}
.note-tooltip-content {
padding: 8px;
}
.note-tooltip-content .note-title-with-path {
display: flex;
flex-direction: column-reverse;
border-bottom: 2px solid currentColor;
padding-bottom: 6px;
}
.note-tooltip-content .note-title-with-path .path-bracket {
/* Hide the leading and trailing bracket from the path */
display: none;
}
.note-tooltip-content .note-title-with-path .path-delimiter {
/* Hide the path delimiters (slashes) */
display: none;
}
.note-tooltip-content .note-title-with-path .path-delimiter + span::before {
/* Replace the path delimiters with arrows */
display: inline-block;
content: "\ebe6";
padding: 0 4px;
line-height: 1;
vertical-align: bottom;
font-family: boxicons;
opacity: .75;
}
.note-tooltip-content .note-path {
display: block;
color: var(--muted-text-color);
font-size: .75em;
}
.note-tooltip-content .note-tooltip-attributes {
margin-top: -4px;
font-size: .75em;
}
.note-tooltip-content .rendered-content {
padding-top: 12px;
}
/*
* Recent changes list
*/
.recent-changes-content small {
color: var(--muted-text-color);
}
.recent-changes-content > div {
padding-left: var(--timeline-left-gap);
}
/* Date headings */
.recent-changes-content > div > b {
display: block;
padding: 10px 0;
font-size: 1.25em;
font-weight: 300;
}
.recent-changes-content ul {
list-style: none;
margin: 0;
padding: 0;
}
/* Timeline items */
.recent-changes-content ul li,
.recent-changes-content > div > b {
position: relative;
margin: 0;
padding-left: var(--timeline-right-gap);
}
/* Timeline connector */
.recent-changes-content ul li::before,
.recent-changes-content > div > b::before {
position: absolute;
content: "";
top: var(--connector-top, 0);
left: calc((var(--timeline-bullet-size) - var(--timeline-connector-size)) / 2);
bottom: var(--connector-bottom, 0);
width: var(--timeline-connector-size);
border-radius: var(--connector-radius, 0) var(--connector-radius, 0) 0 0;
background: var(--timeline-connector-color);
transition: background-color 400ms ease-in-out;
}
.recent-changes-content > div:hover {
--timeline-connector-color: var(--timeline-connector-active-color);
}
/* The first item of the timeline */
.recent-changes-content > div:first-child > *:first-child {
--connector-top: 50%;
--connector-radius: calc(var(--timeline-connector-size) / 2);
}
/* The last item of the timeline */
.recent-changes-content > div:last-child li:last-child {
--connector-bottom: 50%;
}
/* Timeline bullet */
.recent-changes-content ul li::after {
position: absolute;
content: "";
top: var(--timeline-bullet-vertical-pos);
left: 0;
width: var(--timeline-bullet-size);
height: var(--timeline-bullet-size);
border-radius: 50%;
background: var(--timeline-bullet-color);
transform: translateY(-50%);
}
/* Hovered timeline bullet */
.recent-changes-content ul li:hover::after {
background: var(--timeline-bullet-hover-color);
}
/*
* TEXT NOTES
*/
@@ -996,7 +1331,7 @@ html body .dropdown-item.disabled {
overflow: unset;
}
html .note-detail-editable-text :not(figure, .include-note):first-child {
html .note-detail-editable-text :not(figure, .include-note, hr):first-child {
/* Create some space for the top-side shadow */
margin-top: 1px !important;
}
@@ -1029,6 +1364,52 @@ html .note-detail-editable-text :not(figure, .include-note):first-child {
cursor: default;
}
.ck-content blockquote {
background: var(--card-background-color);
border: 1px solid var(--card-border-color) !important;
box-shadow: var(--card-box-shadow);
border-radius: 10px;
padding: 1em 2.5em;
position: relative;
font-style: unset !important;
}
.ck-content blockquote p:last-of-type {
margin-bottom: 0 !important;
}
.ck-content blockquote:before,
.ck-content blockquote:after {
position: absolute;
top: 0;
font-size: 48px;
opacity: 0.1;
}
.ck-content blockquote:before {
content: "“";
left: 0.2em;
}
.ck-content blockquote:after {
content: "”";
right: 0.35em;
}
.ck-content hr {
margin: 5px 0;
height: 1px;
background-color: var(--main-border-color);
opacity: 1;
}
.ck-content p code {
border: 1px solid var(--card-border-color);
box-shadow: var(--card-box-shadow);
border-radius: 6px;
background-color: var(--card-background-color);
}
.note-detail-printable:not(.word-wrap) pre code {
white-space: pre;
margin-right: 1em;
@@ -1102,12 +1483,14 @@ html .note-detail-editable-text :not(figure, .include-note):first-child {
* Note list
*/
.note-list .note-book-card {
--note-list-horizontal-padding: 22px;
--note-list-vertical-padding: 15px;
background-color: var(--card-background-color);
border: 1px solid var(--card-border-color) !important;
box-shadow: 2px 3px 4px var(--card-shadow-color);
border-radius: 12px;
user-select: none;
padding: 15px 22px;
padding: 0;
margin: 5px 10px 5px 0;
}
@@ -1128,9 +1511,10 @@ html .note-detail-editable-text :not(figure, .include-note):first-child {
}
.note-list-wrapper .note-book-card .note-book-header {
font-size: 1.1em;
font-size: 1em;
font-weight: bold;
margin-bottom: 0.25em;
padding: 0.5em 1rem;
border-bottom-color: var(--card-border-color);
}
.note-list-wrapper .note-book-card .note-book-header .note-icon {
@@ -1144,28 +1528,77 @@ html .note-detail-editable-text :not(figure, .include-note):first-child {
vertical-align: middle;
}
.note-list-wrapper .note-book-card .note-book-header:last-child {
border-bottom: 0;
.note-list-wrapper .note-book-card .note-book-header .rendered-note-attributes {
font-size: 0.7em;
font-weight: normal;
margin-bottom: 0;
padding-bottom: 0;
}
.note-list-wrapper .note-book-card .note-book-header .note-book-content {
.note-list-wrapper .note-book-card .note-book-header:last-child {
border-bottom: 0;
}
.note-list-wrapper .note-book-card .note-book-content {
padding: 0 !important;
font-size: 0.8rem;
}
.note-list-wrapper .note-book-card .note-book-header .note-book-content h1,
.note-list-wrapper .note-book-card .note-book-header .note-book-content h2,
.note-list-wrapper .note-book-card .note-book-header .note-book-content h3,
.note-list-wrapper .note-book-card .note-book-header .note-book-content h4,
.note-list-wrapper .note-book-card .note-book-header .note-book-content h5,
.note-list-wrapper .note-book-card .note-book-header .note-book-content h6 {
.note-list-wrapper .note-book-card .note-book-content .rendered-content {
padding: 1rem;
}
.note-list-wrapper .note-book-card .note-book-content .rendered-content.text-with-ellipsis {
padding: 1rem !important;
}
.note-list-wrapper .note-book-card .note-book-content h1,
.note-list-wrapper .note-book-card .note-book-content h2,
.note-list-wrapper .note-book-card .note-book-content h3,
.note-list-wrapper .note-book-card .note-book-content h4,
.note-list-wrapper .note-book-card .note-book-content h5,
.note-list-wrapper .note-book-card .note-book-content h6 {
font-size: 1rem;
color: var(--active-item-text-color);
}
.note-list-wrapper .note-book-card .bx {
color: var(--left-pane-icon-color);
font-weight: bold;
.note-list-wrapper .note-book-card .note-book-content p:last-child {
margin-bottom: 0;
}
.note-list-wrapper .note-book-card .note-book-content.type-canvas .rendered-content,
.note-list-wrapper .note-book-card .note-book-content.type-mindMap .rendered-content,
.note-list-wrapper .note-book-card .note-book-content.type-code .rendered-content {
padding: 0;
}
.note-list-wrapper .note-book-card .note-book-content.type-code pre {
height: 100%;
padding: 1em;
}
.note-list-wrapper .note-book-card .bx {
color: var(--left-pane-icon-color) !important;
}
.note-list.grid-view .note-book-card:hover {
background: var(--card-background-color) !important;
filter: contrast(105%);
}
.note-list.grid-view .note-book-card img {
object-fit: cover !important;
width: 100%;
}
.note-list.grid-view .ck-content {
line-height: 1.3;
}
.note-list.grid-view .ck-content p {
margin-bottom: 0.5em;
}
.note-list.grid-view .ck-content figure.image {
width: 25%;
}
+1 -1
View File
@@ -138,7 +138,7 @@ span.fancytree-node.protected > span.fancytree-custom-icon {
span.fancytree-node.multiple-parents.shared .fancytree-title::after {
font-family: 'boxicons' !important;
font-size: smaller;
content: " \eb3d \ec03";
content: " \eb3d\ec03";
}
span.fancytree-node.multiple-parents .fancytree-title::after {
+1 -1
View File
@@ -93,7 +93,7 @@
"export_note_title": "导出笔记",
"close": "关闭",
"export_type_subtree": "此笔记及其所有子笔记",
"format_html": "HTML ZIP 归档 - 建议使用此选项,因为它保留了所有格式。",
"format_html_zip": "HTML ZIP 归档 - 建议使用此选项,因为它保留了所有格式。",
"format_markdown": "Markdown - 保留大部分格式。",
"format_opml": "OPML - 大纲交换格式,仅限文本。不包括格式、图像和文件。",
"opml_version_1": "OPML v1.0 - 仅限纯文本",
+1 -1
View File
@@ -88,7 +88,7 @@
"export_note_title": "Notiz exportieren",
"close": "Schließen",
"export_type_subtree": "diese Notiz und alle ihre Unternotizen",
"format_html": "HTML im ZIP-Archiv dies wird empfohlen, da dadurch die gesamte Formatierung erhalten bleibt.",
"format_html_zip": "HTML im ZIP-Archiv dies wird empfohlen, da dadurch die gesamte Formatierung erhalten bleibt.",
"format_markdown": "Markdown dadurch bleiben die meisten Formatierungen erhalten.",
"format_opml": "OPML Outliner-Austauschformat nur für Text. Formatierungen, Bilder und Dateien sind nicht enthalten.",
"opml_version_1": "OPML v1.0 nur Klartext",
+2 -1
View File
@@ -93,7 +93,8 @@
"export_note_title": "Export note",
"close": "Close",
"export_type_subtree": "this note and all of its descendants",
"format_html": "HTML in ZIP archive - this is recommended since this preserves all the formatting.",
"format_html": "HTML - recomandat deoarece păstrează toată formatarea",
"format_html_zip": "HTML in ZIP archive - this is recommended since this preserves all the formatting.",
"format_markdown": "Markdown - this preserves most of the formatting.",
"format_opml": "OPML - outliner interchange format for text only. Formatting, images and files are not included.",
"opml_version_1": "OPML v1.0 - plain text only",
+1 -1
View File
@@ -93,7 +93,7 @@
"export_note_title": "Exportar nota",
"close": "Cerrar",
"export_type_subtree": "esta nota y todos sus descendientes",
"format_html": "HTML en un archivo ZIP: se recomienda ya que conserva todo el formato.",
"format_html_zip": "HTML en un archivo ZIP: se recomienda ya que conserva todo el formato.",
"format_markdown": "Markdown: esto conserva la mayor parte del formato.",
"format_opml": "OPML: formato de intercambio de esquemas solo para texto. El formato, las imágenes y los archivos no están incluidos.",
"opml_version_1": "OPML v1.0: solo texto sin formato",
+1 -1
View File
@@ -89,7 +89,7 @@
"export_note_title": "Exporter la note",
"close": "Fermer",
"export_type_subtree": "cette note et tous ses descendants",
"format_html": "HTML dans l'archive ZIP - recommandé car cela préserve tout le formatage.",
"format_html_zip": "HTML dans l'archive ZIP - recommandé car cela préserve tout le formatage.",
"format_markdown": "Markdown - préserve la majeure partie du formatage.",
"format_opml": "OPML - format d'échange pour les outlineurs, uniquement pour le texte. Les mises en forme, images et fichiers ne sont pas inclus.",
"opml_version_1": "OPML v1.0 - texte brut uniquement",
+1 -1
View File
@@ -509,7 +509,7 @@
"export_status": "Starea exportului",
"export_type_single": "doar această notiță fără descendenții ei",
"export_type_subtree": "această notiță și toți descendenții ei",
"format_html": "HTML în arhivă ZIP - recomandat deoarece păstrează toată formatarea",
"format_html_zip": "HTML în arhivă ZIP - recomandat deoarece păstrează toată formatarea",
"format_markdown": "Markdown - păstrează majoritatea formatării",
"format_opml": "OPML - format de interschimbare pentru editoare cu structură ierarhică (outline). Formatarea, imaginile și fișierele nu vor fi incluse.",
"opml_version_1": "OPML v1.0 - text simplu",
+1 -1
View File
@@ -93,7 +93,7 @@
"export_note_title": "匯出筆記",
"close": "關閉",
"export_type_subtree": "此筆記及其所有子筆記",
"format_html": "HTML ZIP 歸檔 - 建議使用此選項,因為它保留了所有格式。",
"format_html_zip": "HTML ZIP 歸檔 - 建議使用此選項,因為它保留了所有格式。",
"format_markdown": "Markdown - 保留大部分格式。",
"format_opml": "OPML - 大綱交換格式,僅限文字。不包括格式、圖片和文件。",
"opml_version_1": "OPML v1.0 - 僅限純文字",
+5 -3
View File
@@ -52,13 +52,15 @@ function sanitize(dirtyHtml: string) {
return sanitizeHtml(dirtyHtml, {
allowedTags,
allowedAttributes: {
'*': [ 'class', 'style', 'title', 'src', 'href', 'hash', 'disabled', 'align', 'alt', 'center', 'data-*' ]
"*": [ 'class', 'style', 'title', 'src', 'href', 'hash', 'disabled', 'align', 'alt', 'center', 'data-*' ],
"input": [ "type", "checked" ]
},
// Be consistent with `allowedSchemes` in `src\public\app\services\link.js`
allowedSchemes: [
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'irc', 'gemini', 'git',
'http', 'https', 'ftp', 'ftps', 'mailto', 'data', 'evernote', 'file', 'facetime', 'gemini', 'git',
'gopher', 'imap', 'irc', 'irc6', 'jabber', 'jar', 'lastfm', 'ldap', 'ldaps', 'magnet', 'message',
'mumble', 'nfs', 'onenote', 'pop', 'rmi', 's3', 'sftp', 'skype', 'sms', 'spotify', 'steam', 'svn', 'udp',
'view-source', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack'
'view-source', 'vlc', 'vnc', 'ws', 'wss', 'xmpp', 'jdbc', 'slack', 'tel', 'smb', 'zotero'
],
nonTextTags: [
'head'