├── .github └── workflows │ └── gh-pages.yml ├── .gitignore ├── .vitepress ├── config.mts └── theme │ ├── index.ts │ └── style.css ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── changelog.md ├── cn ├── guide │ └── getting-started.md ├── index.md └── purchase.md ├── guide └── getting-started.md ├── index.md ├── package.json ├── pnpm-lock.yaml ├── public └── assets │ ├── example.png │ ├── logo.png │ ├── qrcode.png │ ├── result1.png │ ├── result2.png │ ├── screencast │ └── demo.mp4 │ └── screenshot.png ├── purchase.md └── screenshot.png /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: Move Block Docs 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build-and-deploy: 8 | concurrency: ci-${{ github.ref }} # Recommended if you intend to make multiple deployments in quick succession. 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 🛎️ 12 | uses: actions/checkout@v4 13 | - name: Install pnpm 14 | run: curl -L https://unpkg.com/@pnpm/self-installer | node 15 | 16 | - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. 17 | run: | 18 | pnpm install --frozen-lockfile 19 | pnpm run docs:build 20 | 21 | - name: Deploy 🚀 22 | uses: JamesIves/github-pages-deploy-action@v4.5.0 23 | with: 24 | branch: gh-pages # The branch the action should deploy to. 25 | folder: .vitepress/dist # The folder the action should deploy. 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .vitepress/cache 3 | .vitepress/dist -------------------------------------------------------------------------------- /.vitepress/config.mts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vitepress"; 2 | 3 | // https://vitepress.dev/reference/site-config 4 | export default defineConfig({ 5 | title: "Logseq Move Block", 6 | description: "Move blocks to anywhere in Logseq", 7 | base: "/logseq-plugin-move-block/", 8 | assetsDir: "assets", 9 | cleanUrls: true, 10 | locales: { 11 | root: { 12 | label: "English", 13 | lang: "en", 14 | themeConfig: { 15 | outline: { 16 | level: "deep", 17 | }, 18 | nav: [ 19 | { text: "Getting Started", link: "/guide/getting-started" }, 20 | { text: "Changelog", link: "https://github.com/vipzhicheng/logseq-plugin-move-block/blob/main/changelog.md" }, 21 | ], 22 | sidebar: { 23 | "/guide/": [ 24 | { 25 | text: "Getting Started", 26 | link: "/guide/getting-started", 27 | }, 28 | 29 | ], 30 | }, 31 | }, 32 | }, 33 | cn: { 34 | label: "中文", 35 | lang: "cn", // 可选,将作为 `lang` 属性添加到 `html` 标签中 36 | link: "/cn/", // 默认 /fr/ -- 显示在导航栏翻译菜单上,可以是外部的 37 | 38 | themeConfig: { 39 | outline: { 40 | level: "deep", 41 | label: "页面导航", 42 | }, 43 | docFooter: { 44 | prev: "上一页", 45 | next: "下一页", 46 | }, 47 | 48 | nav: [ 49 | { text: "快速开始", link: "/cn/guide/getting-started" }, 50 | { text: "变更日志", link: "https://github.com/vipzhicheng/logseq-plugin-move-block/blob/main/changelog.md" }, 51 | ], 52 | sidebar: { 53 | "/cn/guide/": [ 54 | { 55 | text: "快速开始", 56 | link: "/cn/guide/getting-started", 57 | }, 58 | ], 59 | }, 60 | }, 61 | }, 62 | }, 63 | themeConfig: { 64 | // https://vitepress.dev/reference/default-theme-config 65 | logo: "/assets/logo.png", 66 | socialLinks: [ 67 | { 68 | icon: "github", 69 | link: "https://github.com/vipzhicheng/logseq-plugin-move-block", 70 | }, 71 | ], 72 | search: { 73 | provider: "local", 74 | }, 75 | footer: { 76 | message: "Logseq Move Block", 77 | }, 78 | externalLinkIcon: true, 79 | }, 80 | }); 81 | -------------------------------------------------------------------------------- /.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import { h } from 'vue' 3 | import type { Theme } from 'vitepress' 4 | import DefaultTheme from 'vitepress/theme' 5 | import './style.css' 6 | 7 | export default { 8 | extends: DefaultTheme, 9 | Layout: () => { 10 | return h(DefaultTheme.Layout, null, { 11 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 12 | }) 13 | }, 14 | enhanceApp({ app, router, siteData }) { 15 | // ... 16 | } 17 | } satisfies Theme 18 | -------------------------------------------------------------------------------- /.vitepress/theme/style.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Customize default theme styling by overriding CSS variables: 3 | * https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css 4 | */ 5 | 6 | /** 7 | * Colors 8 | * 9 | * Each colors have exact same color scale system with 3 levels of solid 10 | * colors with different brightness, and 1 soft color. 11 | * 12 | * - `XXX-1`: The most solid color used mainly for colored text. It must 13 | * satisfy the contrast ratio against when used on top of `XXX-soft`. 14 | * 15 | * - `XXX-2`: The color used mainly for hover state of the button. 16 | * 17 | * - `XXX-3`: The color for solid background, such as bg color of the button. 18 | * It must satisfy the contrast ratio with pure white (#ffffff) text on 19 | * top of it. 20 | * 21 | * - `XXX-soft`: The color used for subtle background such as custom container 22 | * or badges. It must satisfy the contrast ratio when putting `XXX-1` colors 23 | * on top of it. 24 | * 25 | * The soft color must be semi transparent alpha channel. This is crucial 26 | * because it allows adding multiple "soft" colors on top of each other 27 | * to create a accent, such as when having inline code block inside 28 | * custom containers. 29 | * 30 | * - `default`: The color used purely for subtle indication without any 31 | * special meanings attched to it such as bg color for menu hover state. 32 | * 33 | * - `brand`: Used for primary brand colors, such as link text, button with 34 | * brand theme, etc. 35 | * 36 | * - `tip`: Used to indicate useful information. The default theme uses the 37 | * brand color for this by default. 38 | * 39 | * - `warning`: Used to indicate warning to the users. Used in custom 40 | * container, badges, etc. 41 | * 42 | * - `danger`: Used to show error, or dangerous message to the users. Used 43 | * in custom container, badges, etc. 44 | * -------------------------------------------------------------------------- */ 45 | 46 | :root { 47 | --vp-c-default-1: var(--vp-c-gray-1); 48 | --vp-c-default-2: var(--vp-c-gray-2); 49 | --vp-c-default-3: var(--vp-c-gray-3); 50 | --vp-c-default-soft: var(--vp-c-gray-soft); 51 | 52 | --vp-c-brand-1: var(--vp-c-indigo-1); 53 | --vp-c-brand-2: var(--vp-c-indigo-2); 54 | --vp-c-brand-3: var(--vp-c-indigo-3); 55 | --vp-c-brand-soft: var(--vp-c-indigo-soft); 56 | 57 | --vp-c-tip-1: var(--vp-c-brand-1); 58 | --vp-c-tip-2: var(--vp-c-brand-2); 59 | --vp-c-tip-3: var(--vp-c-brand-3); 60 | --vp-c-tip-soft: var(--vp-c-brand-soft); 61 | 62 | --vp-c-warning-1: var(--vp-c-yellow-1); 63 | --vp-c-warning-2: var(--vp-c-yellow-2); 64 | --vp-c-warning-3: var(--vp-c-yellow-3); 65 | --vp-c-warning-soft: var(--vp-c-yellow-soft); 66 | 67 | --vp-c-danger-1: var(--vp-c-red-1); 68 | --vp-c-danger-2: var(--vp-c-red-2); 69 | --vp-c-danger-3: var(--vp-c-red-3); 70 | --vp-c-danger-soft: var(--vp-c-red-soft); 71 | } 72 | 73 | /** 74 | * Component: Button 75 | * -------------------------------------------------------------------------- */ 76 | 77 | :root { 78 | --vp-button-brand-border: transparent; 79 | --vp-button-brand-text: var(--vp-c-white); 80 | --vp-button-brand-bg: var(--vp-c-brand-3); 81 | --vp-button-brand-hover-border: transparent; 82 | --vp-button-brand-hover-text: var(--vp-c-white); 83 | --vp-button-brand-hover-bg: var(--vp-c-brand-2); 84 | --vp-button-brand-active-border: transparent; 85 | --vp-button-brand-active-text: var(--vp-c-white); 86 | --vp-button-brand-active-bg: var(--vp-c-brand-1); 87 | } 88 | 89 | /** 90 | * Component: Home 91 | * -------------------------------------------------------------------------- */ 92 | 93 | :root { 94 | --vp-home-hero-name-color: transparent; 95 | --vp-home-hero-name-background: -webkit-linear-gradient( 96 | 120deg, 97 | #bd34fe 30%, 98 | #41d1ff 99 | ); 100 | 101 | --vp-home-hero-image-background-image: linear-gradient( 102 | -45deg, 103 | #bd34fe 50%, 104 | #47caff 50% 105 | ); 106 | --vp-home-hero-image-filter: blur(44px); 107 | } 108 | 109 | @media (min-width: 640px) { 110 | :root { 111 | --vp-home-hero-image-filter: blur(56px); 112 | } 113 | } 114 | 115 | @media (min-width: 960px) { 116 | :root { 117 | --vp-home-hero-image-filter: blur(68px); 118 | } 119 | } 120 | 121 | /** 122 | * Component: Custom Block 123 | * -------------------------------------------------------------------------- */ 124 | 125 | :root { 126 | --vp-custom-block-tip-border: transparent; 127 | --vp-custom-block-tip-text: var(--vp-c-text-1); 128 | --vp-custom-block-tip-bg: var(--vp-c-brand-soft); 129 | --vp-custom-block-tip-code-bg: var(--vp-c-brand-soft); 130 | } 131 | 132 | /** 133 | * Component: Algolia 134 | * -------------------------------------------------------------------------- */ 135 | 136 | .DocSearch { 137 | --docsearch-primary-color: var(--vp-c-brand-1) !important; 138 | } 139 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ansible.python.interpreterPath": "/opt/homebrew/bin/python3" 3 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Richard Yu 2 | 3 | This software is for personal use, whether in your personal computer or in a work 4 | computer. You should not distribute the license used to activate it without the 5 | explicit permission from the author. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 8 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 9 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 10 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 12 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 13 | SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Logseq Plugin Move Block 2 | 3 | [![Github All Releases](https://img.shields.io/github/downloads/vipzhicheng/logseq-plugin-move-block/total.svg)](https://github.com/vipzhicheng/logseq-plugin-move-block/releases) 4 | 5 | A Logseq plugin to help you manage block movement. 6 | 7 | https://github.com/vipzhicheng/logseq-plugin-move-block/assets/1209538/f6832d79-92a7-4113-86d8-163f4adb7f7f 8 | 9 | **Note: Move Block is a paid plugin now. I charge a fee for a few of the features in this plugin. The main features are still free to use.** 10 | 11 | ## Usage 12 | 13 | The default key-binding for the UI is: `mod+shift+m` 14 | 15 | You can learn more from the official [documentation](https://www.vipzhicheng.com/logseq-plugin-move-block/) 16 | 17 | ## Install 18 | 19 | ### Manually 20 | 21 | 1. Git clone this repo 22 | 2. Run `npm install` 23 | 3. Run `npm run build` 24 | 4. In Logseq, click `Plugins` which is in the right top dropdown menu 25 | 5. Click the `Load unpacked plugin` button and select the dist directory of this plugin directory 26 | 6. If the plugin does not work, you can try to disable and enable the plugin by clicking the switch button on the Plugins page. 27 | 28 | ### Marketplace 29 | 30 | Better choice. 31 | 32 | ## Inspiration and Thanks 33 | 34 | Part of my inspiration comes from the following plugins: 35 | 36 | - [logseq-extract-plugin](https://github.com/sidharth-panwar/logseq-extract-plugin) 37 | - [logseq-plugin-block-to-page](https://github.com/hyrijk/logseq-plugin-block-to-page) 38 | 39 | ## Notice 40 | 41 | If you want to move multiple selected blocks at once, you must use the shortcut way. The icon top right corner is not recommended. Because it will lose the selected block state. 42 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## v1.0.0 4 | 5 | - feat: journal action date-picker respect edn config `start-of-week` 6 | - feat: add move to block uuid, support uuid with embed or ref format. 7 | - feat: convert it to paid plugin for better maintainance. 8 | - fix: move multi blocks will not fail fast, but ignore empty blocks. 9 | - fix: cut hierarchial blocks tree. 10 | - chore: upgrade deps 11 | 12 | ## v0.1.0 13 | 14 | - feat: add move block page icon 15 | - feat: add favorites list 16 | - feat: add scenario to favorites directly 17 | - feat: make page auto complete clearable 18 | - feat: make scenario history and favorites clearable and deletable 19 | - feat: change history and favorites order from new to old 20 | - feat: make history and favorites permanent in assets 21 | - feat: favorites support drag and drop 22 | - fix: sometime enter key can not trigger submit 23 | - infra: upgrade deps. 24 | 25 | ## v0.0.13 26 | 27 | - fix: remove version indicator in the title bar. 28 | - feat: add tomorrow, yesterday option. 29 | - feat: add history panel for quick selection. 30 | - feat: add "Cut content and keep embed to target" 31 | 32 | ## v0.0.12 33 | 34 | - fix: try to fix context menu command not work 35 | 36 | ## v0.0.11 37 | 38 | - fix: try to fix console error. 39 | - feat: add a version indicator. 40 | - infra: upgrade deps. 41 | 42 | ## v0.0.10 43 | 44 | - fix: try to fix console error 45 | 46 | ## v0.0.9 47 | 48 | - fix: timezone issue 49 | 50 | ## v0.0.8 51 | 52 | - feat: add block embed action 53 | 54 | ## v0.0.7 55 | 56 | - fix: timezone issue 57 | 58 | ## v0.0.6 59 | 60 | - fix: remove copy ref to contents context command, not that useful. 61 | - fix: add copy to current page and choose at top or bottom. 62 | 63 | ## v0.0.5 64 | 65 | - fix: optimize cut content action using moveBlock 66 | 67 | ## v0.0.4 68 | 69 | - fix: adjust UI style. 70 | 71 | ## v0.0.3 72 | 73 | - infra: change build tool from Webpack to Vite 74 | - infra: add Github Actions for release 75 | - refactor: rename this plugin from `copy ref to journal` to `move block`, add a UI to control 76 | -------------------------------------------------------------------------------- /cn/guide/getting-started.md: -------------------------------------------------------------------------------- 1 | # 快速开始 2 | 3 | 欢迎安装并尝试使用 Logseq Move Block。这是一个简单的说明,让你快速理解和开始使用。 4 | 5 | ## 是什么 6 | 7 | Logseq Move Block 是一个 Logseq 插件,用于在 Logseq 中自由的移动 Block。由于 Logseq 是一个大纲笔记软件,所以你会有越来越多的 Block。远比你的页面要多。所以你通常会有整理的需求,也就是将这些 Block 来回移动,复制,引用,或者嵌入。使用 Move Block 插件,你可以很轻松的做这些操作。 8 | 9 | 使用场景: 10 | 11 | 1. 使用 Namespace 将一个很长的页面改成嵌套页面。 12 | 2. 将部分内容从日历页面移动到某个项目页面,并在日历页面保留引用。或者反过来。 13 | 3. 将部分内容从页面的中间移动到当前页面的顶部或者底部。 14 | 4. ... 15 | 16 | ## 特性 17 | 18 | - 支持 Slash Command 19 | - 支持 Context Command 20 | - 支持快捷键 21 | - 支持页面右上角图标按钮 22 | - 支持移动到任意日历和页面 23 | - 支持移动到顶部或底部 24 | - 支持复制和移动,并保留引用或者嵌入 25 | - 支持停留在原来的页面或者跳转到目标页面 26 | - 支持保留操作历史,支持收藏常用操作 27 | 28 | ## 安装 29 | 30 | ### 插件市场 31 | 32 | 在插件市场中搜索它,并从那里进行安装。 33 | 34 | ### 手动安装 35 | 36 | 1. 从发布页面下载最新的 zip 文件。 37 | 2. 将 zip 文件解压缩到您想要存储插件的文件夹中。 38 | 3. 在 Logseq 中打开开发者模式。 39 | 4. 通过点击插件模态框上的“加载未打包插件”按钮,加载解压缩后的文件夹 40 | 5. 您现在应该能看到插件已经被安装。 41 | 42 | ## 快速开始 43 | 44 | 1. 光标放在要操作的 Block 上。 45 | 2. 通过快捷键或者 Context Command,Slash Command, 或者插件右上角图标按钮,打开配置窗口。 46 | 3. 根据需求选择合适的选项。 47 | 4. 点击 OK 执行。 48 | 5. 下次如果有类似的操作需求,直接从收藏夹或者操作历史中快速选择。 49 | 50 | ## 关于多行和嵌套的注意事项 51 | 52 | 1. 由于 Logseq 本身的限制,如果是移动多行,在选中多行以后,只能通过快捷键触发操作窗口,才能继续完成多行移动,其他方式会退化成选择时选中的第一个 Block。 53 | 2. 选择多行时,选择的顺序很重要,决定了操作的顺序,而不是实际在页面中呈现的顺序。 54 | 3. 剪切操作支持嵌套 Block,但是复制操作不支持嵌套。所以这意味着如果是剪切,只要选择了根 Block,整个 Block 树都会被剪切过去,并且维持原来的结构,而如果是复制,则不会保持原来的结构,都会被拉平,需要在新的目标页面重新手动组织结构。从视觉上,除了要关注 Logseq 高亮的区域,还需要关注区块前面的小圆点是否变色。 55 | 4. 剪切操作支持同时剪切多个嵌套 Block 树,也支持从一颗大 Block 树中剪切出多个 Block 子树,判断依据是选择高亮的 Block 之间的相互关系,只有连续的父子级关系才会认为是一颗树,如果中间断开或者本身是兄弟关系,则会被识别为是一个新的子树。小圆点未高亮的也可能因为父节点被选中而包含在剪切的树里。 56 | 57 | ### 举个例子 58 | 59 | ![](/assets/example.png) 60 | 61 | 这里看到高亮的区域是 `1,2,3,4,5,7,8,0`。其中小圆点高亮的只有`1,3,7,0`, 在这种情况下: 62 | 63 | 如果是复制,目标页将得到如下结果: 64 | 65 | ![](/assets/result1.png) 66 | 67 | 如果是剪切,目标页将得到如下结果: 68 | 69 | ![](/assets/result2.png) 70 | 71 | 可以看到,这里因为 7 和 0 之间的 8 没有被选中,所以 0 在剪切后作为了一颗新的子树,而 2,4,5 虽然没有被选中,但是,因为父节点被选中了,所以也一起被剪切了。 72 | 73 | 这个例子比较极端,是为了演示插件的处理逻辑,日常使用时,一般很少出现不连续的选择一起移动的情况。 74 | -------------------------------------------------------------------------------- /cn/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | 4 | hero: 5 | name: "Logseq Move Block" 6 | text: "移动 Block 到任何地方" 7 | tagline: "Logseq 移动 Block 解决方案" 8 | image: 9 | src: /assets/logo.png 10 | alt: Logseq Move Block 11 | actions: 12 | - theme: brand 13 | text: 开始使用 14 | link: /cn/guide/getting-started 15 | - theme: alt 16 | text: 购买Pro版本 17 | link: /cn/purchase 18 | 19 | features: 20 | - title: 易于使用 21 | details: 选中要移动的行,点击插件图标即可打开配置窗口。 22 | icon: ☕️ 23 | - title: 配置多样 24 | details: 可以移动到不同的页面,不同的位置,以不同的方式。可以记录操作历史和收藏常用操作。 25 | icon: 🛠️ 26 | - title: 支持多行和嵌套 27 | details: 多行是指选中了多个Block,可以是连续的也可以不连续。嵌套是指以合理方式组织好的Block树。 28 | icon: 📚 29 | --- 30 | 31 |
32 | 33 | ## 示例 34 | 35 |