### Install and Run Development Server Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-imdb-top250-importer/README.md Install project dependencies and start the Vite development server for live preview. This is used for developing the Logseq plugin. ```bash npm install # or yarn install npm run dev # or yarn run dev ``` -------------------------------- ### Install and Build Plugin Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-awesome-fonts/README.md Install dependencies and build the plugin using npm. This is a prerequisite for loading the plugin. ```bash npm install && npm run build ``` -------------------------------- ### Development Build Command Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Command to install dependencies and start the development server for a Logseq plugin. Assumes a build tool like Vite or Rollup is configured. ```bash cd logseq-plugin-name npm install npm run dev ``` -------------------------------- ### Example: Insert Template Slash Command Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md An example of registering a slash command to insert a predefined daily template into the current editing block. ```javascript logseq.Editor.registerSlashCommand('📋 Daily Template', async () => { const template = ` ## Morning - [ ] Review goals ## Evening - [ ] Reflect on day ` await logseq.Editor.insertAtEditingCursor(template) }) ``` -------------------------------- ### Pomodoro Timer Macro Renderer Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Example of a macro renderer that displays a start button or a timer based on whether the pomodoro has started. It uses `logseq.provideUI` to render the button or timer. ```javascript logseq.App.onMacroRendererSlotted(({ slot, payload }) => { const [type, startTime, durationMins] = payload.arguments if (type?.startsWith(':pomodoro_')) { const identity = type.split('_')[1].trim() const pomoId = 'pomodoro-timer-start_' + identity if (!startTime?.trim()) { // Not started - show START button logseq.provideUI({ key: pomoId, slot, reset: true, template: "` `" }) } else { // Started - show timer renderTimer({ pomoId, slotId: slot, startTime, durationMins }) } } }) ``` -------------------------------- ### Example: Pin Block Context Menu Action Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md An example of registering a context menu item to pin or unpin a block by adding/removing a 'pinned' property. ```javascript logseq.Editor.registerBlockContextMenuItem('📌 Pin Block', ({ blockId }) => { logseq.Editor.getBlock(blockId).then(block => { if (block?.properties?.pinned) { logseq.App.showMsg('Already pinned') } else { logseq.Editor.upsertBlockProperty(blockId, 'pinned', true) logseq.App.showMsg('Block pinned!') } }) }) ``` -------------------------------- ### Example: Data Fetching Slash Command Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Demonstrates registering a slash command that fetches data from a user-provided URL and inserts a formatted link into the current editing block. ```javascript logseq.Editor.registerSlashCommand('🔗 Fetch URL', async () => { const url = prompt('Enter URL:') if (!url) return const response = await fetch(url) const title = response.headers.get('content-type') await logseq.Editor.insertAtEditingCursor(`[${url}](${url})`) }) ``` -------------------------------- ### Access and Update Plugin Settings Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Access the current plugin settings and update them using `logseq.updateSettings()`. This example shows how to read settings and listen for changes. ```javascript const [settings, setSettings] = useState(logseq.settings) useEffect(() => { logseq.on('settings:changed', (a) => { setSettings(a) }) }, []) return (
) ``` -------------------------------- ### Logseq Plugin: Async Data Loading and UI Setup Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Initialization pattern for Logseq plugins that involves asynchronous data loading before setting up the UI and providing a model. Includes updating settings with new data. ```javascript async function main() { // Load data const data = await fetchPluginData() // Set up UI with data logseq.provideUI({ key: 'dashboard', template: renderDashboard(data) }) // Register model with data access logseq.provideModel({ updateData: async () => { const newData = await fetchPluginData() logseq.updateSettings({ cachedData: newData }) } }) } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Svelte Plugin Entry Point Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Example of a Svelte component used as a Logseq plugin entry point. It registers a UI item in the toolbar and sets up the main UI. ```typescript import "@logseq/libs" import App from "./App.svelte" function createModel() { return { openQueryPlayground() { logseq.showMainUI() } } } function main() { new App({ target: document.querySelector("#app") }) logseq.setMainUIInlineStyle({ zIndex: 11 }) logseq.App.registerUIItem('toolbar', { key: "open-query-playground", template: `🗄` }) } logseq.ready(createModel()).then(main).catch(console.error) ``` -------------------------------- ### Render React App at Document Root Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md Demonstrates mounting a React application to the '#app' element, which is typically at the document root. This setup is suitable for complex UI frameworks and includes registering a toolbar item to toggle the main UI. ```javascript import { createRoot } from 'react-dom/client' import App from './App.jsx' let reactRoot = null function mountApp() { const el = document.getElementById('app') if (!el) return if (!reactRoot) { reactRoot = createRoot(el) } reactRoot.render() } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', mountApp) } else { mountApp() } function main() { logseq.App.registerUIItem('toolbar', { key: 'my-plugin', template: '🎨' }) logseq.provideModel({ toggle() { logseq.toggleMainUI() } }) } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Vue Plugin with UI Integration Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Demonstrates integrating a Vue application into a Logseq plugin. This example shows how to mount a Vue app and register a UI item in the toolbar to trigger a UI action. ```javascript import '@logseq/libs' import { createApp } from 'vue' import App from './App.vue' function createModel() { return { openCalendar() { logseq.showMainUI() } } } function main() { logseq.setMainUIInlineStyle({ position: 'fixed', zIndex: 11 }) logseq.App.registerUIItem('toolbar', { key: 'open-calendar', template: '📅' }) // Mount Vue app to #app element createApp(App).mount('#app') } logseq.ready(createModel()).then(main).catch(console.error) ``` -------------------------------- ### Preact Plugin Entry Point Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Example of a Preact component used as a Logseq plugin entry point. It registers a UI item in the toolbar and provides a model for UI interaction. ```javascript import '@logseq/libs' import { h, render } from 'preact' import { useState, useEffect } from 'preact/hooks' function App(props) { const [count, setCount] = useState(0) return (
) } function main() { const doc = document render(, doc.querySelector('#app')) logseq.provideModel({ showPanel() { logseq.toggleMainUI() } }) logseq.App.registerUIItem('toolbar', { key: 'my-btn', template: '🎨' }) } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Create and Get Tag Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md Demonstrates creating a new tag and retrieving an existing tag by its name. Useful for managing tags within Logseq. ```javascript const movieTag = await logseq.Editor.createTag('movie') const existingTag = await logseq.Editor.getTag('important') ``` -------------------------------- ### Logseq Plugin Initialization Error Handling Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Example of robust error handling for Logseq plugin initialization. Logs errors to the console and displays a message to the user if loading fails. ```javascript logseq.ready(main).catch(error => { console.error('Plugin initialization failed:', error) logseq.App.showMsg('Failed to load plugin', 'error') }) ``` -------------------------------- ### Real-time Counter Macro Renderer Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md This example demonstrates a real-time counter using a macro renderer. It utilizes `localStorage` to store and update the count, and `logseq.provideUI` to render the counter and increment button. The UI updates automatically when the model's `increment` function is called. ```javascript logseq.App.onMacroRendererSlotted(({ slot, payload }) => { const [type] = payload.arguments if (!type?.startsWith(':counter_')) return const counterId = type.split('_')[1] const key = `counter-${counterId}` function render() { const count = localStorage.getItem(key) || '0' logseq.provideUI({ key, slot, reset: true, template: "`
${count}
`" }) } render() }) ``` ```javascript logseq.provideModel({ increment({ dataset }) { const counterId = dataset.counterId const key = `counter-${counterId}` const count = parseInt(localStorage.getItem(key) || '0') + 1 localStorage.setItem(key, count) // UI re-renders automatically } }) ``` -------------------------------- ### React Plugin with State Management Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Example of a Logseq plugin built with React, demonstrating state management using useState and rendering a button that updates a count. Ensure React and ReactDOM are correctly set up for the plugin environment. ```typescript import React from 'react' import { createRoot } from 'react-dom/client' import '@logseq/libs' const App: React.FC = () => { const [count, setCount] = React.useState(0) return } let reactRoot: Root | null = null function mountAppIfNeeded() { const el = document.getElementById('app') if (!el) return if (!reactRoot) { reactRoot = createRoot(el) } reactRoot.render() } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => mountAppIfNeeded()) } else { mountAppIfNeeded() } function main() { logseq.App.registerUIItem('toolbar', { key: 'my-plugin', template: '🎨' }) logseq.provideModel({ toggleUI() { logseq.toggleMainUI() } }) } logseq.ready(main).catch(console.error) ``` -------------------------------- ### API Reference Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/MANIFEST.txt Provides access to the complete API documentation, including method signatures, parameter tables, return types, usage examples, and source file references. ```APIDOC ## API Reference This section provides comprehensive documentation for the Logseq plugin API. It includes detailed information on all public APIs, method signatures, parameter tables, return types, usage examples, and source file references with line numbers. ### Key Documentation Files: - **logseq-api.md**: Contains the complete API documentation. - **editor-operations.md**: Details block and page operations. - **ui-management.md**: Covers UI rendering functionalities. - **plugin-entry-points.md**: Provides patterns for plugin bootstrapping. ### Type Reference: - **types.md**: Lists and describes all core and custom types used within the Logseq API, including blocks, pages, tags, properties, event types, and configuration types. ``` -------------------------------- ### Theme Plugin Manifest Configuration Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Example JSON snippet for the 'package.json' file, defining theme properties for a Logseq theme plugin. Specifies theme name, CSS URL, description, and mode. ```json { "logseq": { "themes": [ { "name": "base16-default-dark", "url": "./css/base16-default-dark.css", "description": "/* Base16 Default Dark theme */", "mode": "dark" } ] } } ``` -------------------------------- ### Create Tag in Logseq Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Creates a new tag with an optional set of properties. The example shows how to create a 'movie' tag and log its UUID if successful. ```typescript const tag = await logseq.Editor.createTag(tagName, properties) // Example: Create 'movie' tag const movieTag = await logseq.Editor.createTag('movie') if (movieTag?.uuid) { console.log('Tag created:', movieTag.uuid) } ``` -------------------------------- ### Register Block Context Menu Items Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md Add custom items to the block context menu for specific actions. This example shows how to pin a block and copy its link. ```javascript logseq.Editor.registerBlockContextMenuItem( '📌 Pin Block', async ({ blockId }) => { const block = await logseq.Editor.getBlock(blockId) if (block?.properties?.pinned) { logseq.App.showMsg('Already pinned', 'warning') return } await logseq.Editor.upsertBlockProperty(blockId, 'pinned', true) logseq.App.showMsg('Block pinned!', 'success') } ) logseq.Editor.registerBlockContextMenuItem( '🔗 Share Link', async ({ blockId }) => { const block = await logseq.Editor.getBlock(blockId) const link = `logseq://block/${block.uuid}` if (navigator.clipboard) { await navigator.clipboard.writeText(link) logseq.App.showMsg('Link copied!', 'success') } } ) ``` -------------------------------- ### Complete Block Workflow in Logseq Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Demonstrates how to insert, update, and retrieve block details using the Logseq Editor API. Also shows how to get the currently active editing block. ```javascript // Insert a new block after current const newBlock = await logseq.Editor.insertBlock( currentBlockUuid, 'New block content', { before: false, sibling: true } ) // Update existing block await logseq.Editor.updateBlock(blockUuid, 'Updated content') // Get block details const block = await logseq.Editor.getBlock(blockUuid) console.log(block.uuid, block.content, block.properties) // Get current editing block const current = await logseq.Editor.getCurrentBlock() ``` -------------------------------- ### Register Toolbar Button Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md Register a UI item to the Logseq toolbar using `logseq.App.registerUIItem`. This example shows how to add a button with an icon and attach a click handler. ```typescript logseq.App.registerUIItem( 'toolbar', { key: 'awesome-fonts-btn', template: ( ` ` ) } ) logseq.provideModel({ openFontsPanel(e) { const { rect } = e logseq.setMainUIInlineStyle({ top: `${rect.top + 20}px`, left: `${rect.right - 10}px` }) logseq.toggleMainUI() } }) ``` -------------------------------- ### Render Macro with Parameters and Actions Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md Handles macros that accept parameters like duration and task name, and provides a button to trigger model actions. The macro type should start with ':timer_'. ```javascript logseq.App.onMacroRendererSlotted(({ slot, payload }) => { const [type, duration, taskName] = payload.arguments if (!type?.startsWith(':timer_')) return const timerId = type.split('_')[1] logseq.provideUI({ key: `timer-${timerId}`, slot, reset: true, template: `

