diff --git a/changelog.md b/changelog.md index e4b37ad..35a1a8c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,9 +1,13 @@ # Changelog +## 1.5.0 +### Added +- "Headings-only" mode will only list headings (#18) + ## 1.4.0 ### Added - Setting for whether the first item should be selected when opening the palette or not (#12) -- Setting configuring the max. depth of the displayed items (#14) +- Setting for configuring the max. depth of the displayed items (#14) ## 1.3.1 diff --git a/package.json b/package.json index 38172e4..05d279b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "logseq-plugin-jump-to-block", - "version": "1.4.0", + "version": "1.5.0", "main": "dist/index.html", "logseq": { "id": "logseq-plugin-jump-to-block" diff --git a/src/components/App.tsx b/src/components/App.tsx index 77b25e2..349f07c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ import type { BlockEntity } from '@logseq/libs/dist/LSPlugin.user'; -import type { InitalSelectionOption } from '../types'; +import type { InitalSelectionOption, ModeOption } from '../types'; import React, { useEffect, useState, Fragment } from 'react'; import CommandPalette, { Command } from 'react-command-palette'; @@ -8,11 +8,16 @@ import * as R from 'ramda'; import { Global, css } from '@emotion/react'; import { prepareLabel } from '../utils'; +import { + defaultMaxDepth, + headingRegex, + initialSelectionDefault, + modeDefault +} from '../constants'; // @ts-ignore import theme from '../../node_modules/react-command-palette/dist/themes/sublime-theme'; import '../../node_modules/react-command-palette/dist/themes/sublime.css'; -import { defaultMaxDepth, initialSelectionOptionDefault } from '../constants'; type PathItem = { @@ -59,6 +64,7 @@ const selectionHandler = async ( const makeCommands = ( blocks: BlockEntity[], + mode: ModeOption, maxDepth = Infinity ) => { const items: Command[] = []; @@ -67,11 +73,28 @@ const makeCommands = ( depth: number, path: Array ) => { - if (depth > maxDepth) { - return; + if (mode === 'Default') { + if (depth > maxDepth) { + return; + } } + const blockContent = (block.content || '').trim(); + if (mode === 'Headings-only') { + // ignore non-headings + if (!headingRegex.test(blockContent)) { + return; + } + const level = R.takeWhile( + (c) => c === '#', + blockContent.split('') + ).length; + if (level > maxDepth) { + return; + } + } + // ignore empty blocks if (blockContent === '') { return; } @@ -155,6 +178,8 @@ const makeStyles = () => { function App() { + const mode: ModeOption = logseq.settings?.mode || modeDefault; + const [open, setOpen] = useState(false); const [items, setItems] = useState([]); @@ -194,7 +219,7 @@ function App() { 0, logseq.settings?.maxDepth || defaultMaxDepth ); - const items = makeCommands(blocks, maxDepth); + const items = makeCommands(blocks, mode, maxDepth); setItems(items); setOpen(true); } else { @@ -207,10 +232,10 @@ function App() { logseq.off('ui:visible:changed', visibilityHandler); }; }, - [] + [mode] ); - const initialSelection: InitalSelectionOption = logseq.settings?.initialSelection || initialSelectionOptionDefault; + const initialSelection: InitalSelectionOption = logseq.settings?.initialSelection || initialSelectionDefault; const highlightFirstSuggestion = initialSelection === 'First block'; // TODO: implement 'Current block' const defaultInputValue = ''; diff --git a/src/constants.ts b/src/constants.ts index 217af78..4f55fd9 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,7 @@ -import type { InitalSelectionOption } from './types'; +import type { InitalSelectionOption, ModeOption } from './types'; -export const initialSelectionOptionDefault: InitalSelectionOption = 'Nothing'; +export const initialSelectionDefault: InitalSelectionOption = 'Nothing'; export const defaultMaxDepth = 3; +export const modeDefault: ModeOption = 'Headings-only'; + +export const headingRegex = /^#{1,6} (.*)/gi; diff --git a/src/main.tsx b/src/main.tsx index 132e9f1..bd09da7 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,18 +2,21 @@ import type { SettingSchemaDesc, SimpleCommandKeybinding } from '@logseq/libs/dist/LSPlugin'; -import type { InitalSelectionOption } from './types'; +import type { InitalSelectionOption, ModeOption } from './types'; import React from 'react'; import ReactDOM from 'react-dom/client'; import '@logseq/libs'; import { makeToolbarIcon } from './toolbar'; -import { defaultMaxDepth, initialSelectionOptionDefault } from './constants'; +import { + defaultMaxDepth, + initialSelectionDefault, + modeDefault +} from './constants'; import App from './components/App'; - const cmdKey = 'jumpToBlock'; const cmdLabel = 'Jump to blockā€¦'; const settingsKey = cmdKey; @@ -21,6 +24,9 @@ const settingsLabel = cmdLabel; const initialSelectionOptions: InitalSelectionOption[] = [ /* 'Current block', */ 'First block', 'Nothing' ]; +const modeOptions: ModeOption[] = [ + 'Default', 'Headings-only' +]; const settings: SettingSchemaDesc[] = [ { key: settingsKey, @@ -29,6 +35,15 @@ const settings: SettingSchemaDesc[] = [ default: 'mod+t', type: 'string', }, + { + key: 'mode', + title: 'Mode', + description: '', + default: modeDefault, + type: 'enum', + enumChoices: modeOptions as string[], + enumPicker: 'radio', + }, { key: 'autoOpen', title: 'Auto-open palette', @@ -40,7 +55,7 @@ const settings: SettingSchemaDesc[] = [ key: 'initialSelection', title: 'What to select when opening the palette', description: '', - default: initialSelectionOptionDefault, + default: initialSelectionDefault, type: 'enum', enumChoices: initialSelectionOptions as string[], enumPicker: 'radio', @@ -48,7 +63,7 @@ const settings: SettingSchemaDesc[] = [ { key: 'maxDepth', title: 'Maximum block depth', - description: 'Limits the depth of blocks to be shown in the palette (0 = root-level)', + description: 'Limits the depth of blocks to be shown in the palette.', default: defaultMaxDepth, type: 'number', }, diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 626bb8b..112a872 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,2 +1,3 @@ // TODO: 'Current block' export type InitalSelectionOption = 'First block' | 'Nothing'; +export type ModeOption = 'Default' | 'Headings-only';