mirror of
https://github.com/zadam/trilium.git
synced 2025-11-15 17:55:52 +01:00
Merge branch 'math2'
# Conflicts: # package-lock.json # package.json
This commit is contained in:
@@ -162,7 +162,10 @@ const editorConfig = {
|
||||
'CodeBlock',
|
||||
'SelectAll',
|
||||
'IncludeNote',
|
||||
'CutToNote'
|
||||
'CutToNote',
|
||||
'Mathematics',
|
||||
'indentBlockShortcutPlugin',
|
||||
'removeFormatLinksPlugin'
|
||||
],
|
||||
toolbar: {
|
||||
items: []
|
||||
|
||||
@@ -5,14 +5,20 @@ const WIDGET_TPL = `
|
||||
<div class="card widget">
|
||||
<div class="card-header">
|
||||
<div>
|
||||
<button class="btn btn-sm widget-title" data-toggle="collapse" data-target="#[to be set]">
|
||||
<span class="widget-title">
|
||||
Collapsible Group Item
|
||||
</button>
|
||||
|
||||
<a class="widget-help external no-arrow bx bx-info-circle"></a>
|
||||
</span>
|
||||
|
||||
<span class="widget-header-actions"></span>
|
||||
</div>
|
||||
|
||||
<div class="widget-header-actions"></div>
|
||||
<div>
|
||||
<a class="widget-help external no-arrow bx bx-info-circle"></a>
|
||||
|
||||
<a class="widget-toggle-button no-arrow bx bx-minus"
|
||||
title="Minimize/maximize widget"
|
||||
data-toggle="collapse" data-target="#[to be set]"></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="[to be set]" class="collapse body-wrapper" style="transition: none; ">
|
||||
@@ -38,13 +44,18 @@ export default class CollapsibleWidget extends TabAwareWidget {
|
||||
// not using constructor name because of webpack mangling class names ...
|
||||
this.widgetName = this.widgetTitle.replace(/[^[a-zA-Z0-9]/g, "_");
|
||||
|
||||
if (!options.is(this.widgetName + 'Collapsed')) {
|
||||
this.$toggleButton = this.$widget.find('.widget-toggle-button');
|
||||
|
||||
const collapsed = options.is(this.widgetName + 'Collapsed');
|
||||
if (!collapsed) {
|
||||
this.$bodyWrapper.collapse("show");
|
||||
}
|
||||
|
||||
this.updateToggleButton(collapsed);
|
||||
|
||||
// using immediate variants of the event so that the previous collapse is not caught
|
||||
this.$bodyWrapper.on('hide.bs.collapse', () => this.saveCollapsed(true));
|
||||
this.$bodyWrapper.on('show.bs.collapse', () => this.saveCollapsed(false));
|
||||
this.$bodyWrapper.on('hide.bs.collapse', () => this.toggleCollapsed(true));
|
||||
this.$bodyWrapper.on('show.bs.collapse', () => this.toggleCollapsed(false));
|
||||
|
||||
this.$body = this.$bodyWrapper.find('.card-body');
|
||||
|
||||
@@ -66,19 +77,35 @@ export default class CollapsibleWidget extends TabAwareWidget {
|
||||
}
|
||||
|
||||
this.$headerActions = this.$widget.find('.widget-header-actions');
|
||||
this.$headerActions.append(...this.headerActions);
|
||||
this.$headerActions.append(this.headerActions);
|
||||
|
||||
this.initialized = this.doRenderBody();
|
||||
|
||||
this.decorateWidget();
|
||||
}
|
||||
|
||||
saveCollapsed(collapse) {
|
||||
toggleCollapsed(collapse) {
|
||||
this.updateToggleButton(collapse);
|
||||
|
||||
options.save(this.widgetName + 'Collapsed', collapse.toString());
|
||||
|
||||
this.triggerEvent(`widgetCollapsedStateChanged`, {widgetName: this.widgetName, collapse});
|
||||
}
|
||||
|
||||
updateToggleButton(collapse) {
|
||||
if (collapse) {
|
||||
this.$toggleButton
|
||||
.addClass("bx-window")
|
||||
.removeClass("bx-minus")
|
||||
.attr("title", "Show");
|
||||
} else {
|
||||
this.$toggleButton
|
||||
.addClass("bx-minus")
|
||||
.removeClass("bx-window")
|
||||
.attr("title", "Hide");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is used to synchronize collapsed state of all the tab-cached widgets since they are all rendered
|
||||
* separately but should behave uniformly for the user.
|
||||
|
||||
@@ -24,7 +24,11 @@ export default class LinkMapWidget extends CollapsibleWidget {
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
const $showFullButton = $("<a>").append("show full").addClass('widget-header-action');
|
||||
const $showFullButton = $("<a>")
|
||||
.addClass("bx bx-map-alt")
|
||||
.addClass('widget-header-action')
|
||||
.attr('title', 'Show full link map');
|
||||
|
||||
$showFullButton.on('click', async () => {
|
||||
const linkMapDialog = await import("../../dialogs/link_map.js");
|
||||
linkMapDialog.showDialog();
|
||||
|
||||
@@ -21,7 +21,11 @@ class NoteRevisionsWidget extends CollapsibleWidget {
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
const $showFullButton = $("<a>").append("show dialog").addClass('widget-header-action');
|
||||
const $showFullButton = $("<a>")
|
||||
.addClass("bx bx-list-ul")
|
||||
.addClass('widget-header-action')
|
||||
.attr('title', 'Show Note revisions dialog');
|
||||
|
||||
$showFullButton.on('click', async () => {
|
||||
const attributesDialog = await import("../../dialogs/note_revisions.js");
|
||||
attributesDialog.showCurrentNoteRevisions(this.noteId);
|
||||
|
||||
@@ -15,7 +15,11 @@ export default class WhatLinksHereWidget extends CollapsibleWidget {
|
||||
}
|
||||
|
||||
get headerActions() {
|
||||
const $showFullButton = $("<a>").append("show link map").addClass('widget-header-action');
|
||||
const $showFullButton = $("<a>")
|
||||
.addClass("bx bx-map-alt")
|
||||
.addClass('widget-header-action')
|
||||
.attr('title', 'Show full link map');
|
||||
|
||||
$showFullButton.on('click', async () => {
|
||||
const linkMapDialog = await import("../../dialogs/link_map.js");
|
||||
linkMapDialog.showDialog();
|
||||
|
||||
@@ -126,13 +126,6 @@ export default class NoteActionsWidget extends TabAwareWidget {
|
||||
this.$showSourceButton.attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
if (note.type === 'text') {
|
||||
this.$exportNoteButton.removeAttr('disabled');
|
||||
}
|
||||
else {
|
||||
this.$exportNoteButton.attr('disabled', 'disabled');
|
||||
}
|
||||
|
||||
this.$protectButton.toggle(!note.isProtected);
|
||||
this.$unprotectButton.toggle(!!note.isProtected);
|
||||
}
|
||||
|
||||
@@ -158,7 +158,9 @@ export default class NotePathsWidget extends TabAwareWidget {
|
||||
}
|
||||
|
||||
entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.getBranches().find(branch => branch.noteId === this.noteId)) {
|
||||
if (loadResults.getBranches().find(branch => branch.noteId === this.noteId)
|
||||
|| loadResults.isNoteReloaded(this.noteId)) {
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,16 +159,6 @@ const TPL = `
|
||||
</div>
|
||||
`;
|
||||
|
||||
const NOTE_TYPE_ICONS = {
|
||||
"file": "bx bx-file",
|
||||
"image": "bx bx-image",
|
||||
"code": "bx bx-code",
|
||||
"render": "bx bx-extension",
|
||||
"search": "bx bx-file-find",
|
||||
"relation-map": "bx bx-map-alt",
|
||||
"book": "bx bx-book"
|
||||
};
|
||||
|
||||
export default class NoteTreeWidget extends TabAwareWidget {
|
||||
constructor(treeName) {
|
||||
super();
|
||||
@@ -369,8 +359,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
data.dataTransfer.setData("text", JSON.stringify(notes));
|
||||
return true; // allow dragging to start
|
||||
},
|
||||
dragEnter: (node, data) => true, // allow drop on any node
|
||||
dragOver: (node, data) => true,
|
||||
dragEnter: (node, data) => node.data.noteType !== 'search',
|
||||
dragDrop: async (node, data) => {
|
||||
if ((data.hitMode === 'over' && node.data.noteType === 'search') ||
|
||||
(['after', 'before'].includes(data.hitMode)
|
||||
@@ -407,7 +396,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
notes = JSON.parse(jsonStr);
|
||||
}
|
||||
catch (e) {
|
||||
console.error(`Cannot parse ${jsonStr} into notes for drop`);
|
||||
logError(`Cannot parse ${jsonStr} into notes for drop`);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -461,7 +450,11 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
&& node.data.noteId === hoistedNoteService.getHoistedNoteId()
|
||||
&& $span.find('.unhoist-button').length === 0) {
|
||||
|
||||
const unhoistButton = $('<span class="unhoist-button-wrapper" title="Unhoist current note to show the whole note tree">[<a class="unhoist-button">unhoist</a>]</span>');
|
||||
const action = await keyboardActionsService.getAction('unhoist');
|
||||
let shortcuts = action.effectiveShortcuts.join(',');
|
||||
shortcuts = shortcuts ? `(${shortcuts})` : '';
|
||||
|
||||
const unhoistButton = $(`<span class="unhoist-button-wrapper" title="Unhoist current note to show the whole note tree ${shortcuts}">[<a class="unhoist-button">unhoist</a>]</span>`);
|
||||
|
||||
// prepending since appending could push out (when note title is too long)
|
||||
// the button too much to the right so that it's not visible
|
||||
@@ -559,40 +552,14 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
return noteList;
|
||||
}
|
||||
|
||||
getIconClass(note) {
|
||||
const labels = note.getLabels('iconClass');
|
||||
|
||||
return labels.map(l => l.value).join(' ');
|
||||
}
|
||||
|
||||
getIcon(note, isFolder) {
|
||||
const hoistedNoteId = hoistedNoteService.getHoistedNoteId();
|
||||
|
||||
const iconClass = this.getIconClass(note);
|
||||
|
||||
if (iconClass) {
|
||||
return iconClass;
|
||||
}
|
||||
else if (note.noteId === 'root') {
|
||||
return "bx bx-chevrons-right";
|
||||
}
|
||||
else if (note.noteId === hoistedNoteId) {
|
||||
if (note.noteId !== 'root' && note.noteId === hoistedNoteId) {
|
||||
return "bx bxs-arrow-from-bottom";
|
||||
}
|
||||
else if (note.type === 'text') {
|
||||
if (isFolder) {
|
||||
return "bx bx-folder";
|
||||
}
|
||||
else {
|
||||
return "bx bx-note";
|
||||
}
|
||||
}
|
||||
else if (note.type === 'code' && note.mime.startsWith('text/x-sql')) {
|
||||
return "bx bx-data";
|
||||
}
|
||||
else {
|
||||
return NOTE_TYPE_ICONS[note.type];
|
||||
}
|
||||
|
||||
return note.getIcon(isFolder);
|
||||
}
|
||||
|
||||
updateNode(node) {
|
||||
@@ -810,7 +777,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
|
||||
if (!resolvedNotePathSegments) {
|
||||
if (logErrors) {
|
||||
console.error("Could not find run path for notePath:", notePath);
|
||||
logError("Could not find run path for notePath:", notePath);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1153,7 +1120,19 @@ export default class NoteTreeWidget extends TabAwareWidget {
|
||||
async setExpanded(branchId, isExpanded) {
|
||||
utils.assertArguments(branchId);
|
||||
|
||||
const branch = treeCache.getBranch(branchId);
|
||||
const branch = treeCache.getBranch(branchId, true);
|
||||
|
||||
if (!branch) {
|
||||
if (branchId && branchId.startsWith('virt')) {
|
||||
// in case of virtual branches there's nothing to update
|
||||
return;
|
||||
}
|
||||
else {
|
||||
logError(`Cannot find branch=${branchId}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
branch.isExpanded = isExpanded;
|
||||
|
||||
await server.put(`branches/${branchId}/expanded/${isExpanded ? 1 : 0}`);
|
||||
|
||||
@@ -173,6 +173,9 @@ export default class PromotedAttributesWidget extends TabAwareWidget {
|
||||
}
|
||||
else if (definition.labelType === 'boolean') {
|
||||
$input.prop("type", "checkbox");
|
||||
// hack, without this the checkbox is invisible
|
||||
// we should be using a different bootstrap structure for checkboxes
|
||||
$input.css('width', '80px');
|
||||
|
||||
if (valueAttr.value === "true") {
|
||||
$input.prop("checked", "checked");
|
||||
|
||||
@@ -88,6 +88,11 @@ export default class SimilarNotesWidget extends TabAwareWidget {
|
||||
|
||||
const similarNotes = await server.get('similar-notes/' + this.noteId);
|
||||
|
||||
if (!similarNotes) {
|
||||
this.toggleInt(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this.toggleInt(similarNotes.length > 0);
|
||||
|
||||
if (similarNotes.length === 0) {
|
||||
|
||||
@@ -104,6 +104,13 @@ export default class EditableTextTypeWidget extends AbstractTextTypeWidget {
|
||||
mention: mentionSetup,
|
||||
codeBlock: {
|
||||
languages: codeBlockLanguages
|
||||
},
|
||||
math: {
|
||||
engine: 'katex',
|
||||
outputType: 'span', // or script
|
||||
lazyLoad: async () => await libraryLoader.requireLibrary(libraryLoader.KATEX),
|
||||
forceOutputType: false, // forces output to use outputType
|
||||
enablePreview: true // Enable preview view
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -75,11 +75,17 @@ export default class FileTypeWidget extends TypeWidget {
|
||||
|
||||
this.$downloadButton.on('click', () => utils.download(this.getFileUrl()));
|
||||
|
||||
this.$openButton.on('click', () => {
|
||||
this.$openButton.on('click', async () => {
|
||||
if (utils.isElectron()) {
|
||||
const open = utils.dynamicRequire("open");
|
||||
const resp = await server.post("notes/" + this.noteId + "/saveToTmpDir");
|
||||
|
||||
open(this.getFileUrl(), {url: true});
|
||||
const electron = utils.dynamicRequire('electron');
|
||||
const res = await electron.shell.openPath(resp.tmpFilePath);
|
||||
|
||||
if (res) {
|
||||
// fallback in case there's no default application for this file
|
||||
open(this.getFileUrl(), {url: true});
|
||||
}
|
||||
}
|
||||
else {
|
||||
window.location.href = this.getFileUrl();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import treeCache from "../../services/tree_cache.js";
|
||||
import AbstractTextTypeWidget from "./abstract_text_type_widget.js";
|
||||
import treeService from "../../services/tree.js";
|
||||
import libraryLoader from "../../services/library_loader.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="note-detail-readonly-text note-detail-printable">
|
||||
@@ -65,10 +66,6 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
|
||||
this.$content.html('');
|
||||
}
|
||||
|
||||
scrollToTop() {
|
||||
this.$content.scrollTop(0);
|
||||
}
|
||||
|
||||
async doRefresh(note) {
|
||||
const noteComplement = await treeCache.getNoteComplement(note.noteId);
|
||||
|
||||
@@ -86,6 +83,12 @@ export default class ReadOnlyTextTypeWidget extends AbstractTextTypeWidget {
|
||||
|
||||
this.loadIncludedNote(noteId, $(el));
|
||||
});
|
||||
|
||||
if (this.$content.find('span.math-tex').length > 0) {
|
||||
await libraryLoader.requireLibrary(libraryLoader.KATEX);
|
||||
|
||||
renderMathInElement(this.$content[0], {});
|
||||
}
|
||||
}
|
||||
|
||||
async refreshIncludedNoteEvent({noteId}) {
|
||||
|
||||
@@ -539,7 +539,7 @@ export default class RelationMapTypeWidget extends TypeWidget {
|
||||
const note = this.mapData.notes.find(note => note.noteId === noteId);
|
||||
|
||||
if (!note) {
|
||||
console.error(`Note ${noteId} not found!`);
|
||||
logError(`Note ${noteId} not found!`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,12 @@ export default class TypeWidget extends TabAwareWidget {
|
||||
}
|
||||
}
|
||||
|
||||
async noteSwitched() {
|
||||
this.scrollToTop();
|
||||
|
||||
await super.noteSwitched();
|
||||
}
|
||||
|
||||
isActive() {
|
||||
return this.$widget.is(":visible");
|
||||
}
|
||||
@@ -54,4 +60,4 @@ export default class TypeWidget extends TabAwareWidget {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user