Skip to content

cjohansen/portable-text-clj

Repository files navigation

Portable Text for Clojure

A Clojure library for rendering the PortableText rich text format content (used in Sanity) to hiccup or HTML.

Passes most of the official tests, except for some JavaScript library-specific features, and some image transforms (to be implemented).

Install

With tools.deps:

cjohansen/portable-text-clj {:mvn/version "2021.07.17"}

With Leiningen:

[cjohansen/portable-text-clj "2021.07.17"]

Usage

(require '[portable-text.html :as pt])

(def content-blocks
  [{:_key "R5FvMrjo"
    :_type "block"
    :children
    [{:_key "cZUQGmh4"
      :_type "span"
      :marks []
      :text "Plain text."}]
    :markDefs []
    :style "normal"}])

(pt/render content-blocks)
;;=> "<p>Plain text.</p>"

(pt/to-hiccup content-blocks)
;;=> [:p {} ("Plain text.")]

You can optionally pass an options map to both to-hiccup and render to specify details about your Sanity installation, which is necessary to render images correctly:

(require '[portable-text.html :as pt])

(pt/render
 [{:_type "image",
   :_key "d234a4fa317a",
   :asset
   {:_type "reference",
    :_ref "image-YiOKD0O6AdjKPaK24WtbOEv0-3456x2304-jpg"}}]
 {:sanity/project-id "3do82whm"
  :sanity/dataset "production"})

;;=> "<figure><img src=\"https://cdn.sanity.io/images/3do82whm/production/YiOKD0O6AdjKPaK24WtbOEv0-3456x2304.jpg\"/></figure>"

Images

Images are rendered from Sanity's CDN by default, but you can override it:

(require '[portable-text.html :as pt])

(pt/to-hiccup
 [{:_type "image",
   :_key "d234a4fa317a",
   :asset
   {:_type "reference",
    :_ref "image-yoda-3456x2304-jpg"}}]
 {:sanity/project-id "abcd"
  :sanity/dataset "prod"
  :cdn-url "https://cdn.mysite.com"})

;;=> [:figure {}
;;    [:img
;;     {:src "https://cdn.mysite.com/images/abcd/prod/yoda-3456x2304.jpg"}]]

Image transforms such as crop and hotspot are not (yet) supported.

Custom mark definitions

If you've customized the block editor to include custom marks, you might want custom rendering of those marks. Implement portable-text.html/render-mark for the :_type of your mark definition:

(require '[portable-text.html :as pt])

(defmethod pt/render-mark :internalLink [config mark content]
  [:a {:href (format "/files/%s" (-> mark :reference :_id))} content])

(pt/render
 [{:_key "8cff0fcf4e1c"
   :_type "block"
   :children
   [{:_key "8cff0fcf4e1c1"
     :_type "span"
     :marks ["7d81b2a6f6b6"]
     :text "A document"}]
   :mark-defs
   [{:_key "7d81b2a6f6b6"
     :_type "internalLink"
     :reference {:_id "666"
                 :_type "file"
                 :title "My file"}}]
   :style "normal"}])

;;=> "<p><a href=\"/files/666\">A document</a></p>"

Tests

make test # ...or
make autotest

License

Copyright © 2020-2021 Christian Johansen

Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.

About

Render sanity.io Portable Text to HTML with Clojure

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages