-
Notifications
You must be signed in to change notification settings - Fork 0
/
token.clj
66 lines (55 loc) · 1.64 KB
/
token.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
(ns cljmd.inline.token
(:require [clojure.string :as string]
[cljmd.ast.common :as common]))
(defmulti inner
"Nested inline content if the represented entity supports it, nil otherwise."
:tag
:hierarchy common/ontology)
(defmethod inner :emphasis
[{:keys [content]}]
content)
(defmethod inner :link
[{:keys [text]}]
text)
(defmethod inner :default
[_]
nil)
(defn inner-bounds
"A [start end] vector containing :re/start and :re/end when the token has no
inner content, or the start / end indices of its inner content otherwise."
[token]
(let [{:re/keys [match start]} token
content (or (inner token) match)
outer-start (+ start (string/index-of match content))]
[outer-start
(+ outer-start (count content))]))
(defn within?
"True if x lies within y, false otherwise."
[x y]
(let [{inner-start :re/start inner-end :re/end} x
[outer-start outer-end] (inner-bounds y)]
(and (>= inner-start outer-start)
(<= inner-end outer-end))))
(defn before?
"True if token x ends before token y, false otherwise."
[x y]
(<= (:re/end x) (:re/start y)))
(defn after?
"True if token x begins after token y, false otherwise."
[x y]
(>= (:re/start x) (:re/end y)))
(defn translate
"Adjusts token boundaries by offset."
[token offset]
(-> token
(update :re/start + offset)
(update :re/end + offset)))
(defn cross?
"True if either of the following holds, false otherwise:
* x begins after y and x ends after y
* y begins after x and y ends after x"
[x y]
(not (or (before? x y)
(before? y x)
(within? x y)
(within? y x))))