diff --git a/src/marginalia/core.clj b/src/marginalia/core.clj index 6c2b624..09ffdc2 100644 --- a/src/marginalia/core.clj +++ b/src/marginalia/core.clj @@ -148,7 +148,122 @@ (defn merge-line [line m] (cond (:docstring-text line) (assoc m -]) + :docs + (conj (get m :docs []) line)) + (:code-text line) (assoc m + :codes + (conj (get m :codes []) line)) + (:docs-text line) (assoc m + :docs + (conj (get m :docs []) line)))) + +(defn group-lines [doc-lines] + (loop [cur-group {} + groups [] + lines doc-lines] + (cond + (empty? lines) (conj groups cur-group) + + (end-of-block? cur-group groups lines) + (recur (merge-line (first lines) {}) (conj groups cur-group) (rest lines)) + + :else (recur (merge-line (first lines) cur-group) groups (rest lines))))) + +(defn path-to-doc [fn] + (let [file (java.io.File. fn) + ns (-> file + (read-file-ns-decl) + (second) + (str)) + ns (if (or (nil? ns) (empty? ns)) (.getName file) ns) + groups (parse-file fn)] + {:ns ns + :groups groups})) + + +;; ## Output Generation + +(defn filename-contents + [props output-dir all-files parsed-file] + {:name (io/file output-dir (str (:ns parsed-file) ".html")) + :contents (single-page-html props parsed-file all-files)}) + +(defn multidoc! + [output-dir files-to-analyze props] + (let [parsed-files (map path-to-doc files-to-analyze) + index (index-html props parsed-files) + pages (map #(filename-contents props output-dir parsed-files %) parsed-files)] + (doseq [f (conj pages {:name (io/file output-dir "toc.html") + :contents index})] + (spit (:name f) (:contents f))))) + +(defn uberdoc! + "Generates an uberdoc html file from 3 pieces of information: + + 2. The path to spit the result (`output-file-name`) + 1. Results from processing source files (`path-to-doc`) + 3. Project metadata as a map, containing at a minimum the following: + - :name + - :version + " + [output-file-name files-to-analyze props] + (let [source (uberdoc-html + props + (map path-to-doc files-to-analyze))] + (spit output-file-name source))) + +;; ## External Interface (command-line, lein, cake, etc) + +;; These functions support Marginalia's use by client software or command-line +;; users. + +(def ^:private file-extensions #{"clj" "cljs" "cljx"}) + +(defn format-sources + "Given a collection of filepaths, returns a lazy sequence of filepaths to all + .clj, .cljs, and .cljx files on those paths: directory paths will be searched + recursively for files." + [sources] + (if (nil? sources) + (find-processable-file-paths "./src" file-extensions) + (->> sources + (mapcat #(if (dir? %) + (find-processable-file-paths % file-extensions) + [(.getCanonicalPath (io/file %))]))))) + +(defn split-deps [deps] + (when deps + (for [d (.split deps ";") + :let [[group artifact version] (.split d ":")]] + [(if (= group artifact) artifact (str group "/" artifact)) + version]))) + +(defn run-marginalia + "Default generation: given a collection of filepaths in a project, find the .clj + files at these paths and, if Clojure source files are found: + + 1. Print out a message to std out letting a user know which files are to be processed; + 1. Create the docs directory inside the project folder if it doesn't already exist; + 1. Call the uberdoc! function to generate the output file at its default location, + using the found source files and a project file expected to be in its default location. + + If no source files are found, complain with a usage message." + [args & [project]] + (let [[{:keys [dir file name version desc deps css js multi leiningen]} files help] + (cli args + ["-d" "--dir" "Directory into which the documentation will be written" :default "./docs"] + ["-f" "--file" "File into which the documentation will be written" :default "uberdoc.html"] + ["-n" "--name" "Project name - if not given will be taken from project.clj"] + ["-v" "--version" "Project version - if not given will be taken from project.clj"] + ["-D" "--desc" "Project description - if not given will be taken from project.clj"] + ["-a" "--deps" "Project dependencies in the form ::;... + If not given will be taken from project.clj"] + ["-c" "--css" "Additional css resources ;;... + If not given will be taken from project.clj."] + ["-j" "--js" "Additional javascript resources ;;... + If not given will be taken from project.clj"] + ["-m" "--multi" "Generate each namespace documentation as a separate file" :flag true] + ["-l" "--leiningen" "Generate the documentation for a Leiningen project file."]) sources (distinct (format-sources (seq files))) sources (if leiningen (cons leiningen sources) sources)] (if-not sources