Как я могу предотвратить закрытие компилятором определенных методов в clojurescript? - PullRequest
0 голосов
/ 01 апреля 2019

Я интегрирую quilljs с моим приложением clojurescript. Я включил его в мой файл project.cljs примерно так: [cljsjs/quill "1.3.5-0"].

Компилятор минимизирует некоторые методы и вызывает ошибку:

function xA(a, b) {
        var c = t(a).getSelection(!0)
          , d = c.index
          , e = c.length
          , h = Quill.import("delta");
        c = function(b, c, d, e) {
            return function(b) {
                return t(a).updateContents((new e).rf(c).delete(d).nf({
                    image: b
                }))
            }
        }(c, d, e, h);
        return b.c ? b.c(c) : b.call(null, c)
    }

Это ошибка: Uncaught TypeError: (intermediate value).rf is not a function

Код clojurescript выглядит следующим образом:

(defn file-recieve-handler [this cb]
  (let [range (.getSelection @this true)
        index (.-index range)
        length (.-length range)
        delta (.import js/Quill "delta")]

    (cb (fn [url]
            (.updateContents @this
                             (.insert
                               (.delete
                                 (.retain (new delta) index)
                                 length)
                               #js {:image url}))))))

Метод retain и метод insert становятся минимизированными - и не должны. (Удаление не по какой-то причине, я предполагаю, что это потому, что это ключевое слово в javascript.)

Я нашел файл externs для quilljs: https://github.com/cljsjs/packages/blob/master/quill/resources/cljsjs/quill/common/quill.ext.js

Нужно ли мне как-то дополнить файл extern или как-то еще, как я могу написать код, чтобы эти два метода не минимизировались, когда для компилятора включена расширенная компиляция?

Для некоторого контекста ниже приводится полный файл. Он основан на этом https://github.com/benhowell/reagent-quill/blob/master/quill.cljs

(ns quill.core
  (:require
   [reagent.core :as r]))


(defn quill-toolbar [id]
  [:div {:id (str "quill-toolbar-" id)}

   [:span {:class "ql-formats"}
    [:select {:class "ql-header"}
     [:option {:value "1"}]
     [:option {:value "2"}]
     [:option {:value "3"}]
     [:option {:value "4"}]
     [:option {:value "5"}]
     [:option]]]

   [:span {:class "ql-formats"}
    [:select {:class "ql-font"}
     [:option]
     [:option {:value "serif"}]
     [:option {:value "monospace"}]]]

   [:span {:class "ql-formats"}
    [:select {:class "ql-size"}
     [:option {:value "small"}]
     [:option]
     [:option {:value "large"}]
     [:option {:value "huge"}]]]

   [:span {:class "ql-formats"}
    [:button {:class "ql-bold"}]
    [:button {:class "ql-italic"}]
    [:button {:class "ql-underline"}]
    [:button {:class "ql-strike"}]
    [:button {:class "ql-blockquote"}]]

   [:span {:class "ql-formats"}
    [:select {:class "ql-align"}]]

   [:span {:class "ql-formats"}
    [:button {:class "ql-script" :value "sub"}]
    [:button {:class "ql-script" :value "super"}]]

   [:span {:class "ql-formats"}
    [:button {:class "ql-indent" :value "-1"}]
    [:button {:class "ql-indent" :value "+1"}]]

   [:span {:class "ql-formats"}
    [:button {:class "ql-image"}] ]

   [:span {:class "ql-formats"}
    [:select {:class "ql-color"}]
    [:select {:class "ql-background"}]]

   [:span {:class "ql-formats"}
    [:button {:class "ql-clean"}]]])


(defn file-recieve-handler [this cb]
  (let [range (.getSelection @this true)
        index (.-index range)
        length (.-length range)
        delta (.import js/Quill "delta")]

    (cb (fn [url]
            (.updateContents @this
                             (.insert
                               (.delete
                                 (.retain (new delta) index)
                                 length)
                               #js {:image url}))))))


(defn editor [{:keys [id value selection on-change image-handler]}]
  (let [this (r/atom nil)
        get-value #(aget @this "container" "firstChild" "innerHTML")
        string-id (if (keyword? id) (name id) id) ]
    (r/create-class
     {:component-did-mount
      (fn [component]
        (reset! this
                (js/Quill.
                 (aget (.-children (r/dom-node component)) 1)
                 #js {:modules #js {:toolbar (aget (.-children (r/dom-node component)) 0)}
                      :theme "snow"
                      :scrollingContainer (str "quill-wrapper-" string-id)
                      :placeholder "Compose an epic..."}))

        (.on @this "text-change"
             (fn [delta old-delta source]
                 (on-change source (get-value))))

        ; FYI this is another area I had trouble. I got around it using 
        ; get and set in the goog.object
        (let [toolbar (.getModule @this "toolbar")
              handlers (goog.object/get toolbar "handlers")]
          (goog.object/set handlers "image" #(file-recieve-handler this image-handler)))

        (if (= selection nil)
          (.setSelection @this nil)
          (.setSelection @this (first selection) (second selection) "api")))

      :component-will-receive-props
      (fn [component next-props]
        (if
            (or
             (not= (:value (second next-props)) (get-value))
             (not= (:id (r/props component)) (:id (second next-props))))
          (do
            (if (= selection nil)
              (.setSelection @this nil)
              (.setSelection @this (first selection) (second selection) "api"))
            (.pasteHTML @this (:value (second next-props))))))

      :display-name  (str "quill-editor-" string-id)

      :reagent-render
      (fn []
        [:div {:id (str "quill-wrapper-" string-id) :class "quill-wrapper"}
         [quill-toolbar string-id]
         [:div {:id (str "quill-editor-" string-id)
                :class "quill-editor"
                :dangerouslySetInnerHTML {:__html value}}]])})))


(defn display-area [{:keys [id content]}]
  (let [this (r/atom nil)]
    (r/create-class
     {:component-did-mount
      (fn [component]
        (reset! this (js/Quill. (r/dom-node component)
                                #js {:theme "snow"
                                     :modules #js {:toolbar false}
                                     :placeholder ""}))
        (.disable @this))

      :component-will-receive-props
      (fn [component next-props]
        (.pasteHTML @this (:content (second next-props))))

      :display-name  (str "quill-display-area-" id)

      :reagent-render
      (fn []
        [:div {:id (str "quill-display-area-" id)
               :class "quill-display-area"
               :dangerouslySetInnerHTML {:__html content}}])})))

Ответы [ 2 ]

1 голос
/ 02 апреля 2019

Вы можете включить предупреждения внешнего вида, и компилятор расскажет вам о вещах, которые могут быть переименованы.

;; in the actual ns
(set! *warn-on-infer* true)

;; in the build config compiler options
:infer-externs true

См. https://clojurescript.org/guides/externs#externs-inference

Чтобы помочь отладить проблемы с переименованием, вы можете включить :pseudo-names true в опциях компилятора. Это облегчит определение того, какие методы будут переименованы, и, возможно, потребуется ^js typehint или ручной внешний вид.

0 голосов
/ 02 апреля 2019

Я использовал подсказки типа, как предложил @ thomas-heller, и это сработало. Я разбил исходную функцию на две отдельные функции. Вот это переписано:

(defn add-image [^js/Quill quill ^js/Quill.imports.delta delta index length url]
  (.updateContents quill
                   (.insert
                     (.delete
                       (.retain delta index)
                       length)
                     #js {:image url})))

;https://github.com/quilljs/quill/pull/995/files#diff-6dafc0fe6b5e9aed0859eef541e68372
(defn file-recieve-handler [^js/Quill quill cb]
  (let [range (.getSelection quill true)
        index (.-index range)
        length (.-length range)
        delta  (new (.-delta (.-imports js/Quill)))]

    (cb (fn [url]
            (add-image quill delta index length url)))))
...