Skip to content

Commit fbe6b99

Browse files
authored
enhance(plugins): apis related improvements (#12266)
1 parent 33e34ab commit fbe6b99

8 files changed

Lines changed: 274 additions & 190 deletions

File tree

clj-e2e/test/logseq/e2e/plugins_basic_test.clj

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,72 @@
335335
result (ls-api-call! :editor.get_tag_objects "logseq.class/Task")]
336336
(is (= (count result) 1))
337337
(is (= "task 1" (get (first result) "title"))))))
338+
339+
(deftest create-and-get-tag-test
340+
(testing "create and get tag with title or ident"
341+
(let [title "book1"
342+
title-ident (str :plugin.class._test_plugin/book1)
343+
tag1 (ls-api-call! :editor.createTag title)
344+
tag2 (ls-api-call! :editor.getTag title)
345+
tag3 (ls-api-call! :editor.getTag title-ident)
346+
tag4 (ls-api-call! :editor.getTag (get tag1 "uuid"))]
347+
(is (= (get tag1 "ident") title-ident) "create tag with title from test as plugin")
348+
(is (= (get tag2 "ident") title-ident) "get tag with title")
349+
(is (= (get tag3 "title") title) "get tag with ident")
350+
(is (= (get tag4 "title") title) "get tag with uuid")))
351+
352+
(testing "add and remove tag extends"
353+
(let [tag1 (ls-api-call! :editor.createTag "tag1")
354+
tag2 (ls-api-call! :editor.createTag "tag2")
355+
tag3 (ls-api-call! :editor.createTag "tag3")
356+
id1 (get tag1 "id")
357+
id2 (get tag2 "id")
358+
id3 (get tag3 "id")
359+
_ (ls-api-call! :editor.addTagExtends id1 id2)
360+
tag1 (ls-api-call! :editor.getTag id1)]
361+
(is (= (get tag1 ":logseq.property.class/extends") [id2]) "tag1 extends tag2 with db id")
362+
(let [_ (ls-api-call! :editor.addTagExtends id1 id3)
363+
tag1 (ls-api-call! :editor.getTag id1)]
364+
(is (= (get tag1 ":logseq.property.class/extends") [id2 id3]) "tag1 extends tag2,tag3 with db ids"))
365+
)))
366+
367+
(deftest get-tags-by-name-test
368+
(testing "get tags by exact name"
369+
(let [tag-name "product"
370+
tag1 (ls-api-call! :editor.createTag tag-name)
371+
result (ls-api-call! :editor.getTagsByName tag-name)]
372+
(is (= 1 (count result)) "should return exactly one tag")
373+
(is (= (get tag1 "uuid") (get (first result) "uuid")) "should return the created tag")
374+
(is (= (get tag1 "title") (get (first result) "title")) "tag title should match")))
375+
376+
(testing "get tags by name is case-insensitive"
377+
(let [tag-name "TestTag123"
378+
_ (ls-api-call! :editor.createTag tag-name)
379+
result-lower (ls-api-call! :editor.getTagsByName "testtag123")
380+
result-upper (ls-api-call! :editor.getTagsByName "TESTTAG123")
381+
result-mixed (ls-api-call! :editor.getTagsByName "TeStTaG123")]
382+
(is (= 1 (count result-lower)) "should find tag with lowercase search")
383+
(is (= 1 (count result-upper)) "should find tag with uppercase search")
384+
(is (= 1 (count result-mixed)) "should find tag with mixed case search")
385+
(is (= (get (first result-lower) "uuid") (get (first result-upper) "uuid")) "all searches should return same tag")
386+
(is (= (get (first result-lower) "uuid") (get (first result-mixed) "uuid")) "all searches should return same tag")))
387+
388+
(testing "get tags by name returns empty array for non-existent tag"
389+
(let [result (ls-api-call! :editor.getTagsByName "NonExistentTag12345")]
390+
(is (empty? result) "should return empty array for non-existent tag")))
391+
392+
(testing "get tags by name filters out non-tag pages"
393+
(let [page-name "regular-page"
394+
_ (page/new-page page-name)
395+
result (ls-api-call! :editor.getTagsByName page-name)]
396+
(is (empty? result) "should not return regular pages, only tags")))
397+
398+
(testing "get tags by name with multiple tags having similar names"
399+
(let [tag1 (ls-api-call! :editor.createTag "category")
400+
tag2 (ls-api-call! :editor.createTag "Category")
401+
result (ls-api-call! :editor.getTagsByName "category")]
402+
;; Due to case-insensitive name normalization, both tags should be the same
403+
(is (>= (count result) 1) "should return at least one tag")
404+
;; Verify the result contains valid tag structure
405+
(is (string? (get (first result) "uuid")) "returned tag should have uuid")
406+
(is (string? (get (first result) "title")) "returned tag should have title"))))

