Clojurescript Hickory на NodeJS (разбор HTML до икоты)

Мне нужен способ парсить HTML-разметку, чтобы сбивать приложение node.js, написанное на Clojurescript. На стороне клиента я использовал для работы гикори, который, к сожалению, плохо работает на Node.js. Если для какого-либо пространства имен требуется узел hickory.core, он отказывается запускать приложение, говоря:

ReferenceError: Node is not defined
    at hickory$core$node_type (/media/lapdaten/ARBEITSSD/dev/violinas_macchiato/target/out/hickory/core.cljs:35:1)
    at Object.<anonymous> (/media/lapdaten/ARBEITSSD/dev/violinas_macchiato/target/out/hickory/core.cljs:39:16)

Если я загружаю библиотеку с помощью figwheel, когда узел уже работает, CIDER дает мне завершение кода для различных функций гикори, но hickory.core/parse-fragment не определено во время выполнения (hickory.core/as-hiccup по какой-то причине доступно).

На самом деле это известная проблема с hickory, поскольку она зависит от API DOM браузера, который недоступен в Node.js. Я попробовал (set! js/DOMParser (.-DOMParser (js/require "xmldom"))), как было предложено на GitHub, но на самом деле я не знаю, куда поместить это выражение. Как правило, обсуждения на GitHub не оставляли меня в покое…

Кто-нибудь получил гикори для работы над Node.js? Любые другие предложения относительно того, как мое приложение может преобразовать HTML в икоту?

Спасибо заранее!

Оливер


person Phylax    schedule 12.12.2019    source источник


Ответы (1)


Из-за того, что hickory не поддерживает Node.js, как я мог понять, я недавно изучал собственные решения Node.js. Вот posthtml-parser. Самое приятное в этом то, что создаваемый JSON находится всего в одном js->clj от почти точного формата hickory, то есть следующего:

(ns utils.phtmltohiccup
  (:require
   ["posthtml-parser" :as phr] ; requiring the shadow-cljs way
   ))
   
(def testhtml
  "<ul class=\"list\" important=\"false\"><li>Hello World</li><li>Hello Again</li></ul>")

(js->clj
 (phr
  testhtml) :keywordize-keys true)

производит:

[{:tag "ul"
  :attrs
  {:class "list"
   :important "false"}
  :content
  [{:tag "li"
    :content
    ["Hello World"]}
   {:tag "li"
    :content
    ["Hello Again"]}]}]

Единственная разница в отношении правильного гикори, по-видимому, заключается в отсутствии ключей :type и предполагаемом типе :element. Эта структура является очень работоспособной формой в Clojurescript как таковой. Когда мне действительно нужна икота, я теперь использую одну из двух очень наивных функций, чтобы преобразовать гикори выше в икоту. Потребление стека:

(defn parsed-to-hiccup-sc
  ""
  [hickory]
  (map
   (fn [element]
     (if (:tag element)
       (do
         (print (:tag element))
         (let [{:keys [tag attrs content]} element]
           (into [(keyword tag) attrs] (parsed-to-hiccup-sc content))
           ))
       (str element)))
   hickory))

В качестве альтернативы я использую clojure.walk (который, я полагаю, не потребляет много стека):

(defn parsed-to-hiccup-ns
  ""
  [hickory]
  (walk/postwalk
   (fn [element]
     (if (:tag element)
       (let [{:keys [tag attrs content]} element]
         (into [(keyword tag) attrs] content))
       (str element)))
   hickory))

На данный момент это решение достаточно хорошо для моих намерений и целей. Однако я доведу эту библиотеку до сведения тех, кто сопровождает гикори. Может быть, окажется, что есть простой способ интегрировать posthtml-parser в hickory для правильной поддержки Node.js.

person Phylax    schedule 04.09.2020