qerub/camel-snake-kebab — pull request #11 by bbbates (2014-06-16 03:01:35+00:00)
Title: Add clojurescript support/build

I've been using this camel-snake-kebab for quite some time now, and recently had the need to use it for a clojurescript project I was working on. I was all set to fork it and create a standalone project (which I am still happy to do if need-be), but I thought it would be nice and convenient to have support for both Clj and Cljs in the one dependency. How hard could it be?
As it turns out, a bit harder than I initially had planned for.
I'll walk you through the changes I've had to do to get camel-snake-kebab to build for both clojure and clojurescript with (almost) the same codebase. There's quite a few, including a solution of sorts to Issue #6 (splitting the camel-snake-kebab ns).

`project.clj`
* I've upped the version of clojure required, as the clojurescript compiler requires a much more recent one than 1.4.0
* Using the [cljx](https://github.com/lynaghk/cljx) plugin. Both the .clj and .cljs files get generated from the same .cljx file.
* Use clojurescript.test for testing the clojurescript build (using the same tests, which is very neat)
* Add a "test-all" alias to build and run the tests for both the clj and cljs builds.

`camel-snake-kebab -> camel-snake-kebab.core + camel-snake-kebab.macros + camel-snake-kebab.case-convert`
The reason I had to split this into multiple namespaces stems from the fact that namespace interning is not supported in clojurescript. So, to generate the conversion functions I needed to create a macro (`gen-conversion-fns`), which meant I needed at least one extra namespace to move this into. The macro needed to reference the `case-convert` function, so I had to shift that a third namespace to avoid a circular dependency.

`camel-snake-kebab.case-convert`
Unfortunately, lookbehinds are not supported in javascript's regular expression interpreter, so therefore they can't be used in Cljs. This means I had to absolutely mangle the nice and elegant expression that was, to the monster in the changes below.
Certainly, using cljx we could use different functions for splitting strings for clj and cljs, which would mean the old way of splitting words could still be used for clj, but I wanted to try and minimise the differences between the two.