fix(cli): cli block-ref rendering

This commit is contained in:
rcmerci
2026-05-01 22:43:50 +08:00
parent 67f2ba6c9e
commit 1d027cba3a
10 changed files with 767 additions and 103 deletions

View File

@@ -6,6 +6,7 @@
[logseq.cli.command.task-status :as task-status-command]
[logseq.cli.server :as cli-server]
[logseq.cli.transport :as transport]
[logseq.cli.uuid-refs :as uuid-refs]
[logseq.common.util :as common-util]
[logseq.db.frontend.property :as db-property]
[promesa.core :as p]))
@@ -309,6 +310,12 @@
(some? offset) (->> (drop offset) vec)
(some? limit) (->> (take limit) vec)))
(defn- normalize-visible-title-fields
[config repo items fields]
(let [uuid-strings (uuid-refs/collect-uuid-refs-from-items items fields)]
(p/let [uuid->label (uuid-refs/fetch-uuid-labels config repo uuid-strings)]
(uuid-refs/normalize-item-string-fields items fields uuid->label))))
(defn- prepare-tag-item
[item {:keys [with-properties with-extends fields]}]
(cond-> item
@@ -334,7 +341,8 @@
fields (parse-field-list (:fields options))
sorted (apply-sort items sort-field order list-page-field-map)
limited (apply-offset-limit sorted (:offset options) (:limit options))
final (apply-fields limited fields list-page-field-map)]
final (apply-fields limited fields list-page-field-map)
final (normalize-visible-title-fields cfg (:repo action) final [:block/title])]
{:status :ok
:data {:items final}})))
@@ -352,7 +360,8 @@
prepared (mapv #(prepare-tag-item % options) items)
sorted (apply-sort prepared sort-field order list-tag-field-map)
limited (apply-offset-limit sorted (:offset options) (:limit options))
final (apply-fields limited fields list-tag-field-map)]
final (apply-fields limited fields list-tag-field-map)
final (normalize-visible-title-fields cfg (:repo action) final [:block/title])]
{:status :ok
:data {:items final}})))
@@ -369,7 +378,8 @@
prepared (mapv #(prepare-property-item % options) items)
sorted (apply-sort prepared sort-field order list-property-field-map)
limited (apply-offset-limit sorted (:offset options) (:limit options))
final (apply-fields limited fields list-property-field-map)]
final (apply-fields limited fields list-property-field-map)
final (normalize-visible-title-fields cfg (:repo action) final [:block/title])]
{:status :ok
:data {:items final}})))
@@ -423,7 +433,8 @@
fields (parse-field-list (:fields options))
sorted (apply-sort items sort-field order list-node-field-map)
limited (apply-offset-limit sorted (:offset options) (:limit options))
final (apply-fields limited fields list-node-field-map)]
final (apply-fields limited fields list-node-field-map)
final (normalize-visible-title-fields cfg (:repo action) final [:block/title :block/page-title])]
{:status :ok
:data {:items final}})))
@@ -452,7 +463,8 @@
fields (parse-field-list (:fields options))
sorted (apply-sort items sort-field order list-asset-field-map)
limited (apply-offset-limit sorted (:offset options) (:limit options))
final (apply-fields limited fields list-asset-field-map)]
final (apply-fields limited fields list-asset-field-map)
final (normalize-visible-title-fields cfg (:repo action) final [:block/title])]
{:status :ok
:data {:items final}})))
@@ -489,6 +501,7 @@
fields (parse-field-list (:fields normalized-options))
sorted (apply-sort items sort-field order list-task-field-map)
limited (apply-offset-limit sorted (:offset normalized-options) (:limit normalized-options))
final (apply-fields limited fields list-task-field-map)]
final (apply-fields limited fields list-task-field-map)
final (normalize-visible-title-fields cfg (:repo action) final [:block/title])]
{:status :ok
:data {:items final}}))))))

View File

