diff --git a/spec/more_speech/ui/formatters_spec.clj b/spec/more_speech/ui/formatters_spec.clj
index b578aa1..e7e2ca8 100644
--- a/spec/more_speech/ui/formatters_spec.clj
+++ b/spec/more_speech/ui/formatters_spec.clj
@@ -230,27 +230,44 @@
(describe "Segment article content"
(it "returns empty list if content is empty"
(should= '() (segment-article "")))
+
(it "returns a single :text element if no url in content"
(should= '([:text "no url"]) (segment-article "no url")))
+
(it "returns a single :url element if whole content is a url"
(should= '([:url "http://nostr.com"]) (segment-article "http://nostr.com")))
- (it "returns a list of :text and :url elements when content contains multiple text and url segments"
- (should= '([:text "Check this "] [:url "http://nostr.com"] [:text " It's cool"])
- (segment-article "Check this http://nostr.com It's cool")))
+
+ (it "returns a :namereference segment"
+ (should= [[:namereference "@name"] [:text " text"]]
+ (segment-article "@name text")))
+
+ (it "returns a list of :text and :url and :namereference segments"
+ (should= [[:text "Hey "] [:namereference "@bob"] [:text " Check this "] [:url "http://nostr.com"] [:text " It's cool"]]
+ (segment-article "Hey @bob Check this http://nostr.com It's cool")))
)
(describe "Format article"
(it "should escape HTML entities"
(should= "<b>text</b>" (reformat-article "text")))
+
(it "should linkify url"
(should= "nostr.com" (reformat-article "https://nostr.com")))
+
+ (it "should ms-link a namereference"
+ (should= "@name"
+ (reformat-article "@name")))
+
(it "should escape HTML entities and linkify url"
(should= "<b>Clojure</b>: clojure.org/"
(reformat-article "Clojure: https://clojure.org/")))
+
(it "should format replies and escape HTML entities properly"
(should= ">this is
>a reply" (reformat-article ">this is >a reply")))
+
(it "should replace multiple spaces with  "
(should= "one two  three   ." (reformat-article "one two three .")))
+
+
)
(declare db)
@@ -305,3 +322,17 @@
(set-mem :pubkey my-pubkey)
(should= "2-deg<-trusted-pet" (format-user-id trusted-by-trusted-user))))
)
+
+(describe "combine patterns"
+ (it "combines a single pattern and name"
+ (let [pattern (combine-patterns [:name1 #"pattern1"])]
+ (should= java.util.regex.Pattern (type pattern))
+ (should= "(?pattern1)" (str pattern))))
+
+ (it "combines multiple patterns and names"
+ (let [pattern (combine-patterns [:name1 #"pattern1"]
+ [:name2 #"pattern2"])]
+ (should= java.util.regex.Pattern (type pattern))
+ (should= "(?pattern1)|(?pattern2)" (str pattern))))
+
+ )
diff --git a/src/more_speech/ui/formatters.clj b/src/more_speech/ui/formatters.clj
index 6d09a1f..922749e 100644
--- a/src/more_speech/ui/formatters.clj
+++ b/src/more_speech/ui/formatters.clj
@@ -6,8 +6,7 @@
[more-speech.nostr.contact-list :as contact-list]
[more-speech.ui.formatter-util :refer :all]
[more-speech.config :as config :refer [get-db]]
- [more-speech.db.gateway :as gateway])
- )
+ [more-speech.db.gateway :as gateway]))
(defn format-user-id
([user-id]
@@ -153,30 +152,56 @@
uri (if (= 2 (count split-url)) (second split-url) url)]
(str "" uri "")))
+(defn ms-linkify [type subject]
+ (str "" subject ""))
+
+(defn combine-patterns
+ "patterns are a list of [:name pattern]"
+ [& patterns]
+ (let [grouped-patterns (map #(str "(?<" (name (first %)) ">" (second %) ")") patterns)
+ combined-patterns (interpose "|" grouped-patterns)]
+ (re-pattern (apply str combined-patterns))))
+
(defn segment-article
([content]
- (let [segment (re-find config/url-pattern content)]
- (cond
- (not (nil? segment))
- (let [url-start-index (string/index-of content segment)
- url-end-index (+ url-start-index (.length segment))
- text-sub (subs content 0 url-start-index)
- url-sub (subs content url-start-index url-end-index)
- rest (subs content url-end-index)]
- (concat
- (if (empty? text-sub)
- [[:url url-sub]]
- [[:text text-sub] [:url url-sub]])
- (segment-article rest)))
- (not (empty? content)) (list [:text content])
- :else '()))))
+ (segment-article content []))
+
+ ([content segments]
+ (let [patterns [[:url config/url-pattern]
+ [:namereference config/user-name-pattern]]
+ pattern (apply combine-patterns patterns)
+ group-names (map first patterns)]
+ (loop [content content
+ segments segments]
+ (let [matcher (re-matcher pattern content)
+ segment (first (re-find matcher))]
+ (cond
+ (empty? content)
+ segments
+
+ (some? segment)
+ (let [grouped-by-name (map #(vector (keyword %) (.group matcher (name %))) group-names)
+ the-group (filter #(some? (second %)) grouped-by-name)
+ segment-type (ffirst the-group)
+ url-start-index (string/index-of content segment)
+ url-end-index (+ url-start-index (.length segment))
+ text-sub (subs content 0 url-start-index)
+ url-sub (subs content url-start-index url-end-index)
+ rest (subs content url-end-index)]
+ (recur rest
+ (concat segments
+ (if (empty? text-sub)
+ [[segment-type url-sub]]
+ [[:text text-sub] [segment-type url-sub]]))))
+ :else
+ (concat segments (list [:text content]))))))))
(defn reformat-article [article]
(let [segments (segment-article article)]
(reduce
(fn [formatted-content [seg-type seg]]
- (cond
- (= seg-type :text)
+ (condp = seg-type
+ :text
(str formatted-content
((comp
non-breaking-spaces
@@ -185,8 +210,11 @@
format-replies
) seg)
)
- (= seg-type :url)
- (str formatted-content (linkify seg))))
+ :url
+ (str formatted-content (linkify seg))
+
+ :namereference
+ (str formatted-content (ms-linkify "ms-namereference" seg))))
""
segments)))