(defn encode*
"Take an internal source map representation represented as nested
sorted maps of file, line, column and return a v3 representation."
[m opts]
(let [lines (atom [[]])
names->idx (atom {})
name-idx (atom 0)
preamble-lines (take (or (:preamble-line-count opts) 0) (repeat []))
info->segv
(fn [info source-idx line col]
(let [segv [(:gcol info) source-idx line col]]
(if-let [name (:name info)]
(let [idx (if-let [idx (get @names->idx name)]
idx
(let [cidx @name-idx]
(swap! names->idx assoc name cidx)
(swap! name-idx inc)
cidx))]
(conj segv idx))
segv)))
encode-cols
(fn [infos source-idx line col]
(doseq [info infos]
(let [segv (info->segv info source-idx line col)
gline (:gline info)
lc (count @lines)]
(if (> gline (dec lc))
(swap! lines
(fn [lines]
(conj (into lines (repeat (dec (- gline (dec lc))) [])) [segv])))
(swap! lines
(fn [lines]
(update-in lines [gline] conj segv)))))))]
(doseq [[source-idx [_ lines]] (map-indexed (fn [i v] [i v]) m)]
(doseq [[line cols] lines]
(doseq [[col infos] cols]
(encode-cols infos source-idx line col))))
(cond-> {"version" 3
"file" (:file opts)
"sources" (into []
(let [paths (keys m)
f (comp
(if (true? (:source-map-timestamp opts))
(fn [uri]
(if-not (string/index-of uri "?")
(str uri "?rel=" (System/currentTimeMillis))
(str uri "&rel=" (System/currentTimeMillis))))
identity)
(if (or (:output-dir opts)
(:source-map-path opts))
#(relativize-path % opts)
#(last (string/split % #"/"))))]
(map f paths)))
"lineCount" (:lines opts)
"mappings" (->> (lines->segs (concat preamble-lines @lines))
(map #(string/join "," %))
(string/join ";"))
"names" (into []
(map (set/map-invert @names->idx)
(range (count @names->idx))))}
(:sources-content opts)
(assoc "sourcesContent" (:sources-content opts)))))