block.cljs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. (ns frontend.handler.block
  2. (:require [frontend.util :as util]
  3. [frontend.util.property :as property]
  4. [clojure.walk :as walk]
  5. [frontend.db :as db]
  6. [frontend.state :as state]
  7. [frontend.format.mldoc :as mldoc]
  8. [frontend.date :as date]
  9. [frontend.config :as config]
  10. [datascript.core :as d]
  11. [clojure.set :as set]
  12. [medley.core :as medley]
  13. [frontend.format.block :as block]
  14. [frontend.debug :as debug]
  15. [clojure.string :as string]
  16. [frontend.text :as text]
  17. [frontend.handler.common :as common-handler]))
  18. (defn get-block-ids
  19. [block]
  20. (let [ids (atom [])
  21. _ (walk/prewalk
  22. (fn [form]
  23. (when (map? form)
  24. (when-let [id (:block/uuid form)]
  25. (swap! ids conj id)))
  26. form)
  27. block)]
  28. @ids))
  29. ;; TODO: should we remove this dummy block and use the page's root block instead?
  30. (defn with-dummy-block
  31. ([blocks format]
  32. (with-dummy-block blocks format {} {}))
  33. ([blocks format default-option {:keys [journal? page-name]
  34. :or {journal? false}}]
  35. (let [format (or format (state/get-preferred-format) :markdown)
  36. blocks (vec blocks)]
  37. (if (seq blocks)
  38. blocks
  39. (let [page-block (when page-name (db/pull [:block/name (string/lower-case page-name)]))
  40. create-title-property? (and page-name (util/include-windows-reserved-chars? page-name))
  41. content (if create-title-property?
  42. (let [title (or (:block/original-name page-block)
  43. (:block/name page-block))
  44. properties (common-handler/get-page-default-properties title)]
  45. (property/build-properties-str format properties))
  46. "")
  47. page-id {:db/id (:db/id page-block)}
  48. dummy (merge {:block/uuid (db/new-block-id)
  49. :block/left page-id
  50. :block/parent page-id
  51. :block/page page-id
  52. :block/title ""
  53. :block/content content
  54. :block/format format
  55. :block/dummy? true}
  56. default-option)
  57. dummy (if (:db/id (:block/file dummy))
  58. dummy
  59. (dissoc dummy :block/file))]
  60. [dummy])))))
  61. (defn filter-blocks
  62. [repo ref-blocks filters group-by-page?]
  63. (let [ref-pages (->> (if group-by-page?
  64. (mapcat last ref-blocks)
  65. ref-blocks)
  66. (mapcat (fn [b] (concat (:block/refs b) (:block/children-refs b))))
  67. (concat (when group-by-page? (map first ref-blocks)))
  68. (distinct)
  69. (map :db/id)
  70. (db/pull-many repo '[:db/id :block/name]))
  71. ref-pages (zipmap (map :block/name ref-pages) (map :db/id ref-pages))
  72. exclude-ids (->> (map (fn [page] (get ref-pages page)) (get filters false))
  73. (remove nil?)
  74. (set))
  75. include-ids (->> (map (fn [page] (get ref-pages page)) (get filters true))
  76. (remove nil?)
  77. (set))]
  78. (if (empty? filters)
  79. ref-blocks
  80. (let [filter-f (fn [ref-blocks]
  81. (cond->> ref-blocks
  82. (seq exclude-ids)
  83. (remove (fn [block]
  84. (let [ids (set (concat (map :db/id (:block/refs block))
  85. (map :db/id (:block/children-refs block))
  86. [(:db/id (:block/page block))]))]
  87. (seq (set/intersection exclude-ids ids)))))
  88. (seq include-ids)
  89. (remove (fn [block]
  90. (let [page-block-id (:db/id (:block/page block))
  91. ids (set (concat (map :db/id (:block/refs block))
  92. (map :db/id (:block/children-refs block))))]
  93. (if (and (contains? include-ids page-block-id)
  94. (= 1 (count include-ids)))
  95. (not= page-block-id (first include-ids))
  96. (empty? (set/intersection include-ids (set (conj ids page-block-id))))))))))]
  97. (if group-by-page?
  98. (->> (map (fn [[p ref-blocks]]
  99. [p (filter-f ref-blocks)]) ref-blocks)
  100. (remove #(empty? (second %))))
  101. (->> (filter-f ref-blocks)
  102. (remove nil?)))))))
  103. ;; TODO: reduced version
  104. (defn walk-block
  105. [block check? transform]
  106. (let [result (atom nil)]
  107. (walk/postwalk
  108. (fn [x]
  109. (if (check? x)
  110. (reset! result (transform x))
  111. x))
  112. (:block/body block))
  113. @result))
  114. (defn get-timestamp
  115. [block typ]
  116. (walk-block block
  117. (fn [x]
  118. (and (block/timestamp-block? x)
  119. (= typ (first (second x)))))
  120. #(second (second %))))
  121. (defn get-scheduled-ast
  122. [block]
  123. (get-timestamp block "Scheduled"))
  124. (defn get-deadline-ast
  125. [block]
  126. (get-timestamp block "Deadline"))