|
3 | 3 | [clj-yaml.core :as yaml] |
4 | 4 | [clojure.string :as str] |
5 | 5 | [clojure.walk :as walk] |
| 6 | + [hickory.core :as hickory] |
| 7 | + [hiccup2.core :as hiccup] |
6 | 8 | [tasks.util :as u])) |
7 | 9 |
|
8 | 10 | (def outbound-link-roots |
|
60 | 62 |
|
61 | 63 | ;; YAML processing for _data dir (which stores nav info): |
62 | 64 |
|
63 | | -(defn- add-metabase-prefix? [node] |
64 | | - (and (map? node) |
65 | | - (contains? node :url) |
66 | | - (not (str/starts-with? (:url node) "/docs/")) |
67 | | - (not (str/starts-with? (:url node) "https://metabase.com")) |
68 | | - (not (str/starts-with? (:url node) "https://www.metabase.com")) |
69 | | - (not (str/starts-with? (:url node) "http://metabase.com")) |
70 | | - (not (str/starts-with? (:url node) "http://www.metabase.com")))) |
71 | | - |
72 | | -(defn- remove-metabase-prefix? [node] |
73 | | - (and (map? node) |
74 | | - (contains? node :url) |
75 | | - (or (str/starts-with? (:url node) "https://metabase.com/docs") |
76 | | - (str/starts-with? (:url node) "https://www.metabase.com/docs") |
77 | | - (str/starts-with? (:url node) "http://metabase.com/docs") |
78 | | - (str/starts-with? (:url node) "http://www.metabase.com/docs")))) |
79 | | - |
80 | | -(defn- update-node [node] |
81 | | - (let [add? (add-metabase-prefix? node) |
82 | | - remove? (remove-metabase-prefix? node)] |
83 | | - (when add? (u/log " 📝" (str "Adding prefix to: " (:url node)))) |
84 | | - (when remove? (u/log " 📝" (str "Removing prefix from: " (:url node)))) |
85 | | - (cond-> node |
86 | | - add? (update-in [:url] #(str "https://metabase.com" %)) |
87 | | - remove? (update-in [:url] |
88 | | - (comp |
89 | | - #(str/replace % #"^http://www.metabase.com" "") |
90 | | - #(str/replace % #"^http://metabase.com" "") |
91 | | - #(str/replace % #"^https://www.metabase.com" "") |
92 | | - #(str/replace % #"^https://metabase.com" "")))))) |
| 65 | + |
| 66 | +;; YAML values can be html, so we update their links too. |
| 67 | + |
| 68 | +(defn ->hiccup |
| 69 | + "Wraps a html string with divs to capture any strings before or after the html." |
| 70 | + [html-str] |
| 71 | + (let [with-html-head-body (hickory/as-hiccup (hickory/parse (str "<div>" html-str "</div>")))] |
| 72 | + (-> with-html-head-body first (nth 3) (nth 2)))) |
| 73 | + |
| 74 | +(defn <-hiccup |
| 75 | + "Unwraps a hiccup structure from the divs added by ->hiccup." |
| 76 | + [hiccup] |
| 77 | + (-> hiccup hiccup/html (str/replace #"^\<div\>" "") (str/replace #"\<\/div\>$" "") str)) |
| 78 | + |
| 79 | +(defn update-html! [html-str walk-fn] |
| 80 | + (let [data (->hiccup html-str)] |
| 81 | + (<-hiccup (walk/postwalk walk-fn data)))) |
| 82 | + |
| 83 | +(def attrs-to-update #{:href}) |
| 84 | + |
| 85 | +(def yaml-keys-to-update #{:url :link :oss :enterprise :starter :pro}) |
| 86 | + |
| 87 | +(defn fix-link-string? [x] |
| 88 | + (and |
| 89 | + (instance? clojure.lang.MapEntry x) |
| 90 | + (contains? yaml-keys-to-update (first x)) |
| 91 | + (string? (second x)) |
| 92 | + x)) |
| 93 | + |
| 94 | +(defn fix-strategy [s] |
| 95 | + (cond |
| 96 | + (some #(str/starts-with? s %) (mapv #(str "/" % "/") outbound-link-roots)) |
| 97 | + :add |
| 98 | + |
| 99 | + (or (str/starts-with? s "https://metabase.com/docs") |
| 100 | + (str/starts-with? s "https://www.metabase.com/docs") |
| 101 | + (str/starts-with? s "http://metabase.com/docs") |
| 102 | + (str/starts-with? s "http://www.metabase.com/docs")) |
| 103 | + :remove |
| 104 | + |
| 105 | + :else nil)) |
93 | 106 |
|
94 | 107 | (comment |
95 | | - (mapv (comp :url update-node) |
96 | | - [{:url "/learn/latest/cloud/start"} |
97 | | - {:url "http://www.metabase.com/docs/latest/cloud/start"}]) |
98 | | -;; => ["https://metabase.com/learn/latest/cloud/start" |
99 | | -;; "/docs/latest/cloud/start"] |
| 108 | + (fix-strategy "/foob/latest/cloud/start") |
| 109 | + ;; => :add |
| 110 | + (fix-strategy "https://metabase.com/docs/latest/cloud/start") |
| 111 | + ;; => :remove |
| 112 | + (fix-strategy "/docs/x") |
| 113 | + ;; => nil |
100 | 114 | ) |
101 | 115 |
|
| 116 | +(declare fix-html-links) |
| 117 | + |
| 118 | +(defn fix-link-string |
| 119 | + ([s] (fix-link-string s true)) |
| 120 | + ([s fix-html?] |
| 121 | + (let [strat (fix-strategy s) |
| 122 | + fixed (case strat |
| 123 | + :add (str "https://metabase.com" (when-not (str/starts-with? s "/") "/") s) |
| 124 | + :remove (let [replacement (if (str/starts-with? s "/") "" "/")] |
| 125 | + (-> s |
| 126 | + (str/replace #"^http://metabase.com" replacement) |
| 127 | + (str/replace #"^http://www.metabase.com" replacement) |
| 128 | + (str/replace #"^https://metabase.com" replacement) |
| 129 | + (str/replace #"^https://www.metabase.com" replacement))) |
| 130 | + nil s)] |
| 131 | + (if fix-html? (fix-html-links fixed) fixed)))) |
| 132 | + |
| 133 | +(defn fix-html-links [s] |
| 134 | + (update-html! s |
| 135 | + (fn [x] |
| 136 | + (if (and (instance? clojure.lang.MapEntry x) |
| 137 | + (contains? attrs-to-update (first x)) |
| 138 | + (string? (second x))) |
| 139 | + [(first x) (fix-link-string (second x) false)] |
| 140 | + x)))) |
| 141 | + |
| 142 | +(comment |
| 143 | + (fix-link-string "/foob/latest/cloud/start") |
| 144 | + ;; => "https://metabase.com/foob/latest/cloud/start" |
| 145 | + (fix-link-string "https://metabase.com/docs/latest/cloud/start") |
| 146 | + ;; => "/docs/latest/cloud/start" |
| 147 | + (fix-link-string "/docs/x") |
| 148 | + ;; => "/docs/x" |
| 149 | + ) |
| 150 | + |
| 151 | +(defn update-links [link-data] |
| 152 | + (walk/postwalk |
| 153 | + (fn [x] |
| 154 | + (if-let [[k v] (fix-link-string? x)] |
| 155 | + [k (fix-link-string v)] |
| 156 | + x)) |
| 157 | + link-data)) |
| 158 | + |
102 | 159 | (defn- fix-yaml-links [path dry-run?] |
103 | 160 | (let [parsed (yaml/parse-string (slurp path)) |
104 | | - updated (walk/postwalk update-node parsed)] |
| 161 | + updated (update-links parsed)] |
105 | 162 | (cond |
106 | 163 | (and (= parsed updated) dry-run?) |
107 | 164 | (u/log " ℹ️" (str "Dry run: No update to: " path)) |
|
0 commit comments