├── icon.png
├── screenshots
├── logseq_tidy_blocks_v.1.1.0.gif
├── logseq_tidy_blocks_v.1.2.0.gif
├── logseq_tidy_blocks_settings.png
└── logseq_tidy_blocks_keyboard_shortcut_demo.gif
├── src
├── index.html
└── index.js
├── package.json
├── LICENSE
├── .github
└── workflows
│ └── publish.yml
├── .gitignore
└── README.md
/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vyleung/logseq-tidy-blocks-plugin/HEAD/icon.png
--------------------------------------------------------------------------------
/screenshots/logseq_tidy_blocks_v.1.1.0.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vyleung/logseq-tidy-blocks-plugin/HEAD/screenshots/logseq_tidy_blocks_v.1.1.0.gif
--------------------------------------------------------------------------------
/screenshots/logseq_tidy_blocks_v.1.2.0.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vyleung/logseq-tidy-blocks-plugin/HEAD/screenshots/logseq_tidy_blocks_v.1.2.0.gif
--------------------------------------------------------------------------------
/screenshots/logseq_tidy_blocks_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vyleung/logseq-tidy-blocks-plugin/HEAD/screenshots/logseq_tidy_blocks_settings.png
--------------------------------------------------------------------------------
/screenshots/logseq_tidy_blocks_keyboard_shortcut_demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/vyleung/logseq-tidy-blocks-plugin/HEAD/screenshots/logseq_tidy_blocks_keyboard_shortcut_demo.gif
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "logseq-tidy-blocks-plugin",
3 | "version": "1.2.1",
4 | "description": "Remove whitespace and line breaks and hide block properties to keep blocks nice and tidy",
5 | "main": "dist/index.html",
6 | "targets": {
7 | "main": false
8 | },
9 | "scripts": {
10 | "test": "echo \"Error: no test specified\" && exit 1",
11 | "build": "parcel build --no-source-maps src/index.html --public-url ./"
12 | },
13 | "keywords": [],
14 | "author": "vyleung",
15 | "license": "MIT",
16 | "logseq": {
17 | "id": "logseq-tidy-blocks-plugin",
18 | "title": "Tidy Blocks",
19 | "icon": "./icon.png"
20 | },
21 | "dependencies": {
22 | "@logseq/libs": "^0.0.15",
23 | "driftless": "^2.0.3"
24 | },
25 | "devDependencies": {
26 | "parcel": "^2.9.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 vyleung
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Build plugin
2 |
3 | on:
4 | push:
5 | # Sequence of patterns matched against refs/tags
6 | tags:
7 | - '*' # Push events to matching any tag format, i.e. 1.0, 20.15.10
8 |
9 | env:
10 | PLUGIN_NAME: logseq-tidy-blocks-plugin
11 |
12 | jobs:
13 | build:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Use Node.js
19 | uses: actions/setup-node@v1
20 | with:
21 | node-version: '16.x' # You might need to adjust this value to your own version
22 | - name: Build
23 | id: build
24 | run: |
25 | npm i && npm run build
26 | mkdir ${{ env.PLUGIN_NAME }}
27 | cp README.md package.json icon.png ${{ env.PLUGIN_NAME }}
28 | mv dist ${{ env.PLUGIN_NAME }}
29 | zip -r ${{ env.PLUGIN_NAME }}.zip ${{ env.PLUGIN_NAME }}
30 | ls
31 | echo "::set-output name=tag_name::$(git tag --sort version:refname | tail -n 1)"
32 | - name: Create Release
33 | uses: ncipollo/release-action@v1
34 | id: create_release
35 | env:
36 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37 | VERSION: ${{ github.ref }}
38 | with:
39 | allowUpdates: true
40 | draft: false
41 | prerelease: false
42 |
43 | - name: Upload zip file
44 | id: upload_zip
45 | uses: actions/upload-release-asset@v1
46 | env:
47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48 | with:
49 | upload_url: ${{ steps.create_release.outputs.upload_url }}
50 | asset_path: ./${{ env.PLUGIN_NAME }}.zip
51 | asset_name: ${{ env.PLUGIN_NAME }}-${{ steps.build.outputs.tag_name }}.zip
52 | asset_content_type: application/zip
53 |
54 | - name: Upload package.json
55 | id: upload_metadata
56 | uses: actions/upload-release-asset@v1
57 | env:
58 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
59 | with:
60 | upload_url: ${{ steps.create_release.outputs.upload_url }}
61 | asset_path: ./package.json
62 | asset_name: package.json
63 | asset_content_type: application/json
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | # Logs
3 | logs
4 | *.log
5 | npm-debug.log*
6 | yarn-debug.log*
7 | yarn-error.log*
8 | lerna-debug.log*
9 | .pnpm-debug.log*
10 |
11 | # Diagnostic reports (https://nodejs.org/api/report.html)
12 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
13 |
14 | # Runtime data
15 | pids
16 | *.pid
17 | *.seed
18 | *.pid.lock
19 |
20 | # Directory for instrumented libs generated by jscoverage/JSCover
21 | lib-cov
22 |
23 | # Coverage directory used by tools like istanbul
24 | coverage
25 | *.lcov
26 |
27 | # nyc test coverage
28 | .nyc_output
29 |
30 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
31 | .grunt
32 |
33 | # Bower dependency directory (https://bower.io/)
34 | bower_components
35 |
36 | # node-waf configuration
37 | .lock-wscript
38 |
39 | # Compiled binary addons (https://nodejs.org/api/addons.html)
40 | build/Release
41 |
42 | # Dependency directories
43 | node_modules/
44 | jspm_packages/
45 |
46 | # Snowpack dependency directory (https://snowpack.dev/)
47 | web_modules/
48 |
49 | # TypeScript cache
50 | *.tsbuildinfo
51 |
52 | # Optional npm cache directory
53 | .npm
54 |
55 | # Optional eslint cache
56 | .eslintcache
57 |
58 | # Microbundle cache
59 | .rpt2_cache/
60 | .rts2_cache_cjs/
61 | .rts2_cache_es/
62 | .rts2_cache_umd/
63 |
64 | # Optional REPL history
65 | .node_repl_history
66 |
67 | # Output of 'npm pack'
68 | *.tgz
69 |
70 | # Yarn Integrity file
71 | .yarn-integrity
72 |
73 | # dotenv environment variables file
74 | .env
75 | .env.test
76 | .env.production
77 |
78 | # parcel-bundler cache (https://parceljs.org/)
79 | .cache
80 | .parcel-cache
81 |
82 | # Next.js build output
83 | .next
84 | out
85 |
86 | # Nuxt.js build / generate output
87 | .nuxt
88 | dist
89 |
90 | # Gatsby files
91 | .cache/
92 | # Comment in the public line in if your project uses Gatsby and not Next.js
93 | # https://nextjs.org/blog/next-9-1#public-directory-support
94 | # public
95 |
96 | # vuepress build output
97 | .vuepress/dist
98 |
99 | # Serverless directories
100 | .serverless/
101 |
102 | # FuseBox cache
103 | .fusebox/
104 |
105 | # DynamoDB Local files
106 | .dynamodb/
107 |
108 | # TernJS port file
109 | .tern-port
110 |
111 | # Stores VSCode versions used for testing VSCode extensions
112 | .vscode-test
113 | .vscode
114 |
115 | # yarn v2
116 | .yarn/cache
117 | .yarn/unplugged
118 | .yarn/build-state.yml
119 | .yarn/install-state.gz
120 | .pnp.*
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## logseq-tidy-blocks-plugin
2 | > If you find this plugin – or any of my other [Logseq plugins](https://github.com/vyleung?tab=repositories&q=logseq&type=source) – useful and would like to support me, you can [buy me a coffee](https://www.buymeacoffee.com/vyleung) 🙂
3 |
4 | ## Features
5 | ### Remove empty blocks and whitespace from _one_ block or _multiple_ blocks in [3 ways](#3-ways-to-use-the-plugin)
6 | #### Demo
7 | 
8 |
9 | ### Toggle the display of block properties in [3 ways](#3-ways-to-use-the-plugin)
10 | - Limitation for manually hiding block properties is that the display state of block properties is NOT remembered when Logseq is reloaded
11 | #### Demo
12 | 
13 |
14 | ### 3 ways to use the plugin
15 | - Block context menu (right-click on bullet)
16 | - Slash (/) command
17 | - Keyboard shortcuts (can be configured in the [settings](#settings))
18 | - Usage for one block: Click on the block (as if to edit it) → Activate the keyboard shortcut
19 | - Usage for multiple blocks: Click on the first block (as if to edit it) → Select blocks above (`shift+up`) or below (`shift+down`) → Activate the keyboard
20 | - Demo: 
21 |
22 | ### Settings
23 | - Each time you make changes to the plugin settings, please reload Logseq to ensure that all settings are updated
24 | 
25 |
26 | ## Installation
27 | ### Preparation
28 | 1. Click the 3 dots in the righthand corner → `Settings` → `Advanced` → Enable `Developer mode` and `Plug-in system`
29 | 2. Click the 3 dots in the righthand corner → `Plugins` – OR – Use keyboard shortcut `Esc t p`
30 |
31 | ### Load plugin via the marketplace (recommended)
32 | 1. Click the 3 dots in the righthand corner → `Plugins` – OR – Use keyboard shortcut `Esc t p`
33 | 2. Go to the `Marketplace` tab and search for `Tidy Blocks` → Click `Install`
34 |
35 | ### Load plugin manually
36 | 1. Download the [latest release](https://github.com/vyleung/logseq-tidy-blocks-plugin/releases) of the plugin (e.g logseq-tidy-blocks-plugin-v.1.0.0.zip) from Github
37 | 2. Unzip the file
38 | 3. Navigate to plugins (Click the 3 dots → `Plugins` – OR – Use keyboard shortcut `Esc t p`) → `Load unpacked plugin` → Select the folder of the unzipped file
39 |
40 | ## License
41 | MIT
42 |
43 | ## Credits
44 | - Plugin Marketplace Icon: Tidy icons created by Freepik - Flaticon
45 | - Plugin Toolbar Icon: [Material Design Icons](https://materialdesignicons.com/)
46 | - Plugin nspired by the [Obsidian Text Format plugin](https://github.com/Benature/obsidian-text-format)
47 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import "@logseq/libs";
2 | import { setDriftlessTimeout } from "driftless";
3 |
4 | const settings = [
5 | {
6 | key: "DeleteEmptyBlocks",
7 | title: "Delete empty blocks?",
8 | description: "Check the box if you would like to delete empty blocks when tidying up",
9 | default: false,
10 | type: "boolean",
11 | enumPicker: "checkbox"
12 | },
13 | {
14 | key: "KeyboardShortcut_LineBreak",
15 | title: "Keyboard shortcut to tidy block(s) and keep a line break",
16 | description: "This is the the keyboard shortcut to tidy one block or multiple blocks and keep a line break (default: alt+t)",
17 | type: "string",
18 | default: "alt+t"
19 | },
20 | {
21 | key: "KeyboardShortcut_RemoveAll",
22 | title: "Keyboard shortcut to tidy block(s) and remove all whitespace",
23 | description: "This is the the keyboard shortcut to tidy one block or multiple blocks and remove all whitespace (default: alt+r)",
24 | type: "string",
25 | default: "alt+r"
26 | },
27 | {
28 | key: "ToggleBlockProperties",
29 | title: "Toggle block properties?",
30 | description: "Automatic: Automatically hide all block properties and have the ability to toggle them | Manual: Use the slash command to hide the properties per block | None: Leave block properties as is (default: manual)",
31 | type: "enum",
32 | enumPicker: "radio",
33 | enumChoices: ["automatic", "manual", "none"],
34 | default: "manual"
35 | },
36 | {
37 | key: "KeyboardShortcut_ToggleBlockProperties",
38 | title: "Keyboard shortcut to toggle block properties",
39 | description: "This is the the keyboard shortcut to toggle block properties (default: mod+ctrl+x)",
40 | type: "string",
41 | default: "mod+ctrl+x"
42 | }
43 | ]
44 | logseq.useSettingsSchema(settings);
45 | const up_icon = ``;
49 | const down_icon = ``;
53 | let tidy_type;
54 | let parent_block_uuid;
55 | let all_blocks_with_properties;
56 | let selected_block_with_properties;
57 | let all_blocks_with_buttons;
58 | let button_block_uuid;
59 | let button_block_properties;
60 | let block_properties;
61 | let toggle_icon_container;
62 | let toggle_icon;
63 |
64 | // ref for traversing through a block and their children: https://gist.github.com/umidjons/6865350#file-walk-dom-js
65 | function tidy(block) {
66 | logseq.Editor.getBlock(block.uuid, {includeChildren: true}).then(tree_block => {
67 | let block_content = tree_block.content;
68 |
69 | // delete empty blocks if indicated in settings
70 | if ((logseq.settings.DeleteEmptyBlocks) && (block_content == "")) {
71 | logseq.Editor.removeBlock(tree_block.uuid);
72 | }
73 |
74 | if (tidy_type == "keep a line break") {
75 | // ref for replacing extra spaces and tabs (1st .replace()): https://stackoverflow.com/questions/5310821/removing-space-and-retaining-the-new-line
76 | // ref for replacing extra line breaks (2nd .replace()): https://stackoverflow.com/questions/22962220/remove-multiple-line-breaks-n-in-javascript
77 | logseq.Editor.updateBlock(tree_block.uuid, block_content.trim().replace(/[ \t]{2,}/gu, " ").replace(/[\r\n]{2,}/g, "\n"));
78 | }
79 | else {
80 | // ref for removing all whitespace: https://github.com/sindresorhus/condense-whitespace
81 | logseq.Editor.updateBlock(tree_block.uuid, block_content.trim().replace(/\s{2,}/gu, " ").replace(/[\r\n]/g, " "));
82 | }
83 |
84 | if (tree_block.children.length > 0) {
85 | let children_block = tree_block.children;
86 | children_block.forEach(child => {
87 | tidy(child);
88 | });
89 | }
90 | });
91 | }
92 |
93 | // tidy one selected block
94 | function tidySelectedBlock(e) {
95 | tidy(e);
96 | logseq.UI.showMsg("Block is tidied!")
97 | }
98 |
99 | // tidy multiple selected blocks
100 | function tidyMultipleSelectedBlocks() {
101 | logseq.Editor.getSelectedBlocks().then(selected_blocks => {
102 | selected_blocks.forEach(selected_block => {
103 | tidy(selected_block);
104 | });
105 | });
106 | logseq.UI.showMsg("Blocks are tidied!");
107 | }
108 |
109 | function tidyBlocks(e) {
110 | // if the uuid exists, one block has been selected; otherwise, multiple blocks have been selected
111 | (e.uuid) ? tidySelectedBlock(e) : tidyMultipleSelectedBlocks();
112 | }
113 |
114 | logseq.onSettingsChanged(updated_settings => {
115 | if (logseq.settings.ToggleBlockProperties == "automatic") {
116 | const mutation_observer = new MutationObserver((mutations) => {
117 | for (const mutation of mutations) {
118 | insertToggleBlockPropertiesButton("automatic", "");
119 | }
120 | });
121 | mutation_observer.observe(parent.document.body, {
122 | childList: true,
123 | subtree: true
124 | });
125 | logseq.beforeunload(async () => {
126 | mutation_observer.disconnect();
127 | });
128 | }
129 | else if (logseq.settings.ToggleBlockProperties == "manual") {
130 | // right click - hide block properties
131 | logseq.Editor.registerBlockContextMenuItem("🧹 Tidy up & hide block properties", async (e) => {
132 | insertToggleBlockPropertiesButton("manual", e);
133 | });
134 |
135 | // slash command - hide block properties
136 | logseq.Editor.registerSlashCommand("🧹 Tidy up & hide block properties", async (e) => {
137 | insertToggleBlockPropertiesButton("manual", e);
138 | });
139 |
140 | // keyboard shortcut: hide block properties
141 | logseq.App.registerCommandPalette({
142 | key: `tidy-blocks-ToggleBlockProperties`,
143 | label: "Tidy up & toggle all block properties",
144 | keybinding: {
145 | binding: logseq.settings.KeyboardShortcut_ToggleBlockProperties,
146 | mode: "global",
147 | }
148 | }, async () => {
149 | logseq.Editor.checkEditing().then(editing_block => {
150 | if (editing_block) {
151 | insertToggleBlockPropertiesButton("manual", editing_block);
152 | }
153 | else {
154 | logseq.Editor.getSelectedBlocks().then(all_selected_blocks => {
155 | all_selected_blocks.forEach(a_selected_block => {
156 | insertToggleBlockPropertiesButton("manual", a_selected_block);
157 | });
158 | });
159 | }
160 | });
161 | });
162 | }
163 | });
164 |
165 | function insertToggleBlockPropertiesButton(type, block) {
166 | if (type == "automatic") {
167 | // get all blocks that have properties
168 | all_blocks_with_properties = parent.document.querySelectorAll(".block-properties");
169 |
170 | if (all_blocks_with_properties) {
171 | // for each block that has properties, if the block-properties div doesn't have an id, add one and insert the toggle button
172 | for (const block_with_properties of all_blocks_with_properties) {
173 | if (!block_with_properties.id) {
174 | parent_block_uuid = block_with_properties.parentElement.id.split("block-content-")[1];
175 | block_with_properties.id = `tidy-block-properties-${parent_block_uuid}`;
176 | showToggleBlockPropertiesButton(parent_block_uuid);
177 | }
178 | }
179 | }
180 | }
181 | else {
182 | (block.uuid) ? parent_block_uuid = block.uuid : parent_block_uuid = block;
183 |
184 | logseq.Editor.exitEditingMode();
185 | showToggleBlockPropertiesButton(parent_block_uuid);
186 |
187 | setDriftlessTimeout(() => {
188 | selected_block_with_properties = parent.document.querySelector(`#block-content-${parent_block_uuid} > .block-properties`);
189 |
190 | if (!selected_block_with_properties.id) {
191 | selected_block_with_properties.id = `tidy-block-properties-${parent_block_uuid}`;
192 | }
193 | }, 50);
194 | }
195 | }
196 |
197 | function showToggleBlockPropertiesButton(block_uuid) {
198 | // toggle block properties button
199 | logseq.provideUI({
200 | key: `tidy-blocks-properties-icon-${block_uuid}`,
201 | path: `div[id^="ls-block"][id$="${block_uuid}"`,
202 | template:
203 | ``
206 | });
207 |
208 | logseq.provideStyle(`
209 | .tidy-blocks-properties {
210 | position: absolute;
211 | top: 0;
212 | right: -2.5em;
213 | }
214 | #block-properties-icon-${block_uuid} {
215 | display: flex;
216 | align-items: center;
217 | padding: 0.25em 0.375em;
218 | }
219 | `)
220 |
221 | // hide block properties
222 | setDriftlessTimeout(() => {
223 | parent.document.querySelector(`#block-content-${block_uuid} > .block-properties`).style.display = "none";
224 | }, 25);
225 | }
226 |
227 | function toggleBlockProperties(e) {
228 | parent_block_uuid = e.id.split("block-properties-container-")[1];
229 |
230 | block_properties = parent.document.getElementById(`tidy-block-properties-${parent_block_uuid}`);
231 | toggle_icon = parent.document.querySelector(`#block-properties-icon-${parent_block_uuid}`);
232 |
233 | if (block_properties.style.display == "none") {
234 | block_properties.style.display = "block";
235 | toggle_icon.innerHTML = down_icon;
236 | }
237 | else {
238 | block_properties.style.display = "none";
239 | toggle_icon.innerHTML = up_icon;
240 | }
241 | }
242 |
243 | function removeToggleBlockPropertiesButton() {
244 | all_blocks_with_buttons = parent.document.querySelectorAll(".tidy-blocks-properties");
245 |
246 | for (const block_with_buttons of all_blocks_with_buttons) {
247 | if (all_blocks_with_buttons) {
248 | button_block_uuid = block_with_buttons.id.split("block-properties-container-")[1];
249 | toggle_icon_container = parent.document.querySelector(`div[id*="tidy-blocks-properties-icon-${button_block_uuid}"]`);
250 | button_block_properties = parent.document.querySelector(`#block-content-${button_block_uuid} > .block-properties`);
251 |
252 | logseq.Editor.getBlockProperties(button_block_uuid).then(properties => {
253 | if (Object.keys(properties).length == 0) {
254 | toggle_icon_container.remove();
255 | }
256 | else {
257 | if (button_block_properties) {
258 | setDriftlessTimeout(() => {
259 | if (button_block_properties.id == "") {
260 | button_block_properties.id = `tidy-block-properties-${button_block_uuid}`;
261 | button_block_properties.style.display = "none";
262 | }
263 | }, 50);
264 | }
265 | }
266 | });
267 | }
268 | }
269 | }
270 |
271 | // remove toggle block button if the block has a button, but has no properties
272 | const mutation_observer_buttons = new MutationObserver((changes) => {
273 | for (const change of changes) {
274 | removeToggleBlockPropertiesButton();
275 | }
276 | });
277 | mutation_observer_buttons.observe(parent.document.body, {
278 | childList: true,
279 | subtree: true
280 | });
281 | logseq.beforeunload(async () => {
282 | mutation_observer_buttons.disconnect();
283 | });
284 |
285 | const main = async () => {
286 | console.log("logseq-tidy-blocks-plugin loaded");
287 |
288 | logseq.provideModel ({
289 | toggle_block_properties(e) {
290 | toggleBlockProperties(e);
291 | }
292 | });
293 |
294 | // right click - tidy one block (keep a line break)
295 | logseq.Editor.registerBlockContextMenuItem("🧹 Tidy up & keep a line break", async (e) => {
296 | tidy_type = "keep a line break";
297 | tidySelectedBlock(e);
298 | });
299 |
300 | // slash command - tidy one block (keep a line break)
301 | logseq.Editor.registerSlashCommand("🧹 Tidy up & keep a line break", async (e) => {
302 | tidy_type = "keep a line break";
303 | tidySelectedBlock(e);
304 | });
305 |
306 | // right click - tidy one block (remove all whitespace)
307 | logseq.Editor.registerBlockContextMenuItem("🧹 Tidy up & remove all whitespace", async (e) => {
308 | tidy_type = "remove all whitespace";
309 | tidySelectedBlock(e);
310 | });
311 |
312 | // slash command - tidy one block (remove all whitespace)
313 | logseq.Editor.registerSlashCommand("🧹 Tidy up & remove all whitespace", async (e) => {
314 | tidy_type = "remove all whitespace";
315 | tidySelectedBlock(e);
316 | });
317 |
318 | // keyboard shortcut: tidy block(s) and keep a line break
319 | logseq.App.registerCommandPalette({
320 | key: `tidy-blocks-KeyboardShortcut_LineBreak`,
321 | label: "Tidy up & keep a line break",
322 | keybinding: {
323 | binding: logseq.settings.KeyboardShortcut_LineBreak,
324 | mode: "global",
325 | }
326 | }, async (e) => {
327 | tidy_type = "keep a line break";
328 | tidyBlocks(e);
329 | });
330 |
331 | // keyboard shortcut: tidy block(s) and remove all linespaces
332 | logseq.App.registerCommandPalette({
333 | key: `tidy-blocks-KeyboardShortcut_RemoveAll`,
334 | label: "Tidy up & remove all whitespace",
335 | keybinding: {
336 | binding: logseq.settings.KeyboardShortcut_RemoveAll,
337 | mode: "global",
338 | }
339 | }, async (e) => {
340 | tidy_type = "remove all whitespace";
341 | tidyBlocks(e);
342 | });
343 |
344 | logseq.provideModel({
345 | show_settings() {
346 | logseq.showSettingsUI();
347 | }
348 | });
349 |
350 | // toolbar icon
351 | logseq.App.registerUIItem("toolbar", {
352 | key: "logseq-tidy-blocks",
353 | template:
354 | `
355 |
358 | `
359 | });
360 | }
361 |
362 | logseq.ready(main).catch(console.error);
--------------------------------------------------------------------------------