Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: asciidoctor plugin #183

Merged
merged 2 commits into from
Apr 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/io/perun.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By naming the task after the library you are using, you bind the implementation to the interface. A better task name would be ascidoc.

"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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Asciidoc can use YAML front-matter itself, you might consider passing :keep-yaml true to yaml-metadata. That way, the YAML will still be present in the file when the asciidoctor* task sees it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but the issue arises that the default meta keys used in Perun and !{Asciidoctor](http://asciidoctor.org/docs/user-manual/#attribute-catalog) are different. I was thinking of introducing a translation layer in a next version which contains the necessary translation layer, as I stated in the currently last comment on #100 For now I could indeed also just pass it through. What do you think, considering my comments? Both are fine to me.

(asciidoctor* :out-dir out-dir
:filterer filterer
:extensions extensions
:meta meta))))

(deftask global-metadata
"Read global metadata from `perun.base.edn` or configured file.

Expand Down
16 changes: 16 additions & 0 deletions src/io/perun/asciidoctor.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
(ns io.perun.asciidoctor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

(:require [io.perun.core :as perun]
[clojure.java.io :as io])
(:import [org.asciidoctor Asciidoctor Asciidoctor$Factory]))

(def container
(Asciidoctor$Factory/create ""))

(defn asciidoctor-to-html [file-content]
(.convert container 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)))
45 changes: 45 additions & 0 deletions test/io/perun_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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 "<h1><a href=\"#hello-there\" id=\"hello-there\"></a>Hello there</h1>\n<p>This --- be <strong><em>markdown</em></strong>.</p>\n")

(def parsed-pandoc-basic "<h1 id=\"hello-there\">Hello there</h1>\n<p>This --- be <strong><em>markdown</em></strong>.</p>\n")

(def parsed-asciidoctor-md "<div class=\"paragraph\">\n<p>This --- be <em><em>markdown</em></em>.</p>\n</div>")

(def parsed-asciidoctor-adoc "<div class=\"paragraph\">\n<p>This --- be <em>asciidoc</em>.</p>\n</div>")

(def parsed-md-smarts "<h1><a href=\"#hello-there\" id=\"hello-there\"></a>Hello there</h1>\n<p>This &mdash; be <strong><em>markdown</em></strong>.</p>\n")

(def js-content "(function somejs() { console.log('$foo'); })();")
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you're testing different parsing modes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then again I couldn't get the tests to fail based on content, so perhaps I'm using the framework incorrectly.

: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")
Expand Down