@@ -4,6 +4,7 @@
[logseq.cli.command.core :as core]
[logseq.cli.server :as cli-server]
[logseq.cli.transport :as transport]
[logseq.cli.uuid-refs :as uuid-refs]
[logseq.db :as ldb]
[promesa.core :as p]))
@@ -102,12 +103,19 @@
:db/id))
vec))
(defn- normalize-items
(defn- select-items
[items]
(->> (or items [])
(filter map?)
(map #(select-keys % [:db/id :db/ident :block/title]))
sort-items))
vec))
(defn- normalize-items
[config repo items]
(let [sorted (sort-items (select-items items))
uuid-strings (uuid-refs/collect-uuid-refs-from-items sorted [:block/title])]
(p/let [uuid->label (uuid-refs/fetch-uuid-labels config repo uuid-strings)]
(uuid-refs/normalize-item-string-fields sorted [:block/title] uuid->label))))
(defn- execute-search
[action config]
@@ -121,9 +129,10 @@
;; so the recycle filter only applies to page and block search.
filtered (cond->> (or result [])
(#{:search-page :search-block} (:type action))
(remove ldb/recycled?))]
(remove ldb/recycled?))
items (normalize-items cfg (:repo action) filtered)]
{:status :ok
:data {:items (normalize-items filtered)}})))
:data {:items items}})))
(defn execute-search-block
[action config]

View File

@@ -11,6 +11,7 @@
[logseq.cli.server :as cli-server]
[logseq.cli.style :as style]
[logseq.cli.transport :as transport]
[logseq.cli.uuid-refs :as uuid-refs]
[logseq.common.util :as common-util]
[logseq.db :as ldb]
[logseq.db.frontend.property :as db-property]
@@ -237,36 +238,12 @@
attach-user-properties
attach-user-properties-to-entity)
(def ^:private uuid-ref-pattern #"\[\[([0-9a-fA-F-]{36})\]\]")
(def ^:private uuid-ref-max-depth 10)
(defn- tag-label
[tag]
(or (:block/title tag)
(:block/name tag)
(some-> (:block/uuid tag) str)))
(defn- replace-uuid-refs-once
[value uuid->label]
(if (and (string? value) (seq uuid->label))
(string/replace value uuid-ref-pattern
(fn [[_ id]]
(if-let [label (get uuid->label (string/lower-case id))]
(str "[[" label "]]")
(str "[[" id "]]"))))
value))
(defn- replace-uuid-refs
[value uuid->label]
(loop [current value
remaining uuid-ref-max-depth]
(if (or (not (string? current)) (zero? remaining) (empty? uuid->label))
current
(let [next (replace-uuid-refs-once current uuid->label)]
(if (= next current)
current
(recur next (dec remaining)))))))
(defn- tags->suffix
[tags]
(let [labels (->> tags
@@ -316,40 +293,46 @@
(.toISOString (js/Date. ms)))
(defn- property-value->string
([value] (property-value->string value nil))
([value labels]
(cond
(string? value) (nonblank-string value)
(number? value) (or (get labels value) (str value))
(uuid? value) (or (get labels value) (str value))
(lookup-ref? value) (let [uuid (second value)]
(or (get labels uuid) (str uuid)))
(boolean? value) (str value)
(keyword? value) (str value)
(map? value) (or (nonblank-string (:block/title value))
(nonblank-string (:block/name value))
(when-let [id (:db/id value)]
(get labels id))
(when-let [uuid (:block/uuid value)]
(get labels uuid))
(when-let [val (:logseq.property/value value)]
(if (string? val)
(nonblank-string val)
(str val)))
(pr-str value))
(some? value) (str value)
:else nil)))
([value] (property-value->string value nil nil))
([value labels] (property-value->string value labels nil))
([value labels uuid->label]
(let [render-visible (fn [text]
(some-> text
nonblank-string
(uuid-refs/replace-uuid-refs uuid->label)))]
(cond
(string? value) (render-visible value)
(number? value) (render-visible (or (get labels value) (str value)))
(uuid? value) (render-visible (or (get labels value) (str value)))
(lookup-ref? value) (let [uuid (second value)]
(render-visible (or (get labels uuid) (str uuid))))
(boolean? value) (str value)
(keyword? value) (str value)
(map? value) (or (render-visible (:block/title value))
(render-visible (:block/name value))
(when-let [id (:db/id value)]
(render-visible (get labels id)))
(when-let [uuid (:block/uuid value)]
(render-visible (get labels uuid)))
(when-let [val (:logseq.property/value value)]
(if (string? val)
(render-visible val)
(str val)))
(pr-str value))
(some? value) (str value)
:else nil))))
(defn- normalize-property-values
([value] (normalize-property-values value nil))
([value labels]
([value] (normalize-property-values value nil nil))
([value labels] (normalize-property-values value labels nil))
([value labels uuid->label]
(let [values (cond
(set? value) (seq value)
(sequential? value) value
(nil? value) nil
:else [value])
rendered (->> values
(map #(property-value->string % labels))
(map #(property-value->string % labels uuid->label))
(remove string/blank?)
vec)]
(if (set? value)
@@ -357,11 +340,12 @@
rendered))))
(defn- node-user-property-entries
([node] (node-user-property-entries node nil))
([node labels]
([node] (node-user-property-entries node nil nil))
([node labels] (node-user-property-entries node labels nil))
([node labels uuid->label]
(->> node
(filter (fn [[k _]] (displayable-property-key? k)))
(map (fn [[k v]] [k (normalize-property-values v labels)]))
(map (fn [[k v]] [k (normalize-property-values v labels uuid->label)]))
(remove (fn [[_ values]] (empty? values)))
vec)))
@@ -385,8 +369,8 @@
(map #(str item-indent "- " %) values)))))))
(defn- node-property-lines
[node property-titles property-value-labels indent]
(let [property-entries (->> (node-user-property-entries node property-value-labels)
[node property-titles property-value-labels uuid->label indent]
(let [property-entries (->> (node-user-property-entries node property-value-labels uuid->label)
sort-property-entries)]
(->> property-entries
(mapcat (fn [[property-key values]]
@@ -418,7 +402,7 @@
text text
(:block/name node) (:block/name node)
(:block/uuid node) (some-> (:block/uuid node) str))
base (replace-uuid-refs base uuid->label)
base (uuid-refs/replace-uuid-refs base uuid->label)
tags-suffix (tags->suffix (:block/tags node))]
(cond
(and base tags-suffix) (str base " " tags-suffix)
@@ -428,8 +412,8 @@
(defn- resolve-uuid-refs-in-node
[node uuid->label]
(cond-> node
(:block/title node) (update :block/title replace-uuid-refs uuid->label)
(:block/name node) (update :block/name replace-uuid-refs uuid->label)
(:block/title node) (update :block/title uuid-refs/replace-uuid-refs uuid->label)
(:block/name node) (update :block/name uuid-refs/replace-uuid-refs uuid->label)
(:block/children node) (update :block/children (fn [children]
(mapv #(resolve-uuid-refs-in-node % uuid->label) children)))
(:block/page node) (update :block/page (fn [page]
@@ -545,13 +529,6 @@
:property-value-labels property-value-labels})))
groups))))
(defn- extract-uuid-refs
[value]
(->> (re-seq uuid-ref-pattern (or value ""))
(map second)
(filter common-util/uuid-string?)
distinct))
(defn- collect-uuid-refs
[{:keys [root]} linked-refs]
(let [collect-nodes (fn collect-nodes [node]
@@ -565,35 +542,10 @@
(mapcat (fn [node] (keep node [:block/title :block/name])))
(remove string/blank?))]
(->> texts
(mapcat extract-uuid-refs)
(mapcat uuid-refs/extract-uuid-refs)
distinct
vec)))
(defn- uuid-entity-label
[entity]
(let [uuid-str (some-> (:block/uuid entity) str)]
(or (:block/title entity)
(:block/name entity)
uuid-str)))
(defn- fetch-uuid-entities
[config repo uuid-strings]
(if (seq uuid-strings)
(p/let [blocks (p/all (map (fn [uuid-str]
(transport/invoke config :thread-api/pull false
[repo [:db/id :block/uuid :block/title :block/name]
[:block/uuid (uuid uuid-str)]]))
uuid-strings))]
(->> blocks
(remove nil?)
(map (fn [block]
(let [uuid-str (some-> (:block/uuid block) str)]
[(string/lower-case uuid-str)
{:id (:db/id block)
:label (uuid-entity-label block)}])))
(into {})))
(p/resolved {})))
(defn- collect-user-property-keys
[{:keys [root linked-references]}]
(letfn [(collect-node [node]
@@ -923,7 +875,7 @@
(str id-padding (style-glyph prefix)))
append-property-lines (fn [node prefix]
(let [indent (property-indent prefix)
prop-lines (node-property-lines node property-titles property-value-labels indent)]
prop-lines (node-property-lines node property-titles property-value-labels uuid->label indent)]
(doseq [line prop-lines]
(swap! lines conj line))))
walk (fn walk [node prefix]
@@ -1031,7 +983,7 @@
(or linked-refs {:count 0 :blocks []})
{:count 0 :blocks []})
uuid-refs (collect-uuid-refs tree-data linked-refs*)
uuid->entity (fetch-uuid-entities config (:repo action) uuid-refs)
uuid->entity (uuid-refs/fetch-uuid-entities config (:repo action) uuid-refs)
uuid->label (->> uuid->entity
(keep (fn [[uuid-key {:keys [label]}]]
(when (seq label)
@@ -1119,9 +1071,27 @@
(assoc tree-data :breadcrumb-line breadcrumb-line)
tree-data)))
(defn- attach-property-value-uuid-labels
[config action tree-data]
(let [property-value-labels (:property-value-labels tree-data)
nested-uuid-refs (uuid-refs/collect-uuid-refs-from-strings (vals property-value-labels))]
(if (seq nested-uuid-refs)
(p/let [nested-uuid->entity (uuid-refs/fetch-uuid-entities config (:repo action) nested-uuid-refs)
nested-uuid->label (->> nested-uuid->entity
(keep (fn [[uuid-key {:keys [label]}]]
(when (seq label)
[uuid-key label])))
(into {}))]
(-> tree-data
(update :uuid->entity merge nested-uuid->entity)
(update :uuid->label merge nested-uuid->label)
(update :referenced-uuids #(vec (distinct (concat (or % []) nested-uuid-refs))))))
(p/resolved tree-data))))
(defn- render-tree-text-with-properties
[config action tree-data]
(p/let [tree-data (attach-property-titles config (:repo action) tree-data)
tree-data (attach-property-value-uuid-labels config action tree-data)
tree-data (attach-breadcrumb-line config action tree-data)]
(render-tree-text tree-data action)))

View File

@@ -0,0 +1,104 @@
(ns logseq.cli.uuid-refs
"Shared CLI helpers for rendering block refs stored as `[[uuid]]`."
(:require [clojure.string :as string]
[logseq.cli.transport :as transport]
[logseq.common.util :as common-util]
[promesa.core :as p]))
(def ^:private uuid-ref-pattern #"\[\[([0-9a-fA-F-]{36})\]\]")
(def ^:private uuid-ref-max-depth 10)
(def ^:private uuid-lookup-selector [:db/id :block/uuid :block/title :block/name])
(defn extract-uuid-refs
[value]
(->> (re-seq uuid-ref-pattern (or value ""))
(map second)
(filter common-util/uuid-string?)
(map string/lower-case)
distinct))
(defn- replace-uuid-refs-once
[value uuid->label]
(if (and (string? value) (seq uuid->label))
(string/replace value uuid-ref-pattern
(fn [[_ id]]
(if-let [label (get uuid->label (string/lower-case id))]
(str "[[" label "]]" )
(str "[[" id "]]"))))
value))
(defn replace-uuid-refs
[value uuid->label]
(loop [current value
remaining uuid-ref-max-depth]
(if (or (not (string? current)) (zero? remaining) (empty? uuid->label))
current
(let [next (replace-uuid-refs-once current uuid->label)]
(if (= next current)
current
(recur next (dec remaining)))))))
(defn collect-uuid-refs-from-strings
[values]
(->> values
(filter string?)
(mapcat extract-uuid-refs)
distinct
vec))
(defn collect-uuid-refs-from-items
[items fields]
(->> items
(mapcat (fn [item]
(keep #(get item %) fields)))
collect-uuid-refs-from-strings))
(defn normalize-item-string-fields
[items fields uuid->label]
(mapv (fn [item]
(reduce (fn [item field]
(cond-> item
(string? (get item field))
(update field replace-uuid-refs uuid->label)))
item
fields))
items))
(defn uuid-entity-label
[entity]
(let [uuid-str (some-> (:block/uuid entity) str)]
(or (:block/title entity)
(:block/name entity)
uuid-str)))
(defn fetch-uuid-entities
[config repo uuid-strings]
(let [uuid-strings (->> uuid-strings
(filter common-util/uuid-string?)
(map string/lower-case)
distinct
vec)]
(if (seq uuid-strings)
(p/let [blocks (p/all (map (fn [uuid-str]
(transport/invoke config :thread-api/pull false
[repo uuid-lookup-selector
[:block/uuid (uuid uuid-str)]]))
uuid-strings))]
(->> blocks
(remove nil?)
(map (fn [block]
(let [uuid-str (some-> (:block/uuid block) str string/lower-case)]
[uuid-str
{:id (:db/id block)
:label (uuid-entity-label block)}])))
(into {})))
(p/resolved {}))))
(defn fetch-uuid-labels
[config repo uuid-strings]
(p/let [uuid->entity (fetch-uuid-entities config repo uuid-strings)]
(->> uuid->entity
(keep (fn [[uuid-key {:keys [label]}]]
(when (seq label)
[uuid-key label])))
(into {}))))

View File

@@ -0,0 +1,86 @@
(ns logseq.cli.command.list-test
(:require [cljs.test :refer [async deftest is]]
[logseq.cli.command.list :as list-command]
[logseq.cli.server :as cli-server]
[logseq.cli.transport :as transport]
[promesa.core :as p]))
(deftest test-execute-list-page-renders-block-ref-labels
(async done
(let [ref-uuid "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
calls* (atom [])]
(-> (p/with-redefs [cli-server/ensure-server! (fn [_ _] {:base-url "http://example"})
transport/invoke (fn [_ method _ args]
(swap! calls* conj {:method method :args args})
(case method
:thread-api/cli-list-pages
[{:db/id 1
:block/title (str "Project [[" ref-uuid "]]" )}]
:thread-api/pull
{:db/id 42
:block/uuid (uuid ref-uuid)
:block/title "Home"}
nil))]
(p/let [result (list-command/execute-list-page
{:type :list-page
:repo "demo"
:options {}}
{})]
(is (= :ok (:status result)))
(is (= [{:db/id 1
:block/title "Project [[Home]]"}]
(get-in result [:data :items])))
(is (= [:thread-api/cli-list-pages :thread-api/pull]
(mapv :method @calls*)))
(is (= ["demo"
[:db/id :block/uuid :block/title :block/name]
[:block/uuid (uuid ref-uuid)]]
(-> @calls* second :args)))))
(p/catch (fn [e]
(is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest test-execute-list-node-renders-title-like-fields-through-block-ref-labels
(async done
(let [ref-uuid "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
calls* (atom [])]
(-> (p/with-redefs [cli-server/ensure-server! (fn [_ _] {:base-url "http://example"})
transport/invoke (fn [_ method _ args]
(swap! calls* conj {:method method :args args})
(case method
:thread-api/cli-list-nodes
[{:db/id 9
:block/title (str "Task [[" ref-uuid "]]" )
:block/page-title (str "Page [[" ref-uuid "]]" )
:node/type "block"
:block/page-id 2}]
:thread-api/pull
{:db/id 100
:block/uuid (uuid ref-uuid)
:block/title "Resolved page"}
nil))]
(p/let [result (list-command/execute-list-node
{:type :list-node
:repo "demo"
:options {}}
{})]
(is (= :ok (:status result)))
(is (= [{:db/id 9
:block/title "Task [[Resolved page]]"
:block/page-title "Page [[Resolved page]]"
:node/type "block"
:block/page-id 2}]
(get-in result [:data :items])))
(is (= [:thread-api/cli-list-nodes :thread-api/pull]
(mapv :method @calls*)))
(is (= ["demo"
[:db/id :block/uuid :block/title :block/name]
[:block/uuid (uuid ref-uuid)]]
(-> @calls* second :args)))))
(p/catch (fn [e]
(is false (str "unexpected error: " e))))
(p/finally done)))))

View File

@@ -84,6 +84,41 @@
(is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest test-execute-search-block-renders-block-ref-labels
(async done
(let [ref-uuid "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
calls* (atom [])]
(-> (p/with-redefs [cli-server/ensure-server! (fn [_ _] {:base-url "http://example"})
transport/invoke (fn [_ method _ args]
(swap! calls* conj {:method method :args args})
(case method
:thread-api/q
[{:db/id 7
:block/title (str "foo [[" ref-uuid "]]" )}]
:thread-api/pull
{:db/id 99
:block/uuid (uuid ref-uuid)
:block/title "bar"}
nil))]
(p/let [result (search-command/execute-search-block
{:type :search-block :repo "demo" :query "foo"}
{})]
(is (= :ok (:status result)))
(is (= [{:db/id 7
:block/title "foo [[bar]]"}]
(get-in result [:data :items])))
(is (= [:thread-api/q :thread-api/pull]
(mapv :method @calls*)))
(is (= ["demo"
[:db/id :block/uuid :block/title :block/name]
[:block/uuid (uuid ref-uuid)]]
(-> @calls* second :args)))))
(p/catch (fn [e]
(is false (str "unexpected error: " e))))
(p/finally done)))))
(deftest test-execute-search-block-skips-block-on-recycled-page
;; Recycled pages get :block/parent set to the Recycle page id and
;; :logseq.property/deleted-at stamped on themselves. The recursive

View File

@@ -214,6 +214,57 @@
(p/resolved nil))))
(deftest test-tree->text-renders-block-refs-inside-string-property-values
(let [ref-uuid "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
output (-> (show-command/tree->text
{:root {:db/id 1
:block/title "Root"
:user.property/summary (str "Depends on [[" ref-uuid "]]" )}
:uuid->label {(string/lower-case ref-uuid) "Resolved ref"}
:property-titles {:user.property/summary "Summary"}
:property-value-labels {}})
style/strip-ansi)]
(is (string/includes? output "Summary: Depends on [[Resolved ref]]"))))
(deftest test-tree->text-renders-block-refs-inside-map-backed-property-values
(let [title-ref-uuid "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
value-ref-uuid "cccccccc-cccc-cccc-cccc-cccccccccccc"
output (-> (show-command/tree->text
{:root {:db/id 1
:block/title "Root"
:user.property/title-ref {:block/title (str "Mapped [[" title-ref-uuid "]]" )}
:user.property/value-ref {:logseq.property/value (str "Value [[" value-ref-uuid "]]" )}}
:uuid->label {(string/lower-case title-ref-uuid) "Title ref"
(string/lower-case value-ref-uuid) "Value ref"}
:property-titles {:user.property/title-ref "Title ref"
:user.property/value-ref "Value ref"}
:property-value-labels {}})
style/strip-ansi)]
(is (string/includes? output "Title ref: Mapped [[Title ref]]"))
(is (string/includes? output "Value ref: Value [[Value ref]]"))))
(deftest test-tree->text-renders-block-refs-inside-many-ref-default-property-values
;; Simulates a normal block with a user property:
;; - property name: "Reproducible steps"
;; - :logseq.property/type :default
;; - :db/valueType :db.type/ref
;; - :db/cardinality :db.cardinality/many
;; where the property values are referenced blocks and one referenced
;; block title contains a serialized block ref.
(let [nested-ref-uuid "dddddddd-dddd-dddd-dddd-dddddddddddd"
output (-> (show-command/tree->text
{:root {:db/id 1
:block/title "Root"
:user.property/reproducible-steps [42 43]}
:uuid->label {(string/lower-case nested-ref-uuid) "Resolved nested step"}
:property-titles {:user.property/reproducible-steps "Reproducible steps"}
:property-value-labels {42 (str "Step [[" nested-ref-uuid "]]" )
43 "Verify output"}})
style/strip-ansi)]
(is (string/includes? output "Reproducible steps:"))
(is (string/includes? output "- Step [[Resolved nested step]]"))
(is (string/includes? output "- Verify output"))))
(defn- contains-block-uuid?
[value]
(cond

View File

@@ -0,0 +1,41 @@
(ns logseq.cli.uuid-refs-test
(:require [cljs.test :refer [deftest is]]
[logseq.cli.uuid-refs :as uuid-refs]))
(deftest test-extract-uuid-refs
(let [uuid-a "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
uuid-b "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"]
(is (= ["aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
"bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"]
(uuid-refs/extract-uuid-refs
(str "One [[" uuid-a "]] and two [[" uuid-b "]] and one again [[" uuid-a "]]"))))))
(deftest test-replace-uuid-refs
(let [uuid-a "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
uuid-b "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"
missing-uuid "cccccccc-cccc-cccc-cccc-cccccccccccc"]
(is (= "alpha [[Ref A]] omega [[Ref B]]"
(uuid-refs/replace-uuid-refs
(str "alpha [[" uuid-a "]] omega [[" uuid-b "]]" )
{uuid-a "Ref A"
uuid-b "Ref B"})))
(is (= (str "[[Parent [[Child]]]] and [[" missing-uuid "]]" )
(uuid-refs/replace-uuid-refs
(str "[[" uuid-a "]] and [[" missing-uuid "]]" )
{uuid-a (str "Parent [[" uuid-b "]]" )
uuid-b "Child"})))
(is (= (str "missing [[" missing-uuid "]]" )
(uuid-refs/replace-uuid-refs
(str "missing [[" missing-uuid "]]" )
{})))))
(deftest test-collect-uuid-refs-from-strings
(let [uuid-a "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
uuid-b "bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"]
(is (= ["aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
"bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb"]
(uuid-refs/collect-uuid-refs-from-strings
[(str "Step [[" uuid-a "]]" )
nil
"No refs here"
(str "Then [[" uuid-b "]] and again [[" uuid-a "]]" )])))))