From 7c4bc5ca4f21068a3446a38ec263b9d1198af3ac Mon Sep 17 00:00:00 2001 From: Nico Rikken Date: Thu, 6 Apr 2017 23:34:56 +0200 Subject: [PATCH 1/2] feat: asciidoctor plugin A basic tasks for processing asciidoc files using AsciidoctorJ. This implementation is bare-bones, it does not cover Asciidoctor extensions and does not relate asciidoc attributes with Perun meta. The page title is not rendered by the Asciidoctor task, to mimic the behavior of the markdown extension. --- src/io/perun.clj | 49 ++++++++++++++++++++++++++++++++++++ src/io/perun/asciidoctor.clj | 13 ++++++++++ test/io/perun_test.clj | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 src/io/perun/asciidoctor.clj diff --git a/src/io/perun.clj b/src/io/perun.clj index 8fe7ef53..0311681f 100644 --- a/src/io/perun.clj +++ b/src/io/perun.clj @@ -458,6 +458,55 @@ :meta meta :cmd-opts cmd-opts)))) +(def ^:private ^:deps asciidoctor-deps + '[[org.clojure/tools.namespace "0.3.0-alpha3"] + [org.asciidoctor/asciidoctorj "1.5.4"]]) + +(def ^:private +asciidoctor-defaults+ + {:out-dir "public" + :out-ext ".html" + :filterer identity + :extensions [".ad" ".asc" ".adoc" ".asciidoc"] + :meta {:original true + :include-rss true + :include-atom true}}) + +(deftask asciidoctor* + "Parse asciidoc files using Asciidoctor + + Asciidoctor has basic support for markdown, and can therefore also be used + for parsing `.md` files." + [d out-dir OUTDIR str "the output directory" + _ filterer FILTER code "predicate to use for selecting entries (default: `identity`)" + e extensions EXTENSIONS [str] "extensions of files to process" + m meta META edn "metadata to set on each entry"] + (let [pod (create-pod asciidoctor-deps) + options (merge +asciidoctor-defaults+ *opts*)] + (content-task + {:render-form-fn (fn [data] `(io.perun.asciidoctor/process-asciidoctor ~data)) + :paths-fn #(content-paths % options) + :passthru-fn content-passthru + :task-name "asciidoctor" + :tracer :io.perun/asciidoctor + :rm-originals true + :pod pod}))) + +(deftask asciidoctor + "Parse asciidoc files with yaml front matter using Asciidoctor + + Asciidoctor has basic support for markdown, and can therefore also be used + for parsing `.md` files." + [d out-dir OUTDIR str "the output directory" + _ filterer FILTER code "predicate to use for selecting entries (default: `identity`)" + e extensions EXTENSIONS [str] "extensions of files to process" + m meta META edn "metadata to set on each entry"] + (let [{:keys [out-dir filterer extensions meta]} (merge +asciidoctor-defaults+ *opts*)] + (comp (yaml-metadata :filterer filterer :extensions extensions) + (asciidoctor* :out-dir out-dir + :filterer filterer + :extensions extensions + :meta meta)))) + (deftask global-metadata "Read global metadata from `perun.base.edn` or configured file. diff --git a/src/io/perun/asciidoctor.clj b/src/io/perun/asciidoctor.clj new file mode 100644 index 00000000..98ee0d31 --- /dev/null +++ b/src/io/perun/asciidoctor.clj @@ -0,0 +1,13 @@ +(ns io.perun.asciidoctor + (:require [io.perun.core :as perun] + [clojure.java.io :as io]) + (:import [org.asciidoctor Asciidoctor Asciidoctor$Factory])) + +(defn asciidoctor-to-html [file-content] + (.convert (Asciidoctor$Factory/create "") file-content {})) + +(defn process-asciidoctor [{:keys [entry]}] + (perun/report-debug "asciidoctor" "processing asciidoctor" (:filename entry)) + (let [file-content (-> entry :full-path io/file slurp) + html (asciidoctor-to-html file-content)] + (assoc entry :rendered html))) diff --git a/test/io/perun_test.clj b/test/io/perun_test.clj index c79f3307..d6e60c07 100644 --- a/test/io/perun_test.clj +++ b/test/io/perun_test.clj @@ -188,12 +188,23 @@ This --- be ___markdown___.") +(def adoc-content + "= Hello there + +This --- be _asciidoc_.") + (def input-strings (map #(str "---\n" % "\n---\n" md-content) yamls)) +(def adoc-input-strings (map #(str "---\n" % "\n---\n" adoc-content) yamls)) + (def parsed-md-basic "

Hello there

\n

This --- be markdown.

\n") (def parsed-pandoc-basic "

Hello there

\n

This --- be markdown.

\n") +(def parsed-asciidoctor-md "
\n

This --- be markdown.

\n
") + +(def parsed-asciidoctor-adoc "
\n

This --- be asciidoc.

\n
") + (def parsed-md-smarts "

Hello there

\n

This — be markdown.

\n") (def js-content "(function somejs() { console.log('$foo'); })();") @@ -246,6 +257,20 @@ This --- be ___markdown___.") :content parsed-pandoc-basic :msg "`pandoc` should populate HTML file with parsed content")) + (add-txt-file :path "2017-01-01-test.adoc" :content (nth input-strings 0)) + (p/asciidoctor) + (testing "asciidoctor for markdown" + (content-check :path (perun/url-to-path "public/2017-01-01-test.html") + :content parsed-asciidoctor-md + :msg "`asciidoctor` should populate HTML file with parsed markdown content")) + + (add-txt-file :path "2017-01-01-test.adoc" :content (nth adoc-input-strings 0)) + (p/asciidoctor) + (testing "asciidoctor for asciidoc" + (content-check :path (perun/url-to-path "public/2017-01-01-test.html") + :content parsed-asciidoctor-adoc + :msg "`asciidoctor` should populate HTML file with parsed asciidoc content")) + (add-txt-file :path "2017-01-01-test.md" :content (nth input-strings 0)) (p/markdown) @@ -399,6 +424,26 @@ This --- be ___markdown___.") :content "Hello there\n===========\n\nThis --- be ***markdown***.\n" :msg "`pandoc` should parse HTML to markdown")) + (add-txt-file :path "test.md" :content (nth input-strings 0)) + (p/asciidoctor :out-dir nil + :filterer #(= (:path %) "test.md") + :extensions [".md"] + :meta {:asciidoctor-set :metadata}) + (testing "asciidoctor for markdown" + (content-check :path "test.html" + :content parsed-asciidoctor-md + :msg "`asciidoctor` should populate HTML with parsed markdown content")) + + (add-txt-file :path "test.adoc" :content (nth adoc-input-strings 0)) + (p/asciidoctor :out-dir nil + :filterer #(= (:path %) "test.adoc") + :extensions [".adoc"] + :meta {:asciidoctor-set :metadata}) + (testing "asciidoctor for asciidoc" + (content-check :path "test.html" + :content parsed-asciidoctor-adoc + :msg "`asciidoctor` should populate HTML with parsed asciidoc content")) + (add-txt-file :path "test.md" :content (nth input-strings 0)) (p/markdown :out-dir "hammock" :filterer #(= (:path %) "test.md") From d422a8c35b70312fca4c7a5ff3d88067d69b69ec Mon Sep 17 00:00:00 2001 From: Nico Rikken Date: Sat, 22 Apr 2017 11:49:16 +0200 Subject: [PATCH 2/2] refactor: shared asciidoctor container Based on comments raised at https://github.com/hashobject/perun/pull/183 the asciidoctor container is now bound to the namespace and shared between processing calls. --- src/io/perun/asciidoctor.clj | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/io/perun/asciidoctor.clj b/src/io/perun/asciidoctor.clj index 98ee0d31..02c52529 100644 --- a/src/io/perun/asciidoctor.clj +++ b/src/io/perun/asciidoctor.clj @@ -3,8 +3,11 @@ [clojure.java.io :as io]) (:import [org.asciidoctor Asciidoctor Asciidoctor$Factory])) +(def container + (Asciidoctor$Factory/create "")) + (defn asciidoctor-to-html [file-content] - (.convert (Asciidoctor$Factory/create "") file-content {})) + (.convert container file-content {})) (defn process-asciidoctor [{:keys [entry]}] (perun/report-debug "asciidoctor" "processing asciidoctor" (:filename entry))