Task: ${taskName}

Duration: ${duration} minutes

` }) }) logseq.provideModel({ startTimer({ dataset }) { const timerId = dataset.timerId // Start timer logic... } }) ``` -------------------------------- ### Initialize Plugin Settings with Defaults Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md Initializes plugin settings with default values and demonstrates how to access them, providing fallbacks for undefined settings. ```javascript // Initialize with default settings function main() { const defaults = { googleFontFamily: 'Noto Serif SC', contentWidthMode: 'normal', zoomFactor: 100 } // Settings available at logseq.settings const currentFontFamily = logseq.settings?.googleFontFamily || defaults.googleFontFamily } ``` -------------------------------- ### logseq.ready() - Bootstrap Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/MANIFEST.txt Initializes the plugin and provides access to the Logseq API once the application is ready. This is the primary entry point for plugin execution. ```APIDOC ## logseq.ready() ### Description Bootstrap function to ensure the Logseq API is available before executing plugin code. It takes a callback function that will be executed once the Logseq application is ready. ### Method Function Call ### Endpoint N/A (JavaScript function) ### Parameters #### Callback Function - **callback** (function) - Required - The function to execute once Logseq is ready. ### Request Example ```javascript logseq.ready(() => { console.log('Logseq is ready!'); // Plugin initialization code here }).catch(err => { console.error('Error initializing plugin:', err); }); ``` ### Response #### Success Response N/A (Executes callback) #### Response Example N/A ``` -------------------------------- ### Initialize Plugin with Bootstrap Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Initializes the plugin using `logseq.ready`. The optional model parameter can provide event handlers and callback methods. This is the core entrypoint for all plugins. ```typescript logseq.ready(model?: object): Promise ``` ```javascript import '@logseq/libs' async function main() { logseq.App.showMsg('Plugin loaded') } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Get Tag in Logseq Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Retrieves a tag by its name. This is typically used to check for the existence of a tag before creating it or to get its properties. ```javascript const tag = await logseq.Editor.getTag('tagName') if (tag?.uuid) { // Tag exists, use it logseq.App.pushState('page', { name: tag.uuid }) } ``` -------------------------------- ### Build for Production Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-imdb-top250-importer/README.md Compile the plugin for production deployment. This command bundles the application for distribution. ```bash npm run build # or yarn run build ``` -------------------------------- ### Retrieve and Apply User Configurations Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md Fetches the user's configuration and applies a dark theme if the preferred theme mode is 'dark'. Demonstrates accessing and acting on user settings. ```javascript const config = await logseq.App.getUserConfigs() if (config.preferredThemeMode === 'dark') { applyDarkTheme() } ``` -------------------------------- ### getEditingCursorPosition Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Gets the current editing cursor position and DOM rect. This is useful for positioning UI elements relative to the cursor. ```APIDOC ## getEditingCursorPosition ### Description Gets the current editing cursor position and DOM rect. ### Method GET (conceptual) ### Endpoint logseq.Editor.getEditingCursorPosition() ### Return Type ```typescript interface CursorPosition { left: number top: number rect: DOMRect } ``` ### Example ```javascript const { left, top, rect } = await logseq.Editor.getEditingCursorPosition() // Position UI at cursor location element.style.left = (left + rect.left) + 'px' element.style.top = (top + rect.top) + 'px' ``` ``` -------------------------------- ### Render Simple Macro Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md Renders custom content for a simple macro based on its identity. Ensure the macro type starts with ':my-macro_'. ```javascript logseq.App.onMacroRendererSlotted(({ slot, payload }) => { const [type] = payload.arguments if (!type?.startsWith(':my-macro_')) return const identity = type.split('_')[1] logseq.provideUI({ key: `my-macro-${identity}`, slot, reset: true, template: `

