carbon-wrapper/src/dev/user.clj

118 lines
4.4 KiB
Clojure

(ns user
(:require
[clojure.string :as str]
[clojure.data.json :as json]
[clojure.java.io :as io]))
(defn gen-prop-docstring [prop {:keys [defaultValue type required description]}]
(let [prop (name prop)
required (if required " (required)" "")
type (format "(%s)" (:name type))
description description
defaultValue (if defaultValue (format "Default: %s" (:value defaultValue)) "")
values (if (:value type) (format "Possible values: %s" (:value type)) "")]
(format " - %s %s%s: %s %s %s\n" prop type required description defaultValue values)))
(defn gen-docstring [{:keys [description props]}]
(let [description (if-not (str/blank? description) (str description "\n") description)
props (reduce #(str %1 (gen-prop-docstring (key %2) (val %2)))
"Props:\n"
props)]
(str description props)))
(defn quoted [s] (str "\"" s "\""))
(defn escaped [s] (str/replace s "\"" "\\\""))
(defn hyphenated [camelCase]
(println "Hyphenating" camelCase)
(if (= "UIShell" camelCase)
"ui-shell"
(-> camelCase
(str/replace #"([A-Z])" "-$1")
(str/lower-case)
(str/replace #"^-" ""))))
(def input-factory-classes
#{"Checkbox"
"ComboBox"
"FormInput"
"DropdownSearchInput"
"Search"
"TextArea"
"TextInput"})
(defn factory-helper [class]
(if (contains? input-factory-classes class)
"wrapped-factory-apply"
"factory-apply"))
(defn gen-json [js]
(let [datasplit (str/split js #";\n")
match (first (filter #(re-find #".*__docgen.*" %) datasplit))]
(if-not (nil? match)
(json/read-str (apply str (drop-while #(not= % \{) match)) :key-fn keyword)
nil)))
(defn guess-display-name [file display-name]
(if (nil? display-name)
(do (print "No display name found for" file "and thus will guess...")
(let [display-name (-> file
(str/replace #"\.js" "")
(str/replace #"\." ""))]
(println "Guessed name:" display-name)
display-name))
display-name))
(defn gen-factory-map [dir]
(fn [{:keys [subdir file]}]
(println "Generating" subdir "/" file "...")
(if-let [{:keys [displayName description props] :as docs} (gen-json (slurp (str dir "/" subdir "/" file)))]
(let [displayName (guess-display-name file displayName)
class displayName
factory-name (str "ui-" (hyphenated class))
filename (str "src/main/ch/lyrion/carbon/" (str/replace (hyphenated subdir) #"-" "_") "/" (str/replace factory-name #"-" "_") ".cljs")
nns (str "ch.lyrion.carbon." (hyphenated subdir) "." factory-name)
include-file (str "carbon-components-react/lib/components/" subdir "/" file)
docstring (gen-docstring docs)]
{:class class
:factory-name factory-name
:filename filename
:ns nns
:include-file include-file
:docstring docstring})
nil)))
(defn gen-component-filelist [dir]
(fn [subdir]
(let [path (str dir "/" subdir)]
(->> (seq (.list (io/file path)))
(remove #(or (= % "index.js")
(str/ends-with? % "-story.js")
(str/ends-with? % "-test.js")
(not (str/ends-with? % ".js"))))
(map #(identity {:subdir subdir
:file %}))))))
(defn factory-ns-shadow [ns class factory-name include-file docstring]
(str "(ns " ns "\n"
" (:require\n"
" [ch.lyrion.carbon.factory-helpers :as h]\n"
" [\"" include-file "\" :default " class "]))\n\n"
"(def " factory-name "\n"
"\n"
(quoted (escaped docstring))
"\n (h/" (factory-helper class) " " class "))"))
(defn gen-factories [component-dir]
(let [modules (->> (seq (.list (io/file component-dir)))
(map (gen-component-filelist component-dir))
flatten
(map (gen-factory-map component-dir))
(remove nil?)
(sort-by :factory-name))]
(io/make-parents "src/main/ch/lyrion/carbon/factories.cljs")
(doseq [{:keys [filename ns class factory-name include-file filename docstring] :as m} modules]
(println "Generating" filename "...")
(io/make-parents filename)
(spit (io/as-file filename) (factory-ns-shadow ns class factory-name include-file docstring)))))