block.cljs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. (ns frontend.format.block
  2. "Block code needed by app but not graph-parser"
  3. (:require [clojure.string :as string]
  4. [logseq.graph-parser.block :as gp-block]
  5. [frontend.config :as config]
  6. [frontend.db :as db]
  7. [frontend.format :as format]
  8. [frontend.state :as state]
  9. [logseq.graph-parser.config :as gp-config]
  10. [logseq.graph-parser.property :as gp-property]
  11. [logseq.graph-parser.mldoc :as gp-mldoc]))
  12. (defn extract-blocks
  13. "Wrapper around logseq.graph-parser.block/extract-blocks that adds in system state"
  14. [blocks content with-id? format]
  15. (gp-block/extract-blocks blocks content with-id? format
  16. {:user-config (state/get-config)
  17. :block-pattern (config/get-block-pattern format)
  18. :supported-formats (gp-config/supported-formats)
  19. :db (db/get-db (state/get-current-repo))
  20. :date-formatter (state/get-date-formatter)}))
  21. (defn page-name->map
  22. "Wrapper around logseq.graph-parser.block/page-name->map that adds in db"
  23. ([original-page-name with-id?]
  24. (page-name->map original-page-name with-id? true))
  25. ([original-page-name with-id? with-timestamp?]
  26. (gp-block/page-name->map original-page-name with-id? (db/get-db (state/get-current-repo)) with-timestamp? (state/get-date-formatter))))
  27. (defn parse-block
  28. ([block]
  29. (parse-block block nil))
  30. ([{:block/keys [uuid content page format] :as block} {:keys [with-id?]
  31. :or {with-id? true}}]
  32. (when-not (string/blank? content)
  33. (let [block (dissoc block :block/pre-block?)
  34. ast (format/to-edn content format nil)
  35. blocks (extract-blocks ast content with-id? format)
  36. new-block (first blocks)
  37. parent-refs (->> (db/get-block-parent (state/get-current-repo) uuid)
  38. :block/path-refs
  39. (map :db/id))
  40. {:block/keys [refs]} new-block
  41. ref-pages (filter :block/name refs)
  42. path-ref-pages (->> (concat ref-pages parent-refs [(:db/id page)])
  43. (remove nil?))
  44. block (cond->
  45. (merge
  46. block
  47. new-block
  48. {:block/path-refs path-ref-pages})
  49. (> (count blocks) 1)
  50. (assoc :block/warning :multiple-blocks))
  51. block (dissoc block :block/title :block/body :block/level)]
  52. (if uuid (assoc block :block/uuid uuid) block)))))
  53. (defn parse-title-and-body
  54. ([block]
  55. (when (map? block)
  56. (merge block
  57. (parse-title-and-body (:block/uuid block)
  58. (:block/format block)
  59. (:block/pre-block? block)
  60. (:block/content block)))))
  61. ([block-uuid format pre-block? content]
  62. (when-not (string/blank? content)
  63. (let [content (if pre-block? content
  64. (str (config/get-block-pattern format) " " (string/triml content)))]
  65. (if-let [result (state/get-block-ast block-uuid content)]
  66. result
  67. (let [ast (->> (format/to-edn content format (gp-mldoc/default-config format))
  68. (map first))
  69. title (when (gp-block/heading-block? (first ast))
  70. (:title (second (first ast))))
  71. body (vec (if title (rest ast) ast))
  72. body (drop-while gp-property/properties-ast? body)
  73. result (cond->
  74. (if (seq body) {:block/body body} {})
  75. title
  76. (assoc :block/title title))]
  77. (state/add-block-ast-cache! block-uuid content result)
  78. result))))))
  79. (defn macro-subs
  80. [macro-content arguments]
  81. (loop [s macro-content
  82. args arguments
  83. n 1]
  84. (if (seq args)
  85. (recur
  86. (string/replace s (str "$" n) (first args))
  87. (rest args)
  88. (inc n))
  89. s)))
  90. (defn break-line-paragraph?
  91. [[typ break-lines]]
  92. (and (= typ "Paragraph")
  93. (every? #(= % ["Break_Line"]) break-lines)))
  94. (defn trim-paragraph-special-break-lines
  95. [ast]
  96. (let [[typ paras] ast]
  97. (if (= typ "Paragraph")
  98. (let [indexed-paras (map-indexed vector paras)]
  99. [typ (->> (filter
  100. #(let [[index value] %]
  101. (not (and (> index 0)
  102. (= value ["Break_Line"])
  103. (contains? #{"Timestamp" "Macro"}
  104. (first (nth paras (dec index)))))))
  105. indexed-paras)
  106. (map #(last %)))])
  107. ast)))
  108. (defn trim-break-lines!
  109. [ast]
  110. (drop-while break-line-paragraph?
  111. (map trim-paragraph-special-break-lines ast)))