Custom macro content

` }) }) ``` -------------------------------- ### Get Current Page Blocks Tree Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Retrieves the block tree structure of the current page. This can be used to access and manipulate existing blocks. ```javascript const blocks = await logseq.Editor.getCurrentPageBlocksTree() const firstBlock = blocks[0] await logseq.Editor.insertBlock(firstBlock.uuid, 'New content', { before: true }) ``` -------------------------------- ### Listen to Logseq Events Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md Demonstrates how to subscribe to various Logseq events, including settings changes, UI visibility, theme mode, text selection, and macro rendering. Ensure necessary functions like applySettings, initializeUI, cleanup, applyTheme, handleSelection, and renderMacro are defined elsewhere. ```javascript // Settings change logseq.on('settings:changed', (settings) => { console.log('Settings updated:', settings) applySettings(settings) }) // UI visibility logseq.on('ui:visible:changed', ({ visible }) => { if (visible) { initializeUI() } else { cleanup() } }) // Theme change logseq.App.onThemeModeChanged(({ mode }) => { applyTheme(mode) }) // Text selection end logseq.Editor.onInputSelectionEnd((e) => { handleSelection(e.text, e.point) }) // Macro rendering logseq.App.onMacroRendererSlotted(({ slot, payload }) => { renderMacro(slot, payload) }) ``` -------------------------------- ### Get Editing Cursor Position Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Retrieves the current cursor position and its DOM rect. Useful for positioning UI elements relative to the cursor. ```javascript const { left, top, rect } = await logseq.Editor.getEditingCursorPosition() // Position UI at cursor location element.style.left = (left + rect.left) + 'px' element.style.top = (top + rect.top) + 'px' ``` -------------------------------- ### Get Current Editing Block Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Retrieves the block that is currently being edited by the user. Returns an object containing the block's content and UUID. ```javascript const { content, uuid } = await logseq.Editor.getCurrentBlock() logseq.App.showMsg(`Block #${uuid}: ${content}`) ``` -------------------------------- ### Logseq Ready Function Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-hello-world/README.md The `ready` function is an entry point for plugins, often used to register callbacks or initialize plugin functionality when Logseq is ready. ```APIDOC ## `ready` ### Description Initializes the plugin or registers a callback function to be executed when Logseq is ready. ### Signature `ready(callback?: (e: any) => void | {}): Promise` ### Parameters * `callback` (function | object) - Optional. A function to be called when Logseq is ready, or an object. ### Returns A Promise that resolves with any relevant data upon completion. ``` -------------------------------- ### Get Block by UUID Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Retrieves a specific block using its unique identifier (UUID). Returns the block object if found, otherwise returns null. ```javascript const block = await logseq.Editor.getBlock(blockUuid) if (block) { const newContent = block.content.replace(/oldText/, 'newText') await logseq.Editor.updateBlock(blockUuid, newContent) } ``` -------------------------------- ### Get Cursor Position Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Retrieves the current cursor's position within the editor. Useful for positioning UI elements like context menus. ```typescript const position = await logseq.Editor.getEditingCursorPosition() // Returns: // { // left: number, // X offset in editor // top: number, // Y offset in editor // rect: DOMRect // Editor container bounds // } ``` ```javascript const { left, top, rect } = await logseq.Editor.getEditingCursorPosition() logseq.provideUI({ key: 'my-popup', template: '', style: { position: 'fixed', left: (left + rect.left) + 'px', top: (top + rect.top + 30) + 'px' } }) ``` -------------------------------- ### Configure Development Entry Point Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md Set the `devEntry` in the `package.json` file to specify a URL for hot-reload development. This allows the plugin to load from a development server instead of built files. ```json { "logseq": { "devEntry": "http://localhost:5173" } } ``` -------------------------------- ### Create and Log New Page Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md Creates a new page with a specified name and logs its name if the creation was successful. Demonstrates basic page creation workflow. ```javascript const page = await logseq.Editor.createPage('My Notes') if (page?.uuid) { console.log('Created page:', page.name) } ``` -------------------------------- ### Get Cursor Position Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Retrieves the current editing cursor's position within the editor, including its X/Y coordinates and the bounding box of the editor container. ```APIDOC ## Get Cursor Position ### Description Retrieves the current editing cursor position. ### Method ```typescript const position = await logseq.Editor.getEditingCursorPosition() ``` ### Response #### Success Response - **position** (object) - An object containing the cursor's position. - **left** (number) - The X offset of the cursor within the editor. - **top** (number) - The Y offset of the cursor within the editor. - **rect** (DOMRect) - The bounding box of the editor container. ### Use Case Position context menu or overlay at cursor ### Example: Show Popup at Cursor ```javascript const { left, top, rect } = await logseq.Editor.getEditingCursorPosition() logseq.provideUI({ key: 'my-popup', template: '', style: { position: 'fixed', left: (left + rect.left) + 'px', top: (top + rect.top + 30) + 'px' } }) ``` ``` -------------------------------- ### Get and Walk Current Page Blocks Tree in Logseq Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md Retrieves all blocks from the current page as a tree structure and provides a function to recursively traverse and process them. ```javascript const blocks = await logseq.Editor.getCurrentPageBlocksTree() // Walk the tree structure function walkBlocks(blocks, depth = 0) { blocks.forEach(block => { console.log(' '.repeat(depth) + block.content) if (block.children?.length) { walkBlocks(block.children, depth + 1) } }) } walkBlocks(blocks) ``` -------------------------------- ### Import Item with Multiple Properties Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md This pattern demonstrates creating a Logseq page for an item and populating it with various properties, including simple key-value pairs and references to other pages. ```javascript async function importMovie(movie) { // Create page const page = await logseq.Editor.createPage( movie.title, {}, { createFirstBlock: true } ) if (!page?.uuid) { throw new Error(`Failed to create page: ${movie.title}`) } try { // Tag the page await logseq.Editor.addBlockTag(page.uuid, 'movie') // Simple properties await logseq.Editor.upsertBlockProperty(page.uuid, 'cover', movie.image || '') await logseq.Editor.upsertBlockProperty(page.uuid, 'url', movie.url || '') await logseq.Editor.upsertBlockProperty(page.uuid, 'rating', movie.rating || 0) // Create related pages for references const directorPages = [] if (movie.directors?.length) { for (const directorName of movie.directors) { const directorPage = await logseq.Editor.createPage(directorName) if (directorPage?.uuid) { await logseq.Editor.addBlockTag(directorPage.uuid, 'director') directorPages.push(directorPage) } } } // Link references if (directorPages.length) { await logseq.Editor.upsertBlockProperty( page.uuid, 'director', directorPages.map(p => p.id), { reset: true } ) } // Add description as content await logseq.Editor.appendBlockInPage(page.uuid, movie.description) return page } catch (error) { console.error(`Failed to import ${movie.title}:`, error) throw error } } ``` -------------------------------- ### provideUI Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Provides dynamic UI content, allowing plugins to replace or create UI elements. It requires a configuration object with a key, and optionally accepts a slot, template, and reset flag. ```APIDOC ## provideUI ### Description Provides dynamic UI content (replaces or creates UI). ### Method void ### Endpoint logseq.provideUI(config: UIConfig) ### Parameters #### Request Body - **config.key** (string) - Required - Unique identifier for this UI - **config.slot** (string) - Optional - Renderer slot name - **config.template** (string) - Required - HTML template - **config.reset** (boolean) - Optional - If true, clear previous content ### Request Example ```javascript logseq.provideUI({ key: 'my-overlay', template: `

