Is there a way to compile to JS files that can be used in project?

I am trying to figure out how to write a plugin for CKEditor. It requires you to load a plugin file from a JS file through a configured path i.e. plugins/my_plugin.js

I am using shadow-cljs and reagent/re-frame.

Ideally I would be able to write this in CLJS. Does anyone have any ideas?

Hard to answer without knowing what kind of JS the CKEditor expects from the plugin. Do you have an example JS plugin?

If you look at this page, it shows a very simple one:


[WRONG LINK BELOW]

Where does it say that CKEditor has to load it?

Seems to me that you can just call (js/CKEditor.plugins.add "name" #js {:init (fn [editor] ...)}) if you are using CKEditor CDN package. Not sure there is an actual npm package that you can import directly.

Either way it seems to just be function calls and the loading part is optional?

that code with the init function lives in a special directory structure. It looks like this:

  • ckeditor root/
    • plugins/
      • abbr/
        • icons/
          • abbr.png
        • dialogs/
          • abbr.js
        • plugin.js

and the place where you use the code you referenced is in the plugin.js file in the above dir structure

[edit]
I can specify a different root directory for the plugin.

Sorry, don’t have time to dig into this.

I don’t think you need the directory structure and can just call the JS fns directly instead. I would try that first with a regular :browser build.

Thanks for your help @thheller I appreciate it!

This is already in a project with :browser. It is a large project I am just using CKEditor as a HTML editor component, and was hoping I could use CLJS instead of having to use JS. But if I have to use JS, I have to.

Anyone else have any ideas?

I don’t know the specifics of CKEditor but do you already know that you can mark a function to be export and then access it via JavaScript?
For example, here the function get-weak-vs-bfs-levels is marked export and accessed via JavaScript here as ron_units.core.get_weak_vs_bfs_levels

Good idea @anurag.peshne. I am using Shadow-cljs so there are some differences there. But unfortunately my understanding is that CKEditor wants an actual JS file living in a specific directory, it’s machinery loads from file and uses the directory structure to find the “whole” of the plugin.

Please try it without “an actual JS file living in a specific directory”! I am almost certain that will work. Did you even try that?

You are correct @thheller. That will work for a simple plugin. But in order to get the editor to load a more complex one, I have to register it as an external library, which requires a specific dir structure in order to provide things like toolbar icons, dialogs , etc… as CKEditors code does some parsing magic to piece together the pieces of a plugin.

Thanks again, for your help. and much more for shadow-cljs! I am just trying to use it for something other than what is was designed for. That was just me hoping that I could get by without actually coding in JS because CLJS is just so much better :slight_smile:

I don’t have any experience with ckeditor requires, so I’m going to go off of a superficial reading of the docs.

It seems like the CKEditor plugins target a browser runtime, so it probably makes sense to use the :browser shadow-cljs target.

It looks like you can configure shadow-cljs to output the required directory structure like so, but there are apparently several different configs that can yield the same directory structure:

{:dependencies [...]
 :source-paths [...]

:builds
{:app {:target :browser
       :output-dir "target/abbr/"
       :asset-path "."
       :modules {:plugin {:init-fn abbr.core/main!}}
       :release {:output-dir "dist/"
                 :build-options {:manifest-name "assets.edn"}}
}

Where I’m guessing abbr.core looks something like:

(def init [editor] (.log js/console "hello world"))

(def init-config {:icons "timestamp", :init init})

(def main! []
  (.add js/CDKEDITOR.plugins (clj->js init-config)))

It’s not clear to me how you get something like live reload with ckeditor, so hooking your builds up to ckeditor is something I’m not sure about. It does seem like ckeditor is expecting ES3 or at most ES5-style JS, so, honestly, it looks like you can do almost whatever you want as long as you call the required registration function in your entry point code and get it executed somehow.

Thanks @johnchristopherjones. It looks like you are on to something.

Since I was hoping this could just be part of the ongoing project and not a new one, I can probably add an additional build with the plugin config similar to what you have. I am unfortunately getting pulled in other directions at work right now, so I won’t be able to give it solid attention for what looks like a couple of weeks. I will update back when I get back to this aspect of the project.