From 33e34ab1be09c0e455933a6a654dd4477a4bfe60 Mon Sep 17 00:00:00 2001 From: "A. S." <12621257+Victor239@users.noreply.github.com> Date: Thu, 25 Dec 2025 03:32:57 +0000 Subject: [PATCH 1/2] Fix vertical line collapse behaviour (#12248) --- src/main/frontend/handler/editor.cljs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/frontend/handler/editor.cljs b/src/main/frontend/handler/editor.cljs index b68ea534ca..ffd1ddf13d 100644 --- a/src/main/frontend/handler/editor.cljs +++ b/src/main/frontend/handler/editor.cljs @@ -3853,10 +3853,11 @@ (defn toggle-open-block-children! [block-id] (p/let [blocks ( Date: Thu, 25 Dec 2025 13:25:12 +0800 Subject: [PATCH 2/2] enhance(plugins): apis related improvements (#12266) --- .../test/logseq/e2e/plugins_basic_test.clj | 69 +++++ deps/outliner/src/logseq/outliner/page.cljs | 50 ++-- libs/package.json | 6 +- libs/src/LSPlugin.ts | 40 +-- .../frontend/components/property/value.cljs | 8 + src/main/logseq/api.cljs | 2 + src/main/logseq/api/db_based.cljs | 46 ++-- src/main/logseq/api/editor.cljs | 243 +++++++++--------- 8 files changed, 274 insertions(+), 190 deletions(-) diff --git a/clj-e2e/test/logseq/e2e/plugins_basic_test.clj b/clj-e2e/test/logseq/e2e/plugins_basic_test.clj index 5f77e40790..4e3b7effc5 100644 --- a/clj-e2e/test/logseq/e2e/plugins_basic_test.clj +++ b/clj-e2e/test/logseq/e2e/plugins_basic_test.clj @@ -335,3 +335,72 @@ result (ls-api-call! :editor.get_tag_objects "logseq.class/Task")] (is (= (count result) 1)) (is (= "task 1" (get (first result) "title")))))) + +(deftest create-and-get-tag-test + (testing "create and get tag with title or ident" + (let [title "book1" + title-ident (str :plugin.class._test_plugin/book1) + tag1 (ls-api-call! :editor.createTag title) + tag2 (ls-api-call! :editor.getTag title) + tag3 (ls-api-call! :editor.getTag title-ident) + tag4 (ls-api-call! :editor.getTag (get tag1 "uuid"))] + (is (= (get tag1 "ident") title-ident) "create tag with title from test as plugin") + (is (= (get tag2 "ident") title-ident) "get tag with title") + (is (= (get tag3 "title") title) "get tag with ident") + (is (= (get tag4 "title") title) "get tag with uuid"))) + + (testing "add and remove tag extends" + (let [tag1 (ls-api-call! :editor.createTag "tag1") + tag2 (ls-api-call! :editor.createTag "tag2") + tag3 (ls-api-call! :editor.createTag "tag3") + id1 (get tag1 "id") + id2 (get tag2 "id") + id3 (get tag3 "id") + _ (ls-api-call! :editor.addTagExtends id1 id2) + tag1 (ls-api-call! :editor.getTag id1)] + (is (= (get tag1 ":logseq.property.class/extends") [id2]) "tag1 extends tag2 with db id") + (let [_ (ls-api-call! :editor.addTagExtends id1 id3) + tag1 (ls-api-call! :editor.getTag id1)] + (is (= (get tag1 ":logseq.property.class/extends") [id2 id3]) "tag1 extends tag2,tag3 with db ids")) + ))) + +(deftest get-tags-by-name-test + (testing "get tags by exact name" + (let [tag-name "product" + tag1 (ls-api-call! :editor.createTag tag-name) + result (ls-api-call! :editor.getTagsByName tag-name)] + (is (= 1 (count result)) "should return exactly one tag") + (is (= (get tag1 "uuid") (get (first result) "uuid")) "should return the created tag") + (is (= (get tag1 "title") (get (first result) "title")) "tag title should match"))) + + (testing "get tags by name is case-insensitive" + (let [tag-name "TestTag123" + _ (ls-api-call! :editor.createTag tag-name) + result-lower (ls-api-call! :editor.getTagsByName "testtag123") + result-upper (ls-api-call! :editor.getTagsByName "TESTTAG123") + result-mixed (ls-api-call! :editor.getTagsByName "TeStTaG123")] + (is (= 1 (count result-lower)) "should find tag with lowercase search") + (is (= 1 (count result-upper)) "should find tag with uppercase search") + (is (= 1 (count result-mixed)) "should find tag with mixed case search") + (is (= (get (first result-lower) "uuid") (get (first result-upper) "uuid")) "all searches should return same tag") + (is (= (get (first result-lower) "uuid") (get (first result-mixed) "uuid")) "all searches should return same tag"))) + + (testing "get tags by name returns empty array for non-existent tag" + (let [result (ls-api-call! :editor.getTagsByName "NonExistentTag12345")] + (is (empty? result) "should return empty array for non-existent tag"))) + + (testing "get tags by name filters out non-tag pages" + (let [page-name "regular-page" + _ (page/new-page page-name) + result (ls-api-call! :editor.getTagsByName page-name)] + (is (empty? result) "should not return regular pages, only tags"))) + + (testing "get tags by name with multiple tags having similar names" + (let [tag1 (ls-api-call! :editor.createTag "category") + tag2 (ls-api-call! :editor.createTag "Category") + result (ls-api-call! :editor.getTagsByName "category")] + ;; Due to case-insensitive name normalization, both tags should be the same + (is (>= (count result) 1) "should return at least one tag") + ;; Verify the result contains valid tag structure + (is (string? (get (first result) "uuid")) "returned tag should have uuid") + (is (string? (get (first result) "title")) "returned tag should have title")))) diff --git a/deps/outliner/src/logseq/outliner/page.cljs b/deps/outliner/src/logseq/outliner/page.cljs index 6ca766d388..3202da624d 100644 --- a/deps/outliner/src/logseq/outliner/page.cljs +++ b/deps/outliner/src/logseq/outliner/page.cljs @@ -247,6 +247,7 @@ (map (fn [id] (d/entity db [:block/uuid id])) tags) tags) class? (or class? (some (fn [t] (= :logseq.class/Tag (:db/ident t))) tags)) + class-ident-namespace? (and class? class-ident-namespace (string? class-ident-namespace)) title (sanitize-title title*) types (cond class? #{:logseq.class/Tag} @@ -258,29 +259,38 @@ (set (map :db/ident tags)) :else #{:logseq.class/Page}) - existing-page-id (first (ldb/page-exists? db title types)) + existing-names-page (ldb/page-exists? db title types) + existing-page-id (some->> existing-names-page + (filter #(try (when-let [e (and class-ident-namespace? (d/entity db %))] + (let [ns' (namespace (:db/ident e))] + (= (str ns') class-ident-namespace))) + (catch :default _ false))) + (first)) existing-page (some->> existing-page-id (d/entity db))] (if (and existing-page (not (:block/parent existing-page))) (let [tx-meta {:persist-op? persist-op? :outliner-op :save-block}] - (when (and class? - (not (ldb/class? existing-page)) - (ldb/internal-page? existing-page)) + (if (and class? + (not (ldb/class? existing-page)) + (ldb/internal-page? existing-page)) ;; Convert existing page to class (let [tx-data [(merge (db-class/build-new-class db (select-keys existing-page [:block/title :block/uuid :block/created-at]) - (when (and class? class-ident-namespace (string? class-ident-namespace)) + (when class-ident-namespace? {:ident-namespace class-ident-namespace})) (select-keys existing-page [:db/ident])) [:db/retract [:block/uuid (:block/uuid existing-page)] :block/tags :logseq.class/Page]]] {:tx-meta tx-meta :tx-data tx-data :page-uuid (:block/uuid existing-page) - :title (:block/title existing-page)}))) - (let [page (gp-block/page-name->map title db true date-formatter - {:class? class? - :page-uuid (when (uuid? uuid') uuid') - :skip-existing-page-check? true}) + :title (:block/title existing-page)}) + ;; Just return existing page info + {:page-uuid (:block/uuid existing-page) + :title (:block/title existing-page)})) + (let [page (gp-block/page-name->map title db true date-formatter + {:class? class? + :page-uuid (when (uuid? uuid') uuid') + :skip-existing-page-check? true}) [page parents'] (if (and (text/namespace-page? title) split-namespace?) (let [pages (split-namespace-pages db page date-formatter class?)] [(last pages) (butlast pages)]) @@ -296,16 +306,16 @@ (outliner-validate/validate-page-title-characters (str (:block/title parent)) {:node parent}))) (let [page-uuid (:block/uuid page) - page-txs (build-page-tx db properties page (select-keys options [:whiteboard? :class? :tags :class-ident-namespace])) - txs (concat - ;; transact doesn't support entities - (remove de/entity? parents') - page-txs) + page-txs (build-page-tx db properties page (select-keys options [:whiteboard? :class? :tags :class-ident-namespace])) + txs (concat + ;; transact doesn't support entities + (remove de/entity? parents') + page-txs) tx-meta (cond-> {:persist-op? persist-op? :outliner-op :create-page} - today-journal? - (assoc :create-today-journal? true - :today-journal-name title))] + today-journal? + (assoc :create-today-journal? true + :today-journal-name title))] {:tx-meta tx-meta :tx-data txs :title title @@ -315,5 +325,5 @@ [conn title opts] (let [{:keys [tx-meta tx-data title' page-uuid]} (create @conn title opts)] (when (seq tx-data) - (ldb/transact! conn tx-data tx-meta) - [title' page-uuid]))) + (ldb/transact! conn tx-data tx-meta)) + [title' page-uuid])) diff --git a/libs/package.json b/libs/package.json index 5577ab6820..6d85176154 100644 --- a/libs/package.json +++ b/libs/package.json @@ -14,8 +14,8 @@ "build": "tsc && rm dist/*.js && npm run build:user", "lint": "prettier --check \"src/**/*.{ts, js}\"", "fix": "prettier --write \"src/**/*.{ts, js}\"", - "build:docs": "typedoc src/LSPlugin.user.ts", - "build:docs:json": "typedoc --plugin typedoc-plugin-lsp-docs src/LSPlugin.user.ts && typedoc --json docs/out.json ./src/LSPlugin.user.ts" + "build:docs": "typedoc --plugin typedoc-plugin-lsp-docs src/LSPlugin.user.ts", + "build:docs:json": "typedoc --json docs/out.json ./src/LSPlugin.user.ts" }, "dependencies": { "csstype": "3.1.0", @@ -41,7 +41,7 @@ "terser-webpack-plugin": "^5.3.6", "ts-loader": "9.3.0", "typedoc": "0.28.15", - "typedoc-plugin-lsp-docs": "^0.0.1", + "typedoc-plugin-lsp-docs": "^0.0.2", "typescript": "5.9.3", "webpack": "5.94.0", "webpack-bundle-analyzer": "4.5.0", diff --git a/libs/src/LSPlugin.ts b/libs/src/LSPlugin.ts index b349933b2f..05d7fc2e56 100644 --- a/libs/src/LSPlugin.ts +++ b/libs/src/LSPlugin.ts @@ -699,15 +699,13 @@ export interface IEditorProxy extends Record { * @param opts */ insertBlock: ( - srcBlock: BlockIdentity, + srcBlock: BlockIdentity | EntityID, content: string, opts?: Partial<{ before: boolean sibling: boolean start: boolean end: boolean - isPageBlock: boolean - focus: boolean customUUID: string properties: {} }> @@ -725,30 +723,20 @@ export interface IEditorProxy extends Record { ) => Promise | null> updateBlock: ( - srcBlock: BlockIdentity, + srcBlock: BlockIdentity | EntityID, content: string, opts?: Partial<{ properties: {} }> ) => Promise - removeBlock: (srcBlock: BlockIdentity) => Promise + removeBlock: (srcBlock: BlockIdentity | EntityID) => Promise getBlock: ( srcBlock: BlockIdentity | EntityID, opts?: Partial<{ includeChildren: boolean }> ) => Promise - /** - * @example - * - * ```ts - * logseq.Editor.setBlockCollapsed('uuid', true) - * logseq.Editor.setBlockCollapsed('uuid', 'toggle') - * ``` - * @param uuid - * @param opts - */ setBlockCollapsed: ( - uuid: BlockUUID, + srcBlock: BlockIdentity | EntityID, opts: { flag: boolean | 'toggle' } | boolean | 'toggle' ) => Promise @@ -782,7 +770,8 @@ export interface IEditorProxy extends Record { getAllProperties: () => Promise getTagObjects: (nameOrIdent: string) => Promise createTag: (tagName: string, opts?: Partial<{ uuid: string }>) => Promise - getTag: (nameOrIdent: string) => Promise + getTag: (nameOrIdent: string | EntityID) => Promise + getTagsByName: (tagName: string) => Promise | null> addTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise removeTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise addTagExtends: (tagId: BlockIdentity, parentTagIdOrName: BlockIdentity) => Promise @@ -808,11 +797,11 @@ export interface IEditorProxy extends Record { ) => Promise getPreviousSiblingBlock: ( - srcBlock: BlockIdentity + srcBlock: BlockIdentity | EntityID ) => Promise getNextSiblingBlock: ( - srcBlock: BlockIdentity + srcBlock: BlockIdentity | EntityID ) => Promise moveBlock: ( @@ -845,17 +834,15 @@ export interface IEditorProxy extends Record { // block property related APIs upsertBlockProperty: ( - block: BlockIdentity, + block: BlockIdentity | EntityID, key: string, value: any ) => Promise - removeBlockProperty: (block: BlockIdentity, key: string) => Promise - - getBlockProperty: (block: BlockIdentity, key: string) => Promise - - getBlockProperties: (block: BlockIdentity) => Promise | null> - getPageProperties: (page: PageIdentity) => Promise | null> + removeBlockProperty: (block: BlockIdentity | EntityID, key: string) => Promise + getBlockProperty: (block: BlockIdentity | EntityID, key: string) => Promise + getBlockProperties: (block: BlockIdentity | EntityID) => Promise | null> + getPageProperties: (page: PageIdentity | EntityID) => Promise | null> scrollToBlockInPage: ( pageName: BlockPageName, @@ -864,6 +851,7 @@ export interface IEditorProxy extends Record { ) => void openInRightSidebar: (id: BlockUUID | EntityID) => void + openPDFViewer: (assetBlockIdOrFileUrl: string | EntityID) => Promise /** * @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-a-translator diff --git a/src/main/frontend/components/property/value.cljs b/src/main/frontend/components/property/value.cljs index 3cfd7c8fb3..3eb190a744 100644 --- a/src/main/frontend/components/property/value.cljs +++ b/src/main/frontend/components/property/value.cljs @@ -1285,6 +1285,13 @@ (fn [] #(set-property-value! @*value)) []) + + (hooks/use-effect! + (fn [] + (set-value! number-value) + #()) + [number-value]) + [:div.ls-number.flex.flex-1.jtrigger {:ref *ref :on-click #(do @@ -1297,6 +1304,7 @@ :class (str "ls-number-input h-6 px-0 py-0 border-none bg-transparent focus-visible:ring-0 focus-visible:ring-offset-0 text-base" (when table-view? " text-sm")) :value value + :type "number" :on-change (fn [e] (set-value! (util/evalue e)) (reset! *value (util/evalue e))) diff --git a/src/main/logseq/api.cljs b/src/main/logseq/api.cljs index 858398eeae..da4a5c7ff2 100644 --- a/src/main/logseq/api.cljs +++ b/src/main/logseq/api.cljs @@ -135,6 +135,7 @@ (def ^:export set_block_collapsed api-editor/set_block_collapsed) (def ^:export update_block api-editor/update_block) (def ^:export upsert_block_property api-editor/upsert_block_property) +(def ^:export open_pdf_viewer api-editor/open_pdf_viewer) ;; ui (def ^:export show_msg sdk-ui/-show_msg) @@ -203,6 +204,7 @@ (def ^:export get_tag_objects db-based-api/get-tag-objects) (def ^:export create_tag db-based-api/create-tag) (def ^:export get_tag db-based-api/get-tag) +(def ^:export get_tags_by_name db-based-api/get-tags-by-name) (def ^:export add_tag_extends db-based-api/add-tag-extends) (def ^:export remove_tag_extends db-based-api/remove-tag-extends) (def ^:export add_block_tag db-based-api/add-block-tag) diff --git a/src/main/logseq/api/db_based.cljs b/src/main/logseq/api/db_based.cljs index b47a9dfc73..39fd79c94f 100644 --- a/src/main/logseq/api/db_based.cljs +++ b/src/main/logseq/api/db_based.cljs @@ -7,6 +7,7 @@ [clojure.walk :as walk] [datascript.core :as d] [frontend.db :as db] + [frontend.db.conn :as db-conn] [frontend.db.async :as db-async] [frontend.db.model :as db-model] [frontend.handler.common.page :as page-common-handler] @@ -17,6 +18,7 @@ [frontend.modules.layout.core] [frontend.state :as state] [frontend.util :as util] + [logseq.db.frontend.entity-util :as entity-util] [goog.object :as gobj] [logseq.api.block :as api-block] [logseq.db :as ldb] @@ -220,9 +222,12 @@ (when (text/namespace-page? title) (throw (ex-info "Tag title shouldn't include forward slash" {:title title}))) (let [opts (bean/->clj opts) + custom-ident-namespace (:customIdentNamespace opts) + class-ident-namespace (or (some-> custom-ident-namespace (api-block/sanitize-user-property-name)) + (api-block/resolve-class-prefix-for-db this)) opts' (assoc opts - :redirect? false - :class-ident-namespace (api-block/resolve-class-prefix-for-db this))] + :redirect? false + :class-ident-namespace class-ident-namespace)] (p/let [tag (db-page-handler/js tag))))) @@ -255,21 +260,28 @@ (:db/id extend)))) (defn get-tag [class-uuid-or-ident-or-title] - (this-as - this - (let [title-or-ident (-> (if-not (string? class-uuid-or-ident-or-title) - (str class-uuid-or-ident-or-title) - class-uuid-or-ident-or-title) - (string/replace #"^:+" "")) - eid (if (text/namespace-page? title-or-ident) - (keyword title-or-ident) - (if (util/uuid-string? title-or-ident) - (when-let [id (sdk-utils/uuid-or-throw-error title-or-ident)] - [:block/uuid id]) - (keyword (api-block/resolve-class-prefix-for-db this) title-or-ident))) - tag (db/entity eid)] - (when (ldb/class? tag) - (sdk-utils/result->js tag))))) + (this-as this + (let [eid (if (number? class-uuid-or-ident-or-title) + class-uuid-or-ident-or-title + (let [title-or-ident (-> (if-not (string? class-uuid-or-ident-or-title) + (str class-uuid-or-ident-or-title) + class-uuid-or-ident-or-title) + (string/replace #"^:+" ""))] + (if (text/namespace-page? title-or-ident) + (keyword title-or-ident) + (if (util/uuid-string? title-or-ident) + (when-let [id (sdk-utils/uuid-or-throw-error title-or-ident)] + [:block/uuid id]) + (keyword (api-block/resolve-class-prefix-for-db this) title-or-ident))))) + tag (db/entity eid)] + (when (ldb/class? tag) + (sdk-utils/result->js tag))))) + +(defn get-tags-by-name [name] + (when-let [tags (some->> (entity-util/get-pages-by-name (db-conn/get-db) name) + (map #(some-> % (first) (db/entity))) + (filter ldb/class?))] + (sdk-utils/result->js tags))) (defn tag-add-property [tag-id property-id-or-name] (p/let [tag (db/get-case-page tag-id) diff --git a/src/main/logseq/api/editor.cljs b/src/main/logseq/api/editor.cljs index 4741afc98f..3372e55d9d 100644 --- a/src/main/logseq/api/editor.cljs +++ b/src/main/logseq/api/editor.cljs @@ -2,7 +2,6 @@ "Editor related APIs" (:require [cljs-bean.core :as bean] [cljs.reader] - [clojure.string :as string] [frontend.commands :as commands] [frontend.config :as config] [frontend.date :as date] @@ -17,6 +16,8 @@ [frontend.handler.page :as page-handler] [frontend.handler.property :as property-handler] [frontend.handler.shell :as shell] + [frontend.handler.assets :as assets-handler] + [frontend.extensions.pdf.assets :as pdf-assets] [frontend.modules.layout.core] [frontend.modules.outliner.tree :as outliner-tree] [frontend.state :as state] @@ -27,6 +28,7 @@ [logseq.api.block :as api-block] [logseq.api.db-based :as db-based-api] [logseq.common.util.date-time :as date-time-util] + [logseq.common.path :as path] [logseq.db :as ldb] [logseq.outliner.core :as outliner-core] [logseq.sdk.core] @@ -192,60 +194,46 @@ block)) (defn insert_block - [block-uuid-or-page-name content ^js opts] + [id content ^js opts] (this-as this - (when (string/blank? block-uuid-or-page-name) - (throw (js/Error. "Page title or block UUID shouldn't be empty."))) - - (p/let [block? (util/uuid-string? (str block-uuid-or-page-name)) - block (clj opts) - [page-name block-uuid] (if (util/uuid-string? block-uuid-or-page-name) - [nil (uuid block-uuid-or-page-name)] - [block-uuid-or-page-name nil]) - page-name (when page-name (util/page-name-sanity-lc page-name)) - _ (when (and page-name - (nil? (ldb/get-page (db/get-db) page-name))) - (page-handler/js (sdk-utils/normalize-keyword-for-json new-block))))))))) + (p/let [block (clj opts) + custom-uuid (or customUUID (:id properties)) + custom-uuid (when custom-uuid (sdk-utils/uuid-or-throw-error custom-uuid)) + _ (when (and custom-uuid (db-model/query-block-by-uuid custom-uuid)) + (throw (js/Error. + (util/format "Custom block UUID already exists (%s)." custom-uuid)))) + block-uuid' (if (and (not sibling) before block-uuid) + (let [block (db/entity [:block/uuid block-uuid]) + first-child (ldb/get-first-child (db/get-db) (:db/id block))] + (if first-child + (:block/uuid first-child) + block-uuid)) + block-uuid) + insert-at-first-child? (not= block-uuid' block-uuid) + [sibling? before?] (if insert-at-first-child? + [true true] + [sibling before]) + db-based? (config/db-based-graph?) + before? (if (and (false? sibling?) before? (not insert-at-first-child?)) + false + before?) + opts' {:block-uuid block-uuid' + :sibling? sibling? + :before? before? + :start? start + :end? end + :edit-block? false + :custom-uuid custom-uuid + :ordered-list? (if (boolean? autoOrderedList) autoOrderedList false) + :properties (when (not db-based?) + (merge properties + (when custom-uuid {:id custom-uuid})))}] + (if db-based? + (db-based-api/insert-block this content properties schema opts') + (p/let [new-block (editor-handler/api-insert-new-block! content opts')] + (bean/->js (sdk-utils/normalize-keyword-for-json new-block))))))))) (def insert_batch_block (fn [block-uuid ^js batch-blocks-js ^js opts-js] @@ -279,25 +267,25 @@ bean/->js)))))))))))) (def remove_block - (fn [block-uuid ^js _opts] - (p/let [repo (state/get-current-repo) - _ (clj opts)] - (when block + (when-let [block-uuid (:block/uuid block)] (if db-based? (db-based-api/update-block this block content opts') - (editor-handler/save-block! repo - (sdk-utils/uuid-or-throw-error block-uuid) content + (editor-handler/save-block! repo block-uuid content (if db-based? (dissoc opts' :properties) opts')))))))) (def move_block @@ -335,9 +323,8 @@ (get_block (:block/uuid block) opts)))) (def get_previous_sibling_block - (fn [block-uuid ^js opts] - (p/let [id (sdk-utils/uuid-or-throw-error block-uuid) - block (clj opts) + (let [block-uuid (:block/uuid block) + opts (bean/->clj opts) opts (if (or (string? opts) (boolean? opts)) {:flag opts} opts) {:keys [flag]} opts flag (if (= "toggle" flag) @@ -467,64 +453,59 @@ ;; block properties (defn upsert_block_property - [block-uuid key ^js value ^js options] - (this-as - this - (p/let [key' (api-block/sanitize-user-property-name key) - opts (bean/->clj options) - block-uuid (sdk-utils/uuid-or-throw-error block-uuid) - repo (state/get-current-repo) - block (clj value)] - (when block - (if db-based? - (db-based-api/upsert-block-property this block key' value opts) - (property-handler/set-block-property! repo block-uuid key' value)))))) + [id key ^js value ^js options] + (this-as this + (p/let [key' (api-block/sanitize-user-property-name key) + opts (bean/->clj options) + repo (state/get-current-repo) + block (clj value)] + (when-let [block-uuid (:block/uuid block)] + (if db-based? + (db-based-api/upsert-block-property this block key' value opts) + (property-handler/set-block-property! repo block-uuid key' value)))))) (defn remove_block_property - [block-uuid key] + [id key] (this-as this - (p/let [key (api-block/sanitize-user-property-name key) - block-uuid (sdk-utils/uuid-or-throw-error block-uuid) - _block ( block-uuid (db-model/get-block-by-uuid) (:block/properties))] - (when (seq properties) - (let [property-name (api-block/sanitize-user-property-name key) - ident (api-block/get-db-ident-from-property-name property-name this) - property-value (or (get properties property-name) - (get properties (keyword property-name)) - (get properties ident)) - property-value (if-let [property-id (:db/id property-value)] - (db/pull property-id) property-value) - property-value (cond-> property-value - (map? property-value) - (assoc - :value (or (:logseq.property/value property-value) - (:block/title property-value)) - :ident ident)) - parsed-value (api-block/parse-property-json-value-if-need ident property-value)] - (or parsed-value - (bean/->js (sdk-utils/normalize-keyword-for-json property-value))))))))) + (p/let [block ( block (:block/uuid) (db-model/get-block-by-uuid) (:block/properties))] + (when (seq properties) + (let [property-name (api-block/sanitize-user-property-name key) + ident (api-block/get-db-ident-from-property-name property-name this) + property-value (or (get properties property-name) + (get properties (keyword property-name)) + (get properties ident)) + property-value (if-let [property-id (:db/id property-value)] + (db/pull property-id) property-value) + property-value (cond-> property-value + (map? property-value) + (assoc + :value (or (:logseq.property/value property-value) + (:block/title property-value)) + :ident ident)) + parsed-value (api-block/parse-property-json-value-if-need ident property-value)] + (or parsed-value + (bean/->js (sdk-utils/normalize-keyword-for-json property-value))))))))) (def get_block_properties - (fn [block-uuid] - (p/let [block-uuid (sdk-utils/uuid-or-throw-error block-uuid) - block (