2025-01-09 18:07:02 +02:00
import server from "./server.js" ;
import utils from "./utils.js" ;
import toastService from "./toast.js" ;
import linkService from "./link.js" ;
import froca from "./froca.js" ;
import noteTooltipService from "./note_tooltip.js" ;
import protectedSessionService from "./protected_session.js" ;
import dateNotesService from "./date_notes.js" ;
import searchService from "./search.js" ;
import RightPanelWidget from "../widgets/right_panel_widget.js" ;
2019-10-20 17:49:58 +02:00
import ws from "./ws.js" ;
2024-12-21 23:47:18 +02:00
import appContext from "../components/app_context.js" ;
2021-05-22 12:35:41 +02:00
import NoteContextAwareWidget from "../widgets/note_context_aware_widget.js" ;
2020-03-19 17:15:14 +01:00
import BasicWidget from "../widgets/basic_widget.js" ;
2022-09-17 23:06:17 +02:00
import SpacedUpdate from "./spaced_update.js" ;
2022-12-01 00:17:15 +01:00
import shortcutService from "./shortcuts.js" ;
2023-09-23 00:04:16 +02:00
import dialogService from "./dialog.js" ;
2025-01-13 23:18:10 +02:00
import type FNote from "../entities/fnote.js" ;
2025-01-09 18:07:02 +02:00
import { t } from "./i18n.js" ;
2025-02-27 22:44:18 +01:00
import dayjs from "dayjs" ;
2025-01-13 23:18:10 +02:00
import type NoteContext from "../components/note_context.js" ;
import type NoteDetailWidget from "../widgets/note_detail.js" ;
import type Component from "../components/component.js" ;
2023-08-21 04:15:53 -04:00
/ * *
* A whole number
* @typedef { number } int
* /
/ * *
* An instance of the frontend api available globally .
* @global
* @var { FrontendScriptApi } api
* /
2024-12-19 22:06:42 +02:00
interface AddToToolbarOpts {
title : string ;
/** callback handling the click on the button */
action : ( ) = > void ;
/ * * i d o f t h e b u t t o n , u s e d t o i d e n t i f y t h e o l d i n s t a n c e s o f t h i s b u t t o n t o b e r e p l a c e d
* ID is optional because of BC , but not specifying it is deprecated . ID can be alphanumeric only . * /
2025-01-09 18:07:02 +02:00
id : string ;
2024-12-19 22:06:42 +02:00
/** name of the boxicon to be used (e.g. "time" for "bx-time" icon) */
icon : string ;
/** keyboard shortcut for the button, e.g. "alt+t" */
shortcut : string ;
}
// TODO: Deduplicate me with the server.
interface ExecResult {
success : boolean ;
executionResult : unknown ;
error? : string ;
}
2024-12-21 16:43:50 +02:00
export interface Entity {
2024-12-19 22:06:42 +02:00
noteId : string ;
}
type Func = ( ( . . . args : unknown [ ] ) = > unknown ) | string ;
interface Api {
2023-09-06 09:24:41 +02:00
/ * *
2023-08-21 04:15:53 -04:00
* Container of all the rendered script content
* * /
2024-12-19 22:06:42 +02:00
$container : JQuery < HTMLElement > | null ;
2019-10-05 10:55:29 +02:00
2023-08-21 04:15:53 -04:00
/ * *
2023-10-07 20:57:53 +03:00
* Note where the script started executing , i . e . , the ( event ) entrypoint of the current script execution .
2023-08-21 04:15:53 -04:00
* /
2024-12-19 22:06:42 +02:00
startNote : FNote ;
2023-08-21 04:15:53 -04:00
/ * *
2023-10-07 20:57:53 +03:00
* Note where the script is currently executing , i . e . the note where the currently executing source code is written .
2023-08-21 04:15:53 -04:00
* /
2024-12-19 22:06:42 +02:00
currentNote : FNote ;
2023-10-07 20:57:53 +03:00
2023-09-06 09:24:41 +02:00
/ * *
2023-10-07 20:57:53 +03:00
* Entity whose event triggered this execution .
2023-08-21 04:15:53 -04:00
* /
2024-12-19 22:06:42 +02:00
originEntity : unknown | null ;
2018-08-23 12:55:45 +02:00
2023-08-21 04:15:53 -04:00
/ * *
* day . js library for date manipulation .
* See { @link https : //day.js.org} for documentation
* @see https : //day.js.org
* /
2025-02-27 22:44:18 +01:00
dayjs : typeof dayjs ;
2019-08-17 11:28:36 +02:00
2024-12-19 22:06:42 +02:00
RightPanelWidget : typeof RightPanelWidget ;
NoteContextAwareWidget : typeof NoteContextAwareWidget ;
BasicWidget : typeof BasicWidget ;
2020-03-19 17:15:14 +01:00
2018-08-23 12:55:45 +02:00
/ * *
* Activates note in the tree and in the note detail .
*
2024-12-19 22:06:42 +02:00
* @param notePath ( or noteId )
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
activateNote ( notePath : string ) : Promise < void > ;
2018-08-23 12:55:45 +02:00
/ * *
2020-01-04 21:53:49 +01:00
* Activates newly created note . Compared to this . activateNote ( ) also makes sure that frontend has been fully synced .
2018-08-23 12:55:45 +02:00
*
2024-12-19 22:06:42 +02:00
* @param notePath ( or noteId )
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
activateNewNote ( notePath : string ) : Promise < void > ;
2018-08-23 12:55:45 +02:00
2025-01-09 18:07:02 +02:00
/ * *
2021-02-17 23:55:51 +01:00
* Open a note in a new tab .
*
2023-01-05 23:38:41 +01:00
* @method
2024-12-19 22:06:42 +02:00
* @param notePath ( or noteId )
* @param activate - set to true to activate the new tab , false to stay on the current tab
2021-02-17 23:55:51 +01:00
* /
2024-12-19 22:06:42 +02:00
openTabWithNote ( notePath : string , activate : boolean ) : Promise < void > ;
2021-02-17 23:55:51 +01:00
2022-06-02 17:36:30 +02:00
/ * *
* Open a note in a new split .
*
2024-12-19 22:06:42 +02:00
* @param notePath ( or noteId )
* @param activate - set to true to activate the new split , false to stay on the current split
2022-06-02 17:36:30 +02:00
* /
2024-12-19 22:06:42 +02:00
openSplitWithNote ( notePath : string , activate : boolean ) : Promise < void > ;
2022-06-02 17:36:30 +02:00
2018-08-23 12:55:45 +02:00
/ * *
2022-12-17 21:46:51 +01:00
* Adds a new launcher to the launchbar . If the launcher ( id ) already exists , it will be updated .
*
2023-01-05 23:38:41 +01:00
* @method
2022-12-17 21:46:51 +01:00
* @deprecated you can now create / modify launchers in the top - left Menu - > Configure Launchbar
2022-12-22 14:59:20 +01:00
* for special needs there 's also backend API' s createOrUpdateLauncher ( )
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
addButtonToToolbar ( opts : AddToToolbarOpts ) : void ;
2022-12-17 21:46:51 +01:00
2025-01-09 18:07:02 +02:00
/ * *
2023-10-29 00:51:23 +02:00
* @private
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
__runOnBackendInner ( func : unknown , params : unknown [ ] , transactional : boolean ) : unknown ;
2023-10-29 00:51:23 +02:00
/ * *
* Executes given anonymous function on the backend .
* Internally this serializes the anonymous function into string and sends it to backend via AJAX .
* Please make sure that the supplied function is synchronous . Only sync functions will work correctly
* with transaction management . If you really know what you ' re doing , you can call api . runAsyncOnBackendWithManualTransactionHandling ( )
*
* @method
2024-12-19 22:06:42 +02:00
* @param func - ( synchronous ) function to be executed on the backend
* @param params - list of parameters to the anonymous function to be sent to backend
* @returns return value of the executed function on the backend
2023-10-29 00:51:23 +02:00
* /
2024-12-19 22:06:42 +02:00
runOnBackend ( func : Func , params : unknown [ ] ) : unknown ;
2023-10-29 00:51:23 +02:00
/ * *
* Executes given anonymous function on the backend .
* Internally this serializes the anonymous function into string and sends it to backend via AJAX .
* This function is meant for advanced needs where an async function is necessary .
* In this case , the automatic request - scoped transaction management is not applied ,
* and you need to manually define transaction via api . transactional ( ) .
*
* If you have a synchronous function , please use api . runOnBackend ( ) .
*
* @method
2024-12-19 22:06:42 +02:00
* @param func - ( synchronous ) function to be executed on the backend
* @param params - list of parameters to the anonymous function to be sent to backend
* @returns return value of the executed function on the backend
2023-10-29 00:51:23 +02:00
* /
2024-12-19 22:06:42 +02:00
runAsyncOnBackendWithManualTransactionHandling ( func : Func , params : unknown [ ] ) : unknown ;
2018-08-23 12:55:45 +02:00
2019-04-22 22:52:09 +02:00
/ * *
* This is a powerful search method - you can search by attributes and their values , e . g . :
2024-08-09 23:44:41 +03:00
* "#dateModified =* MONTH AND #log" . See full documentation for all options at : https : //triliumnext.github.io/Docs/Wiki/search.html
2019-04-22 22:52:09 +02:00
* /
2024-12-19 22:06:42 +02:00
searchForNotes ( searchString : string ) : Promise < FNote [ ] > ;
2019-04-22 22:52:09 +02:00
/ * *
* This is a powerful search method - you can search by attributes and their values , e . g . :
2024-08-09 23:44:41 +03:00
* "#dateModified =* MONTH AND #log" . See full documentation for all options at : https : //triliumnext.github.io/Docs/Wiki/search.html
2019-04-22 22:52:09 +02:00
* /
2024-12-19 22:06:42 +02:00
searchForNote ( searchString : string ) : Promise < FNote | null > ;
2019-04-22 22:52:09 +02:00
2019-04-09 21:13:47 +02:00
/ * *
2023-05-05 23:41:11 +02:00
* Returns note by given noteId . If note is missing from the cache , it ' s loaded .
2019-04-09 21:13:47 +02:00
* /
2024-12-19 22:06:42 +02:00
getNote ( noteId : string ) : Promise < FNote | null > ;
2019-04-09 21:13:47 +02:00
2018-08-23 12:55:45 +02:00
/ * *
2023-05-05 23:41:11 +02:00
* Returns list of notes . If note is missing from the cache , it ' s loaded .
2018-08-23 12:55:45 +02:00
*
* This is often used to bulk - fill the cache with notes which would have to be picked one by one
2023-05-29 00:19:54 +02:00
* otherwise ( by e . g . createLink ( ) )
2018-08-23 12:55:45 +02:00
*
2024-12-19 22:06:42 +02:00
* @param [ silentNotFoundError ] - don ' t report error if the note is not found
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
getNotes ( noteIds : string [ ] , silentNotFoundError : boolean ) : Promise < FNote [ ] > ;
2018-08-23 12:55:45 +02:00
2019-04-13 22:56:45 +02:00
/ * *
2019-10-26 10:00:26 +02:00
* Update frontend tree ( note ) cache from the backend .
2019-04-13 22:56:45 +02:00
* /
2024-12-19 22:06:42 +02:00
reloadNotes ( noteIds : string [ ] ) : Promise < void > ;
2019-04-13 22:56:45 +02:00
2018-08-23 12:55:45 +02:00
/ * *
* Instance name identifies particular Trilium instance . It can be useful for scripts
* if some action needs to happen on only one specific instance .
* /
2024-12-19 22:06:42 +02:00
getInstanceName ( ) : string ;
2018-08-23 12:55:45 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns date in YYYY - MM - DD format
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
formatDateISO : typeof utils . formatDateISO ;
2018-08-23 12:55:45 +02:00
2024-12-19 22:06:42 +02:00
parseDate : typeof utils . parseDate ;
2018-08-23 12:55:45 +02:00
/ * *
2023-09-23 00:04:16 +02:00
* Show an info toast message to the user .
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
showMessage : typeof toastService . showMessage ;
2018-08-23 12:55:45 +02:00
/ * *
2023-09-23 00:04:16 +02:00
* Show an error toast message to the user .
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
showError : typeof toastService . showError ;
2018-08-23 12:55:45 +02:00
2023-09-23 00:04:16 +02:00
/ * *
* Show an info dialog to the user .
* /
2024-12-19 22:06:42 +02:00
showInfoDialog : typeof dialogService . info ;
2023-09-23 00:04:16 +02:00
/ * *
* Show confirm dialog to the user .
2024-12-19 22:06:42 +02:00
* @returns promise resolving to true if the user confirmed
2023-09-23 00:04:16 +02:00
* /
2024-12-19 22:06:42 +02:00
showConfirmDialog : typeof dialogService . confirm ;
2023-09-23 00:04:16 +02:00
/ * *
* Show prompt dialog to the user .
*
2024-12-19 22:06:42 +02:00
* @returns promise resolving to the answer provided by the user
2023-09-23 00:04:16 +02:00
* /
2024-12-19 22:06:42 +02:00
showPromptDialog : typeof dialogService . prompt ;
2023-09-23 00:04:16 +02:00
2022-05-13 22:33:57 +02:00
/ * *
2023-06-27 00:14:13 +02:00
* Trigger command . This is a very low - level API which should be avoided if possible .
2022-05-13 22:33:57 +02:00
* /
2024-12-21 23:47:18 +02:00
triggerCommand : typeof appContext . triggerCommand ;
2022-05-13 22:33:57 +02:00
/ * *
2023-06-27 00:14:13 +02:00
* Trigger event . This is a very low - level API which should be avoided if possible .
2022-05-13 22:33:57 +02:00
* /
2024-12-21 23:47:18 +02:00
triggerEvent : typeof appContext . triggerEvent ;
2022-05-13 22:33:57 +02:00
2025-01-09 18:07:02 +02:00
/ * *
2023-05-05 23:41:11 +02:00
* Create a note link ( jQuery object ) for given note .
2018-08-23 12:55:45 +02:00
*
* @param { string } notePath ( or noteId )
2020-11-17 20:11:10 +01:00
* @param { object } [ params ]
2024-12-19 22:06:42 +02:00
* @param { boolean } [ params . showTooltip ] - enable / disable tooltip on the link
* @param { boolean } [ params . showNotePath ] - show also whole note ' s path as part of the link
* @param { boolean } [ params . showNoteIcon ] - show also note icon before the title
2023-08-21 04:15:53 -04:00
* @param { string } [ params . title ] - custom link tile with note ' s title as default
2022-11-08 10:11:52 +01:00
* @param { string } [ params . title = ] - custom link tile with note ' s title as default
2023-09-06 09:20:32 +02:00
* @returns { jQuery } - jQuery element with the link ( wrapped in < span > )
2018-08-23 12:55:45 +02:00
* /
2024-12-19 22:06:42 +02:00
createLink : typeof linkService . createLink ;
2018-09-03 16:05:28 +02:00
2023-07-24 23:46:02 +02:00
/** @deprecated - use api.createLink() instead */
2024-12-19 22:06:42 +02:00
createNoteLink : typeof linkService . createLink ;
2023-07-24 23:46:02 +02:00
2022-05-09 23:13:34 +02:00
/ * *
* Adds given text to the editor cursor
*
2024-12-19 22:06:42 +02:00
* @param text - this must be clear text , HTML is not supported .
2022-05-09 23:13:34 +02:00
* /
2024-12-19 22:06:42 +02:00
addTextToActiveContextEditor ( text : string ) : void ;
2022-05-09 23:13:34 +02:00
2018-09-03 16:05:28 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns active note ( loaded into center pane )
2019-03-12 21:39:35 +01:00
* /
2024-12-19 22:06:42 +02:00
getActiveContextNote ( ) : FNote ;
2022-05-09 23:13:34 +02:00
2023-09-13 09:01:55 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns returns active context ( split )
2023-09-13 09:01:55 +02:00
* /
2024-12-19 22:06:42 +02:00
getActiveContext ( ) : NoteContext ;
2023-09-13 09:01:55 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns returns active main context ( first split in a tab , represents the tab as a whole )
2023-09-13 09:01:55 +02:00
* /
2024-12-19 22:06:42 +02:00
getActiveMainContext ( ) : NoteContext ;
2023-09-13 09:01:55 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns returns all note contexts ( splits ) in all tabs
2023-09-13 09:01:55 +02:00
* /
2024-12-19 22:06:42 +02:00
getNoteContexts ( ) : NoteContext [ ] ;
2023-09-13 09:01:55 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns returns all main contexts representing tabs
2023-09-13 09:01:55 +02:00
* /
2024-12-19 22:06:42 +02:00
getMainNoteContexts ( ) : NoteContext [ ] ;
2023-09-13 09:01:55 +02:00
2020-01-10 20:10:17 +01:00
/ * *
2023-05-05 23:41:11 +02:00
* See https : //ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for documentation on the returned instance.
2020-01-10 20:10:17 +01:00
*
2023-05-05 23:17:23 +02:00
* @returns { Promise < BalloonEditor > } instance of CKEditor
2020-01-10 20:10:17 +01:00
* /
2024-12-19 22:06:42 +02:00
getActiveContextTextEditor ( ) : Promise < unknown > ;
2022-05-03 23:25:28 +02:00
/ * *
* See https : //codemirror.net/doc/manual.html#api
*
* @method
2024-12-19 22:06:42 +02:00
* @returns instance of CodeMirror
2022-05-03 23:25:28 +02:00
* /
2024-12-19 22:06:42 +02:00
getActiveContextCodeEditor ( ) : Promise < unknown > ;
2022-05-03 23:25:28 +02:00
/ * *
* Get access to the widget handling note detail . Methods like ` getWidgetType() ` and ` getTypeWidget() ` to get to the
* implementation of actual widget type .
* /
2024-12-19 22:06:42 +02:00
getActiveNoteDetailWidget ( ) : Promise < NoteDetailWidget > ;
2019-04-09 21:13:47 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @returns returns a note path of active note or null if there isn ' t active note
2019-04-09 21:13:47 +02:00
* /
2024-12-19 22:06:42 +02:00
getActiveContextNotePath ( ) : string | null ;
2019-04-09 21:13:47 +02:00
2022-05-03 23:25:28 +02:00
/ * *
2023-05-05 23:41:11 +02:00
* Returns component which owns the given DOM element ( the nearest parent component in DOM tree )
2022-05-03 23:25:28 +02:00
*
* @method
2024-12-19 22:06:42 +02:00
* @param el DOM element
2022-05-03 23:25:28 +02:00
* /
2024-12-19 22:06:42 +02:00
getComponentByEl ( el : HTMLElement ) : Component ;
2022-05-03 23:25:28 +02:00
2018-12-22 20:57:09 +01:00
/ * *
2023-01-05 23:38:41 +01:00
* @param { object } $el - jquery object on which to set up the tooltip
2018-12-22 20:57:09 +01:00
* /
2024-12-19 22:06:42 +02:00
setupElementTooltip : typeof noteTooltipService . setupElementTooltip ;
2019-01-01 15:39:13 +01:00
2020-02-26 16:37:17 +01:00
/ * *
* @param { boolean } protect - true to protect note , false to unprotect
* /
2024-12-19 22:06:42 +02:00
protectNote : typeof protectedSessionService . protectNote ;
2020-02-26 16:37:17 +01:00
/ * *
2024-12-19 22:06:42 +02:00
* @param noteId
* @param protect - true to protect subtree , false to unprotect
2020-02-26 16:37:17 +01:00
* /
2024-12-19 22:06:42 +02:00
protectSubTree : typeof protectedSessionService . protectNote ;
2019-04-14 12:24:48 +02:00
/ * *
* Returns date - note for today . If it doesn ' t exist , it is automatically created .
* /
2024-12-19 22:06:42 +02:00
getTodayNote : typeof dateNotesService . getTodayNote ;
2019-04-14 12:24:48 +02:00
2021-10-21 03:16:51 -07:00
/ * *
2022-01-10 17:09:20 +01:00
* Returns day note for a given date . If it doesn ' t exist , it is automatically created .
*
2024-12-19 22:06:42 +02:00
* @param date - e . g . "2019-04-29"
2022-01-10 17:09:20 +01:00
* /
2024-12-19 22:06:42 +02:00
getDayNote : typeof dateNotesService . getDayNote ;
2022-01-10 17:09:20 +01:00
/ * *
* Returns day note for the first date of the week of the given date . If it doesn ' t exist , it is automatically created .
2021-10-21 03:16:51 -07:00
*
2024-12-19 22:06:42 +02:00
* @param date - e . g . "2019-04-29"
2021-10-21 03:16:51 -07:00
* /
2024-12-19 22:06:42 +02:00
getWeekNote : typeof dateNotesService . getWeekNote ;
2021-10-21 03:16:51 -07:00
2019-04-14 12:24:48 +02:00
/ * *
* Returns month - note . If it doesn ' t exist , it is automatically created .
*
2024-12-19 22:06:42 +02:00
* @param month - e . g . "2019-04"
2019-04-14 12:24:48 +02:00
* /
2024-12-19 22:06:42 +02:00
getMonthNote : typeof dateNotesService . getMonthNote ;
2019-04-14 12:24:48 +02:00
/ * *
* Returns year - note . If it doesn ' t exist , it is automatically created .
*
* @method
* @param { string } year - e . g . "2019"
2023-01-05 23:38:41 +01:00
* @returns { Promise < FNote > }
2019-04-14 12:24:48 +02:00
* /
2024-12-19 22:06:42 +02:00
getYearNote : typeof dateNotesService . getYearNote ;
2019-10-21 21:22:53 +02:00
/ * *
2024-08-09 23:44:41 +03:00
* Hoist note in the current tab . See https : //triliumnext.github.io/Docs/Wiki/note-hoisting.html
2019-10-21 21:22:53 +02:00
*
* @param { string } noteId - set hoisted note . 'root' will effectively unhoist
* /
2024-12-19 22:06:42 +02:00
setHoistedNoteId ( noteId : string ) : void ;
2020-11-23 22:52:48 +01:00
2025-01-09 18:07:02 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @param keyboardShortcut - e . g . "ctrl+shift+a"
* @param [ namespace ] specify namespace of the handler for the cases where call for bind may be repeated .
2022-12-01 10:03:04 +01:00
* If a handler with this ID exists , it ' s replaced by the new handler .
2019-11-05 21:26:54 +01:00
* /
2024-12-19 22:06:42 +02:00
bindGlobalShortcut : typeof shortcutService . bindGlobalShortcut ;
2019-12-09 23:07:45 +01:00
/ * *
2023-05-05 23:41:11 +02:00
* Trilium runs in a backend and frontend process , when something is changed on the backend from a script ,
2019-12-10 23:04:18 +01:00
* frontend will get asynchronously synchronized .
*
* This method returns a promise which resolves once all the backend - > frontend synchronization is finished .
2023-05-05 23:41:11 +02:00
* Typical use case is when a new note has been created , we should wait until it is synced into frontend and only then activate it .
2019-12-09 23:07:45 +01:00
* /
2024-12-19 22:06:42 +02:00
waitUntilSynced : typeof ws . waitForMaxKnownEntityChangeId ;
2020-06-14 10:49:37 +02:00
/ * *
* This will refresh all currently opened notes which have included note specified in the parameter
*
* @param includedNoteId - noteId of the included note
* /
2024-12-19 22:06:42 +02:00
refreshIncludedNote ( includedNoteId : string ) : void ;
2021-04-07 22:01:52 +02:00
/ * *
* Return randomly generated string of given length . This random string generation is NOT cryptographically secure .
*
* @method
2024-12-19 22:06:42 +02:00
* @param length of the string
* @returns random string
2021-04-07 22:01:52 +02:00
* /
2024-12-19 22:06:42 +02:00
randomString : typeof utils . randomString ;
2022-09-17 23:06:17 +02:00
2023-06-02 16:05:02 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @param size in bytes
* @return formatted string
2023-06-02 16:05:02 +02:00
* /
2024-12-19 22:06:42 +02:00
formatSize : typeof utils . formatSize ;
2023-06-29 23:32:19 +02:00
/ * *
2024-12-19 22:06:42 +02:00
* @param size in bytes
* @return formatted string
2023-06-29 23:32:19 +02:00
* @deprecated - use api . formatSize ( )
* /
2024-12-19 22:06:42 +02:00
formatNoteSize : typeof utils . formatSize ;
2023-06-02 16:05:02 +02:00
2024-12-19 22:06:42 +02:00
logMessages : Record < string , string [ ] > ;
logSpacedUpdates : Record < string , SpacedUpdate > ;
2022-09-17 23:06:17 +02:00
/ * *
* Log given message to the log pane in UI
* /
2024-12-19 22:06:42 +02:00
log ( message : string ) : void ;
}
/ * *
* < p > This is the main frontend API interface for scripts . All the properties and methods are published in the "api" object
* available in the JS frontend notes . You can use e . g . < code > api . showMessage ( api . startNote . title ) ; < / code > < / p >
* /
2024-12-19 22:16:03 +02:00
function FrontendScriptApi ( this : Api , startNote : FNote , currentNote : FNote , originEntity : Entity | null = null , $container : JQuery < HTMLElement > | null = null ) {
2024-12-19 22:06:42 +02:00
this . $container = $container ;
this . startNote = startNote ;
2025-01-09 18:07:02 +02:00
this . currentNote = currentNote ;
2024-12-19 22:06:42 +02:00
this . originEntity = originEntity ;
this . dayjs = dayjs ;
this . RightPanelWidget = RightPanelWidget ;
this . NoteContextAwareWidget = NoteContextAwareWidget ;
this . BasicWidget = BasicWidget ;
2025-01-09 18:07:02 +02:00
this . activateNote = async ( notePath ) = > {
2024-12-19 22:06:42 +02:00
await appContext . tabManager . getActiveContext ( ) . setNote ( notePath ) ;
} ;
2025-01-09 18:07:02 +02:00
this . activateNewNote = async ( notePath ) = > {
2024-12-19 22:06:42 +02:00
await ws . waitForMaxKnownEntityChangeId ( ) ;
await appContext . tabManager . getActiveContext ( ) . setNote ( notePath ) ;
2025-01-14 20:08:57 +02:00
await appContext . triggerEvent ( "focusAndSelectTitle" , { } ) ;
2024-12-19 22:06:42 +02:00
} ;
this . openTabWithNote = async ( notePath , activate ) = > {
await ws . waitForMaxKnownEntityChangeId ( ) ;
await appContext . tabManager . openTabWithNoteWithHoisting ( notePath , { activate } ) ;
if ( activate ) {
2025-01-14 20:08:57 +02:00
await appContext . triggerEvent ( "focusAndSelectTitle" , { } ) ;
2024-12-19 22:06:42 +02:00
}
} ;
2025-01-09 18:07:02 +02:00
2024-12-19 22:06:42 +02:00
this . openSplitWithNote = async ( notePath , activate ) = > {
await ws . waitForMaxKnownEntityChangeId ( ) ;
const subContexts = appContext . tabManager . getActiveContext ( ) . getSubContexts ( ) ;
2025-01-09 18:07:02 +02:00
const { ntxId } = subContexts [ subContexts . length - 1 ] ;
2024-12-19 22:06:42 +02:00
2025-01-09 18:07:02 +02:00
await appContext . triggerCommand ( "openNewNoteSplit" , { ntxId , notePath } ) ;
2024-12-19 22:06:42 +02:00
if ( activate ) {
2025-01-14 20:08:57 +02:00
await appContext . triggerEvent ( "focusAndSelectTitle" , { } ) ;
2024-12-19 22:06:42 +02:00
}
} ;
2025-01-09 18:07:02 +02:00
this . addButtonToToolbar = async ( opts ) = > {
2024-12-19 22:06:42 +02:00
console . warn ( "api.addButtonToToolbar() has been deprecated since v0.58 and may be removed in the future. Use Menu -> Configure Launchbar to create/update launchers instead." ) ;
2025-01-09 18:07:02 +02:00
const { action , . . . reqBody } = opts ;
await server . put ( "special-notes/api-script-launcher" , {
2024-12-19 22:06:42 +02:00
action : action.toString ( ) ,
. . . reqBody
} ) ;
} ;
function prepareParams ( params : unknown [ ] ) {
if ( ! params ) {
return params ;
}
2025-01-09 18:07:02 +02:00
return params . map ( ( p ) = > {
2024-12-19 22:06:42 +02:00
if ( typeof p === "function" ) {
return ` !@#Function: ${ p . toString ( ) } ` ;
2025-01-09 18:07:02 +02:00
} else {
2024-12-19 22:06:42 +02:00
return p ;
}
} ) ;
}
this . __runOnBackendInner = async ( func , params , transactional ) = > {
if ( typeof func === "function" ) {
func = func . toString ( ) ;
}
2025-01-09 18:07:02 +02:00
const ret = await server . post < ExecResult > (
"script/exec" ,
{
script : func ,
params : prepareParams ( params ) ,
startNoteId : startNote.noteId ,
currentNoteId : currentNote.noteId ,
originEntityName : "notes" , // currently there's no other entity on the frontend which can trigger event
originEntityId : originEntity ? originEntity.noteId : null ,
transactional
} ,
"script"
) ;
2024-12-19 22:06:42 +02:00
if ( ret . success ) {
await ws . waitForMaxKnownEntityChangeId ( ) ;
return ret . executionResult ;
} else {
throw new Error ( ` server error: ${ ret . error } ` ) ;
}
2025-01-09 18:07:02 +02:00
} ;
2024-12-19 22:06:42 +02:00
this . runOnBackend = async ( func , params = [ ] ) = > {
if ( func ? . constructor . name === "AsyncFunction" || ( typeof func === "string" && func ? . startsWith ? . ( "async " ) ) ) {
toastService . showError ( t ( "frontend_script_api.async_warning" ) ) ;
}
return await this . __runOnBackendInner ( func , params , true ) ;
} ;
this . runAsyncOnBackendWithManualTransactionHandling = async ( func , params = [ ] ) = > {
if ( func ? . constructor . name === "Function" || ( typeof func === "string" && func ? . startsWith ? . ( "function" ) ) ) {
toastService . showError ( t ( "frontend_script_api.sync_warning" ) ) ;
}
return await this . __runOnBackendInner ( func , params , false ) ;
} ;
2025-01-09 18:07:02 +02:00
this . searchForNotes = async ( searchString ) = > {
2024-12-19 22:06:42 +02:00
return await searchService . searchForNotes ( searchString ) ;
} ;
2025-01-09 18:07:02 +02:00
this . searchForNote = async ( searchString ) = > {
2024-12-19 22:06:42 +02:00
const notes = await this . searchForNotes ( searchString ) ;
return notes . length > 0 ? notes [ 0 ] : null ;
} ;
2025-01-09 18:07:02 +02:00
this . getNote = async ( noteId ) = > await froca . getNote ( noteId ) ;
this . getNotes = async ( noteIds , silentNotFoundError = false ) = > await froca . getNotes ( noteIds , silentNotFoundError ) ;
this . reloadNotes = async ( noteIds ) = > await froca . reloadNotes ( noteIds ) ;
this . getInstanceName = ( ) = > window . glob . instanceName ;
2024-12-19 22:06:42 +02:00
this . formatDateISO = utils . formatDateISO ;
this . parseDate = utils . parseDate ;
this . showMessage = toastService . showMessage ;
this . showError = toastService . showError ;
2025-01-09 18:07:02 +02:00
this . showInfoDialog = dialogService . info ;
2024-12-19 22:06:42 +02:00
this . showConfirmDialog = dialogService . confirm ;
this . showPromptDialog = dialogService . prompt ;
2025-01-09 18:07:02 +02:00
this . triggerCommand = ( name , data ) = > appContext . triggerCommand ( name , data ) ;
2024-12-19 22:06:42 +02:00
this . triggerEvent = ( name , data ) = > appContext . triggerEvent ( name , data ) ;
this . createLink = linkService . createLink ;
this . createNoteLink = linkService . createLink ;
2025-01-09 18:07:02 +02:00
this . addTextToActiveContextEditor = ( text ) = > appContext . triggerCommand ( "addTextToActiveEditor" , { text } ) ;
2024-12-19 22:06:42 +02:00
this . getActiveContextNote = ( ) = > appContext . tabManager . getActiveContextNote ( ) ;
this . getActiveContext = ( ) = > appContext . tabManager . getActiveContext ( ) ;
this . getActiveMainContext = ( ) = > appContext . tabManager . getActiveMainContext ( ) ;
2025-01-09 18:07:02 +02:00
this . getNoteContexts = ( ) = > appContext . tabManager . getNoteContexts ( ) ;
2024-12-19 22:06:42 +02:00
this . getMainNoteContexts = ( ) = > appContext . tabManager . getMainNoteContexts ( ) ;
2025-01-09 18:07:02 +02:00
this . getActiveContextTextEditor = ( ) = > appContext . tabManager . getActiveContext ( ) ? . getTextEditor ( ) ;
2024-12-19 22:06:42 +02:00
this . getActiveContextCodeEditor = ( ) = > appContext . tabManager . getActiveContext ( ) ? . getCodeEditor ( ) ;
2025-01-09 18:07:02 +02:00
this . getActiveNoteDetailWidget = ( ) = > new Promise ( ( resolve ) = > appContext . triggerCommand ( "executeInActiveNoteDetailWidget" , { callback : resolve } ) ) ;
2024-12-19 22:06:42 +02:00
this . getActiveContextNotePath = ( ) = > appContext . tabManager . getActiveContextNotePath ( ) ;
2025-01-09 18:07:02 +02:00
this . getComponentByEl = ( el ) = > appContext . getComponentByEl ( el ) ;
2024-12-19 22:06:42 +02:00
this . setupElementTooltip = noteTooltipService . setupElementTooltip ;
2025-01-09 18:07:02 +02:00
2024-12-19 22:06:42 +02:00
this . protectNote = async ( noteId , protect ) = > {
await protectedSessionService . protectNote ( noteId , protect , false ) ;
} ;
2025-01-09 18:07:02 +02:00
2024-12-19 22:06:42 +02:00
this . protectSubTree = async ( noteId , protect ) = > {
await protectedSessionService . protectNote ( noteId , protect , true ) ;
} ;
2025-01-09 18:07:02 +02:00
this . getTodayNote = dateNotesService . getTodayNote ;
2024-12-19 22:06:42 +02:00
this . getDayNote = dateNotesService . getDayNote ;
2025-01-09 18:07:02 +02:00
this . getWeekNote = dateNotesService . getWeekNote ;
2024-12-19 22:06:42 +02:00
this . getMonthNote = dateNotesService . getMonthNote ;
this . getYearNote = dateNotesService . getYearNote ;
this . setHoistedNoteId = ( noteId ) = > {
const activeNoteContext = appContext . tabManager . getActiveContext ( ) ;
if ( activeNoteContext ) {
activeNoteContext . setHoistedNoteId ( noteId ) ;
}
} ;
this . bindGlobalShortcut = shortcutService . bindGlobalShortcut ;
2025-01-09 18:07:02 +02:00
2024-12-19 22:06:42 +02:00
this . waitUntilSynced = ws . waitForMaxKnownEntityChangeId ;
2025-01-09 18:07:02 +02:00
this . refreshIncludedNote = ( includedNoteId ) = > appContext . triggerEvent ( "refreshIncludedNote" , { noteId : includedNoteId } ) ;
2024-12-19 22:06:42 +02:00
this . randomString = utils . randomString ;
this . formatSize = utils . formatSize ;
this . formatNoteSize = utils . formatSize ;
this . logMessages = { } ;
2025-01-09 18:07:02 +02:00
this . logSpacedUpdates = { } ;
this . log = ( message ) = > {
const { noteId } = this . startNote ;
2022-09-17 23:06:17 +02:00
2022-12-21 15:19:05 +01:00
message = ` ${ utils . now ( ) } : ${ message } ` ;
2022-09-17 23:06:17 +02:00
console . log ( ` Script ${ noteId } : ${ message } ` ) ;
this . logMessages [ noteId ] = this . logMessages [ noteId ] || [ ] ;
2025-01-09 18:07:02 +02:00
this . logSpacedUpdates [ noteId ] =
this . logSpacedUpdates [ noteId ] ||
new SpacedUpdate ( ( ) = > {
const messages = this . logMessages [ noteId ] ;
this . logMessages [ noteId ] = [ ] ;
2022-09-17 23:06:17 +02:00
2025-01-09 18:07:02 +02:00
appContext . triggerEvent ( "apiLogMessages" , { noteId , messages } ) ;
} , 100 ) ;
2022-09-17 23:06:17 +02:00
this . logMessages [ noteId ] . push ( message ) ;
this . logSpacedUpdates [ noteId ] . scheduleUpdate ( ) ;
} ;
2018-08-23 12:55:45 +02:00
}
2024-12-19 22:16:03 +02:00
export default FrontendScriptApi as any as {
2025-01-09 18:07:02 +02:00
new ( startNote : FNote , currentNote : FNote , originEntity : Entity | null , $container : JQuery < HTMLElement > | null ) : Api ;
2024-12-19 22:16:03 +02:00
} ;