Hello from plugin

`, reset: true }) ``` ### Response None ``` -------------------------------- ### Popup at Cursor Position on Selection End Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md Display a popup near the cursor when text selection ends. This example shows how to capture selected text and display it in a custom UI. ```javascript logseq.Editor.onInputSelectionEnd((e) => { const { x, y } = e.point const selectedText = e.text logseq.provideUI({ key: 'selection-popup', template: ` `, style: { position: 'fixed', left: x + 'px', top: y + 30 + 'px', zIndex: '1000', backgroundColor: 'var(--ls-primary-background-color)', color: 'var(--ls-primary-text-color)', padding: '10px', borderRadius: '4px' } }) logseq.showMainUI() }) ``` -------------------------------- ### logseq.ready Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Initializes the plugin. The optional model parameter provides event handlers and callback methods that can be invoked from UI templates. ```APIDOC ## logseq.ready ### Description Initializes the plugin. The optional model parameter provides event handlers and callback methods. ### Method ```typescript logseq.ready(model?: object): Promise ``` ### Parameters #### Path Parameters - **model** (object) - Optional - Object containing methods callable from UI templates via `data-on-click` ### Request Example ```javascript import '@logseq/libs' async function main() { logseq.App.showMsg('Plugin loaded') } logseq.ready(main).catch(console.error) ``` ### Source Core entrypoint, used in all samples ``` -------------------------------- ### Simple Function-based Plugin Initialization Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Initializes a plugin using a simple async function and displays a message. Wrap the call with .catch(console.error) for robust error handling. ```javascript import '@logseq/libs' async function main() { logseq.App.showMsg('Plugin initialized!') } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Get and Use Editing Cursor Position Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md Retrieves the current editing cursor's position and dimensions, then uses these values to style an element. Useful for UI elements that follow the cursor. ```javascript const { left, top, rect } = await logseq.Editor.getEditingCursorPosition() element.style.left = (left + rect.left) + 'px' element.style.top = (top + rect.top) + 'px' ``` -------------------------------- ### Full package.json Configuration for Logseq Plugin Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md Includes all available configuration options in package.json for a Logseq plugin, such as development server entry point, icon, and repository URL. ```json { "name": "logseq-plugin-example", "version": "0.0.1", "main": "index.html", "logseq": { "id": "logseq-plugin-example", "title": "Example Plugin", "description": "A sample plugin", "author": "author name", "version": "0.0.1", "minAppVersion": "0.9.0", "devEntry": "http://localhost:5173", "icon": "icon.png", "repo": "https://github.com/user/repo", "themes": [] } } ``` -------------------------------- ### Logseq Plugin with Settings Persistence Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md This plugin demonstrates how to load default settings, merge them with user-defined preferences, and react to setting changes. It also includes a toolbar button to open a settings UI. ```javascript import '@logseq/libs' function main() { // Load default settings const defaults = { fontSize: 14, darkMode: false } const settings = { ...defaults, ...logseq.settings } // Watch for setting changes logseq.on('settings:changed', (newSettings) => { applySettings(newSettings) }) // UI for changing settings logseq.App.registerUIItem('toolbar', { key: 'settings-btn', template: '⚙️' }) logseq.provideModel({ openSettings() { logseq.showMainUI() } }) } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Vanilla JavaScript Plugin DOM Manipulation Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md A basic plugin example using vanilla JavaScript to directly manipulate the DOM. This is suitable for plugins that primarily interact with the page's structure. ```javascript import '@logseq/libs' function main() { // Direct DOM access const app = document.getElementById('app') const button = document.createElement('button') button.textContent = 'Click me' app.appendChild(button) } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Logseq Plugin Bootstrap Pattern Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/OVERVIEW.md This is the basic structure for all Logseq plugins, demonstrating the entry point and initialization process. ```javascript async function main() { // Initialize plugin // Register commands, handlers, UI items } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Minimal Logseq Plugin Initialization Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/common-patterns.md The simplest Logseq plugin structure. It loads the necessary libraries and displays a message upon successful initialization. ```javascript import '@logseq/libs' function main() { logseq.App.showMsg('Plugin loaded') } logseq.ready(main).catch(console.error) ``` -------------------------------- ### Get User Configuration Settings Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Retrieves the user's current Logseq configuration settings, including preferred theme mode. This is useful for adapting plugin behavior based on user preferences. ```typescript const config = await logseq.App.getUserConfigs() if (config.preferredThemeMode === 'dark') { // Apply dark theme } ``` -------------------------------- ### Portal-Based UI Rendering Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md Demonstrates how to render complex UI applications (React, Vue, Svelte) into a specific DOM element, typically the '#app' element, for root-level rendering. ```APIDOC ## Portal-Based UI Rendering ### Description For complex React/Vue/Svelte applications, this pattern allows rendering your UI directly to a designated DOM element, such as `#app`, enabling root-level rendering. ### Example: Rendering React App ```javascript import { createRoot } from 'react-dom/client' import App from './App.jsx' let reactRoot = null function mountApp() { const el = document.getElementById('app') if (!el) return if (!reactRoot) { reactRoot = createRoot(el) } reactRoot.render() } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', mountApp) } else { mountApp() } function main() { logseq.App.registerUIItem('toolbar', { key: 'my-plugin', template: '🎨' }) logseq.provideModel({ toggle() { logseq.toggleMainUI() } }) } logseq.ready(main).catch(console.error) ``` ### Key Concepts - **`mountApp()`**: Function to find the target DOM element and render the application. - **`logseq.App.registerUIItem()`**: Used to add custom UI elements, like a toolbar button. - **`logseq.provideModel()`**: Exposes functions to the Logseq UI for interaction. - **`logseq.ready()`**: Ensures Logseq is ready before executing the main function. ``` -------------------------------- ### Provide Dynamic UI Content Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Use `provideUI` to dynamically render HTML content. It requires a unique key and an HTML template, and can optionally specify a slot and reset behavior. ```javascript logseq.provideUI({ key: 'my-overlay', template: `

