Skip to content

Instantly share code, notes, and snippets.

@green-coder
Last active March 15, 2022 08:28
Show Gist options
  • Save green-coder/8466647525b880e802f252ae79e1ebb2 to your computer and use it in GitHub Desktop.
Save green-coder/8466647525b880e802f252ae79e1ebb2 to your computer and use it in GitHub Desktop.
Cross platform (CLJC) and hackable `html->hiccup` function.
(ns hiccdown.html
(:require [clojure.edn :as edn]
[instaparse.core :as insta :refer [defparser]]))
;; A cross-platform (CLJC) html->hiccup converter for Hiccdown's own needs.
;; For now, only used in the tests.
(defparser html-parser "
nodes = node*
<node> = text | open-close-tags | self-closing-tag
open-close-tags = opening-tag nodes closing-tag
opening-tag = <'<'> <spaces>? tag-name attributes? <spaces>? <'>'>
closing-tag = <'</'> tag-name <'>'>
self-closing-tag = <'<'> <spaces>? tag-name attributes? <spaces>? <'/>'>
tag-name = #'[^ </>]+'
attributes = (<spaces> attribute)+
attribute = attribute-name (<'='> attribute-value)?
<attribute-name> = #'[^ \t=]+'
<attribute-value> = #'[^ \t]+' | #'\"[^\"]*\"'
<text> = #'[^<]+'
spaces = #'[ \t]+'
")
(defn html->hiccup [html-str]
(->> (html-parser html-str)
(insta/transform {:nodes (fn [& nodes] nodes)
:open-close-tags (fn [opening-tag nodes _closing-tag]
(into opening-tag nodes))
:opening-tag (fn ([tag-name] [tag-name])
([tag-name attributes] [tag-name attributes]))
:self-closing-tag (fn ([tag-name] [tag-name])
([tag-name attributes] [tag-name attributes]))
:tag-name keyword
:attributes (fn [& attributes]
(into {} attributes))
:attribute (fn ([attribute-name]
[(keyword attribute-name) true])
([attribute-name attribute-value]
[(keyword attribute-name) (edn/read-string attribute-value)]))})))
@green-coder
Copy link
Author

This gist is now superseded by a Clojure lib at https://github.com/green-coder/html-to-hiccup

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment