improvements in API docs generation

This commit is contained in:
zadam 2023-01-05 23:38:41 +01:00
parent 19f4870280
commit d7cae7d5bb
30 changed files with 189 additions and 138 deletions

16
bin/build-api-docs.sh Executable file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env bash
rm -rf ./tmp/api_docs/backend_api
rm -rf ./tmp/api_docs/frontend_api
./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./tmp/api_docs/backend_api src/becca/entities/*.js \
src/services/backend_script_api.js src/services/sql.js
./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./tmp/api_docs/frontend_api src/public/app/entities/*.js \
src/public/app/services/frontend_script_api.js src/public/app/widgets/right_panel_widget.js
rm -rf ./docs/api_docs/backend_api ./docs/api_docs/frontend_api
node src/transform_api_docs.js
rm -rf ./docs/api_docs/fonts ./docs/api_docs/styles ./docs/api_docs/scripts ./docs/api_docs/backend_api/index.html ./docs/api_docs/frontend_api/index.html

View File

@ -19,9 +19,7 @@
"start-electron-no-dir": "cross-env TRILIUM_ENV=dev electron --inspect=5858 .",
"switch-server": "rm -rf ./node_modules/better-sqlite3 && npm install",
"switch-electron": "rm -rf ./node_modules/better-sqlite3 && npm install && ./node_modules/.bin/electron-rebuild",
"build-backend-docs": "rm -rf ./docs/backend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/backend_api src/becca/entities/*.js src/services/backend_script_api.js src/services/sql.js",
"build-frontend-docs": "rm -rf ./docs/frontend_api && ./node_modules/.bin/jsdoc -c jsdoc-conf.json -d ./docs/frontend_api src/public/app/entities/*.js src/public/app/services/frontend_script_api.js src/public/app/widgets/right_panel_widget.js",
"build-docs": "npm run build-backend-docs && npm run build-frontend-docs",
"build-api-docs": "./bin/build-api-docs.sh",
"webpack": "npx webpack -c webpack-desktop.config.js && npx webpack -c webpack-mobile.config.js && npx webpack -c webpack-setup.config.js",
"test-jasmine": "jasmine",
"test-es6": "node -r esm spec-es6/attribute_parser.spec.js ",

View File

@ -36,7 +36,7 @@ class Becca {
return this.getNote('root');
}
/** @returns {Attribute[]} */
/** @returns {BAttribute[]} */
findAttributes(type, name) {
name = name.trim().toLowerCase();
@ -47,7 +47,7 @@ class Becca {
return this.attributeIndex[`${type}-${name}`] || [];
}
/** @returns {Attribute[]} */
/** @returns {BAttribute[]} */
findAttributesWithPrefix(type, name) {
const resArr = [];
const key = `${type}-${name}`;
@ -103,7 +103,7 @@ class Becca {
return this.branches[branchId];
}
/** @returns {Attribute|null} */
/** @returns {BAttribute|null} */
getAttribute(attributeId) {
return this.attributes[attributeId];
}

View File

@ -39,7 +39,7 @@ function isArchived(noteId) {
/**
* @param {string} noteId
* @param {string} ancestorNoteId
* @return {boolean} - true if given noteId has ancestorNoteId in any of its paths (even archived)
* @returns {boolean} - true if given noteId has ancestorNoteId in any of its paths (even archived)
*/
function isInAncestor(noteId, ancestorNoteId) {
if (ancestorNoteId === 'root' || ancestorNoteId === noteId) {

View File

@ -152,7 +152,7 @@ class BAttribute extends AbstractBeccaEntity {
}
/**
* @return {boolean}
* @returns {boolean}
*/
isDefinition() {
return this.type === 'label' && (this.name.startsWith('label:') || this.name.startsWith('relation:'));

View File

@ -140,7 +140,7 @@ class BBranch extends AbstractBeccaEntity {
* @param {string} [deleteId] - optional delete identified
* @param {TaskContext} [taskContext]
*
* @return {boolean} - true if note has been deleted, false otherwise
* @returns {boolean} - true if note has been deleted, false otherwise
*/
deleteBranch(deleteId, taskContext) {
if (!deleteId) {

View File

@ -98,18 +98,18 @@ class BNote extends AbstractBeccaEntity {
/** @type {BNote[]}
* @private*/
this.children = [];
/** @type {Attribute[]}
/** @type {BAttribute[]}
* @private */
this.ownedAttributes = [];
/** @type {Attribute[]|null}
/** @type {BAttribute[]|null}
* @private */
this.__attributeCache = null;
/** @type {Attribute[]|null}
/** @type {BAttribute[]|null}
* @private*/
this.inheritableAttributeCache = null;
/** @type {Attribute[]}
/** @type {BAttribute[]}
* @private*/
this.targetRelations = [];
@ -369,7 +369,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} [type] - (optional) attribute type to filter
* @param {string} [name] - (optional) attribute name to filter
* @returns {Attribute[]} all note's attributes, including inherited ones
* @returns {BAttribute[]} all note's attributes, including inherited ones
*/
getAttributes(type, name) {
this.__validateTypeName(type, name);
@ -449,7 +449,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @private
* @returns {Attribute[]}
* @returns {BAttribute[]}
*/
__getInheritableAttributes(path) {
if (path.includes(this.noteId)) {
@ -536,25 +536,25 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} name - label name
* @returns {Attribute|null} label if it exists, null otherwise
* @returns {BAttribute|null} label if it exists, null otherwise
*/
getLabel(name) { return this.getAttribute(LABEL, name); }
/**
* @param {string} name - label name
* @returns {Attribute|null} label if it exists, null otherwise
* @returns {BAttribute|null} label if it exists, null otherwise
*/
getOwnedLabel(name) { return this.getOwnedAttribute(LABEL, name); }
/**
* @param {string} name - relation name
* @returns {Attribute|null} relation if it exists, null otherwise
* @returns {BAttribute|null} relation if it exists, null otherwise
*/
getRelation(name) { return this.getAttribute(RELATION, name); }
/**
* @param {string} name - relation name
* @returns {Attribute|null} relation if it exists, null otherwise
* @returns {BAttribute|null} relation if it exists, null otherwise
*/
getOwnedRelation(name) { return this.getOwnedAttribute(RELATION, name); }
@ -595,7 +595,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} type - attribute type (label, relation, etc.)
* @param {string} name - attribute name
* @returns {Attribute} attribute of given type and name. If there's more such attributes, first is returned. Returns null if there's no such attribute belonging to this note.
* @returns {BAttribute} attribute of given type and name. If there's more such attributes, first is returned. Returns null if there's no such attribute belonging to this note.
*/
getAttribute(type, name) {
const attributes = this.getAttributes();
@ -627,7 +627,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} [name] - label name to filter
* @returns {Attribute[]} all note's labels (attributes with type label), including inherited ones
* @returns {BAttribute[]} all note's labels (attributes with type label), including inherited ones
*/
getLabels(name) {
return this.getAttributes(LABEL, name);
@ -643,7 +643,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} [name] - label name to filter
* @returns {Attribute[]} all note's labels (attributes with type label), excluding inherited ones
* @returns {BAttribute[]} all note's labels (attributes with type label), excluding inherited ones
*/
getOwnedLabels(name) {
return this.getOwnedAttributes(LABEL, name);
@ -659,7 +659,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} [name] - relation name to filter
* @returns {Attribute[]} all note's relations (attributes with type relation), including inherited ones
* @returns {BAttribute[]} all note's relations (attributes with type relation), including inherited ones
*/
getRelations(name) {
return this.getAttributes(RELATION, name);
@ -667,7 +667,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param {string} [name] - relation name to filter
* @returns {Attribute[]} all note's relations (attributes with type relation), excluding inherited ones
* @returns {BAttribute[]} all note's relations (attributes with type relation), excluding inherited ones
*/
getOwnedRelations(name) {
return this.getOwnedAttributes(RELATION, name);
@ -677,7 +677,7 @@ class BNote extends AbstractBeccaEntity {
* @param {string|null} [type] - (optional) attribute type to filter
* @param {string|null} [name] - (optional) attribute name to filter
* @param {string|null} [value] - (optional) attribute value to filter
* @returns {Attribute[]} note's "owned" attributes - excluding inherited ones
* @returns {BAttribute[]} note's "owned" attributes - excluding inherited ones
*/
getOwnedAttributes(type = null, name = null, value = null) {
this.__validateTypeName(type, name);
@ -700,7 +700,7 @@ class BNote extends AbstractBeccaEntity {
}
/**
* @returns {Attribute} attribute belonging to this specific note (excludes inherited attributes)
* @returns {BAttribute} attribute belonging to this specific note (excludes inherited attributes)
*
* This method can be significantly faster than the getAttribute()
*/
@ -735,7 +735,7 @@ class BNote extends AbstractBeccaEntity {
* - fast searching
* - note similarity evaluation
*
* @return {string} - returns flattened textual representation of note, prefixes and attributes
* @returns {string} - returns flattened textual representation of note, prefixes and attributes
*/
getFlatText() {
if (!this.flatTextCache) {
@ -863,7 +863,7 @@ class BNote extends AbstractBeccaEntity {
return Array.from(set);
}
/** @return {BNote[]} */
/** @returns {BNote[]} */
getSearchResultNotes() {
if (this.type !== 'search') {
return [];
@ -1088,7 +1088,7 @@ class BNote extends AbstractBeccaEntity {
}
/**
* @return {string[][]} - array of notePaths (each represented by array of noteIds constituting the particular note path)
* @returns {string[][]} - array of notePaths (each represented by array of noteIds constituting the particular note path)
*/
getAllNotePaths() {
if (this.noteId === 'root') {
@ -1109,7 +1109,7 @@ class BNote extends AbstractBeccaEntity {
/**
* @param ancestorNoteId
* @return {boolean} - true if ancestorNoteId occurs in at least one of the note's paths
* @returns {boolean} - true if ancestorNoteId occurs in at least one of the note's paths
*/
isDescendantOfNote(ancestorNoteId) {
const notePaths = this.getAllNotePaths();
@ -1174,7 +1174,7 @@ class BNote extends AbstractBeccaEntity {
* @param {string} [value] - value of the attribute - text for labels, target note ID for relations; optional.
* @param {boolean} [isInheritable=false]
* @param {int} [position]
* @return {Attribute}
* @returns {BAttribute}
*/
addAttribute(type, name, value = "", isInheritable = false, position = 1000) {
const BAttribute = require("./battribute");
@ -1195,7 +1195,7 @@ class BNote extends AbstractBeccaEntity {
* @param {string} name - name of the label, not including the leading #
* @param {string} [value] - text value of the label; optional
* @param {boolean} [isInheritable=false]
* @return {Attribute}
* @returns {BAttribute}
*/
addLabel(name, value = "", isInheritable = false) {
return this.addAttribute(LABEL, name, value, isInheritable);
@ -1208,7 +1208,7 @@ class BNote extends AbstractBeccaEntity {
* @param {string} name - name of the relation, not including the leading ~
* @param {string} targetNoteId
* @param {boolean} [isInheritable=false]
* @return {Attribute}
* @returns {BAttribute}
*/
addRelation(name, targetNoteId, isInheritable = false) {
return this.addAttribute(RELATION, name, targetNoteId, isInheritable);
@ -1359,7 +1359,7 @@ class BNote extends AbstractBeccaEntity {
}
/**
* @return {BNoteRevision|null}
* @returns {BNoteRevision|null}
*/
saveNoteRevision() {
const content = this.getContent();

View File

@ -88,12 +88,12 @@ class AppContext extends Component {
this.triggerEvent('initialRenderComplete');
}
/** @returns {Promise} */
/** @returns {Promise<void>} */
triggerEvent(name, data) {
return this.handleEvent(name, data);
}
/** @returns {Promise} */
/** @returns {Promise<*>} */
triggerCommand(name, data = {}) {
for (const executor of this.components) {
const fun = executor[`${name}Command`];

View File

@ -40,7 +40,7 @@ export default class Component {
return this;
}
/** @returns {Promise} */
/** @returns {Promise<void>} */
handleEvent(name, data) {
try {
const callMethodPromise = this.initialized
@ -61,12 +61,12 @@ export default class Component {
}
}
/** @returns {Promise} */
/** @returns {Promise<void>} */
triggerEvent(name, data) {
return this.parent.triggerEvent(name, data);
}
/** @returns {Promise} */
/** @returns {Promise<void>} */
handleEventInChildren(name, data) {
const promises = [];
@ -82,7 +82,7 @@ export default class Component {
return promises.length > 0 ? Promise.all(promises) : null;
}
/** @returns {Promise} */
/** @returns {Promise<*>} */
triggerCommand(name, data = {}) {
const fun = this[`${name}Command`];

View File

@ -738,7 +738,7 @@ class FNote {
/**
* Return note complement which is most importantly note's content
*
* @return {Promise<FNoteComplement>}
* @returns {Promise<FNoteComplement>}
*/
async getNoteComplement() {
return await this.froca.getNoteComplement(this.noteId);

View File

@ -22,7 +22,7 @@ async function removeAttributeById(noteId, attributeId) {
}
/**
* @return {boolean} - returns true if this attribute has the potential to influence the note in the argument.
* @returns {boolean} - returns true if this attribute has the potential to influence the note in the argument.
* That can happen in multiple ways:
* 1. attribute is owned by the note
* 2. attribute is owned by the template of the note

View File

@ -310,7 +310,7 @@ class Froca {
}
/**
* @return {Promise<FNoteComplement>}
* @returns {Promise<FNoteComplement>}
*/
async getNoteComplement(noteId) {
if (!this.noteComplementPromises[noteId]) {

View File

@ -16,10 +16,10 @@ import SpacedUpdate from "./spaced_update.js";
import shortcutService from "./shortcuts.js";
/**
* This is the main frontend API interface for scripts. It's published in the local "api" object.
* <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>
*
* @constructor
* @hideconstructor
*/
function FrontendScriptApi(startNote, currentNote, originEntity = null, $container = null) {
/** @property {jQuery} container of all the rendered script content */
@ -32,7 +32,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/** @property {object|null} entity whose event triggered this execution */
this.originEntity = originEntity;
// to keep consistency with backend API
/** @property {dayjs} day.js library for date manipulation. See {@link https://day.js.org} for documentation */
this.dayjs = dayjs;
/**
@ -83,7 +83,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* Activates newly created note. Compared to this.activateNote() also makes sure that frontend has been fully synced.
*
* @param {string} notePath (or noteId)
* @return {Promise<void>}
* @returns {Promise<void>}
*/
this.activateNewNote = async notePath => {
await ws.waitForMaxKnownEntityChangeId();
@ -95,9 +95,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Open a note in a new tab.
*
* @method
* @param {string} notePath (or noteId)
* @param {boolean} activate - set to true to activate the new tab, false to stay on the current tab
* @return {Promise<void>}
* @returns {Promise<void>}
*/
this.openTabWithNote = async (notePath, activate) => {
await ws.waitForMaxKnownEntityChangeId();
@ -112,9 +113,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Open a note in a new split.
*
* @method
* @param {string} notePath (or noteId)
* @param {boolean} activate - set to true to activate the new split, false to stay on the current split
* @return {Promise<void>}
* @returns {Promise<void>}
*/
this.openSplitWithNote = async (notePath, activate) => {
await ws.waitForMaxKnownEntityChangeId();
@ -132,6 +134,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Adds a new launcher to the launchbar. If the launcher (id) already exists, it will be updated.
*
* @method
* @deprecated you can now create/modify launchers in the top-left Menu -> Configure Launchbar
* for special needs there's also backend API's createOrUpdateLauncher()
* @param {object} opts
@ -170,9 +173,10 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* Executes given anonymous function on the backend.
* Internally this serializes the anonymous function into string and sends it to backend via AJAX.
*
* @method
* @param {string} script - script to be executed on the backend
* @param {Array.<?>} params - list of parameters to the anonymous function to be send to backend
* @return {Promise<*>} return value of the executed function on the backend
* @returns {Promise<*>} return value of the executed function on the backend
*/
this.runOnBackend = async (script, params = []) => {
if (typeof script === "function") {
@ -233,8 +237,9 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Returns note by given noteId. If note is missing from cache, it's loaded.
**
* @method
* @param {string} noteId
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
*/
this.getNote = async noteId => await froca.getNote(noteId);
@ -244,17 +249,18 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* This is often used to bulk-fill the cache with notes which would have to be picked one by one
* otherwise (by e.g. createNoteLink())
*
* @method
* @param {string[]} noteIds
* @param {boolean} [silentNotFoundError] - don't report error if the note is not found
* @return {Promise<FNote[]>}
* @returns {Promise<FNote[]>}
*/
this.getNotes = async (noteIds, silentNotFoundError = false) => await froca.getNotes(noteIds, silentNotFoundError);
/**
* Update frontend tree (note) cache from the backend.
*
* @param {string[]} noteIds
* @method
* @param {string[]} noteIds
*/
this.reloadNotes = async noteIds => await froca.reloadNotes(noteIds);
@ -262,7 +268,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* Instance name identifies particular Trilium instance. It can be useful for scripts
* if some action needs to happen on only one specific instance.
*
* @return {string}
* @method
* @returns {string}
*/
this.getInstanceName = () => window.glob.instanceName;
@ -316,7 +323,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* @method
* @deprecated - this is now no-op since all the changes should be gracefully handled per widget
* @deprecated this is now no-op since all the changes should be gracefully handled per widget
*/
this.refreshTree = () => {};
@ -336,9 +343,9 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Adds given text to the editor cursor
*
* @method
* @deprecated use addTextToActiveContextEditor() instead
* @param {string} text - this must be clear text, HTML is not supported.
* @method
*/
this.addTextToActiveTabEditor = text => {
console.warn("api.addTextToActiveTabEditor() is deprecated, use addTextToActiveContextEditor() instead.");
@ -349,8 +356,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* Adds given text to the editor cursor
*
* @param {string} text - this must be clear text, HTML is not supported.
* @method
* @param {string} text - this must be clear text, HTML is not supported.
*/
this.addTextToActiveContextEditor = text => appContext.triggerCommand('addTextToActiveEditor', {text});
@ -374,8 +381,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
*
* @deprecated use getActiveContextTextEditor()
* @method
* @deprecated use getActiveContextTextEditor()
* @param [callback] - callback receiving "textEditor" instance
*/
this.getActiveTabTextEditor = callback => {
@ -437,13 +444,15 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
/**
* @method
* @param {object} $el - jquery object on which to setup the tooltip
* @param {object} $el - jquery object on which to set up the tooltip
* @returns {Promise<void>}
*/
this.setupElementTooltip = noteTooltipService.setupElementTooltip;
/**
* @deprecated use protectNote and protectSubtree instead
* @method
* @deprecated use protectNote and protectSubtree instead
* @returns {Promise<void>}
*/
this.protectActiveNote = async () => {
const activeNote = appContext.tabManager.getActiveContextNote();
@ -455,6 +464,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @method
* @param {string} noteId
* @param {boolean} protect - true to protect note, false to unprotect
* @returns {Promise<void>}
*/
this.protectNote = async (noteId, protect) => {
await protectedSessionService.protectNote(noteId, protect, false);
@ -464,6 +474,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @method
* @param {string} noteId
* @param {boolean} protect - true to protect subtree, false to unprotect
* @returns {Promise<void>}
*/
this.protectSubTree = async (noteId, protect) => {
await protectedSessionService.protectNote(noteId, protect, true);
@ -473,7 +484,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* Returns date-note for today. If it doesn't exist, it is automatically created.
*
* @method
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
*/
this.getTodayNote = dateNotesService.getTodayNote;
@ -482,7 +493,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*
* @method
* @param {string} date - e.g. "2019-04-29"
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
* @deprecated use getDayNote instead
*/
this.getDateNote = dateNotesService.getDayNote;
@ -492,7 +503,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*
* @method
* @param {string} date - e.g. "2019-04-29"
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
*/
this.getDayNote = dateNotesService.getDayNote;
@ -501,7 +512,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*
* @method
* @param {string} date - e.g. "2019-04-29"
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
*/
this.getWeekNote = dateNotesService.getWeekNote;
@ -510,7 +521,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*
* @method
* @param {string} month - e.g. "2019-04"
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
*/
this.getMonthNote = dateNotesService.getMonthNote;
@ -519,7 +530,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*
* @method
* @param {string} year - e.g. "2019"
* @return {Promise<FNote>}
* @returns {Promise<FNote>}
*/
this.getYearNote = dateNotesService.getYearNote;
@ -528,7 +539,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
*
* @method
* @param {string} noteId - set hoisted note. 'root' will effectively unhoist
* @return {Promise}
* @returns {Promise<void>}
*/
this.setHoistedNoteId = (noteId) => {
const activeNoteContext = appContext.tabManager.getActiveContext();
@ -544,6 +555,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* @param {function} handler
* @param {string} [namespace] - specify namespace of the handler for the cases where call for bind may be repeated.
* If a handler with this ID exists, it's replaced by the new handler.
* @returns {Promise<void>}
*/
this.bindGlobalShortcut = shortcutService.bindGlobalShortcut;
@ -555,6 +567,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* Typical use case is when new note has been created, we should wait until it is synced into frontend and only then activate it.
*
* @method
* @returns {Promise<void>}
*/
this.waitUntilSynced = ws.waitForMaxKnownEntityChangeId;
@ -562,6 +575,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* This will refresh all currently opened notes which have included note specified in the parameter
*
* @param includedNoteId - noteId of the included note
* @returns {Promise<void>}
*/
this.refreshIncludedNote = includedNoteId => appContext.triggerEvent('refreshIncludedNote', {noteId: includedNoteId});
@ -581,6 +595,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, $contain
* Log given message to the log pane in UI
*
* @param message
* @returns {void}
*/
this.log = message => {
const {noteId} = this.startNote;

View File

@ -115,7 +115,7 @@ export default class LoadResults {
}
/**
* @return {boolean} true if there are changes which could affect the attributes (including inherited ones)
* @returns {boolean} true if there are changes which could affect the attributes (including inherited ones)
* notably changes in note itself should not have any effect on attributes
*/
hasAttributeRelatedChanges() {

View File

@ -6,7 +6,7 @@ import hoistedNoteService from '../services/hoisted_note.js';
import appContext from "../components/app_context.js";
/**
* @return {string|null}
* @returns {string|null}
*/
async function resolveNotePath(notePath, hoistedNoteId = 'root') {
const runPath = await resolveNotePathToSegments(notePath, hoistedNoteId);
@ -19,7 +19,7 @@ async function resolveNotePath(notePath, hoistedNoteId = 'root') {
* notePath as possible. Part of the path might not be valid because of note moving (which causes
* path change) or other corruption, in that case this will try to get some other valid path to the correct note.
*
* @return {string[]}
* @returns {string[]}
*/
async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logErrors = true) {
utils.assertArguments(notePath);

View File

@ -850,7 +850,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
collapseTreeEvent() { this.collapseTree(); }
/**
* @return {FancytreeNode|null}
* @returns {FancytreeNode|null}
*/
getActiveNode() {
return this.tree.getActiveNode();
@ -859,7 +859,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
/**
* focused & not active node can happen during multiselection where the node is selected
* but not activated (its content is not displayed in the detail)
* @return {FancytreeNode|null}
* @returns {FancytreeNode|null}
*/
getFocusedNode() {
return this.tree.getFocusNode();

View File

@ -40,7 +40,7 @@ function getNoteRevision(req) {
/**
* @param {BNoteRevision} noteRevision
* @return {string}
* @returns {string}
*/
function getRevisionFilename(noteRevision) {
let filename = utils.formatDownloadTitle(noteRevision.title, noteRevision.type, noteRevision.mime);

View File

@ -21,28 +21,28 @@ const branchService = require("./branches");
const exportService = require("./export/zip");
/**
* This is the main backend API interface for scripts. It's published in the local "api" object.
* <p>This is the main backend API interface for scripts. All the properties and methods are published in the "api" object
* available in the JS backend notes. You can use e.g. <code>api.log(api.startNote.title);</code></p>
*
* @constructor
* @hideconstructor
*/
function BackendScriptApi(currentNote, apiParams) {
/** @property {BNote} note where script started executing */
this.startNote = apiParams.startNote;
/** @property {BNote} note where script is currently executing. Don't mix this up with concept of active note */
this.currentNote = currentNote;
/** @property {Entity} entity whose event triggered this executions */
/** @property {AbstractBeccaEntity} entity whose event triggered this executions */
this.originEntity = apiParams.originEntity;
for (const key in apiParams) {
this[key] = apiParams[key];
}
/** @property {axios} Axios library for HTTP requests. See https://axios-http.com/ for documentation */
/** @property {axios} Axios library for HTTP requests. See {@link https://axios-http.com} for documentation */
this.axios = axios;
/** @property {dayjs} day.js library for date manipulation. See https://day.js.org/ for documentation */
/** @property {dayjs} day.js library for date manipulation. See {@link https://day.js.org} for documentation */
this.dayjs = dayjs;
/** @property {axios} xml2js library for XML parsing. See https://github.com/Leonidas-from-XIV/node-xml2js for documentation */
/** @property {axios} xml2js library for XML parsing. See {@link https://github.com/Leonidas-from-XIV/node-xml2js} for documentation */
this.xml2js = xml2js;
// DEPRECATED - use direct api.unescapeHtml
@ -75,13 +75,13 @@ function BackendScriptApi(currentNote, apiParams) {
/**
* @method
* @param {string} attributeId
* @returns {Attribute|null}
* @returns {BAttribute|null}
*/
this.getAttribute = attributeId => becca.getAttribute(attributeId);
/**
* This is a powerful search method - you can search by attributes and their values, e.g.:
* "#dateModified =* MONTH AND #log". See full documentation for all options at: https://github.com/zadam/trilium/wiki/Search
* "#dateModified =* MONTH AND #log". See {@link https://github.com/zadam/trilium/wiki/Search} for full documentation for all options
*
* @method
* @param {string} query
@ -105,7 +105,7 @@ function BackendScriptApi(currentNote, apiParams) {
/**
* This is a powerful search method - you can search by attributes and their values, e.g.:
* "#dateModified =* MONTH AND #log". See full documentation for all options at: https://github.com/zadam/trilium/wiki/Search
* "#dateModified =* MONTH AND #log". See {@link https://github.com/zadam/trilium/wiki/Search} for full documentation for all options
*
* @method
* @param {string} query
@ -174,10 +174,11 @@ function BackendScriptApi(currentNote, apiParams) {
/**
* Create text note. See also createNewNote() for more options.
*
* @method
* @param {string} parentNoteId
* @param {string} title
* @param {string} content
* @return {{note: BNote, branch: BBranch}} - object having "note" and "branch" keys representing respective objects
* @returns {{note: BNote, branch: BBranch}} - object having "note" and "branch" keys representing respective objects
*/
this.createTextNote = (parentNoteId, title, content = '') => noteService.createNewNote({
parentNoteId,
@ -190,10 +191,11 @@ function BackendScriptApi(currentNote, apiParams) {
* Create data note - data in this context means object serializable to JSON. Created note will be of type 'code' and
* JSON MIME type. See also createNewNote() for more options.
*
* @method
* @param {string} parentNoteId
* @param {string} title
* @param {object} content
* @return {{note: BNote, branch: BBranch}} object having "note" and "branch" keys representing respective objects
* @returns {{note: BNote, branch: BBranch}} object having "note" and "branch" keys representing respective objects
*/
this.createDataNote = (parentNoteId, title, content = {}) => noteService.createNewNote({
parentNoteId,
@ -280,7 +282,9 @@ function BackendScriptApi(currentNote, apiParams) {
/**
* Log given message to trilium logs and log pane in UI
*
* @method
* @param message
* @returns {void}
*/
this.log = message => {
log.info(message);
@ -316,7 +320,7 @@ function BackendScriptApi(currentNote, apiParams) {
*
* @method
* @param {string} date in YYYY-MM-DD format
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use default calendar
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use the default calendar
* @returns {BNote|null}
* @deprecated use getDayNote instead
*/
@ -327,7 +331,7 @@ function BackendScriptApi(currentNote, apiParams) {
*
* @method
* @param {string} date in YYYY-MM-DD format
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use default calendar
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use the default calendar
* @returns {BNote|null}
*/
this.getDayNote = dateNoteService.getDayNote;
@ -336,7 +340,7 @@ function BackendScriptApi(currentNote, apiParams) {
* Returns today's day note. If such note doesn't exist, it is created.
*
* @method
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use default calendar
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use the default calendar
* @returns {BNote|null}
*/
this.getTodayNote = dateNoteService.getTodayNote;
@ -346,8 +350,9 @@ function BackendScriptApi(currentNote, apiParams) {
*
* @method
* @param {string} date in YYYY-MM-DD format
* @param {object} [options] - "startOfTheWeek" - either "monday" (default) or "sunday"
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use default calendar
* @param {object} [options]
* @param {string} [options.startOfTheWeek=monday] - either "monday" (default) or "sunday"
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use the default calendar
* @returns {BNote|null}
*/
this.getWeekNote = dateNoteService.getWeekNote;
@ -357,7 +362,7 @@ function BackendScriptApi(currentNote, apiParams) {
*
* @method
* @param {string} date in YYYY-MM format
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use default calendar
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use the default calendar
* @returns {BNote|null}
*/
this.getMonthNote = dateNoteService.getMonthNote;
@ -367,15 +372,16 @@ function BackendScriptApi(currentNote, apiParams) {
*
* @method
* @param {string} year in YYYY format
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use default calendar
* @param {BNote} [rootNote] - specify calendar root note, normally leave empty to use the default calendar
* @returns {BNote|null}
*/
this.getYearNote = dateNoteService.getYearNote;
/**
* @method
* @deprecated - use sortNotes instead
* @deprecated use sortNotes instead
* @param {string} parentNoteId - this note's child notes will be sorted
* @returns {void}
*/
this.sortNotesByTitle = parentNoteId => treeService.sortNotes(parentNoteId);
@ -386,9 +392,10 @@ function BackendScriptApi(currentNote, apiParams) {
* @param {string} parentNoteId - this note's child notes will be sorted
* @param {object} [sortConfig]
* @property {string} [sortConfig.sortBy=title] - 'title', 'dateCreated', 'dateModified' or a label name
* see https://github.com/zadam/trilium/wiki/Sorting for details.
* See {@link https://github.com/zadam/trilium/wiki/Sorting} for details.
* @property {boolean} [sortConfig.reverse=false]
* @property {boolean} [sortConfig.foldersFirst=false]
* @returns {void}
*/
this.sortNotes = (parentNoteId, sortConfig = {}) => treeService.sortNotes(
parentNoteId,
@ -404,10 +411,11 @@ function BackendScriptApi(currentNote, apiParams) {
* This method looks similar to toggleNoteInParent() but differs because we're looking up branch by prefix.
*
* @method
* @deprecated - this method is pretty confusing and serves specialized purpose only
* @deprecated this method is pretty confusing and serves specialized purpose only
* @param {string} noteId
* @param {string} prefix
* @param {string|null} parentNoteId
* @returns {void}
*/
this.setNoteToParent = treeService.setNoteToParent;
@ -451,20 +459,23 @@ function BackendScriptApi(currentNote, apiParams) {
/**
* @method
* @deprecated - this is now no-op since all the changes should be gracefully handled per widget
* @deprecated this is now no-op since all the changes should be gracefully handled per widget
* @returns {void}
*/
this.refreshTree = () => {
console.warn("api.refreshTree() is a NO-OP and can be removed from your script.")
};
/**
* @return {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version
* @method
* @returns {{syncVersion, appVersion, buildRevision, dbVersion, dataDirectory, buildDate}|*} - object representing basic info about running Trilium version
*/
this.getAppInfo = () => appInfo
/**
* Creates a new launcher to the launchbar. If the launcher (id) already exists, it will be updated.
*
* @method
* @param {object} opts
* @property {string} opts.id - id of the launcher, only alphanumeric at least 6 characters long
* @property {string} opts.type - one of
@ -544,7 +555,7 @@ function BackendScriptApi(currentNote, apiParams) {
* @param {string} noteId
* @param {string} format - either 'html' or 'markdown'
* @param {string} zipFilePath
* @returns {Promise}
* @returns {Promise<void>}
*/
this.exportSubtreeToZipFile = async (noteId, format, zipFilePath) => await exportService.exportToZipFile(noteId, format, zipFilePath);

View File

@ -9,7 +9,7 @@ const htmlSanitizer = require('../html_sanitizer');
* @param {TaskContext} taskContext
* @param {Buffer} fileBuffer
* @param {BNote} parentNote
* @return {Promise<*[]|*>}
* @returns {Promise<*[]|*>}
*/
async function importOpml(taskContext, fileBuffer, parentNote) {
const xml = await new Promise(function(resolve, reject)

View File

@ -19,7 +19,7 @@ const becca = require("../../becca/becca");
* @param {TaskContext} taskContext
* @param {Buffer} fileBuffer
* @param {BNote} importRootNote
* @return {Promise<*>}
* @returns {Promise<*>}
*/
async function importZip(taskContext, fileBuffer, importRootNote) {
// maps from original noteId (in ZIP file) to newly generated noteId

View File

@ -130,7 +130,7 @@ function getAndValidateParent(params) {
* - {integer} notePosition - default is last existing notePosition in a parent + 10
*
* @param params
* @return {{note: BNote, branch: BBranch}}
* @returns {{note: BNote, branch: BBranch}}
*/
function createNewNote(params) {
const parentNote = getAndValidateParent(params);
@ -674,7 +674,7 @@ function undeleteBranch(branchId, deleteId, taskContext) {
}
/**
* @return return deleted branchIds of an undeleted parent note
* @returns return deleted branchIds of an undeleted parent note
*/
function getUndeletedParentBranchIds(noteId, deleteId) {
return sql.getColumn(`

View File

@ -25,7 +25,7 @@ function getOption(name) {
}
/**
* @return {number}
* @returns {number}
*/
function getOptionInt(name) {
const val = getOption(name);
@ -40,7 +40,7 @@ function getOptionInt(name) {
}
/**
* @return {boolean}
* @returns {boolean}
*/
function getOptionBool(name) {
const val = getOption(name);

View File

@ -9,7 +9,7 @@ class Expression {
* @param {NoteSet} inputNoteSet
* @param {object} executionContext
* @param {SearchContext} searchContext
* @return {NoteSet}
* @returns {NoteSet}
*/
execute(inputNoteSet, executionContext, searchContext) {}
}

View File

@ -123,7 +123,7 @@ class NoteFlatTextExp extends Expression {
* Returns noteIds which have at least one matching tokens
*
* @param {NoteSet} noteSet
* @return {BNote[]}
* @returns {BNote[]}
*/
getCandidateNotes(noteSet) {
const candidateNotes = [];

View File

@ -138,7 +138,7 @@ function loadNeededInfoFromDatabase() {
/**
* @param {Expression} expression
* @param {SearchContext} searchContext
* @return {SearchResult[]}
* @returns {SearchResult[]}
*/
function findResultsWithExpression(expression, searchContext) {
if (searchContext.dbLoadNeeded) {
@ -230,7 +230,7 @@ function parseQueryToExpression(query, searchContext) {
/**
* @param {string} query
* @return {BNote[]}
* @returns {BNote[]}
*/
function searchNotes(query, params = {}) {
const searchResults = findResultsWithQuery(query, new SearchContext(params));
@ -241,7 +241,7 @@ function searchNotes(query, params = {}) {
/**
* @param {string} query
* @param {SearchContext} searchContext
* @return {SearchResult[]}
* @returns {SearchResult[]}
*/
function findResultsWithQuery(query, searchContext) {
query = query || "";
@ -259,7 +259,7 @@ function findResultsWithQuery(query, searchContext) {
/**
* @param {string} query
* @param {SearchContext} searchContext
* @return {BNote|null}
* @returns {BNote|null}
*/
function findFirstNoteWithQuery(query, searchContext) {
const searchResults = findResultsWithQuery(query, searchContext);

View File

@ -303,7 +303,7 @@ module.exports = {
* @method
* @param {string} query - SQL query with ? used as parameter placeholder
* @param {object[]} [params] - array of params if needed
* @return [object] - single value
* @returns [object] - single value
*/
getValue,
@ -313,7 +313,7 @@ module.exports = {
* @method
* @param {string} query - SQL query with ? used as parameter placeholder
* @param {object[]} [params] - array of params if needed
* @return {object} - map of column name to column value
* @returns {object} - map of column name to column value
*/
getRow,
getRowOrNull,
@ -324,7 +324,7 @@ module.exports = {
* @method
* @param {string} query - SQL query with ? used as parameter placeholder
* @param {object[]} [params] - array of params if needed
* @return {object[]} - array of all rows, each row is a map of column name to column value
* @returns {object[]} - array of all rows, each row is a map of column name to column value
*/
getRows,
getRawRows,
@ -337,7 +337,7 @@ module.exports = {
* @method
* @param {string} query - SQL query with ? used as parameter placeholder
* @param {object[]} [params] - array of params if needed
* @return {object} - map of first column to second column
* @returns {object} - map of first column to second column
*/
getMap,
@ -347,7 +347,7 @@ module.exports = {
* @method
* @param {string} query - SQL query with ? used as parameter placeholder
* @param {object[]} [params] - array of params if needed
* @return {object[]} - array of first column of all returned rows
* @returns {object[]} - array of first column of all returned rows
*/
getColumn,

View File

@ -229,7 +229,7 @@ function sortNotesIfNeeded(parentNoteId) {
}
/**
* @deprecated - this will be removed in the future
* @deprecated this will be removed in the future
*/
function setNoteToParent(noteId, prefix, parentNoteId) {
const parentNote = becca.getNote(parentNoteId);

View File

@ -38,17 +38,17 @@ class SBranch extends AbstractShacaEntity {
this.shaca.childParentToBranch[`${this.noteId}-${this.parentNoteId}`] = this;
}
/** @return {SNote} */
/** @returns {SNote} */
get childNote() {
return this.shaca.notes[this.noteId];
}
/** @return {SNote} */
/** @returns {SNote} */
getNote() {
return this.childNote;
}
/** @return {SNote} */
/** @returns {SNote} */
get parentNote() {
return this.shaca.notes[this.parentNoteId];
}

View File

@ -200,7 +200,7 @@ class SNote extends AbstractShacaEntity {
return this.__attributeCache;
}
/** @return {SAttribute[]} */
/** @returns {SAttribute[]} */
__getInheritableAttributes(path) {
if (path.includes(this.noteId)) {
return [];

View File

@ -1,13 +1,14 @@
const sanitizeHtml = require('sanitize-html');
function transform(content) {
return sanitizeHtml(content, {
const result = sanitizeHtml(content, {
allowedTags: [
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
'h4', 'h5', 'h6', 'blockquote', 'p', 'a', 'ul', 'ol',
'li', 'b', 'i', 'strong', 'em', 'strike', 's', 'del', 'abbr', 'code', 'hr', 'br', 'div',
'table', 'thead', 'caption', 'tbody', 'tr', 'th', 'td', 'pre', 'section', 'img',
'figure', 'figcaption', 'span', 'label', 'input',
],
nonTextTags: [ 'style', 'script', 'textarea', 'option', 'h1', 'h2', 'h3', 'nav' ],
allowedAttributes: {
'a': [ 'href', 'class', 'data-note-path' ],
'img': [ 'src' ],
@ -22,19 +23,27 @@ function transform(content) {
'en-media': [ 'hash' ]
},
allowedSchemes: ['http', 'https', 'ftp', 'mailto', 'data', 'evernote'],
// transformTags: {
// 'h1': (tagName, attribs) => {
// return {
// tagName: '<span>',
// // text: 'ddd'
// };
// }
// },
transformTags: {
// 'h5': sanitizeHtml.simpleTransform('strong', {}, false),
'table': sanitizeHtml.simpleTransform('table', {}, false)
},
});
return result.replace(/<table>/gi, '<figure class="table"><table>')
.replace(/<\/table>/gi, '</table></figure>')
.replace(/<div><\/div>/gi, '')
.replace(/<h5>/gi, '<p><strong>')
.replace(/<\/h5>/gi, '</strong></p>')
.replace(/<h4>/gi, '<h2>')
.replace(/<\/h4>/gi, '</h2>')
.replace(/<span class="signature-attributes">opt<\/span>/gi, '')
.replace(/<h2>.*new (BackendScriptApi|FrontendScriptApi).*<\/h2>/gi, '')
;
}
const fs = require("fs");
const path = require("path");
const html = require("html");
let sourceFiles = [];
const getFilesRecursively = (directory) => {
@ -43,24 +52,26 @@ const getFilesRecursively = (directory) => {
const absolute = path.join(directory, file);
if (fs.statSync(absolute).isDirectory()) {
getFilesRecursively(absolute);
} else {
} else if (file.endsWith('.html')) {
sourceFiles.push(absolute);
}
}
};
getFilesRecursively('./docs');
getFilesRecursively('./tmp/api_docs');
for (const sourcePath of sourceFiles) {
console.log("Transforming file", sourcePath);
const content = fs.readFileSync(sourcePath);
const content = fs.readFileSync(sourcePath).toString();
const transformedContent = transform(content);
const prettifiedContent = html.prettyPrint(transformedContent, {indent_size: 2});
const filteredContent = prettifiedContent
.replace(/<br \/>Documentation generated by <a href="https:\/\/github.com\/jsdoc\/jsdoc">[^<]+<\/a>/gi, '')
.replace(/JSDoc: (Class|Module): [a-z]+/gi, '');
const destPath = sourcePath.replaceAll("docs", "docs/transformed");
const destPath = sourcePath.replaceAll("tmp", "docs");
fs.mkdirSync(path.dirname(destPath), {recursive: true});
fs.writeFileSync(destPath, transformedContent);
fs.writeFileSync(destPath, filteredContent.trim());
console.log(destPath);
}
}