Hello from plugin

`, reset: true }) ``` -------------------------------- ### Logseq Plugin: Register Commands and UI Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Common initialization pattern for Logseq plugins. Registers slash commands first, then registers UI items and provides a model for interaction. ```javascript function main() { // Register all commands logseq.Editor.registerSlashCommand('🔍 Search', handleSearch) logseq.Editor.registerSlashCommand('📝 Note', handleNote) // Then register UI logseq.App.registerUIItem('toolbar', { key: 'search-btn', template: '🔍' }) logseq.provideModel({ openSearch() { logseq.showMainUI() } }) } ``` -------------------------------- ### React to Setting Changes in a React Component Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md Demonstrates how to use `useState` and `useEffect` in a React component to display and react to changes in Logseq plugin settings. ```javascript function App() { const [settings, setSettings] = useState(logseq.settings) useEffect(() => { logseq.on('settings:changed', (newSettings) => { setSettings(newSettings) }) }, []) return (

Current font: {settings.googleFontFamily}

) } ``` -------------------------------- ### Show Main UI Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md Displays the plugin's main UI panel. Optionally, it can auto-focus the panel when shown. ```APIDOC ## Show Main UI ### Description Displays the plugin's main UI panel. Optionally, it can auto-focus the panel when shown. ### Method ```typescript logseq.showMainUI(options?: { autoFocus?: boolean }): void ``` ### Parameters #### Query Parameters - **autoFocus** (boolean) - Optional - Auto-focus the UI panel when shown. Defaults to `false`. ### Request Example ```javascript logseq.Editor.registerSlashCommand('⚙️ Settings', async () => { logseq.showMainUI({ autoFocus: true }) }) ``` ``` -------------------------------- ### Minimal package.json Configuration for Logseq Plugin Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/configuration.md Defines the essential metadata for a Logseq plugin, including its ID, title, description, and minimum required Logseq version. ```json { "name": "logseq-plugin-name", "version": "0.0.1", "main": "index.html", "logseq": { "id": "logseq-plugin-name", "title": "Plugin Title", "description": "Plugin description", "author": "Your Name", "version": "0.0.1", "minAppVersion": "0.9.0" } } ``` -------------------------------- ### Object-based Plugin Initialization with Model Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/plugin-entry-points.md Initializes a plugin by providing a model object with methods callable from UI templates. This pattern is useful for managing plugin settings and UI interactions. ```javascript import '@logseq/libs' function createModel() { return { openSettings() { logseq.showMainUI() }, saveSetting(name, value) { logseq.updateSettings({ [name]: value }) } } } function main() { // Initialize UI, register commands, etc. logseq.App.registerUIItem('toolbar', { key: 'my-plugin-btn', template: '⚙️' }) } logseq.ready(createModel()).then(main).catch(console.error) ``` -------------------------------- ### Create Page with Properties Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/editor-operations.md This function demonstrates how to create a new page in Logseq, add tags, set properties like cover and rating, and link to other pages (e.g., director). It also appends the description as the first block of the new page. ```javascript async function createMoviePage(movieData) { // Create page const page = await logseq.Editor.createPage(movieData.title) if (!page?.uuid) throw new Error('Failed to create page') // Add tags await logseq.Editor.addBlockTag(page.uuid, 'movie') // Set properties await logseq.Editor.upsertBlockProperty(page.uuid, 'cover', movieData.image) await logseq.Editor.upsertBlockProperty(page.uuid, 'rating', movieData.rating) await logseq.Editor.upsertBlockProperty(page.uuid, 'year', movieData.year) // Create director page and link const director = await logseq.Editor.createPage(movieData.director) if (director?.uuid) { await logseq.Editor.upsertBlockProperty(page.uuid, 'director', director.id) } // Add description as first block content await logseq.Editor.appendBlockInPage(page.uuid, movieData.description) return page } ``` -------------------------------- ### Import All Movies with Throttling Source: https://github.com/logseq/logseq-plugin-samples/blob/master/logseq-imdb-top250-importer/README.md Illustrates how to import all movies from the list, including progress messages and a throttle to prevent overwhelming Logseq. This function manages the bulk import process. ```typescript importAllToLogseq() Shows progress messages during import Navigates to `#movie` tag page after completion 100ms throttle between imports to avoid overwhelming Logseq ``` -------------------------------- ### ShowUIOptions Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/types.md Options for the `logseq.showMainUI()` function, enabling control over whether the UI panel should automatically receive focus. ```APIDOC ## ShowUIOptions ### Description Options for showing the main UI. This allows for controlling whether the UI panel should automatically gain focus upon being shown. ### Fields - **autoFocus** (boolean) - If true, auto-focus the UI panel ### Used by `logseq.showMainUI()` ### Example ```javascript logseq.showMainUI({ autoFocus: true }) ``` ``` -------------------------------- ### showMainUI Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Shows the plugin's main UI panel. Optionally allows auto-focusing the UI. ```APIDOC ## showMainUI ### Description Shows the plugin's main UI panel. ### Method (Not specified, likely an SDK function call) ### Parameters - **options.autoFocus** (boolean) - Optional - Auto-focus the UI. ### Example ```javascript logseq.showMainUI({ autoFocus: true }) ``` ``` -------------------------------- ### on Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/logseq-api.md Registers a listener for plugin events. It takes an event name and a callback function that will be executed when the event occurs. ```APIDOC ## on ### Description Registers a listener for plugin events. ### Method void ### Endpoint logseq.on(eventName: string, callback: (data: any) => void) ### Parameters #### Request Body - **eventName** (string) - Required - Event name, e.g., 'settings:changed', 'ui:visible:changed' - **callback** (function) - Required - Handler function ### Request Example ```javascript logseq.on('settings:changed', (settings) => { setSettings(settings) }) logseq.on('ui:visible:changed', async ({ visible }) => { if (visible) { const blocks = await logseq.Editor.getCurrentPageBlocksTree() // Render mind map } }) ``` ### Response None ``` -------------------------------- ### UI Show Message for Progress Updates Source: https://github.com/logseq/logseq-plugin-samples/blob/master/_autodocs/api-reference/ui-management.md Demonstrates using `logseq.UI.showMsg` to display progress updates during a bulk import process. Messages are configured with `timeout: 0` to remain visible and use the `key` option for updates and closing. ```javascript async function importBulkData(items) { const msgKey = await logseq.UI.showMsg( 'Starting import...', 'info', { timeout: 0 } ) for (let i = 0; i < items.length; i++) { await logseq.UI.showMsg( `Importing ${i + 1}/${items.length}...`, 'info', { timeout: 0, key: msgKey } ) await importItem(items[i]) } logseq.UI.closeMsg(msgKey) logseq.UI.showMsg('Import complete!', 'success') } ```