deps/outliner/src/logseq/outliner/page.cljs

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@
247247
(map (fn [id] (d/entity db [:block/uuid id])) tags)
248248
tags)
249249
class? (or class? (some (fn [t] (= :logseq.class/Tag (:db/ident t))) tags))
250+
class-ident-namespace? (and class? class-ident-namespace (string? class-ident-namespace))
250251
title (sanitize-title title*)
251252
types (cond class?
252253
#{:logseq.class/Tag}
@@ -258,29 +259,38 @@
258259
(set (map :db/ident tags))
259260
:else
260261
#{:logseq.class/Page})
261-
existing-page-id (first (ldb/page-exists? db title types))
262+
existing-names-page (ldb/page-exists? db title types)
263+
existing-page-id (some->> existing-names-page
264+
(filter #(try (when-let [e (and class-ident-namespace? (d/entity db %))]
265+
(let [ns' (namespace (:db/ident e))]
266+
(= (str ns') class-ident-namespace)))
267+
(catch :default _ false)))
268+
(first))
262269
existing-page (some->> existing-page-id (d/entity db))]
263270
(if (and existing-page (not (:block/parent existing-page)))
264271
(let [tx-meta {:persist-op? persist-op?
265272
:outliner-op :save-block}]
266-
(when (and class?
267-
(not (ldb/class? existing-page))
268-
(ldb/internal-page? existing-page))
273+
(if (and class?
274+
(not (ldb/class? existing-page))
275+
(ldb/internal-page? existing-page))
269276
;; Convert existing page to class
270277
(let [tx-data [(merge (db-class/build-new-class db
271278
(select-keys existing-page [:block/title :block/uuid :block/created-at])
272-
(when (and class? class-ident-namespace (string? class-ident-namespace))
279+
(when class-ident-namespace?
273280
{:ident-namespace class-ident-namespace}))
274281
(select-keys existing-page [:db/ident]))
275282
[:db/retract [:block/uuid (:block/uuid existing-page)] :block/tags :logseq.class/Page]]]
276283
{:tx-meta tx-meta
277284
:tx-data tx-data
278285
:page-uuid (:block/uuid existing-page)
279-
:title (:block/title existing-page)})))
280-
(let [page (gp-block/page-name->map title db true date-formatter
281-
{:class? class?
282-
:page-uuid (when (uuid? uuid') uuid')
283-
:skip-existing-page-check? true})
286+
:title (:block/title existing-page)})
287+
;; Just return existing page info
288+
{:page-uuid (:block/uuid existing-page)
289+
:title (:block/title existing-page)}))
290+
(let [page (gp-block/page-name->map title db true date-formatter
291+
{:class? class?
292+
:page-uuid (when (uuid? uuid') uuid')
293+
:skip-existing-page-check? true})
284294
[page parents'] (if (and (text/namespace-page? title) split-namespace?)
285295
(let [pages (split-namespace-pages db page date-formatter class?)]
286296
[(last pages) (butlast pages)])
@@ -296,16 +306,16 @@
296306
(outliner-validate/validate-page-title-characters (str (:block/title parent)) {:node parent})))
297307

298308
(let [page-uuid (:block/uuid page)
299-
page-txs (build-page-tx db properties page (select-keys options [:whiteboard? :class? :tags :class-ident-namespace]))
300-
txs (concat
301-
;; transact doesn't support entities
302-
(remove de/entity? parents')
303-
page-txs)
309+
page-txs (build-page-tx db properties page (select-keys options [:whiteboard? :class? :tags :class-ident-namespace]))
310+
txs (concat
311+
;; transact doesn't support entities
312+
(remove de/entity? parents')
313+
page-txs)
304314
tx-meta (cond-> {:persist-op? persist-op?
305315
:outliner-op :create-page}
306-
today-journal?
307-
(assoc :create-today-journal? true
308-
:today-journal-name title))]
316+
today-journal?
317+
(assoc :create-today-journal? true
318+
:today-journal-name title))]
309319
{:tx-meta tx-meta
310320
:tx-data txs
311321
:title title
@@ -315,5 +325,5 @@
315325
[conn title opts]
316326
(let [{:keys [tx-meta tx-data title' page-uuid]} (create @conn title opts)]
317327
(when (seq tx-data)
318-
(ldb/transact! conn tx-data tx-meta)
319-
[title' page-uuid])))
328+
(ldb/transact! conn tx-data tx-meta))
329+
[title' page-uuid]))

libs/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"build": "tsc && rm dist/*.js && npm run build:user",
1515
"lint": "prettier --check \"src/**/*.{ts, js}\"",
1616
"fix": "prettier --write \"src/**/*.{ts, js}\"",
17-
"build:docs": "typedoc src/LSPlugin.user.ts",
18-
"build:docs:json": "typedoc --plugin typedoc-plugin-lsp-docs src/LSPlugin.user.ts && typedoc --json docs/out.json ./src/LSPlugin.user.ts"
17+
"build:docs": "typedoc --plugin typedoc-plugin-lsp-docs src/LSPlugin.user.ts",
18+
"build:docs:json": "typedoc --json docs/out.json ./src/LSPlugin.user.ts"
1919
},
2020
"dependencies": {
2121
"csstype": "3.1.0",
@@ -41,7 +41,7 @@
4141
"terser-webpack-plugin": "^5.3.6",
4242
"ts-loader": "9.3.0",
4343
"typedoc": "0.28.15",
44-
"typedoc-plugin-lsp-docs": "^0.0.1",
44+
"typedoc-plugin-lsp-docs": "^0.0.2",
4545
"typescript": "5.9.3",
4646
"webpack": "5.94.0",
4747
"webpack-bundle-analyzer": "4.5.0",

libs/src/LSPlugin.ts

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -699,15 +699,13 @@ export interface IEditorProxy extends Record<string, any> {
699699
* @param opts
700700
*/
701701
insertBlock: (
702-
srcBlock: BlockIdentity,
702+
srcBlock: BlockIdentity | EntityID,
703703
content: string,
704704
opts?: Partial<{
705705
before: boolean
706706
sibling: boolean
707707
start: boolean
708708
end: boolean
709-
isPageBlock: boolean
710-
focus: boolean
711709
customUUID: string
712710
properties: {}
713711
}>
@@ -725,30 +723,20 @@ export interface IEditorProxy extends Record<string, any> {
725723
) => Promise<Array<BlockEntity> | null>
726724

727725
updateBlock: (
728-
srcBlock: BlockIdentity,
726+
srcBlock: BlockIdentity | EntityID,
729727
content: string,
730728
opts?: Partial<{ properties: {} }>
731729
) => Promise<void>
732730

733-
removeBlock: (srcBlock: BlockIdentity) => Promise<void>
731+
removeBlock: (srcBlock: BlockIdentity | EntityID) => Promise<void>
734732

735733
getBlock: (
736734
srcBlock: BlockIdentity | EntityID,
737735
opts?: Partial<{ includeChildren: boolean }>
738736
) => Promise<BlockEntity | null>
739737

740-
/**
741-
* @example
742-
*
743-
* ```ts
744-
* logseq.Editor.setBlockCollapsed('uuid', true)
745-
* logseq.Editor.setBlockCollapsed('uuid', 'toggle')
746-
* ```
747-
* @param uuid
748-
* @param opts
749-
*/
750738
setBlockCollapsed: (
751-
uuid: BlockUUID,
739+
srcBlock: BlockIdentity | EntityID,
752740
opts: { flag: boolean | 'toggle' } | boolean | 'toggle'
753741
) => Promise<void>
754742

@@ -782,7 +770,8 @@ export interface IEditorProxy extends Record<string, any> {
782770
getAllProperties: () => Promise<PageEntity[] | null>
783771
getTagObjects: (nameOrIdent: string) => Promise<BlockEntity[] | null>
784772
createTag: (tagName: string, opts?: Partial<{ uuid: string }>) => Promise<PageEntity | null>
785-
getTag: (nameOrIdent: string) => Promise<PageEntity | null>
773+
getTag: (nameOrIdent: string | EntityID) => Promise<PageEntity | null>
774+
getTagsByName: (tagName: string) => Promise<Array<PageEntity> | null>
786775
addTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise<void>
787776
removeTagProperty: (tagId: BlockIdentity, propertyIdOrName: BlockIdentity) => Promise<void>
788777
addTagExtends: (tagId: BlockIdentity, parentTagIdOrName: BlockIdentity) => Promise<void>
@@ -808,11 +797,11 @@ export interface IEditorProxy extends Record<string, any> {
808797
) => Promise<BlockEntity | null>
809798

810799
getPreviousSiblingBlock: (
811-
srcBlock: BlockIdentity
800+
srcBlock: BlockIdentity | EntityID
812801
) => Promise<BlockEntity | null>
813802

814803
getNextSiblingBlock: (
815-
srcBlock: BlockIdentity
804+
srcBlock: BlockIdentity | EntityID
816805
) => Promise<BlockEntity | null>
817806

818807
moveBlock: (
@@ -845,17 +834,15 @@ export interface IEditorProxy extends Record<string, any> {
845834

846835
// block property related APIs
847836
upsertBlockProperty: (
848-
block: BlockIdentity,
837+
block: BlockIdentity | EntityID,
849838
key: string,
850839
value: any
851840
) => Promise<void>
852841

853-
removeBlockProperty: (block: BlockIdentity, key: string) => Promise<void>
854-
855-
getBlockProperty: (block: BlockIdentity, key: string) => Promise<BlockEntity | unknown>
856-
857-
getBlockProperties: (block: BlockIdentity) => Promise<Record<string, any> | null>
858-
getPageProperties: (page: PageIdentity) => Promise<Record<string, any> | null>
842+
removeBlockProperty: (block: BlockIdentity | EntityID, key: string) => Promise<void>
843+
getBlockProperty: (block: BlockIdentity | EntityID, key: string) => Promise<BlockEntity | null>
844+
getBlockProperties: (block: BlockIdentity | EntityID) => Promise<Record<string, any> | null>
845+
getPageProperties: (page: PageIdentity | EntityID) => Promise<Record<string, any> | null>
859846

860847
scrollToBlockInPage: (
861848
pageName: BlockPageName,
@@ -864,6 +851,7 @@ export interface IEditorProxy extends Record<string, any> {
864851
) => void
865852

866853
openInRightSidebar: (id: BlockUUID | EntityID) => void
854+
openPDFViewer: (assetBlockIdOrFileUrl: string | EntityID) => Promise<void>
867855

868856
/**
869857
* @example https://github.com/logseq/logseq-plugin-samples/tree/master/logseq-a-translator

src/main/frontend/components/property/value.cljs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1285,6 +1285,13 @@
12851285
(fn []
12861286
#(set-property-value! @*value))
12871287
[])
1288+
1289+
(hooks/use-effect!
1290+
(fn []
1291+
(set-value! number-value)
1292+
#())
1293+
[number-value])
1294+
12881295
[:div.ls-number.flex.flex-1.jtrigger
12891296
{:ref *ref
12901297
:on-click #(do
@@ -1297,6 +1304,7 @@
12971304
: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"
12981305
(when table-view? " text-sm"))
12991306
:value value
1307+
:type "number"
13001308
:on-change (fn [e]
13011309
(set-value! (util/evalue e))
13021310
(reset! *value (util/evalue e)))

src/main/logseq/api.cljs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@
135135
(def ^:export set_block_collapsed api-editor/set_block_collapsed)
136136
(def ^:export update_block api-editor/update_block)
137137
(def ^:export upsert_block_property api-editor/upsert_block_property)
138+
(def ^:export open_pdf_viewer api-editor/open_pdf_viewer)
138139

139140
;; ui
140141
(def ^:export show_msg sdk-ui/-show_msg)
@@ -203,6 +204,7 @@
203204
(def ^:export get_tag_objects db-based-api/get-tag-objects)
204205
(def ^:export create_tag db-based-api/create-tag)
205206
(def ^:export get_tag db-based-api/get-tag)
207+
(def ^:export get_tags_by_name db-based-api/get-tags-by-name)
206208
(def ^:export add_tag_extends db-based-api/add-tag-extends)
207209
(def ^:export remove_tag_extends db-based-api/remove-tag-extends)
208210
(def ^:export add_block_tag db-based-api/add-block-tag)

0 commit comments

Comments
 (0)