├── .github
└── issue_template.md
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build_docs.sh
├── code_of_conduct.md
├── doc
├── .gitignore
├── 01_00_getting_started.md
├── 01_01_list_of_contents.md
├── 01_02_invoking_chestnut.md
├── 02_00_recipes.md
├── 02_01_alternatives_to_om_dom.md
├── 02_02_testing.md
├── 03_00_developer_notes.md
├── FAQ.md
├── GLOSSARY.md
├── README.md
├── SUMMARY.md
├── book.json
├── img
│ └── hello_chestnut.png
└── testing.md
├── project.clj
├── repl
└── ancient.clj
├── resources
├── DSTRootCAX3.crt
├── chestnut.eps
├── chestnut.png
├── chestnut.svg
└── favicon.ico
└── src
├── chestnut
├── httpclient.clj
└── test
│ ├── integration.clj
│ └── scratch.clj
├── leiningen
└── new
│ ├── chestnut.clj
│ └── chestnut
│ ├── .dir-locals.el
│ ├── .gitignore
│ ├── .travis.yml
│ ├── LICENSE
│ ├── Procfile
│ ├── README.md
│ ├── code_of_conduct.md
│ ├── dev
│ ├── cljs
│ │ └── user.cljs
│ └── user.clj
│ ├── project.clj
│ ├── resources
│ ├── log4j.properties
│ └── public
│ │ ├── css
│ │ └── style.css
│ │ ├── favicon.ico
│ │ └── index.html
│ ├── src
│ ├── clj
│ │ └── chestnut
│ │ │ ├── application.clj
│ │ │ ├── components
│ │ │ ├── server_info.clj
│ │ │ └── shell_component.clj
│ │ │ ├── config.clj
│ │ │ ├── routes.clj
│ │ │ └── styles.clj
│ ├── cljc
│ │ └── chestnut
│ │ │ └── common.cljc
│ ├── cljs
│ │ └── chestnut
│ │ │ ├── components
│ │ │ └── ui.cljs
│ │ │ ├── core_om_next.cljs
│ │ │ ├── core_re_frame.cljs
│ │ │ ├── core_reagent.cljs
│ │ │ ├── core_rum.cljs
│ │ │ ├── core_vanilla.cljs
│ │ │ └── system.cljs
│ ├── less
│ │ └── style.less
│ └── scss
│ │ └── style.scss
│ ├── system.properties
│ └── test
│ ├── clj
│ └── chestnut
│ │ └── example_test.clj
│ ├── cljc
│ └── chestnut
│ │ └── common_test.cljc
│ └── cljs
│ └── chestnut
│ ├── core_test.cljs
│ └── test_runner.cljs
└── mistletoe
├── process.clj
└── test.clj
/.github/issue_template.md:
--------------------------------------------------------------------------------
1 |
7 |
8 | - [ ] I am reporting a bug or problem in Chestnut
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 | /classes
3 | /checkouts
4 | pom.xml
5 | pom.xml.asc
6 | *.jar
7 | *.class
8 | /.lein-*
9 | /.nrepl-port
10 | /.repl
11 | /out
12 | resources/public
13 | .swp
14 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## Changelog
2 |
3 | ### [0.19.0] (unreleased)
4 |
5 | - Bring back `+reagent` / `--reagent` for compatibility
6 |
7 | ### [0.18.0] - 2019-04-03
8 |
9 | - Update CIDER vars in dir-locals.el
10 | - Bump Piggieback for latest jvm support
11 |
12 | ### [0.17.0] - 2019-01-01
13 |
14 | - Drop Om, replace Reagent as the default UI library
15 | - Update critically breaking dependencies
16 | - Add javax xml bind dependency to fix Java 9+ compatability
17 | - Explicitly add dotfiles to project for lein compatability
18 | - Bump dependencies so project flags work out of the box
19 |
20 | ### [0.16.0] - 2018-05-06
21 |
22 | - Add `+edge` and `+bleeding-edge` options for automatically using the latest version of dependencies.
23 | - Upgrade ClojureScript, Om, Reagent, lein-cljsbuild, Figwheel
24 | - Fix middleware order so static files correctly have their media type set
25 | - Bring back logging to file, using [clj-logging-config](https://github.com/malcolmsparks/clj-logging-config)
26 | - Add a help screen (`+help` or when using any unrecognized options)
27 | - Set `goog.DEBUG` to `false` in the production ClojureScript build
28 | - Fix lein 1.8 compatability
29 | - Fix Procfile rendering
30 |
31 | ### [0.15.2] - 2017-07-30
32 |
33 | - Update more docs to refer to `(go)` and `(cljs-repl)` instead of `(run)` and `(browser-repl)`
34 | - Fix less and sass support
35 | - Fix `index.html` generation when project name contains an underscore
36 | - Upgrade several versions (ClojureScript, Ring, lein-cljsbuild, re-frame, piggieback, ring.middleware.logger)
37 |
38 | ### [0.15.1] - 2017-05-29
39 |
40 | - Make the pop-poll work by shelling out to curl
41 |
42 | ### [0.15.0] - 2017-05-29
43 |
44 | - Add Component support, both backend and frontend
45 | - Add a `+re-frame` flag, for [re-frame](https://github.com/Day8/re-frame) projects
46 | - remove `:repl-options {:init (go)}` from `project.clj`. You'll have to call `(go)` yourself after starting a REPL
47 | - clean up the SASS/LESS support. It's still a hack, but a slightly cleaner hack
48 | - Make `code_of_conduct.md` optional (`+coc` or `+code-of-conduct` flag to add it back)
49 | - Make `browser-repl` and `run` deprecated, in favor of `cljs-repl` and `go`
50 | - Collect usage statistics (version + command line flags). It is possible to opt-out with `+no-poll`.
51 | - Bump versions: clojurescript 1.9.562, transit-clj 0.8.300, ring 1.6.1, ring-defaults 0.3.0, compojure 1.6.0, figwheel 0.5.10, figwheel-sidecar 0.5.10, org.clojure/tools.nrepl 0.2.13, om 1.0.0-alpha48
52 |
53 | ### 0.15.0-SNAPSHOT
54 |
55 | - Options now use `+` as a prefix instead of `--`. This is more in line with
56 | other popular templates like Luminus, and it stops Leiningen from eating our
57 | options. The `--` variants still work.
58 | - Add Rum support. Use (`+rum`).
59 | - Add Om Next support. Use (`+om-next`).
60 | - Bump versions: clojurescript 1.9.293, transit-clj 0.8.297, ring 1.5.0, ring-defaults 0.2.1, compojure 1.5.1, environ 1.1.0, reagent 0.6.0, figwheel 0.5.8, http-kit 2.2.0, om 1.0.0-alpha47, doo 0.1.7, lein-cljsbuild 1.1.5, lein-environ 1.1.0
61 |
62 | ### [0.14.0] - 2016-06-23
63 |
64 | - Add cljc support
65 | - ClojureScript 1.9.89
66 | - Figwheel 0.5.4-4
67 |
68 | ### [0.13.0] - 2016-06-13
69 |
70 | - Clojurescript 1.9.36
71 | - Include Transit for faster ClojureScript compilation
72 | - Figwheel 0.5.4-2
73 | - Reagent 0.6.0-rc
74 | - Om 1.0.0-alpha36
75 | - Avoid using Leiningen profile merging for `:cljsbuild` configs
76 |
77 | ### [0.12.0] - 2016-05-24
78 |
79 | * Upgrades
80 | * org.omcljs/om 1.0.0-alpha31 => 1.0.0-alpha35
81 | * lein-auto 0.1.1 => 0.1.2
82 | * lein-less 1.7.3 => 1.7.5
83 | * org.clojure/clojurescript 1.8.40 => 1.8.51
84 | * environ 1.0.2 => 1.0.3
85 | * lein-cljsbuild 1.1.1 => 1.1.3
86 | * lein-environ 1.0.1 => 1.0.3
87 | * figwheel 0.5.2 => 0.5.3-2
88 | * Only add "dev" to the classpath in dev mode, fixes an issue with `lein jar`
89 |
90 | ### [0.11.0] - 2016-03-28
91 |
92 | * Upgrade ClojureScript 1.7.228 => 1.8.40
93 | * Upgrade Figwheel 0.5.1 => 0.5.2
94 |
95 | ### [0.10.1] - 2016-03-27
96 |
97 | * Fix missing dependency when using `--http-kit`
98 |
99 | ### 0.10.0 - 2016-03-24
100 |
101 | * Add switches for --reagent and --vanilla
102 | * Upgrade Figwheel to 0.5.1
103 | * Upgrade to Clojure 1.8.0, Om 1.1.0-alpha31, ring-defaults 0.2.0, compojure 1.5.0
104 |
105 | ### v0.9.1 - 2016-02-02
106 |
107 | * Upgrade Figwheel to 0.5.0-6
108 | * Upgrade Environ to 1.0.2
109 | * Upgrade internal dependencies to play better with Boot
110 |
111 | ### v0.9.0 - 2016-01-29
112 |
113 | * Use Figwheel for REPL and Ring server
114 | * Remove boilerplate that's no longer needed
115 | * Drop Enlive and simplify the dev setup
116 | * Drop CLJX support
117 | * Better inline documentation
118 | * Upgrade all dependencies
119 |
120 | ### v0.8.2-SNAPSHOT
121 | * Version upgrades: clojurescript: 1.7.145 => 1.7.189, om: 1.0.0-alpha15 => 1.0.0-alpha28, figwheel => 0.4.1, figwheel-sidecar 0.4.1 => 0.5.0-2, lein-figwheel 0.4.1 => 0.5.0-2
122 | * Version upgrades: clojurescript: 1.7.122 => 1.7.145, om: 0.9.0 => 1.0.0-alpha15, tools.nrepl => 0.2.12, figwheel => 0.4.1, figwheel-sidecar => 0.4.1, lein-figwheel => 0.4.1,environ => 1.0.1, lein-environ => 1.0.1
123 | * Fix allowing projects to have - in their names.
124 | * Fix allowing groupID/artifactID naming convention.
125 | * Fix "No such namespace" when using om via the REPL.
126 | * Fix specljs auto testing.
127 | * Added gzip compression using [ring.middleware.gzip](https://github.com/bertrandk/ring-gzip).
128 | * Added browser cache-control hinting using [ring.middleware.browser-caching](https://github.com/slester/browser-caching).
129 | * Version upgrades: clojure: 1.6.0 => 1.7.0, clojurescript: 0.0-3058 => 1.7.48, ring: 1.3.2 => 1.4.0, ring-defaults: 0.1.4 => 0.1.5, compojure: 1.3.2 => 1.4.0, om: 0.8.8 => 0.9.0, figwheel: 0.2.5 => 0.3.7, piggieback: 0.1.5 => 0.2.1, weasel: 0.6.0 => 0.7.0
130 |
131 | ### v0.8.1
132 |
133 | * Restore working lein repl for cljx projects ([Josh Daghlian](https://github.com/jcdcodes))
134 | * Use latest version of enlive to fix windows issue ([Justin Squirek](https://github.com/AdaDoom3))
135 |
136 | ### v0.8.0
137 |
138 | * Update Om: 0.8.0-rc1 => 0.8.8 ([Anna Pawlicka](https://github.com/annapawlicka))
139 | * Make Uberjar executable ([Børge Svingen](https://github.com/bsvingen))
140 | * Remove react.js injection in dev html ([Jamie English](https://github.com/english))
141 | * Fix how Less and Sassc are invoked ([Daryl Lau](https://github.com/dlau))
142 | * Fix in figwheel config ([Tim Gilbert](https://github.com/timgilbert)), ([Philip Joseph](https://github.com/lambdahands)), ([Antony Woods](https://github.com/acron0))
143 | * Fix in test setup ([Geoff Shannon](https://github.com/RadicalZephyr))
144 | * Doc fixes ([Anthony Rosequist](https://github.com/arosequist))
145 | * Version upgrades: clojurescript: 0.0-2511 => 0.0-3058 ; figwheel: 0.2.1-SNAPSHOT => 0.2.5 ; weasel: 0.4.2 => 0.6.0 and more
146 |
147 | ### v0.7.0 - 2015-03-06
148 |
149 | * Added Clojure{,script} unit testing support with Phantom JS.
150 | ([Rory Gibson](https://github.com/rorygibson))
151 | * Update om-tools: 0.3.9 => 0.3.10
152 | * Update ring-defaults: 0.1.2 => 0.1.3
153 | * Use figwheel-sidecar, drop the dependency on leiningen
154 | * renamed the per-env namespace from dev to main
155 | * give a proper error message when trying to invoke less in production
156 |
157 | ### v0.7.0-SNAPSHOT-20150103 - 2015-01-03
158 |
159 | * Validate command line arguments
160 | * Mention Chestnut version in the generated README
161 | * Fix om-tools support
162 | * SASSC support has been fixed, but is considered undocumented and unsupported
163 | * Update Om: 0.7.0 => 0.8.0-rc1
164 | * Add Code of Conduct to generated projects
165 | * Update CLJX: 0.4.0 => 0.5.0
166 | * Update Clojurescript: 0.0-2496 => 0.0-2644
167 | * Fixes for regressions: [#71](https://github.com/plexus/chestnut/pull/71)
168 |
169 | ### v0.7.0-SNAPSHOT-20141226 - 2014-12-26
170 |
171 | * Update Clojurescript: 0.0-2371 => 0.0-2496
172 | * Update Compojure: 1.2.0 => 1.3.1
173 | * Update Om: 0.7.0 => 0.8.0-beta3
174 | * Fixes for regressions: [#65](https://github.com/plexus/chestnut/pull/65) [#57](https://github.com/plexus/chestnut/pull/57)
175 |
176 | ### v0.7.0-SNAPSHOT-20141207 - 2014-12-07
177 |
178 | * Make weasel print both to the REPL and the browser console
179 | ([Marcus Lewis](https://github.com/mrcslws))
180 | * Add support for the LESS CSS pre-processor
181 | ([Denis Golovnev](https://github.com/teur))
182 | * Enable auto-reload of enlive templates in dev mode
183 | ([Ray H](https://github.com/rymndhng))
184 | * Add support for the SASS CSS pre-processor
185 | ([Edward Wible](https://github.com/aew))
186 | * Add suport for Speclj ([Edward Wible](https://github.com/aew))
187 | * Switch from the deprecated compojure.handler to ring-defaults
188 | [zakak](https://github.com/zakak))
189 | * Keep dev dependencies (Leiningen, Figwheel, Weasel, Speclj) out of
190 | the Uberjar
191 | * Automatically switch the browser-repl to the right namespace after
192 | starting up, instead of `cljs.user`
193 | * No longer include lein-ancient, easy enough to add for those that
194 | want it
195 | * Update Ring: 1.3.1 => 1.3.2
196 | * Update Figwheel: 0.1.4-SNAPSHOT => 0.1.6-SNAPSHOT
197 | * Update Weasel: 0.4.0-SNAPSHOT => 0.4.2
198 |
199 | ### v0.6.0 - 2014-10-29
200 |
201 | * Add optional support for CLJX
202 | ([Olli Piepponen](https://github.com/luxbock))
203 | * Support generation of projects named using the groupId/artifactId
204 | convention (e.g. com.example/foo)
205 | ([Steeve Beliveau](https://github.com/stebel))
206 |
207 | ### v0.5.0 - 2014-10-10
208 |
209 | * Run figwheel inside `(run)` so we only need one process
210 | * Configure figwheel's CSS reloading and load a placeholder
211 | `style.css`
212 | * Refresh Om when Figwheel reloads
213 | * Update ClojureScript: 0.0-2342 => 0.0-2371
214 | * Update Compojure: 1.1.9 => 1.2.0
215 | * Update Om: 0.7.1 => 0.7.3
216 | * No longer depend on Weasel in production mode
217 |
218 | ### v0.4.0 - 2014-09-27
219 |
220 | * Option to switch to HTTP Kit for a web server
221 | * Add reloading middleware
222 | * Add default compojure.handler.site middleware
223 |
224 | ### v0.3.0 - 2014-09-26
225 |
226 | * Switched to Weasel for Austin
227 | * Optimized uberjar
228 | * Fix usage of {{name}}/{{sanitized}}
229 | * Load react from the jar, instead of from Facebook's CDN
230 | * Update dependencies (Clojurescript, Ring, Compojure, Environ)
231 |
232 | ### v0.2.0 - 2014-09-21
233 |
234 | * Uberjar support
235 | * Heroku support (Procfile, system.properties)
236 | * added .gitignore
237 | * First version of development/production modes
238 |
239 | ### v0.1.0 - 2015-09-19
240 |
241 | * First release, containing Austin, Figwheel, Om
242 |
243 | [Unreleased]: https://github.com/plexus/chestnut/compare/v0.15.2...HEAD
244 | [0.15.2]: https://github.com/plexus/chestnut/compare/v0.15.1...v0.15.2
245 | [0.15.1]: https://github.com/plexus/chestnut/compare/v0.15.0...v0.15.1
246 | [0.15.0]: https://github.com/plexus/chestnut/compare/v0.14.0...v0.15.0
247 | [0.14.0]: https://github.com/plexus/chestnut/compare/v0.13.0...v0.14.0
248 | [0.13.0]: https://github.com/plexus/chestnut/compare/v0.12.0...v0.13.0
249 | [0.12.0]: https://github.com/plexus/chestnut/compare/v0.11.0...v0.12.0
250 | [0.11.0]: https://github.com/plexus/chestnut/compare/v0.10.1...v0.11.0
251 | [0.10.1]: https://github.com/plexus/chestnut/compare/v0.10.0...v0.10.1
252 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
4 |
5 | 1. DEFINITIONS
6 |
7 | "Contribution" means:
8 |
9 | a) in the case of the initial Contributor, the initial code and
10 | documentation distributed under this Agreement, and
11 |
12 | b) in the case of each subsequent Contributor:
13 |
14 | i) changes to the Program, and
15 |
16 | ii) additions to the Program;
17 |
18 | where such changes and/or additions to the Program originate from and are
19 | distributed by that particular Contributor. A Contribution 'originates' from
20 | a Contributor if it was added to the Program by such Contributor itself or
21 | anyone acting on such Contributor's behalf. Contributions do not include
22 | additions to the Program which: (i) are separate modules of software
23 | distributed in conjunction with the Program under their own license
24 | agreement, and (ii) are not derivative works of the Program.
25 |
26 | "Contributor" means any person or entity that distributes the Program.
27 |
28 | "Licensed Patents" mean patent claims licensable by a Contributor which are
29 | necessarily infringed by the use or sale of its Contribution alone or when
30 | combined with the Program.
31 |
32 | "Program" means the Contributions distributed in accordance with this
33 | Agreement.
34 |
35 | "Recipient" means anyone who receives the Program under this Agreement,
36 | including all Contributors.
37 |
38 | 2. GRANT OF RIGHTS
39 |
40 | a) Subject to the terms of this Agreement, each Contributor hereby grants
41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
42 | reproduce, prepare derivative works of, publicly display, publicly perform,
43 | distribute and sublicense the Contribution of such Contributor, if any, and
44 | such derivative works, in source code and object code form.
45 |
46 | b) Subject to the terms of this Agreement, each Contributor hereby grants
47 | Recipient a non-exclusive, worldwide, royalty-free patent license under
48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
49 | transfer the Contribution of such Contributor, if any, in source code and
50 | object code form. This patent license shall apply to the combination of the
51 | Contribution and the Program if, at the time the Contribution is added by the
52 | Contributor, such addition of the Contribution causes such combination to be
53 | covered by the Licensed Patents. The patent license shall not apply to any
54 | other combinations which include the Contribution. No hardware per se is
55 | licensed hereunder.
56 |
57 | c) Recipient understands that although each Contributor grants the licenses
58 | to its Contributions set forth herein, no assurances are provided by any
59 | Contributor that the Program does not infringe the patent or other
60 | intellectual property rights of any other entity. Each Contributor disclaims
61 | any liability to Recipient for claims brought by any other entity based on
62 | infringement of intellectual property rights or otherwise. As a condition to
63 | exercising the rights and licenses granted hereunder, each Recipient hereby
64 | assumes sole responsibility to secure any other intellectual property rights
65 | needed, if any. For example, if a third party patent license is required to
66 | allow Recipient to distribute the Program, it is Recipient's responsibility
67 | to acquire that license before distributing the Program.
68 |
69 | d) Each Contributor represents that to its knowledge it has sufficient
70 | copyright rights in its Contribution, if any, to grant the copyright license
71 | set forth in this Agreement.
72 |
73 | 3. REQUIREMENTS
74 |
75 | A Contributor may choose to distribute the Program in object code form under
76 | its own license agreement, provided that:
77 |
78 | a) it complies with the terms and conditions of this Agreement; and
79 |
80 | b) its license agreement:
81 |
82 | i) effectively disclaims on behalf of all Contributors all warranties and
83 | conditions, express and implied, including warranties or conditions of title
84 | and non-infringement, and implied warranties or conditions of merchantability
85 | and fitness for a particular purpose;
86 |
87 | ii) effectively excludes on behalf of all Contributors all liability for
88 | damages, including direct, indirect, special, incidental and consequential
89 | damages, such as lost profits;
90 |
91 | iii) states that any provisions which differ from this Agreement are offered
92 | by that Contributor alone and not by any other party; and
93 |
94 | iv) states that source code for the Program is available from such
95 | Contributor, and informs licensees how to obtain it in a reasonable manner on
96 | or through a medium customarily used for software exchange.
97 |
98 | When the Program is made available in source code form:
99 |
100 | a) it must be made available under this Agreement; and
101 |
102 | b) a copy of this Agreement must be included with each copy of the Program.
103 |
104 | Contributors may not remove or alter any copyright notices contained within
105 | the Program.
106 |
107 | Each Contributor must identify itself as the originator of its Contribution,
108 | if any, in a manner that reasonably allows subsequent Recipients to identify
109 | the originator of the Contribution.
110 |
111 | 4. COMMERCIAL DISTRIBUTION
112 |
113 | Commercial distributors of software may accept certain responsibilities with
114 | respect to end users, business partners and the like. While this license is
115 | intended to facilitate the commercial use of the Program, the Contributor who
116 | includes the Program in a commercial product offering should do so in a
117 | manner which does not create potential liability for other Contributors.
118 | Therefore, if a Contributor includes the Program in a commercial product
119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend
120 | and indemnify every other Contributor ("Indemnified Contributor") against any
121 | losses, damages and costs (collectively "Losses") arising from claims,
122 | lawsuits and other legal actions brought by a third party against the
123 | Indemnified Contributor to the extent caused by the acts or omissions of such
124 | Commercial Contributor in connection with its distribution of the Program in
125 | a commercial product offering. The obligations in this section do not apply
126 | to any claims or Losses relating to any actual or alleged intellectual
127 | property infringement. In order to qualify, an Indemnified Contributor must:
128 | a) promptly notify the Commercial Contributor in writing of such claim, and
129 | b) allow the Commercial Contributor tocontrol, and cooperate with the
130 | Commercial Contributor in, the defense and any related settlement
131 | negotiations. The Indemnified Contributor may participate in any such claim
132 | at its own expense.
133 |
134 | For example, a Contributor might include the Program in a commercial product
135 | offering, Product X. That Contributor is then a Commercial Contributor. If
136 | that Commercial Contributor then makes performance claims, or offers
137 | warranties related to Product X, those performance claims and warranties are
138 | such Commercial Contributor's responsibility alone. Under this section, the
139 | Commercial Contributor would have to defend claims against the other
140 | Contributors related to those performance claims and warranties, and if a
141 | court requires any other Contributor to pay any damages as a result, the
142 | Commercial Contributor must pay those damages.
143 |
144 | 5. NO WARRANTY
145 |
146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
151 | appropriateness of using and distributing the Program and assumes all risks
152 | associated with its exercise of rights under this Agreement , including but
153 | not limited to the risks and costs of program errors, compliance with
154 | applicable laws, damage to or loss of data, programs or equipment, and
155 | unavailability or interruption of operations.
156 |
157 | 6. DISCLAIMER OF LIABILITY
158 |
159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
166 | OF SUCH DAMAGES.
167 |
168 | 7. GENERAL
169 |
170 | If any provision of this Agreement is invalid or unenforceable under
171 | applicable law, it shall not affect the validity or enforceability of the
172 | remainder of the terms of this Agreement, and without further action by the
173 | parties hereto, such provision shall be reformed to the minimum extent
174 | necessary to make such provision valid and enforceable.
175 |
176 | If Recipient institutes patent litigation against any entity (including a
177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
178 | (excluding combinations of the Program with other software or hardware)
179 | infringes such Recipient's patent(s), then such Recipient's rights granted
180 | under Section 2(b) shall terminate as of the date such litigation is filed.
181 |
182 | All Recipient's rights under this Agreement shall terminate if it fails to
183 | comply with any of the material terms or conditions of this Agreement and
184 | does not cure such failure in a reasonable period of time after becoming
185 | aware of such noncompliance. If all Recipient's rights under this Agreement
186 | terminate, Recipient agrees to cease use and distribution of the Program as
187 | soon as reasonably practicable. However, Recipient's obligations under this
188 | Agreement and any licenses granted by Recipient relating to the Program shall
189 | continue and survive.
190 |
191 | Everyone is permitted to copy and distribute copies of this Agreement, but in
192 | order to avoid inconsistency the Agreement is copyrighted and may only be
193 | modified in the following manner. The Agreement Steward reserves the right to
194 | publish new versions (including revisions) of this Agreement from time to
195 | time. No one other than the Agreement Steward has the right to modify this
196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
197 | Eclipse Foundation may assign the responsibility to serve as the Agreement
198 | Steward to a suitable separate entity. Each new version of the Agreement will
199 | be given a distinguishing version number. The Program (including
200 | Contributions) may always be distributed subject to the version of the
201 | Agreement under which it was received. In addition, after a new version of
202 | the Agreement is published, Contributor may elect to distribute the Program
203 | (including its Contributions) under the new version. Except as expressly
204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
205 | licenses to the intellectual property of any Contributor under this
206 | Agreement, whether expressly, by implication, estoppel or otherwise. All
207 | rights in the Program not expressly granted under this Agreement are
208 | reserved.
209 |
210 | This Agreement is governed by the laws of the State of New York and the
211 | intellectual property laws of the United States of America. No party to this
212 | Agreement will bring a legal action under this Agreement more than one year
213 | after the cause of action arose. Each party waives its rights to a jury trial
214 | in any resulting litigation.
215 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # chestnut
2 |
3 | [](https://gitter.im/plexus/chestnut?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 | [](https://clojureverse.org/c/projects/chestnut)
5 |
6 | [](http://clojars.org/chestnut/lein-template)
7 |
8 |
9 |
10 |
11 | **Getting value out of Chestnut? Consider making [a small donation](https://patreon.com/plexus).**
12 |
13 | Chestnut is a Clojure/ClojureScript application template. It takes the pain out
14 | of getting a working ClojureScript setup with live reloading plus a browser
15 | connected REPL.
16 |
17 | It provides a solid default configuration for a REPL driven workflow, a
18 | ClojureScript setup with separate dev/prod/test builds, Figwheel integration,
19 | and a basic setup for running CLJ and CLJS unit tests. It provides a basic web
20 | backend setup with Compojure, and a frontend based on one of the React wrappers
21 | (your choice of Reagent, Rum, om-next, re-frame, or Vanilla JS). It works out of the
22 | box on popular cloud providers like Heroku.
23 |
24 | While Chestnut it's quite "complete" in a sense, it also tries to be minimal.
25 | Boilerplate code is kept to a minimum, and there is only just enough structure
26 | to get you started. How you build and structure your app from there is up to
27 | you.
28 |
29 | Chestnut should appeal to beginners because it allows you to get started quickly
30 | and with minimal baggage, it should appeal to more seasoned developers because
31 | it provides all the "obvious" configuration for a comfortable setup, without
32 | being so opinionated that it becomes a straight jacket.
33 |
34 | For deployment you get uberjar support, meaning you can get all your code
35 | compiled, optimized, and packaged in a single executable JAR file. It also
36 | contains the necessary artifacts to work on Heroku out of the box.
37 |
38 | **Need help?** Ask [on the mailing list](http://clojureverse.org/c/chestnut)
39 | (issues on GitHub are for bugs. Feature requests can be done either on the
40 | mailing list or on Github.)
41 |
42 | This README may describe unreleased features. Please compare the
43 | [version number on Clojars](https://clojars.org/chestnut/lein-template) to the
44 | [changelog below](https://github.com/plexus/chestnut/blob/master/README.md#changelog),
45 | and check the README in your generated project for instructions pertaining to
46 | your version.
47 |
48 | ## Usage
49 |
50 | **This README may describe unreleased features, instead you can check the [README for the latest stable release](https://github.com/plexus/chestnut/tree/v0.15.1/README.md)**
51 |
52 | ```
53 | lein new chestnut
54 |
55 | e.g.
56 |
57 | lein new chestnut my-app +garden +reagent +http-kit
58 | ```
59 |
60 | If you're using the snapshot version, then make sure to add a `--` to separate Leiningen's and Chestnut's arguments
61 |
62 | ```
63 | lein new chestnut my-app --snapshot -- +garden +reagent +http-kit
64 | ```
65 |
66 | You can get an overview of all recognized options with
67 |
68 | ```
69 | lein new chestnut +help
70 | ```
71 |
72 | After that open the README of your generated project for detailed instructions.
73 |
74 | ### Lighttable
75 |
76 | Lighttable provides a tighter integration for live coding with an inline
77 | browser-tab. Rather than evaluating cljs on the command line with weasel repl,
78 | evaluate code and preview pages inside Lighttable.
79 |
80 | Steps: After running `(go)`, open a browser tab in Lighttable. Open a cljs file
81 | from within a project, go to the end of an s-expression and hit Cmd-ENT.
82 | Lighttable will ask you which client to connect. Click 'Connect a client' and
83 | select 'Browser'. Browse to [http://localhost:10555](http://localhost:10555)
84 |
85 | View LT's console to see a Chrome js console.
86 |
87 | Hereafter, you can save a file and see changes or evaluate cljs code (without
88 | saving a file). Note that running a weasel server is not required to evaluate
89 | code in Lighttable.
90 |
91 | ### Emacs/Cider
92 |
93 | Start a repl in the context of your project with `M-x cider-jack-in`.
94 |
95 | After that it's the regular
96 |
97 | ```
98 | (go)
99 | (cljs-repl)
100 | ```
101 |
102 | as described above.
103 |
104 | ## List of Contents
105 |
106 | This template gives you everything you need to start developing
107 | Clojure/ClojureScript apps effectively. It comes with
108 |
109 | * [Figwheel](https://github.com/bhauman/lein-figwheel) Automatically reload your
110 | ClojureScript and CSS as soon as you save the file, no need for browser
111 | refresh.
112 | * A ClojureScript interface to Facebook's React. You can choose between
113 | Reagent (default), Om-next (`+om-next`), re-frame (`+re-frame`),
114 | Rum (`+rum`), or use `+vanilla` to do without a React wrapper.
115 | * [Ring](https://github.com/ring-clojure/ring) + Compojure. Clojure's de facto
116 | HTTP interface. Chestnut uses a Jetty or HttpKit server to serve the
117 | Clojurescript app. This way you already have an HTTP server running in case
118 | you want to add server-side functionality. Chestnut also inserts a Ring
119 | middleware to reload server-side Clojure files.
120 | * Heroku support. Chestnut apps have all the bits and pieces to be deployable to
121 | Heroku. Getting your app on the web is as simple as `git push`.
122 | * Unit tests for both Clojure and CLJS. Both specs and CLJS tests can be run in
123 | "auto" mode.
124 |
125 | ## Options
126 |
127 | General options:
128 |
129 | - `+help` Show an overview of all recognized options, then exit.
130 | - `+no-poll` Opt out of usage statistics poll.
131 | - `+http-kit` Use [HTTP Kit](http://http-kit.org/server.html) instead of Jetty.
132 | - `+bidi` Use [bidi](https://github.com/juxt/bidi) instead of Compojure.
133 | - `+site-middleware` Use the `ring.middleware.defaults.site-defaults` middleware (session, CSRF), instead of `ring.middleware.defaults.api-defaults` (see
134 | [ring.defaults documentation](https://github.com/ring-clojure/ring-defaults)).
135 | - `+code-of-conduct` / `+coc` Add the [contributor covenant](http://contributor-covenant.org/) Code of Conduct.
136 | - `+edge` Use the latest available version of all libraries/plugins. This includes alpha/beta versions, but does not include SNAPSHOT versions.
137 | - `+bleeding-edge` Like `+edge`, but also use SNAPSHOT versions when available.
138 |
139 | Choice of UI library:
140 |
141 | - `+vanilla` Don't include Reagent, use this if you intend to use some other view library.
142 | - `+om-next` Use om.next, instead of Reagent.
143 | - `+re-frame` Use Reagent and re-frame.
144 | - `+rum` Use Rum instead of Reagent.
145 |
146 | Choice of CSS style:
147 |
148 | - `+less` Use [less](https://github.com/montoux/lein-less) for compiling Less CSS files.
149 | - `+sass` Use SASS for generating CSS.
150 | - `+garden` Use Garden for generating CSS.
151 |
152 | ## Local copy
153 |
154 | If you want to customize Chestnut, or try unreleased features, you can
155 | run directly from master like this:
156 |
157 | ``` sh
158 | git clone https://github.com/plexus/chestnut.git
159 | cd chestnut
160 | lein install
161 | ```
162 |
163 | Note that master may be partially or wholly broken. I try to do
164 | extensive manual testing before releasing a new stable version, so if
165 | you don't like surprises then stick to the version on Clojars. Issue
166 | reports and pull requests are very welcome.
167 |
168 | ## Requirements
169 |
170 | * Java 1.7 or later
171 | * Leiningen 2
172 |
173 | ## FAQ
174 |
175 | * **Q:** How can I get the features in the SNAPSHOT version?
176 | **A:** Use leiningen's `--snapshot` flag, e.g. `lein new chestnut
177 | my-project --snapshot`
178 | * **Q:** I'm seeing warnings while compiling ClojureScript.
179 | **A:** There are a few known warnings, but they should not affect the
180 | functioning of your app.
181 | * **Q:** I changed the `{:text "Hello Chestnut!"}` portion and saved
182 | the file, but the changes don't show up.
183 | **A:** It's a feature. The `app-state` is defined with `defonce`, so your
184 | application state doesn't reset every time you save a file. If you do
185 | want to reset after every change, change `(defonce app-state ..)` to
186 | `(def app-state ...)`.
187 | * **Q:** I just want to compile ClojureScript to fully optimized JavaScript, so
188 | I can use it in a static HTML site.
189 | **A:** Compile the "min" ClojureScript build, like this: `lein cljsbuild once min`, then look
190 | for `resources/public/js/app.js`.
191 | * **Q:** I gave my project a very generic name like `cljs` or `clojure` and now
192 | it's not working.
193 | **A:** This is due to namespace clashes. Try picking
194 | a more unique name. In particular avoid namespace prefixes used by
195 | Clojure, Clojurescript, or existing libraries.
196 |
197 | ## Sources
198 |
199 | I used the
200 | [browser-connected-repl](https://github.com/cemerick/austin/tree/master/browser-connected-repl-sample)
201 | that's included with [Austin](https://github.com/cemerick/austin) as a
202 | starting point, then pulled in bits from
203 | [cljs-liveedit-webapp](https://github.com/ejlo/cljs-liveedit-webapp)
204 | until things worked. Figwheel's
205 | [Flappy Bird Demo app](https://github.com/bhauman/flappy-bird-demo)
206 | also provided some ideas. The concept of refreshing Om when Figwheel
207 | reloads was taken from
208 | [this blog post](http://blog.michielborkent.nl/blog/2014/09/25/figwheel-keep-Om-turning/)
209 | by [Michiel Borkent](https://github.com/borkdude).
210 |
211 | For Heroku support I looked at Heroku's
212 | [clojure-getting-started](https://github.com/heroku/clojure-getting-started)
213 | example app.
214 |
215 |
216 | ## Other Templates
217 |
218 | We hope Chestnut is great for you, but there are also many other templates that tackle
219 | similar tasks.. Each has a slightly different perspective, so it is worth taking a look
220 | at a few. Here is a [comparison chart](https://goo.gl/ZZH8fm) of many interesting
221 | Clojure/ClojureScript templates.
222 |
223 |
224 | ## License
225 |
226 | Copyright © 2014-2018 Arne Brasseur
227 |
228 | Distributed under the Eclipse Public License either version 1.0 or (at
229 | your option) any later version.
230 |
--------------------------------------------------------------------------------
/build_docs.sh:
--------------------------------------------------------------------------------
1 | early_exit() {
2 | echo "Your git repo isn't clean, refusing to continue"
3 | exit 1
4 | }
5 |
6 | git diff-index --quiet --cached HEAD && git diff-files --quiet || early_exit
7 |
8 | # npm -g install gitbook-cli && \
9 |
10 | cd doc/ && \
11 | echo "Building the book" && \
12 | gitbook build && \
13 | rm -rf /tmp/_book && \
14 | mv _book /tmp && \
15 | cd .. && \
16 | echo "Overwriting gh-pages" &&\
17 | git co gh-pages && \
18 | rm -rf * && \
19 | cp -r /tmp/_book/* . && \
20 | git add -A && \
21 | git commit -m 'update docs' && \
22 | echo "Pushing to Github" && \
23 | git push origin gh-pages:gh-pages && \
24 | git co -
25 |
--------------------------------------------------------------------------------
/code_of_conduct.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, we pledge to respect
4 | all people who contribute through reporting issues, posting feature
5 | requests, updating documentation, submitting pull requests or patches,
6 | and other activities.
7 |
8 | We are committed to making participation in this project a
9 | harassment-free experience for everyone, regardless of level of
10 | experience, gender, gender identity and expression, sexual
11 | orientation, disability, personal appearance, body size, race, age, or
12 | religion.
13 |
14 | Examples of unacceptable behavior by participants include the use of
15 | sexual language or imagery, derogatory comments or personal attacks,
16 | trolling, public or private harassment, insults, or other
17 | unprofessional conduct.
18 |
19 | Project maintainers have the right and responsibility to remove, edit,
20 | or reject comments, commits, code, wiki edits, issues, and other
21 | contributions that are not aligned to this Code of Conduct. Project
22 | maintainers who do not follow the Code of Conduct may be removed from
23 | the project team.
24 |
25 | Instances of abusive, harassing, or otherwise unacceptable behavior
26 | may be reported by opening an issue or contacting one or more of the
27 | project maintainers.
28 |
29 | This Code of Conduct is adapted from the
30 | [Contributor Covenant](http:contributor-covenant.org), version 1.0.0,
31 | available at
32 | [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
--------------------------------------------------------------------------------
/doc/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | _book
--------------------------------------------------------------------------------
/doc/01_00_getting_started.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | The only requirement for using Chestnut is that
4 | [Leiningen](http://leiningen.org/), version 2 or greater, is
5 | installed. Leiningen will take care of downloading Chestnut, Clojure,
6 | and other dependencies, so it's literally all you need.
7 |
8 | Leiningen and Clojure depend on Java, but chances are this will
9 | already be available on your system. You will need at least version
10 | 1.7. Oracle Java 1.8 is recommended.
11 |
12 | ## Creating the Application
13 |
14 | With Leiningen installed, open a terminal and type
15 |
16 | ``` sh
17 | lein new chestnut
18 | ```
19 |
20 | This will create a directory with the name of your project, containing
21 | an application skeleton that you can fill in. This directory also
22 | contains a file named `README.md`. It has instructions on how to get
23 | started that are specific to the version of Chestnut you are
24 | using. Make sure to look at it!
25 |
26 | ## Quickstart for the Impatient
27 |
28 | If you want to see your application running as soon as possible, try this.
29 |
30 | In a terminal, start the Clojure REPL.
31 |
32 | ``` sh
33 | lein repl
34 | ```
35 |
36 | Once you see the Clojure REPL prompt, `user=>`, type
37 |
38 | ```
39 | (run)
40 | (browser-repl)
41 | ```
42 |
43 | `(run)` will initiate the Clojurescript compilation, start a web
44 | server, and start the
45 | [Figwheel](https://github.com/bhauman/lein-figwheel) server to enable
46 | instant code reloading.
47 |
48 | `(browser-repl)` will change your Clojure REPL into a Clojurescript
49 | REPL. It needs a connection with a browser to be able to evaluate
50 | Clojurescript, so at this point it's waiting for a browser to connect
51 | to it.
52 |
53 | Once it seems everything has finished starting up and compiling, point
54 | your browser at [http://localhost:10555](http://localhost:10555). You
55 | should be seeing something like this:
56 |
57 | 
58 |
--------------------------------------------------------------------------------
/doc/01_01_list_of_contents.md:
--------------------------------------------------------------------------------
1 | # List of Contents
2 |
3 | Chestnut mostly combines the work of others to give you everything you
4 | need. It's good to have a basic idea of what each of these does.
5 |
6 | ## React
7 |
8 | [React](http://facebook.github.io/react/) is a library for building
9 | user interfaces. It was created by Facebook to help them develop their
10 | applications.
11 |
12 | Its distinguising features are reactive data flow, and a virtual
13 | DOM. This means your UI automatically updates when your data
14 | changes. The virtual DOM lets React very efficiently figure out the
15 | changes in the UI. In React you define components that each render a
16 | piece of data.
17 |
18 | ## Om
19 |
20 | [Om](https://github.com/swannodette/om) provides a ClojureScript
21 | interface to React. By relying on Clojurescripts's persistent data
22 | structures it can be even faster than plain react.
23 |
24 | There are a few other Clojurescript wrappers for React, each with
25 | their merits. But if you're using Chestnut, you get Om.
26 |
27 |
28 | ## Figwheel
29 |
30 | [Figwheel](https://github.com/bhauman/lein-figwheel) powers the
31 | instant reloading of Clojurescript and CSS. When the application loads
32 | in the browser, it will connect to the Figwheel server. Whenever you
33 | save a Clojurescript or CSS file, Figwheel will recompile it, and send
34 | it to the browser. No page refresh required!
35 |
36 | ## Weasel
37 |
38 | In Clojure and other Lisps it's common to make heavy use of a REPL
39 | (read-eval-print-loop, i.e. a command line interface) during
40 | development. Evaluating Clojurescript requires a Javascript
41 | environment, such as provided by your browser.
42 |
43 | Weasel gives you a REPL for Clojurescript. It will wait for a browser
44 | to load and connect, so that it can send code to the browser to be
45 | evaluated. This way you can interact live with your running application.
46 |
47 | ## Ring
48 |
49 | Many web applications also have a server-side component, even for just
50 | an API. The HTML page containing the Clojurescript app also needs to
51 | be served from somewhere. There are a number of HTTP servers available
52 | for this. Chestnut gives you the choice between Jetty and HTTP Kit.
53 |
54 | [Ring](https://github.com/ring-clojure/ring) provides a common
55 | interface for your app to communicate with a web server.
56 |
57 | Ring also makes it easy to set up middleware that does extra
58 | processing as part of a web request/response cycle. Chestnut sets up a
59 | Ring middleware that handles hot reloading of server-side code.
60 |
61 | ## Compojure
62 |
63 | [Compojure](http://weavejester.github.io/compojure/) is a "concise
64 | routing library for Ring". It lets you configure request handlers
65 | based on HTTP method and URL patterns.
66 |
67 | ## Enlive
68 |
69 | [Enlive](https://github.com/cgrand/enlive) a selector based HTML
70 | templating and transformation system. We use this to inject some
71 | development workflow related bits into `index.html`.
72 |
--------------------------------------------------------------------------------
/doc/01_02_invoking_chestnut.md:
--------------------------------------------------------------------------------
1 | # Invoking Chestnut
2 |
3 | Chestnut is a Leiningen template, you use it through the `lein new `
4 | command. When you tell `lein new` to use the
5 | Chestnut template, it will download the latest stable version
6 | [from Clojars](https://clojars.org/chestnut/lein-template), and then
7 | use that to generate the app.
8 |
9 | There are a number of command line flags you can pass in, some are
10 | handled by `lein new`, some are handled by Chestnut. You should
11 | separate them with `--` to not confuse Leiningen
12 |
13 | ``` sh
14 | lein new chestnut --
15 | ```
16 |
17 | You can invoke `lein help new` for more info on Leiningen's flags. The
18 | flags that Chestnut supports are listed below.
19 |
20 | ## Chestnut Flags
21 |
22 | ### `--http-kit`
23 |
24 | Use [HTTP Kit](http://http-kit.org/server.html) as HTTP server,
25 | instead of Jetty. If you're not sure why you would need this, then
26 | you're probably fine sticking to the default.
27 |
28 | ### `--site-middleware`
29 |
30 | We load some default Ring middleware to handle common concerns in web
31 | applications. It is assumed your app will mainly consist of an API and
32 | a Clojurescript client-side app, so only a minimal amount of
33 | middleware is loaded, notable handling of urlencoded parameters.
34 |
35 | If you plan to actually have a server side web app generating HTML
36 | pages, you will want to use `--site-middleware`, which will also set
37 | up middleware for sessions, cookies, xss protection, frame options
38 | headers, static resources, etc.
39 |
40 | ### `--less`
41 |
42 | Add support for the [less](https://github.com/montoux/lein-less) CSS preprocessor.
43 |
44 | ## SNAPSHOT
45 |
46 | New features in Chestnut are first released in a special version with
47 | a name ending in `-SNAPSHOT`. This signals to leiningen that this is a
48 | development release that's not intended for the general public.
49 |
50 | If you are already quite comfortable with Clojure and Clojurescript
51 | development, we recommend running the snapshot version and file any
52 | issues you run into, so we can make sure the next release of Chestnut
53 | will be solid and stable.
54 |
55 | To use the snapshot version, pass the `--snapshot` flag to Leiningen.
56 |
57 | ``` sh
58 | lein new chestnut --snapshot --
59 | ```
60 |
--------------------------------------------------------------------------------
/doc/02_00_recipes.md:
--------------------------------------------------------------------------------
1 | # Recipes
2 |
3 | Things to do after generating your Chestnut app.
4 |
5 | * [Alternatives to om.dom](02_01_alternatives_to_om_dom.md)
6 |
--------------------------------------------------------------------------------
/doc/02_01_alternatives_to_om_dom.md:
--------------------------------------------------------------------------------
1 | # Alternatives to om.dom
2 |
3 | There are a few libraries available that provide alternatives to om.dom.
4 |
5 | ## om-tools
6 |
7 | [Om-tools](https://github.com/Prismatic/om-tools) is a library by
8 | Prismatic to make writing Om components easier.
9 |
10 | First, in `project.clj`, add `om-tools` as a dependency
11 |
12 | ``` clojure
13 | :dependencies [;; ...
14 | [prismatic/om-tools "0.3.9" :exclusions [potemkin]]]
15 | ```
16 |
17 | In `core.cljs`, replace `[om.dom :as dom :include-macros true]` with
18 |
19 | ``` clojurescript
20 | [om-tools.dom :as dom :include-macros true]
21 | [om-tools.core :refer-macros [defcomponent]]
22 | ```
23 |
24 | If you still have a freshly generated Chestnut app, the only further change you need to do is remove the `nil` in `(dom/h1 nil (:text app))`.
25 |
26 | Compared to `om.dom`, `om-tools.dom` does three things different for a cleaner syntax.
27 |
28 | * element attributes can be omitted (that's why the `nil` is no longer necessary), and can be Clojurescript maps. So the `#js` reader macro is not needed
29 | * attribute names are more Clojure-esque "natural". `:className` instead of `:class`, `:onClick` instead of `:on-click`
30 | * children can be collections, so you don't need to use `apply` to when setting a collection as children of an element
31 |
32 | Have a look at the [om-tools.dom docs](https://github.com/Prismatic/om-tools#dom-tools) for more examples.
33 |
34 | ## Sablono
35 |
36 | [Sablono](https://github.com/r0man/sablono) provides Hiccup-style templating for Om.
37 |
38 | First, in `project.clj`, add `sablono` as a dependency
39 |
40 | ``` clojure
41 | :dependencies [;; ...
42 | [sablono "0.2.22"]]
43 | ```
44 |
45 | In `core.cljs`, replace `[om.dom :as dom :include-macros true]` with
46 |
47 | ``` clojurescript
48 | [sablono.core :as html :refer-macros [html]]
49 | ```
50 |
51 | This `h1` definition
52 |
53 | ``` clojurescript
54 | (dom/h1 nil (:text app))
55 | ```
56 |
57 | becomes
58 |
59 | ``` clojurescript
60 | (html [:h1 (:text app)])
61 | ```
62 |
--------------------------------------------------------------------------------
/doc/02_02_testing.md:
--------------------------------------------------------------------------------
1 | # Testing Your App
2 |
3 | By default, a new project created with Chestnut will have regular Clojure and ClojureScript unit tests enabled, the latter using lein-doo to run against various JS backends.
4 |
5 | ## Default ("deftest" style)
6 | ### Clojure unit tests
7 | The Clojure unit tests can be found under ```test/clj```.
8 | They're written using the [Clojure test API]([clojure.test](https://clojure.github.io/clojure/clojure.test-api.html)).
9 | There's an example (*example_test.clj*) ready to be modified as soon as you create the project.
10 |
11 | Run the tests by executing
12 |
13 | ```bash
14 | lein test
15 | ```
16 |
17 | ### ClojureScript tests
18 | Can be found under ```test/cljs```.
19 | Again, there's an example, in this case called *core.cljs*. Find out about the syntax by reading [the test framework source](https://github.com/clojure/clojurescript/blob/master/src/cljs/cljs/test.cljs)
20 |
21 | These tests are set up to run using [PhantomJS](http://phantomjs.org/), so make sure you have that installed and available on your path.
22 |
23 | Then execute
24 |
25 | ```bash
26 | lein doo phantom test once
27 | ```
28 |
29 | If you want to have auto-testing (where the tests automatically run when you make a change to an affected namespace) then use
30 |
31 | ```bash
32 | lein doo phantom test
33 | ```
34 |
--------------------------------------------------------------------------------
/doc/03_00_developer_notes.md:
--------------------------------------------------------------------------------
1 | # Developer notes
2 |
3 | ## Local copy
4 |
5 | If you want to customize Chestnut, or try unreleased features, you can run directly from master like this:
6 |
7 | ``` sh
8 | git clone https://github.com/plexus/chestnut.git
9 | cd chestnut
10 | lein install
11 | ```
12 |
13 | Note that master may be partially or wholly broken. I try to do
14 | extensive manual testing before releasing a new stable version, so if
15 | you don't like surprises then stick to the version on Clojars. Issue
16 | reports and pull requests are very welcome.
17 |
18 | ## Sources
19 |
20 | I used the
21 | [browser-connected-repl](https://github.com/cemerick/austin/tree/master/browser-connected-repl-sample)
22 | that's included with [Austin](https://github.com/cemerick/austin) as a
23 | starting point, then pulled in bits from
24 | [cljs-liveedit-webapp](https://github.com/ejlo/cljs-liveedit-webapp)
25 | until things worked. Figwheel's [Flappy Bird Demo app](https://github.com/bhauman/flappy-bird-demo) also provided some ideas. The concept of refreshing Om when Figwheel reloads was taken from [this blog post](http://blog.michielborkent.nl/blog/2014/09/25/figwheel-keep-Om-turning/) by [Michiel Borkent](https://github.com/borkdude).
26 |
27 | For Heroku support I looked at Heroku's
28 | [clojure-getting-started](https://github.com/heroku/clojure-getting-started)
29 | example app.
30 |
31 | ## License
32 |
33 | Copyright © 2014 Arne Brasseur
34 |
35 | Distributed under the Eclipse Public License either version 1.0 or (at
36 | your option) any later version.
37 |
--------------------------------------------------------------------------------
/doc/FAQ.md:
--------------------------------------------------------------------------------
1 | # FAQ
2 |
3 | * **Q:** How can I get the features in the SNAPSHOT version?
4 | **A:** Use leiningen's `--snapshot` flag, e.g. `lein new chestnut my-project --snapshot`
5 | * **Q:** I'm seeing warnings while compiling ClojureScript.
6 | **A:** There are a few known warnings, but they should not affect the functioning of your app.
7 | * **Q:** I changed the `{:text "Hello Chestnut!"}` portion and saved the file, but the changes don't show up.
8 | **A:** It's a feature. The `app-state` is defined with `defonce`, so your application state doesn't reset every time you save a file. If you do want to reset after every change, change `(defonce app-state ..)` to `(def app-state ...)`.
9 | * **Q:** I just want to compile ClojureScript to fully optimized JavaScript, so I can use it in a static HTML site.
10 | **A:** Invoke cljsbuild with the uberjar profile active, like this: `lein with-profile -dev,+uberjar cljsbuild once`, then look for `resources/public/js/app.js`.
11 | * **Q** I'm getting `CompilerException java.lang.IllegalAccessError: in-seconds does not exist` when using Spyscope 0.1.4 or earlier.
12 | **A** Upgrade to [Spyscope 0.1.5](https://github.com/dgrnbrg/spyscope/issues/15), this issue is caused by an outdated dependency on cljs-time.
13 | * **Q** I upgraded the version of Om in project.clj, but it seems I'm still using the old version, what's up?
14 | **A** If you already did a build before, cljsbuild/figwheel won't pick up on the updated version automatically. Do a `lein cljsbuild clean`, then start Figwheel again.
15 |
--------------------------------------------------------------------------------
/doc/GLOSSARY.md:
--------------------------------------------------------------------------------
1 | # virtual DOM
2 | Similar to the DOM your browser manages, but consisting of simple
3 | Javascript objects. This is what React.js uses so it doesn't have to
4 | touch the real DOM unless necessary.
5 |
--------------------------------------------------------------------------------
/doc/README.md:
--------------------------------------------------------------------------------
1 | # Chestnut
2 |
3 | ***The Fast Track to Clojurescript***
4 |
5 | Chestnut is an application template for a Clojure/Clojurescript web
6 | app. It's beginner friendly and comes with batteries included. With
7 | Chestnut you can be developing in minutes, skipping a lot of tedious
8 | setup.
9 |
10 | ## Features
11 |
12 | ### Smooth Development
13 |
14 | * Instantly reload code and styling, for a short feedback cycle
15 | * Browser-connected REPL, inspect and interact with your app running
16 | in the browser
17 |
18 | ### Solid Choices Across the Stack
19 |
20 | * Reagent, build data driven, component based UIs
21 | * Ring, Compojure, get server side routing and request handling
22 |
23 | ### Easy Deployment
24 |
25 | * Uberjar support, build and package your whole app with dependencies
26 | in a single jar file
27 | * Heroku support, from coding to published on the web in seconds
28 |
29 | Keep reading to find out
30 | [how to get started](01_00_getting_started.md) with Chestnut.
31 |
--------------------------------------------------------------------------------
/doc/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | * [Getting Started](01_00_getting_started.md)
4 | * [List of Contents](01_01_list_of_contents.md)
5 | * [Invoking Chestnut](01_02_invoking_chestnut.md)
6 | * [Recipes](02_00_recipes.md)
7 | * [Alternatives to om.dom](02_01_alternatives_to_om_dom.md)
8 | * [Testing Your App](02_02_testing.md)
9 | * [Developer Notes](03_00_developer_notes.md)
10 | * [Testing Chestnut](testing.md)
11 | * [FAQ](FAQ.md)
12 | * [Changelog](CHANGELOG.md)
13 |
--------------------------------------------------------------------------------
/doc/book.json:
--------------------------------------------------------------------------------
1 | {
2 | "plugins": ["ga", "anchors"],
3 | "pluginsConfig": {
4 | "ga": {
5 | "token": "UA-16178122-5"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/doc/img/hello_chestnut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plexus/chestnut/684b668141586ed5ef4389f94a4dc7f4fde13112/doc/img/hello_chestnut.png
--------------------------------------------------------------------------------
/doc/testing.md:
--------------------------------------------------------------------------------
1 | # Testing Chestnut
2 |
3 | (This page is about testing Chestnut itself, *not* about how to do testing in your Chestnut app. For that see [Testing Your App](02_02_testing.md))
4 |
5 | Because of the nature of Chestnut, testing it requires an interplay between terminal, repl, and browser. This is hard to automate, but we're trying anyway :) There are some basic tests available, but the test suite is not comprehensive.
6 |
7 | For process control the tests depend on unreleased features of [jnr-process](https://github.com/jnr/jnr-process), which in turn relies on unreleased code in [jnr-posix](https://github.com/jnr/jnr-posix). So clone those two repos and for each do `mvn install`. I *think* that's the only dependencies you need to set up. Leiningen will figure out the rest.
8 |
9 | To run the tests do `lein test`. This will start with executing `cd /tmp ; lein new chestnut --snapshot`, possibly with some options. So to run the tests against your local version, you have to first do a `lein install`. Also make sure that if the tests are using `--snapshot`
10 | , that the version you're installing ends with `-SNAPSHOT`.
11 |
12 | For WebDriver, the tests are currently set up to use Chrome, and to look for the chromedriver executable in `~/bin/chromedriver`. This might not be suitable for your system. Check the [clj-webdriver](https://github.com/semperos/clj-webdriver) docs and make sure it's able to open a browser. See `src/chestnut/test/integration.clj` to twiddle with this. You can try this in a REPL to see if a browser pops up:
13 |
14 | ``` clojure
15 | (System/setProperty "webdriver.chrome.driver" (str (System/getenv "HOME") "/bin/chromedriver"))
16 | (use 'clj-webdriver.taxi)
17 | (set-driver! {:browser :chrome} "https://github.com/plexus/chestnut")
18 | ```
19 |
20 | Running these test *takes time*. There's a lot of JVM booting and shutting down, and it seems as the consecutive tests run this process actually becomes even slower. Because of this you might run into the problem where the test tries to boot a REPL, but this times out. To work around that you can add this to `src/leiningen/new/chestnut/project.clj`, after which you do a new `lein install`
21 |
22 | ``` clojure
23 | :repl-options {:timeout 200000} ;; Defaults to 30000 (30 seconds)
24 | ```
25 |
26 | ## Basic Test
27 |
28 | This is implemented now as an automated test, it will be executed for each of the feature flags.
29 |
30 | * generate an app
31 | * lein repl
32 | * (run)
33 | * (browser-repl)
34 | * load the page, you should see "Hello, Chestnut"
35 | * check the browser connected repl (e.g. `@app-state`)
36 | * change some clojurescript (e.g. `s/h1/h2/`), watch the browser update
37 | * change some CSS, watch it reload
38 | * change something in index.html, watch it reload
39 |
40 | ## Production / Heroku test
41 |
42 | This needs to be done for each of the feature flags.
43 |
44 | * generate an app
45 | * build an uberjar
46 | * run with foreman, verify it works
47 | * push to heroku, verify it works
48 |
49 | ## Feature tests
50 |
51 | These are features, some hidden behind feature flags, that should be verified manually
52 |
53 | * Clojure and Clojurescript unit test support
54 | * LESS
55 |
--------------------------------------------------------------------------------
/project.clj:
--------------------------------------------------------------------------------
1 | (defproject chestnut/lein-template "0.19.0-SNAPSHOT"
2 | :description "A Leiningen template for a minimal but complete Clojure/ClojureScript setup."
3 | :url "https://github.com/plexus/chestnut"
4 | :jar-inclusions [#"leiningen/new/chestnut/\.gitignore"
5 | #"leiningen/new/chestnut/\.dir-locals\.el"]
6 | :license {:name "Eclipse Public License"
7 | :url "http://www.eclipse.org/legal/epl-v10.html"}
8 |
9 | :eval-in-leiningen true
10 |
11 | :dependencies [[com.github.plexus/clj-jgit "v0.8.9-preview"]
12 | [org.slf4j/slf4j-nop "1.7.25"]
13 | [org.apache.httpcomponents/httpclient "4.5.3"]
14 | ;;[re-frame/lein-template "0.2.7-1"]
15 | [com.github.plexus/re-frame-template "v0.2.7-1-indent-fix"]
16 | [ancient-clj "0.6.15"]
17 | [clj-http "3.9.1"]]
18 |
19 |
20 | :profiles {:test {:dependencies [[org.clojure/core.async "0.3.443"]
21 | [com.github.jnr/jnr-process "1.0-SNAPSHOT"]
22 | [clj-webdriver "0.7.2"]]}}
23 |
24 | :aliases {"test" ["with-profile" "+test" "run" "-m" "chestnut.test.integration"] }
25 |
26 | :repositories [["jitpack" "https://jitpack.io"]])
27 |
--------------------------------------------------------------------------------
/repl/ancient.clj:
--------------------------------------------------------------------------------
1 | (ns repl.ancient
2 | (:require [ancient-clj.core :as ancient]
3 | [leiningen.new.chestnut :as chestnut]))
4 |
5 | (comment
6 | ancient/default-repositories
7 |
8 | (ancient/latest-version-string! 'ancient-clj))
9 |
10 | (defn update-dep [dep]
11 | (assoc dep 1 (ancient/latest-version-string! dep {:snapshots? false})))
12 |
13 | (let [deps (map update-dep chestnut/default-project-deps)
14 | plugins (map update-dep chestnut/default-project-plugins)
15 | dev-deps (map update-dep chestnut/project-clj-dev-deps)
16 | dev-plugins (map update-dep chestnut/project-clj-dev-plugins)
17 | optional-deps (reduce #(update %1 %2 update-dep)
18 | chestnut/optional-project-deps
19 | (keys chestnut/optional-project-deps))]
20 |
21 | (print
22 | (str "(def default-project-deps '["
23 | (chestnut/indent-next 28 (map pr-str deps))
24 | "])"
25 | "\n\n"
26 | "(def optional-project-deps '{"
27 | (chestnut/indent-next 29 (sort (map #(str (pr-str (first %)) " " (pr-str (second %))) optional-deps)))
28 | "})"
29 | "\n\n"
30 | "(def default-project-plugins '["
31 | (chestnut/indent-next 31 (map pr-str plugins))
32 | "])"
33 | "\n\n"
34 | "(def project-clj-dev-deps '["
35 | (chestnut/indent-next 28 (map pr-str dev-deps))
36 | "])"
37 | "\n\n"
38 | "(def project-clj-dev-plugins '["
39 | (chestnut/indent-next 31 (map pr-str dev-plugins))
40 | "])")))
41 |
--------------------------------------------------------------------------------
/resources/DSTRootCAX3.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
3 | MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
4 | DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
5 | PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
6 | Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
7 | AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
8 | rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
9 | OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
10 | xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
11 | 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
12 | aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
13 | HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
14 | SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
15 | ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
16 | AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
17 | R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
18 | JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
19 | Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/resources/chestnut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plexus/chestnut/684b668141586ed5ef4389f94a4dc7f4fde13112/resources/chestnut.png
--------------------------------------------------------------------------------
/resources/chestnut.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
95 |
--------------------------------------------------------------------------------
/resources/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plexus/chestnut/684b668141586ed5ef4389f94a4dc7f4fde13112/resources/favicon.ico
--------------------------------------------------------------------------------
/src/chestnut/httpclient.clj:
--------------------------------------------------------------------------------
1 | (ns chestnut.httpclient
2 | (:require [clojure.java.io :as io]
3 | [clojure.java.shell :as sh]
4 | [clojure.string :as str])
5 | (:import java.lang.System
6 | [java.nio.file Files OpenOption Paths]
7 | java.security.cert.CertificateFactory
8 | java.security.KeyStore
9 | [javax.net.ssl SSLContext TrustManagerFactory]))
10 |
11 | ;; Not actually working :(
12 | #_
13 | (defn letsencrypt-ssl-context
14 | "Java before 8u101 does not recognize Let's Encrypt, so we do a bit of Java
15 | dancing to load the certificate manually.
16 |
17 | https://stackoverflow.com/a/34111150/1891448"
18 | []
19 | (let [key-store (KeyStore/getInstance (KeyStore/getDefaultType))
20 | key-store-path (Paths/get (System/getProperty "java.home") (into-array String ["lib" "security" "cacerts"]))
21 | cert-factory (CertificateFactory/getInstance "X.509")
22 | cert-file (io/input-stream (io/resource "DSTRootCAX3.crt"))
23 | certificate (.generateCertificate cert-factory cert-file)
24 | trust-manager (TrustManagerFactory/getInstance (TrustManagerFactory/getDefaultAlgorithm))
25 | ssl-context (SSLContext/getInstance "TLS")]
26 | (.load key-store (Files/newInputStream key-store-path (into-array OpenOption ())) (.toCharArray "changeit"))
27 | (.setCertificateEntry key-store "DSTRootCAX3" certificate)
28 | (.init trust-manager key-store)
29 | (.init ssl-context nil (.getTrustManagers trust-manager) nil)
30 | ssl-context
31 | #_(SSLContext/setDefault ssl-context)))
32 |
33 | ;; borrowed from ring
34 | (defn- double-escape [^String x]
35 | (.replace (.replace x "\\" "\\\\") "$" "\\$"))
36 |
37 | (defn percent-encode
38 | "Percent-encode every character in the given string using either the specified
39 | encoding, or UTF-8 by default."
40 | [^String unencoded & [^String encoding]]
41 | (->> (.getBytes unencoded (or encoding "UTF-8"))
42 | (map (partial format "%%%02X"))
43 | (str/join)))
44 |
45 | (defn url-encode
46 | "Returns the url-encoded version of the given string, using either a specified
47 | encoding or UTF-8 by default."
48 | [unencoded & [encoding]]
49 | (str/replace
50 | unencoded
51 | #"[^A-Za-z0-9_~.+-]+"
52 | #(double-escape (percent-encode % encoding))))
53 | ;;/borrowed from ring
54 |
55 | #_(defn http-post!
56 | "A very limited wrapper for doing a POST request, submits parameters in the
57 | URL, rather than the body."
58 | [url params]
59 | (let [param-str (str/join "&" (map
60 | (fn [[k v]]
61 | (str (url-encode (name k)) "=" (url-encode v)))
62 | params))
63 | client (.. (HttpClients/custom)
64 | (setSSLContext (letsencrypt-ssl-context))
65 | build)
66 | post (HttpPost. (str url "?" param-str))]
67 | (.execute client post)))
68 |
69 | (defn http-post!
70 | "A very limited wrapper for doing a POST request, submits parameters in the
71 | URL, rather than the body."
72 | [url params]
73 | (let [param-str (str/join "&" (map
74 | (fn [[k v]]
75 | (str (url-encode (name k)) "=" (url-encode v)))
76 | params))
77 | url (str url "?" param-str)]
78 | (sh/sh "curl" "-X" "POST" url)))
79 |
--------------------------------------------------------------------------------
/src/chestnut/test/integration.clj:
--------------------------------------------------------------------------------
1 | (ns chestnut.test.integration
2 | (:require [clojure.java.io :as io]
3 | [mistletoe.process :refer :all]
4 | [mistletoe.test :refer :all]
5 | [clj-webdriver.taxi :as browser]
6 | [clojure.string :as s]
7 | [leiningen.new.chestnut :as chestnut]
8 | [clojure.java.shell :refer [sh]]))
9 |
10 |
11 | (def browser-type :chrome)
12 |
13 | ;; The path to the driver executable must be set by the
14 | ;; webdriver.chrome.driver system property; for more information, see
15 | ;; http://code.google.com/p/selenium/wiki/ChromeDriver. The latest
16 | ;; version can be downloaded from
17 | ;; http://chromedriver.storage.googleapis.com/index.html
18 | (System/setProperty "webdriver.chrome.driver"
19 | (str (System/getenv "HOME") "/bin/chromedriver"))
20 |
21 | (defn rm-rf [fname]
22 | (if (= fname "/")
23 | (throw (Exception. "Refusing to 'rm -rf /'")))
24 | (let [func (fn [func f]
25 | (when (.isDirectory f)
26 | (doseq [f2 (.listFiles f)]
27 | (func func f2)))
28 | (when (.exists f)
29 | (io/delete-file f)))]
30 | (func func (io/file fname))))
31 |
32 | (defn spawn [name dir cmd]
33 | (chdir dir)
34 | (-> (apply process (s/split cmd #" "))
35 | (start)
36 | (start-pipe :in)
37 | (start-pipe :err)
38 | (log-chan (str name " | "))
39 | (log-chan (str name " (err) | ") :errChan)))
40 |
41 | (defmacro with-process
42 | "Make sure we don't leave subprocess around when an exception bubbles out"
43 | [[bind-var & spawn-args] & forms]
44 | `(let [~bind-var (spawn ~@spawn-args)]
45 | (try
46 | ~@forms
47 | (finally
48 | (println "--> killing" (.getPid (:process ~bind-var)))
49 | (kill ~bind-var)
50 | (println "--> waiting for" (.getPid (:process ~bind-var)))
51 | (wait-for ~bind-var)
52 | (println "--> done!" (.getPid (:process ~bind-var)))))))
53 |
54 | (defmacro with-browser
55 | "Make sure we close the browser when an exception bubbles out"
56 | [address & forms]
57 | `(try
58 | (browser/set-driver! {:browser browser-type} ~address)
59 | ~@forms
60 | (finally
61 | (when browser/*driver*
62 | (browser/close)))))
63 |
64 | (defn generate-new-app [& [flags]]
65 | (println "--> Generating app in /tmp/sesame-seed using" flags)
66 | (rm-rf "/tmp/sesame-seed")
67 | (wait-for (spawn "LEIN NEW" "/tmp"
68 | (str "lein new chestnut sesame-seed --snapshot -- " flags))))
69 |
70 | (defn first-element-text [selector]
71 | (if-let [element (first (browser/css-finder selector))]
72 | (browser/text element)))
73 |
74 | (defn test-basic [& [flags]]
75 | (generate-new-app flags)
76 | (println "--> Starting REPL")
77 |
78 | (binding [*expect-guard-for* #{#"(?i)error" #"Exception"}]
79 | (with-process [repl "REPL" "/tmp/sesame-seed" "lein repl"]
80 | (expect repl #"sesame-seed\.server=>" 250)
81 | (write-str repl "(run)\n")
82 | (expect repl #"notifying browser that file changed" 120)
83 | (write-str repl "(browser-repl)\n")
84 | (expect repl #"sesame-seed\.core=>" 120)
85 |
86 | (with-browser "http://localhost:10555"
87 | (browser/wait-until #(= (first-element-text "h1") "Hello Chestnut!"))
88 | (write-str repl "(swap! app-state assoc :text \"Hello Test :)\")\n")
89 | (browser/wait-until #(= (first-element-text "h1") "Hello Test :)"))
90 | (sh "sed" "s/h1/h2/" "-i" "/tmp/sesame-seed/src/cljs/sesame_seed/core.cljs")
91 | (browser/wait-until #(= (first-element-text "h2") "Hello Test :)")))
92 |
93 | (write-str repl "(quit)\n")
94 | (expect repl #"Bye for now!"))))
95 |
96 | (defn -main []
97 | (test-basic)
98 | (test-basic "--http-kit")
99 | (test-basic "--site-middleware")
100 |
101 | (test-basic "--less")
102 | (test-basic "--less --om-tools --site-middleware --http-kit")
103 |
104 | (comment
105 | ;; SASS is officially unsupported and requires a SASSC binary
106 | (test-basic "--sass")))
107 |
--------------------------------------------------------------------------------
/src/chestnut/test/scratch.clj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | (comment
5 | (ns chestnut.test.integration
6 | (:refer-clojure :exclude [assert])
7 | (:import [java.lang AssertionError]
8 | [java.io InputStream OutputStream Writer Reader]
9 | [java.nio.channels Channels Selector SelectionKey]
10 | [java.nio ByteBuffer CharBuffer]
11 | [expect4j Expect4j]
12 | [jnr.posix POSIXFactory POSIX])
13 | (:require [clojure.java.io :as io]
14 | [clojure.string :as string]
15 | [expect4clj :refer [glob-match eof-match regex-match expect]]))
16 | (def pids (atom []))
17 |
18 | (defmacro assert [bool]
19 | `(when (not ~bool)
20 | (throw (AssertionError. (str "Assertion failed: " ~bool)))))
21 |
22 | (defn process-builder [& args]
23 | (ProcessBuilder. args))
24 |
25 | (defn expect4j [process-map]
26 | (Expect4j. (:out process-map) (:in process-map)))
27 |
28 | (defn set-dir! [process dir]
29 | (.directory process (io/file dir)))
30 |
31 | (defn make-process-map [process]
32 | {:process process
33 | :out (.getInputStream process)
34 | :err (.getErrorStream process)
35 | :in (.getOutputStream process)
36 | :writer (io/writer (.getOutputStream process))})
37 |
38 | (defn start-process [pb]
39 | (let [process (.start pb)
40 | pmap (make-process-map process)]
41 | (swap! pids conj pmap)
42 | pmap))
43 |
44 | (defn rm-rf [fname]
45 | (let [func (fn [func f]
46 | (when (.isDirectory f)
47 | (doseq [f2 (.listFiles f)]
48 | (func func f2)))
49 | (io/delete-file f))]
50 | (func func (io/file fname))))
51 |
52 | (defn start-lein-new []
53 | (rm-rf "/tmp/sesame-seed")
54 | (-> (process-builder "lein" "new" "chestnut" "sesame-seed" "--snapshot")
55 | (set-dir! "/tmp")
56 | (start-process)
57 | ((juxt (comp slurp :out) (comp slurp :err)))))
58 |
59 | (defn start-repl []
60 | (-> (process-builder "lein" "repl")
61 | (set-dir! "/tmp/sesame-seed")
62 | (start-process)))
63 |
64 | (defn do-repl-run [repl]
65 | (expect (expect4j repl)
66 | (regex-match "^.*$" [e]
67 | (println (str "> " (.getMatch e))))
68 | (regex-match "app\\.js" [e]
69 | (println "go app.js!")
70 | (.write (:writer repl) "\u0004"))))
71 |
72 | (defn generate-app []
73 | (let [[out err] (start-lein-new)]
74 | (assert (= "Generating fresh Chestnut project.\nREADME.md contains instructions to get you started.\n" out))
75 | (assert (= "" err))))
76 |
77 |
78 |
79 | #_(run-tests 'chestnut.test.integration)
80 |
81 | (comment
82 | (-> process-map
83 | (expect4j)
84 | (expect
85 | (regex-match "README" [state]
86 | (println "found README!"))))
87 |
88 | (defn prefix-writer [writer prefix]
89 | (proxy [Writer] []
90 | (write [bs]
91 | (doseq [line (clojure.string/split (str bs) #"\n")]
92 | (.write writer prefix)
93 | (.write writer line)
94 | (.write writer "\n")))
95 | (flush [] (.flush writer))))
96 |
97 | (defn inspect-input-stream [stream]
98 | (proxy [InputStream] []
99 | (read
100 | ([bytes]
101 | (print ".")
102 | (let [res (.read stream bytes)]
103 | (println (String. bytes))
104 | res))
105 | ([bytes off len]
106 | (print ".")
107 | (let [res (.read stream bytes)]
108 | (println (String. bytes off len))
109 | res))))))
110 |
111 | (defn posix-spawn [args env pwd]
112 | "Use jnr-posix to launch a subprocess
113 |
114 | @example
115 | (posix-spawn [\"ruby\" \"-e\" \"puts 'foo'\"] [\"RUBYOPT=-w\"] \"/tmp\")"
116 | (-> (POSIXFactory/getPOSIX)
117 | (.newProcessMaker (into-array String args))
118 | (.environment (into-array String args))
119 | (.directory (io/file pwd))
120 | (.start)))
121 |
122 |
123 | (def repl (-> (posix-spawn ["lein" "repl"] [] "/tmp/sesame-seed")
124 | (make-process-map)))
125 |
126 | ;; (def repl (start-repl))
127 | (def in-chan (Channels/newChannel (:out repl)))
128 | (def in-buf (ByteBuffer/allocate 2048))
129 |
130 | (def selector (Selector/open))
131 |
132 | (def out-chan (Channels/newChannel (:in repl)))
133 | (def out-buf (ByteBuffer/allocate 2048))
134 |
135 | (let [buf (java.nio.ByteBuffer/allocate 2048)]
136 | (defn read-next [chan]
137 | (.clear buf)
138 | (.read chan buf)
139 | (String. (into-array Character/TYPE (take (.position buf) (.array buf))))))
140 |
141 | (let [buf (java.nio.ByteBuffer/allocate 2048)]
142 | (defn write-next [chan exp]
143 | (.clear buf)
144 | (.put buf (into-array Byte/TYPE (str exp)))
145 | (.flip buf)
146 | (.write chan buf)))
147 |
148 | (def repl-process
149 | (-> (jnr.process.ProcessBuilder. (into-array ["lein" "repl"]))
150 | (.directory "/tmp/sesame-seed")
151 | (.start)))
152 |
153 | (.configureBlocking (.getIn repl-process) false)
154 | (.configureBlocking (.getErr repl-process) false)
155 |
156 | (def selector (.openSelector (jnr.enxio.channels.NativeSelectorProvider/getInstance)))
157 | (def selection-key (.register (.getIn repl-process) selector java.nio.channels.SelectionKey/OP_READ))
158 | (def selection-key (.register (.getErr repl-process) selector java.nio.channels.SelectionKey/OP_READ))
159 |
160 | (.selectNow selector)
161 |
162 | (read-next (.channel (first (.selectedKeys selector))))
163 | (write-next (.getOut repl-process) "(+ 1 1)\n")
164 |
165 | (expect #"2")
166 |
167 | (defn expect [regex]
168 | ))
169 |
170 |
171 |
172 | (def repl-process
173 | (-> (process "lein" "repl")
174 | (directory "/tmp/sesame-seed")
175 | (start)))
176 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut.clj:
--------------------------------------------------------------------------------
1 | (ns leiningen.new.chestnut
2 | (:require [chestnut.httpclient :as http]
3 | [clj-jgit.porcelain :refer :all]
4 | [clojure.java.io :as io]
5 | [clojure.string :as str]
6 | [leiningen.core.main :as main]
7 | [leiningen.new.templates :refer [->files name-to-path project-name
8 | render-text renderer sanitize-ns slurp-resource]]
9 | [ancient-clj.core :as ancient])
10 | (:import java.io.Writer))
11 |
12 | (def default-project-deps '[[org.clojure/clojure "1.10.0"]
13 | [org.clojure/clojurescript "1.10.439" :scope "provided"]
14 | [com.cognitect/transit-clj "0.8.313"]
15 | [ring "1.7.1"]
16 | [ring/ring-defaults "0.3.2"]
17 | [bk/ring-gzip "0.3.0"]
18 | [radicalzephyr/ring.middleware.logger "0.6.0"]
19 | [clj-logging-config "1.9.12"]
20 | [environ "1.1.0"]
21 | [com.stuartsierra/component "0.3.2"]
22 | [org.danielsz/system "0.4.1"]
23 | [org.clojure/tools.namespace "0.2.11"]])
24 |
25 | (def optional-project-deps '{:garden [lambdaisland/garden-watcher "0.3.3"]
26 | :http-kit [http-kit "2.3.0"]
27 | :compojure [compojure "1.6.1"]
28 | :bidi [bidi "2.1.5"]
29 | :lein-auto [lein-auto "0.1.3"]
30 | :lein-less [lein-less "1.7.5"]
31 | :lein-sassc [lein-sassc "0.10.5"]
32 | :om-next [org.omcljs/om "1.0.0-beta4"]
33 | :re-frame [re-frame "0.10.6"]
34 | :reagent [reagent "0.8.1"]
35 | :rum [rum "0.11.3"]})
36 |
37 | (def default-project-plugins '[[lein-cljsbuild "1.1.7"]
38 | [lein-environ "1.1.0"]])
39 |
40 | (def project-clj-dev-deps '[[figwheel "0.5.18"]
41 | [figwheel-sidecar "0.5.18"]
42 | [cider/piggieback "0.4.0"]
43 | [cider/cider-nrepl "0.18.0"]
44 | [lein-doo "0.1.11"]
45 | [reloaded.repl "0.2.4"]])
46 |
47 | (def project-clj-dev-plugins '[[lein-figwheel "0.5.18"]
48 | [lein-doo "0.1.11"]])
49 |
50 | ;; When using `pr`, output quoted forms as 'foo, and not as (quote foo)
51 | (defmethod clojure.core/print-method clojure.lang.ISeq [o ^Writer w]
52 | (#'clojure.core/print-meta o w)
53 | (if (= (first o) 'quote)
54 | (do
55 | (.write w "'")
56 | (print-method (second o) w))
57 | (#'clojure.core/print-sequential "(" #'clojure.core/pr-on " " ")" o w)))
58 |
59 | (def render (renderer "chestnut"))
60 |
61 | (defn wrap-indent [wrap n list]
62 | (fn []
63 | (->> list
64 | (map #(str "\n" (apply str (repeat n " ")) (wrap %)))
65 | (str/join ""))))
66 |
67 | (defn dep-list [n list]
68 | (wrap-indent #(str "[" % "]") n list))
69 |
70 | (defn indent [n list]
71 | (wrap-indent identity n list))
72 |
73 | (defn indent-next [n list]
74 | (str (first list)
75 | ((indent n (next list)))))
76 |
77 | (def options-descriptions
78 | {"help" "Show this help information and exit."
79 | "http-kit" "Use the http-kit web server, instead of Jetty."
80 | "bidi" "Use bidi for server side routing library instead of compojure."
81 | "site-middleware" "Use Ring's site-middleware, instead of the api-middleware. (session support)"
82 | "less" "Use the LESS CSS pre-processor."
83 | "sass" "Use the SASS CSS pre-processor."
84 | "vanilla" "Don't use a UI library (vanilla Javascript)"
85 | "garden" "Use Garden for writing CSS in Clojure"
86 | "rum" "Use Rum as UI library"
87 | "om-next" "Use om-next as UI library"
88 | "reagent" "Use Reagent as UI library. (default)"
89 | "re-frame" "Use re-frame as UI framework"
90 | "code-of-conduct" "Add a Code of Conduct to the project (Contributor Covenant)"
91 | "coc" "Add a Code of Conduct to the project (Contributor Covenant)"
92 | "no-poll" "Don't submit usage information"
93 | "edge" "Automatically upgrade all libraries to the latest non-SNAPSHOT version."
94 | "bleeding-edge" "Automatically upgrade all libraries to the latest non versions, inclusing SNAPSHOT releases."})
95 |
96 | (def all-options
97 | ["http-kit"
98 | "bidi"
99 | "site-middleware"
100 | "less"
101 | "sass"
102 | "garden"
103 | "reagent"
104 | "re-frame"
105 | "rum"
106 | "om-next"
107 | "vanilla"
108 | "code-of-conduct"
109 | "coc"
110 | "edge"
111 | "bleeding-edge"
112 | "no-poll"
113 | "help"])
114 |
115 | (doseq [opt all-options]
116 | (eval
117 | `(defn ~(symbol (str opt "?")) [opts#]
118 | (some #{~(str "--" opt) ~(str "+" opt)} opts#))))
119 |
120 | (defn compojure? [opts]
121 | (not (bidi? opts)))
122 |
123 | (defn reagent? [opts]
124 | (and (not (rum? opts))
125 | (not (vanilla? opts))
126 | (not (om-next? opts))
127 | (not (re-frame? opts))))
128 |
129 | (defn some-edge? [opts]
130 | (or (edge? opts) (bleeding-edge? opts)))
131 |
132 | (defn server-clj-requires [opts]
133 | (if (http-kit? opts)
134 | ["system.components.http-kit :refer [new-web-server]"]
135 | ["system.components.jetty :refer [new-web-server]"]))
136 |
137 | (defn user-clj-requires [name opts]
138 | (cond-> []
139 | (or (sass? opts) (less? opts))
140 | (conj [(symbol (str (sanitize-ns name) ".components.shell-component :refer [shell-component]"))])
141 |
142 | (garden? opts)
143 | (conj '[garden-watcher.core :refer [new-garden-watcher]])))
144 |
145 | (defn update-dep [dep opts]
146 | (cond-> dep
147 | (some-edge? opts)
148 | (assoc 1 (ancient/latest-version-string! dep {:snapshots? (bleeding-edge? opts)}))))
149 |
150 | (defn update-deps [deps opts]
151 | (map #(update-dep % opts) deps))
152 |
153 | (defn project-clj-deps [opts]
154 | (update-deps
155 | (cond-> default-project-deps
156 | (http-kit? opts) (conj (get optional-project-deps :http-kit))
157 | (compojure? opts) (conj (get optional-project-deps :compojure))
158 | (bidi? opts) (conj (get optional-project-deps :bidi))
159 | (reagent? opts) (conj (get optional-project-deps :reagent))
160 | (om-next? opts) (conj (get optional-project-deps :om-next))
161 | (rum? opts) (conj (get optional-project-deps :rum))
162 | (re-frame? opts) (conj (get optional-project-deps :re-frame))
163 | (garden? opts) (conj (get optional-project-deps :garden)))
164 | opts))
165 |
166 | (defn project-plugins [opts]
167 | (update-deps
168 | (cond-> default-project-plugins
169 | (sass? opts) (conj (get optional-project-deps :lein-sassc)
170 | (get optional-project-deps :lein-auto))
171 | (less? opts) (conj (get optional-project-deps :lein-less)))
172 | opts))
173 |
174 | (defn project-prep-tasks [name opts]
175 | (cond-> ["compile" ["cljsbuild" "once" "min"]]
176 | (garden? opts) (conj ["run" "-m" "garden-watcher.main" (str (sanitize-ns name) ".styles")])))
177 |
178 | (defn project-uberjar-hooks [opts]
179 | (cond-> []
180 | (less? opts) (conj "leiningen.less")
181 | (sass? opts) (conj "leiningen.sassc")))
182 |
183 | (defn extra-dev-components [name opts]
184 | (cond-> []
185 | (garden? opts)
186 | (into [:garden-watcher (list 'new-garden-watcher [(list 'quote (symbol (str (sanitize-ns name) ".styles")))])])
187 |
188 | (less? opts)
189 | (into [:less (list 'shell-component "lein" "less" "auto")])
190 |
191 | (sass? opts)
192 | (into [:sass (list 'shell-component "lein" "auto" "sassc" "once")])))
193 |
194 | (defn load-props [file-name]
195 | (with-open [^java.io.Reader reader (clojure.java.io/reader file-name)]
196 | (let [props (java.util.Properties.)]
197 | (.load props reader)
198 | (into {} (for [[k v] props] [(keyword k) v])))))
199 |
200 | (defn chestnut-version []
201 | (let [resource (io/resource "META-INF/maven/chestnut/lein-template/pom.properties")
202 | props (load-props resource)
203 | version (:version props)
204 | revision (:revision props)
205 | snapshot? (re-find #"SNAPSHOT" version)]
206 | (str version " (" (str/join (take 8 revision)) ")")))
207 |
208 | (defn template-data [name opts]
209 | {:full-name name
210 | :name (project-name name)
211 | :chestnut-version (chestnut-version)
212 | :project-ns (sanitize-ns name)
213 | :ns-name (sanitize-ns name) ;; used by re-frame template
214 | :sanitized (name-to-path name)
215 |
216 | :user-clj-requires (indent 12 (map pr-str (user-clj-requires name opts)))
217 | :server-clj-requires (dep-list 12 (server-clj-requires opts))
218 |
219 | :project-clj-deps (indent-next 17 (map pr-str (project-clj-deps opts)))
220 | :project-plugins (indent-next 12 (map pr-str (project-plugins opts)))
221 | :project-clj-dev-deps (indent-next 29 (map pr-str (update-deps project-clj-dev-deps opts)))
222 | :project-clj-dev-plugins (indent-next 24 (map pr-str (update-deps project-clj-dev-plugins opts)))
223 | :project-prep-tasks (indent-next 27 (map pr-str (project-prep-tasks name opts)))
224 | :project-uberjar-hooks (str/join " " (project-uberjar-hooks opts))
225 |
226 | :server-command (if (http-kit? opts) "run-server" "run-jetty")
227 | :ring-defaults (if (site-middleware? opts) "site-defaults" "api-defaults")
228 |
229 | ;; TODO: get rid of these, instead use something like :project-clj-extras
230 | :less? (less? opts)
231 | :sass? (sass? opts)
232 |
233 | :compojure? (compojure? opts)
234 | :bidi? (bidi? opts)
235 |
236 | :extra-dev-components (indent 4 (->> (extra-dev-components name opts)
237 | (map pr-str)
238 | (partition 2)
239 | (map #(str/join " " %))))})
240 |
241 | (defn files-to-render [opts]
242 | (cond-> ["project.clj"
243 | "resources/public/index.html"
244 | "resources/public/favicon.ico"
245 | "resources/log4j.properties"
246 | "src/clj/chestnut/application.clj"
247 | "src/clj/chestnut/routes.clj"
248 | "src/clj/chestnut/config.clj"
249 | "src/clj/chestnut/components/server_info.clj"
250 | "src/cljc/chestnut/common.cljc"
251 | "src/cljs/chestnut/system.cljs"
252 | "src/cljs/chestnut/components/ui.cljs"
253 | "dev/user.clj"
254 | "dev/cljs/user.cljs"
255 | "LICENSE"
256 | "README.md"
257 | "Procfile"
258 | ".gitignore"
259 | "system.properties"
260 | ".dir-locals.el"
261 | "test/clj/chestnut/example_test.clj"
262 | "test/cljs/chestnut/core_test.cljs"
263 | "test/cljs/chestnut/test_runner.cljs"
264 | "test/cljc/chestnut/common_test.cljc"]
265 | (or (coc? opts) (code-of-conduct? opts)) (conj "code_of_conduct.md")
266 | (less? opts) (conj "src/less/style.less")
267 | (sass? opts) (conj "src/scss/style.scss")
268 | (or (less? opts) (sass? opts)) (conj "src/clj/chestnut/components/shell_component.clj")
269 | (garden? opts) (conj "src/clj/chestnut/styles.clj")
270 | (not (or (less? opts) (sass? opts))) (conj "resources/public/css/style.css")))
271 |
272 | (defn format-files-args
273 | "Returns a list of pairs (vectors). The first element is the file name to
274 | render, the second is the file contents."
275 | [{:keys [name] :as data} opts]
276 | (letfn [(render-file [file]
277 | [(str/replace file "chestnut" "{{sanitized}}")
278 | (render file data)])]
279 | (conj
280 | (map render-file (files-to-render opts))
281 | ["src/cljs/{{sanitized}}/core.cljs"
282 | (render (cond
283 | (reagent? opts) "src/cljs/chestnut/core_reagent.cljs"
284 | (om-next? opts) "src/cljs/chestnut/core_om_next.cljs"
285 | (rum? opts) "src/cljs/chestnut/core_rum.cljs"
286 | (vanilla? opts) "src/cljs/chestnut/core_vanilla.cljs"
287 | (re-frame? opts) "src/cljs/chestnut/core_re_frame.cljs")
288 | data)])))
289 |
290 | (defn re-frame-render
291 | [resource-path data]
292 | (-> (str "leiningen/new/re_frame/" resource-path)
293 | io/resource
294 | slurp-resource
295 | (render-text data)))
296 |
297 | (defn re-frame-files [data]
298 | (for [f ["config" "db" "subs" "events" "views"]]
299 | [(str "src/cljs/{{sanitized}}/" f ".cljs")
300 | (re-frame-render (str "src/cljs/" f ".cljs") data)]))
301 |
302 | (defn do-pop-poll [version flags]
303 | (try
304 | (http/http-post! "https://lambdaisland.com/chestnut-poll" {:version version, :flags (str/join " " flags)})
305 | (catch Throwable e)))
306 |
307 | (defn print-help! []
308 | (main/info "Chestnut: friendly Clojure/ClojureScript application template")
309 | (main/info "")
310 | (main/info "Usage: lein new chestnut ")
311 | (main/info " e.g.: lein new chestnut dating-for-hamsters +http-kit +re-frame +code-of-conduct")
312 | (main/info "")
313 | (doseq [opt all-options]
314 | (main/info (format " +%-20s %s" opt (options-descriptions opt))))
315 | (main/info "")
316 | (main/info "Please consult the Chestnut README (https://github.com/plexus/chestnut) as well as the README in the generated project."))
317 |
318 | (defn chestnut [name & opts]
319 | (when (some #{"+help" "--help"} (cons name opts))
320 | (print-help!)
321 | (System/exit 0))
322 |
323 | (let [dash-opts (map (partial str "--") all-options)
324 | plus-opts (map (partial str "+") all-options)]
325 | (doseq [opt opts]
326 | (when (not (some #{opt} (concat dash-opts plus-opts)))
327 | (print-help!)
328 | (apply main/abort "Unrecognized option:" opt ". Should be one of" plus-opts))))
329 |
330 | (main/info "Generating fresh Chestnut project.")
331 | (main/info "README.md contains instructions to get you started.")
332 |
333 | (let [data (template-data name opts)
334 | files (cond-> (format-files-args data opts)
335 | (re-frame? opts) (concat (re-frame-files data)))]
336 | (apply ->files data files))
337 |
338 | (when-not (no-poll? opts)
339 | (do-pop-poll (chestnut-version) (map #(str/replace % #"^[-\+]+" "") opts)))
340 |
341 | (git-init name)
342 | (let [repo (load-repo name)]
343 | (git-add repo ".")
344 | (git-commit repo (str "lein new chestnut " name " " (str/join " " opts)))))
345 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/.dir-locals.el:
--------------------------------------------------------------------------------
1 | ((nil . ((cider-ns-refresh-before-fn . "reloaded.repl/suspend")
2 | (cider-ns-refresh-after-fn . "reloaded.repl/resume")
3 | (cider-cljs-lein-repl . "(do (user/go) (user/cljs-repl))"))))
4 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.jar
3 | /.lein-*
4 | /.nrepl-port
5 | /.repl
6 | /checkouts/
7 | /classes/
8 | /lib/
9 | /log/
10 | /out/
11 | /resources/public/js/compiled/**
12 | /target/
13 | figwheel_server.log
14 | pom.xml
15 | pom.xml.asc
16 | /dev-target
17 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/.travis.yml:
--------------------------------------------------------------------------------
1 | language: clojure
2 | lein: lein2
3 | script: lein2 test && lein2 doo phantom test once
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/LICENSE:
--------------------------------------------------------------------------------
1 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
2 | LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
3 | CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
4 |
5 | 1. DEFINITIONS
6 |
7 | "Contribution" means:
8 |
9 | a) in the case of the initial Contributor, the initial code and
10 | documentation distributed under this Agreement, and
11 |
12 | b) in the case of each subsequent Contributor:
13 |
14 | i) changes to the Program, and
15 |
16 | ii) additions to the Program;
17 |
18 | where such changes and/or additions to the Program originate from and are
19 | distributed by that particular Contributor. A Contribution 'originates' from
20 | a Contributor if it was added to the Program by such Contributor itself or
21 | anyone acting on such Contributor's behalf. Contributions do not include
22 | additions to the Program which: (i) are separate modules of software
23 | distributed in conjunction with the Program under their own license
24 | agreement, and (ii) are not derivative works of the Program.
25 |
26 | "Contributor" means any person or entity that distributes the Program.
27 |
28 | "Licensed Patents" mean patent claims licensable by a Contributor which are
29 | necessarily infringed by the use or sale of its Contribution alone or when
30 | combined with the Program.
31 |
32 | "Program" means the Contributions distributed in accordance with this
33 | Agreement.
34 |
35 | "Recipient" means anyone who receives the Program under this Agreement,
36 | including all Contributors.
37 |
38 | 2. GRANT OF RIGHTS
39 |
40 | a) Subject to the terms of this Agreement, each Contributor hereby grants
41 | Recipient a non-exclusive, worldwide, royalty-free copyright license to
42 | reproduce, prepare derivative works of, publicly display, publicly perform,
43 | distribute and sublicense the Contribution of such Contributor, if any, and
44 | such derivative works, in source code and object code form.
45 |
46 | b) Subject to the terms of this Agreement, each Contributor hereby grants
47 | Recipient a non-exclusive, worldwide, royalty-free patent license under
48 | Licensed Patents to make, use, sell, offer to sell, import and otherwise
49 | transfer the Contribution of such Contributor, if any, in source code and
50 | object code form. This patent license shall apply to the combination of the
51 | Contribution and the Program if, at the time the Contribution is added by the
52 | Contributor, such addition of the Contribution causes such combination to be
53 | covered by the Licensed Patents. The patent license shall not apply to any
54 | other combinations which include the Contribution. No hardware per se is
55 | licensed hereunder.
56 |
57 | c) Recipient understands that although each Contributor grants the licenses
58 | to its Contributions set forth herein, no assurances are provided by any
59 | Contributor that the Program does not infringe the patent or other
60 | intellectual property rights of any other entity. Each Contributor disclaims
61 | any liability to Recipient for claims brought by any other entity based on
62 | infringement of intellectual property rights or otherwise. As a condition to
63 | exercising the rights and licenses granted hereunder, each Recipient hereby
64 | assumes sole responsibility to secure any other intellectual property rights
65 | needed, if any. For example, if a third party patent license is required to
66 | allow Recipient to distribute the Program, it is Recipient's responsibility
67 | to acquire that license before distributing the Program.
68 |
69 | d) Each Contributor represents that to its knowledge it has sufficient
70 | copyright rights in its Contribution, if any, to grant the copyright license
71 | set forth in this Agreement.
72 |
73 | 3. REQUIREMENTS
74 |
75 | A Contributor may choose to distribute the Program in object code form under
76 | its own license agreement, provided that:
77 |
78 | a) it complies with the terms and conditions of this Agreement; and
79 |
80 | b) its license agreement:
81 |
82 | i) effectively disclaims on behalf of all Contributors all warranties and
83 | conditions, express and implied, including warranties or conditions of title
84 | and non-infringement, and implied warranties or conditions of merchantability
85 | and fitness for a particular purpose;
86 |
87 | ii) effectively excludes on behalf of all Contributors all liability for
88 | damages, including direct, indirect, special, incidental and consequential
89 | damages, such as lost profits;
90 |
91 | iii) states that any provisions which differ from this Agreement are offered
92 | by that Contributor alone and not by any other party; and
93 |
94 | iv) states that source code for the Program is available from such
95 | Contributor, and informs licensees how to obtain it in a reasonable manner on
96 | or through a medium customarily used for software exchange.
97 |
98 | When the Program is made available in source code form:
99 |
100 | a) it must be made available under this Agreement; and
101 |
102 | b) a copy of this Agreement must be included with each copy of the Program.
103 |
104 | Contributors may not remove or alter any copyright notices contained within
105 | the Program.
106 |
107 | Each Contributor must identify itself as the originator of its Contribution,
108 | if any, in a manner that reasonably allows subsequent Recipients to identify
109 | the originator of the Contribution.
110 |
111 | 4. COMMERCIAL DISTRIBUTION
112 |
113 | Commercial distributors of software may accept certain responsibilities with
114 | respect to end users, business partners and the like. While this license is
115 | intended to facilitate the commercial use of the Program, the Contributor who
116 | includes the Program in a commercial product offering should do so in a
117 | manner which does not create potential liability for other Contributors.
118 | Therefore, if a Contributor includes the Program in a commercial product
119 | offering, such Contributor ("Commercial Contributor") hereby agrees to defend
120 | and indemnify every other Contributor ("Indemnified Contributor") against any
121 | losses, damages and costs (collectively "Losses") arising from claims,
122 | lawsuits and other legal actions brought by a third party against the
123 | Indemnified Contributor to the extent caused by the acts or omissions of such
124 | Commercial Contributor in connection with its distribution of the Program in
125 | a commercial product offering. The obligations in this section do not apply
126 | to any claims or Losses relating to any actual or alleged intellectual
127 | property infringement. In order to qualify, an Indemnified Contributor must:
128 | a) promptly notify the Commercial Contributor in writing of such claim, and
129 | b) allow the Commercial Contributor tocontrol, and cooperate with the
130 | Commercial Contributor in, the defense and any related settlement
131 | negotiations. The Indemnified Contributor may participate in any such claim
132 | at its own expense.
133 |
134 | For example, a Contributor might include the Program in a commercial product
135 | offering, Product X. That Contributor is then a Commercial Contributor. If
136 | that Commercial Contributor then makes performance claims, or offers
137 | warranties related to Product X, those performance claims and warranties are
138 | such Commercial Contributor's responsibility alone. Under this section, the
139 | Commercial Contributor would have to defend claims against the other
140 | Contributors related to those performance claims and warranties, and if a
141 | court requires any other Contributor to pay any damages as a result, the
142 | Commercial Contributor must pay those damages.
143 |
144 | 5. NO WARRANTY
145 |
146 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON
147 | AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER
148 | EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR
149 | CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A
150 | PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the
151 | appropriateness of using and distributing the Program and assumes all risks
152 | associated with its exercise of rights under this Agreement , including but
153 | not limited to the risks and costs of program errors, compliance with
154 | applicable laws, damage to or loss of data, programs or equipment, and
155 | unavailability or interruption of operations.
156 |
157 | 6. DISCLAIMER OF LIABILITY
158 |
159 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
160 | CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
161 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
162 | LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
163 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
164 | ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
165 | EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
166 | OF SUCH DAMAGES.
167 |
168 | 7. GENERAL
169 |
170 | If any provision of this Agreement is invalid or unenforceable under
171 | applicable law, it shall not affect the validity or enforceability of the
172 | remainder of the terms of this Agreement, and without further action by the
173 | parties hereto, such provision shall be reformed to the minimum extent
174 | necessary to make such provision valid and enforceable.
175 |
176 | If Recipient institutes patent litigation against any entity (including a
177 | cross-claim or counterclaim in a lawsuit) alleging that the Program itself
178 | (excluding combinations of the Program with other software or hardware)
179 | infringes such Recipient's patent(s), then such Recipient's rights granted
180 | under Section 2(b) shall terminate as of the date such litigation is filed.
181 |
182 | All Recipient's rights under this Agreement shall terminate if it fails to
183 | comply with any of the material terms or conditions of this Agreement and
184 | does not cure such failure in a reasonable period of time after becoming
185 | aware of such noncompliance. If all Recipient's rights under this Agreement
186 | terminate, Recipient agrees to cease use and distribution of the Program as
187 | soon as reasonably practicable. However, Recipient's obligations under this
188 | Agreement and any licenses granted by Recipient relating to the Program shall
189 | continue and survive.
190 |
191 | Everyone is permitted to copy and distribute copies of this Agreement, but in
192 | order to avoid inconsistency the Agreement is copyrighted and may only be
193 | modified in the following manner. The Agreement Steward reserves the right to
194 | publish new versions (including revisions) of this Agreement from time to
195 | time. No one other than the Agreement Steward has the right to modify this
196 | Agreement. The Eclipse Foundation is the initial Agreement Steward. The
197 | Eclipse Foundation may assign the responsibility to serve as the Agreement
198 | Steward to a suitable separate entity. Each new version of the Agreement will
199 | be given a distinguishing version number. The Program (including
200 | Contributions) may always be distributed subject to the version of the
201 | Agreement under which it was received. In addition, after a new version of
202 | the Agreement is published, Contributor may elect to distribute the Program
203 | (including its Contributions) under the new version. Except as expressly
204 | stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
205 | licenses to the intellectual property of any Contributor under this
206 | Agreement, whether expressly, by implication, estoppel or otherwise. All
207 | rights in the Program not expressly granted under this Agreement are
208 | reserved.
209 |
210 | This Agreement is governed by the laws of the State of New York and the
211 | intellectual property laws of the United States of America. No party to this
212 | Agreement will bring a legal action under this Agreement more than one year
213 | after the cause of action arose. Each party waives its rights to a jury trial
214 | in any resulting litigation.
215 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/Procfile:
--------------------------------------------------------------------------------
1 | web: java $JVM_OPTS -cp target/{{name}}.jar clojure.main -m {{project-ns}}.application
2 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/README.md:
--------------------------------------------------------------------------------
1 | # {{name}}
2 |
3 |
4 | ## Development
5 |
6 | Open a terminal and type `lein repl` to start a Clojure REPL
7 | (interactive prompt).
8 |
9 | In the REPL, type
10 |
11 | ```clojure
12 | (go)
13 | (cljs-repl)
14 | ```
15 |
16 | The call to `(go)` starts the Figwheel server at port 3449, which takes care of
17 | live reloading ClojureScript code and CSS, and the app server at port 10555
18 | which forwards requests to the http-handler you define.
19 |
20 | Running `(cljs-repl)` starts the Figwheel ClojureScript REPL. Evaluating
21 | expressions here will only work once you've loaded the page, so the browser can
22 | connect to Figwheel.
23 |
24 | When you see the line `Successfully compiled "resources/public/app.js" in 21.36
25 | seconds.`, you're ready to go. Browse to `http://localhost:10555` and enjoy.
26 |
27 | **Attention: It is not needed to run `lein figwheel` separately. Instead `(go)`
28 | launches Figwheel directly from the REPL**
29 |
30 | ## Trying it out
31 |
32 | If all is well you now have a browser window saying 'Hello Chestnut',
33 | and a REPL prompt that looks like `cljs.user=>`.
34 |
35 | Open `resources/public/css/style.css` and change some styling of the
36 | H1 element. Notice how it's updated instantly in the browser.
37 |
38 | Open `src/cljs/{{name}}/core.cljs`, and change `dom/h1` to
39 | `dom/h2`. As soon as you save the file, your browser is updated.
40 |
41 | In the REPL, type
42 |
43 | ```
44 | (ns {{name}}.core)
45 | (swap! app-state assoc :text "Interactivity FTW")
46 | ```
47 |
48 | Notice again how the browser updates.
49 |
50 | ### Lighttable
51 |
52 | Lighttable provides a tighter integration for live coding with an inline
53 | browser-tab. Rather than evaluating cljs on the command line with the Figwheel
54 | REPL, you can evaluate code and preview pages inside Lighttable.
55 |
56 | Steps: After running `(go)`, open a browser tab in Lighttable. Open a cljs file
57 | from within a project, go to the end of an s-expression and hit Cmd-ENT.
58 | Lighttable will ask you which client to connect. Click 'Connect a client' and
59 | select 'Browser'. Browse to [http://localhost:10555](http://localhost:10555)
60 |
61 | View LT's console to see a Chrome js console.
62 |
63 | Hereafter, you can save a file and see changes or evaluate cljs code (without
64 | saving a file).
65 |
66 | ### Emacs/CIDER
67 |
68 | CIDER is able to start both a Clojure and a ClojureScript REPL simultaneously,
69 | so you can interact both with the browser, and with the server. The command to
70 | do this is `M-x cider-jack-in-clojurescript`.
71 |
72 | We need to tell CIDER how to start a browser-connected Figwheel REPL though,
73 | otherwise it will use a JavaScript engine provided by the JVM, and you won't be
74 | able to interact with your running app.
75 |
76 | Put this in your Emacs configuration (`~/.emacs.d/init.el` or `~/.emacs`)
77 |
78 | ``` emacs-lisp
79 | (setq cider-cljs-lein-repl
80 | "(do (user/go)
81 | (user/cljs-repl))")
82 | ```
83 |
84 | Now `M-x cider-jack-in-clojurescript` (shortcut: `C-c M-J`, that's a capital
85 | "J", so `Meta-Shift-j`), point your browser at `http://localhost:10555`, and
86 | you're good to go.
87 |
88 | ## Testing
89 |
90 | To run the Clojure tests, use
91 |
92 | ``` shell
93 | lein test
94 | ```
95 |
96 | To run the Clojurescript you use [doo](https://github.com/bensu/doo). This can
97 | run your tests against a variety of JavaScript implementations, but in the
98 | browser and "headless". For example, to test with PhantomJS, use
99 |
100 | ``` shell
101 | lein doo phantom
102 | ```
103 |
104 | ## Deploying to Heroku
105 |
106 | This assumes you have a
107 | [Heroku account](https://signup.heroku.com/dc), have installed the
108 | [Heroku toolbelt](https://toolbelt.heroku.com/), and have done a
109 | `heroku login` before.
110 |
111 | ``` sh
112 | git init
113 | git add -A
114 | git commit
115 | heroku create
116 | git push heroku master:master
117 | heroku open
118 | ```
119 |
120 | ## Running with Foreman
121 |
122 | Heroku uses [Foreman](http://ddollar.github.io/foreman/) to run your
123 | app, which uses the `Procfile` in your repository to figure out which
124 | server command to run. Heroku also compiles and runs your code with a
125 | Leiningen "production" profile, instead of "dev". To locally simulate
126 | what Heroku does you can do:
127 |
128 | ``` sh
129 | lein with-profile -dev,+production uberjar && foreman start
130 | ```
131 |
132 | Now your app is running at
133 | [http://localhost:5000](http://localhost:5000) in production mode.
134 | {{#sass?}}
135 | ## SASS
136 |
137 | Currently SASS support in Chestnut depends on SASSC, a C-based SASS
138 | implementation. You will likely have to build the `sassc` binary from
139 | source. This is an advanced, undocumented Chestnut feature. See also
140 |
141 | https://github.com/plexus/chestnut/issues/70
142 |
143 | To compile your SCSS stylesheets to CSS, issue
144 |
145 | lein sassc once
146 |
147 | To automatically recompile when files change, you can use
148 |
149 | lein auto sassc once
150 | {{/sass?}}
151 |
152 | ## License
153 |
154 | Copyright © 2016 FIXME
155 |
156 | Distributed under the Eclipse Public License either version 1.0 or (at
157 | your option) any later version.
158 |
159 | ## Chestnut
160 |
161 | Created with [Chestnut](http://plexus.github.io/chestnut/) {{chestnut-version}}.
162 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/code_of_conduct.md:
--------------------------------------------------------------------------------
1 | # Contributor Code of Conduct
2 |
3 | As contributors and maintainers of this project, we pledge to respect
4 | all people who contribute through reporting issues, posting feature
5 | requests, updating documentation, submitting pull requests or patches,
6 | and other activities.
7 |
8 | We are committed to making participation in this project a
9 | harassment-free experience for everyone, regardless of level of
10 | experience, gender, gender identity and expression, sexual
11 | orientation, disability, personal appearance, body size, race, age, or
12 | religion.
13 |
14 | Examples of unacceptable behavior by participants include the use of
15 | sexual language or imagery, derogatory comments or personal attacks,
16 | trolling, public or private harassment, insults, or other
17 | unprofessional conduct.
18 |
19 | Project maintainers have the right and responsibility to remove, edit,
20 | or reject comments, commits, code, wiki edits, issues, and other
21 | contributions that are not aligned to this Code of Conduct. Project
22 | maintainers who do not follow the Code of Conduct may be removed from
23 | the project team.
24 |
25 | Instances of abusive, harassing, or otherwise unacceptable behavior
26 | may be reported by opening an issue or contacting one or more of the
27 | project maintainers.
28 |
29 | This Code of Conduct is adapted from the
30 | [Contributor Covenant](http:contributor-covenant.org), version 1.0.0,
31 | available at
32 | [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/dev/cljs/user.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.user
2 | (:require [{{project-ns}}.core]
3 | [{{project-ns}}.system :as system]))
4 |
5 | (def go system/go)
6 | (def reset system/reset)
7 | (def stop system/stop)
8 | (def start system/start)
9 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/dev/user.clj:
--------------------------------------------------------------------------------
1 | (ns user
2 | (:require [{{project-ns}}.application]
3 | [com.stuartsierra.component :as component]
4 | [figwheel-sidecar.config :as fw-config]
5 | [figwheel-sidecar.system :as fw-sys]
6 | [reloaded.repl :refer [system init]]
7 | [ring.middleware.reload :refer [wrap-reload]]
8 | [ring.middleware.file :refer [wrap-file]]
9 | [system.components.middleware :refer [new-middleware]]
10 | [figwheel-sidecar.repl-api :as figwheel]{{user-clj-requires}}
11 | [{{project-ns}}.config :refer [config]]))
12 |
13 | (defn dev-system []
14 | (let [config (config)]
15 | (assoc ({{project-ns}}.application/app-system config)
16 | :middleware (new-middleware
17 | {:middleware (into [[wrap-file "dev-target/public"]]
18 | (:middleware config))})
19 | :figwheel-system (fw-sys/figwheel-system (fw-config/fetch-config))
20 | :css-watcher (fw-sys/css-watcher {:watch-paths ["resources/public/css"]}){{{extra-dev-components}}})))
21 |
22 | (reloaded.repl/set-init! #(dev-system))
23 |
24 | (defn cljs-repl []
25 | (fw-sys/cljs-repl (:figwheel-system system)))
26 |
27 | ;; Set up aliases so they don't accidentally
28 | ;; get scrubbed from the namespace declaration
29 | (def start reloaded.repl/start)
30 | (def stop reloaded.repl/stop)
31 | (def go reloaded.repl/go)
32 | (def reset reloaded.repl/reset)
33 | (def reset-all reloaded.repl/reset-all)
34 |
35 | ;; deprecated, to be removed in Chestnut 1.0
36 | (defn run []
37 | (println "(run) is deprecated, use (go)")
38 | (go))
39 |
40 | (defn browser-repl []
41 | (println "(browser-repl) is deprecated, use (cljs-repl)")
42 | (cljs-repl))
43 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/project.clj:
--------------------------------------------------------------------------------
1 | (defproject {{full-name}} "0.1.0-SNAPSHOT"
2 | :description "FIXME: write description"
3 | :url "http://example.com/FIXME"
4 | :license {:name "Eclipse Public License"
5 | :url "http://www.eclipse.org/legal/epl-v10.html"}
6 |
7 | :dependencies [{{{project-clj-deps}}}]
8 |
9 | :plugins [{{{project-plugins}}}]
10 |
11 | :min-lein-version "2.6.1"
12 |
13 | :source-paths ["src/clj" "src/cljs" "src/cljc"]
14 |
15 | :test-paths ["test/clj" "test/cljc"]
16 |
17 | :clean-targets ^{:protect false} [:target-path :compile-path "resources/public/js" "dev-target"]
18 |
19 | :uberjar-name "{{{name}}}.jar"
20 |
21 | ;; Use `lein run` if you just want to start a HTTP server, without figwheel
22 | :main {{{project-ns}}}.application
23 |
24 | ;; nREPL by default starts in the :main namespace, we want to start in `user`
25 | ;; because that's where our development helper functions like (go) and
26 | ;; (browser-repl) live.
27 | :repl-options {:timeout 300000 :init-ns user}
28 |
29 | :cljsbuild {:builds
30 | [{:id "app"
31 | :source-paths ["src/cljs" "src/cljc" "dev"]
32 |
33 | :figwheel {:on-jsload "{{project-ns}}.system/reset"}
34 |
35 | :compiler {:main cljs.user
36 | :asset-path "js/compiled/out"
37 | :output-to "dev-target/public/js/compiled/{{{sanitized}}}.js"
38 | :output-dir "dev-target/public/js/compiled/out"
39 | :source-map-timestamp true}}
40 |
41 | {:id "test"
42 | :source-paths ["src/cljs" "test/cljs" "src/cljc" "test/cljc"]
43 | :compiler {:output-to "dev-target/public/js/compiled/testable.js"
44 | :main {{{project-ns}}}.test-runner
45 | :optimizations :none}}
46 |
47 | {:id "min"
48 | :source-paths ["src/cljs" "src/cljc"]
49 | :jar true
50 | :compiler {:main {{{project-ns}}}.system
51 | :output-to "resources/public/js/compiled/{{{sanitized}}}.js"
52 | :output-dir "target"
53 | :source-map-timestamp true
54 | :optimizations :advanced
55 | :closure-defines {goog.DEBUG false}
56 | :pretty-print false}}]}
57 |
58 | ;; When running figwheel from nREPL, figwheel will read this configuration
59 | ;; stanza, but it will read it without passing through leiningen's profile
60 | ;; merging. So don't put a :figwheel section under the :dev profile, it will
61 | ;; not be picked up, instead configure figwheel here on the top level.
62 |
63 | :figwheel {;; :http-server-root "public" ;; serve static assets from resources/public/
64 | ;; :server-port 3449 ;; default
65 | ;; :server-ip "127.0.0.1" ;; default
66 | :css-dirs ["resources/public/css"] ;; watch and update CSS
67 |
68 | ;; Start an nREPL server into the running figwheel process. We
69 | ;; don't do this, instead we do the opposite, running figwheel from
70 | ;; an nREPL process, see
71 | ;; https://github.com/bhauman/lein-figwheel/wiki/Using-the-Figwheel-REPL-within-NRepl
72 | ;; :nrepl-port 7888
73 |
74 | ;; To be able to open files in your editor from the heads up display
75 | ;; you will need to put a script on your path.
76 | ;; that script will have to take a file path and a line number
77 | ;; ie. in ~/bin/myfile-opener
78 | ;; #! /bin/sh
79 | ;; emacsclient -n +$2 $1
80 | ;;
81 | ;; :open-file-command "myfile-opener"
82 |
83 | :server-logfile "log/figwheel.log"}
84 |
85 | :doo {:build "test"}
86 | {{#less?}}
87 |
88 | :less {:source-paths ["src/less"]
89 | :target-path "resources/public/css"}
90 | {{/less?}}
91 | {{#sass?}}
92 |
93 | :sassc [{:src "src/scss/style.scss"
94 | :output-to "resources/public/css/style.css"}]
95 |
96 | :auto {"sassc" {:file-pattern #"\.(scss)$"
97 | :paths ["src/scss"]}}
98 | {{/sass?}}
99 |
100 | :profiles {:dev
101 | {:dependencies [{{{project-clj-dev-deps}}}]
102 |
103 | :plugins [{{{project-clj-dev-plugins}}}]
104 |
105 | :source-paths ["dev"]
106 | :repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}}
107 |
108 | :uberjar
109 | {:source-paths ^:replace ["src/clj" "src/cljc"]
110 | :prep-tasks [{{{project-prep-tasks}}}]
111 | :hooks [{{{project-uberjar-hooks}}}]
112 | :omit-source true
113 | :aot :all}})
114 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/resources/log4j.properties:
--------------------------------------------------------------------------------
1 | log4j.rootLogger=DEBUG, R
2 |
3 | log4j.appender.R=org.apache.log4j.RollingFileAppender
4 | log4j.appender.R.File=log/server.log
5 |
6 | log4j.appender.R.MaxFileSize=4096KB
7 | log4j.appender.R.MaxBackupIndex=9
8 |
9 | log4j.appender.R.layout=org.apache.log4j.PatternLayout
10 | log4j.appender.R.layout.ConversionPattern=[%d][%p][%c] %m%n
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/resources/public/css/style.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | text-decoration: underline;
3 | }
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/resources/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/plexus/chestnut/684b668141586ed5ef4389f94a4dc7f4fde13112/src/leiningen/new/chestnut/resources/public/favicon.ico
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/resources/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/clj/chestnut/application.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.application
2 | (:gen-class)
3 | (:require [com.stuartsierra.component :as component]
4 | [{{project-ns}}.components.server-info :refer [server-info]]
5 | [system.components.endpoint :refer [new-endpoint]]
6 | [system.components.handler :refer [new-handler]]
7 | [system.components.middleware :refer [new-middleware]]{{{server-clj-requires}}}
8 | [{{project-ns}}.config :refer [config]]
9 | [{{project-ns}}.routes :refer [home-routes]]))
10 |
11 | (defn app-system [config]
12 | (component/system-map
13 | :routes (new-endpoint home-routes)
14 | :middleware (new-middleware {:middleware (:middleware config)})
15 | :handler (-> {{#compojure?}}(new-handler){{/compojure?}}{{#bidi?}}(new-handler :router :bidi){{/bidi?}}
16 | (component/using [:routes :middleware]))
17 | :http (-> (new-web-server (:http-port config))
18 | (component/using [:handler]))
19 | :server-info (server-info (:http-port config))))
20 |
21 | (defn -main [& _]
22 | (let [config (config)]
23 | (-> config
24 | app-system
25 | component/start)))
26 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/clj/chestnut/components/server_info.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.components.server-info
2 | (:require [com.stuartsierra.component :as component]))
3 |
4 | (defrecord ServerInfoPrinter [http-port]
5 | component/Lifecycle
6 | (start [component]
7 | (println "Started {{project-ns}} on" (str "http://localhost:" http-port))
8 | component)
9 | (stop [component]
10 | component))
11 | (defn server-info [http-port]
12 | (->ServerInfoPrinter http-port))
13 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/clj/chestnut/components/shell_component.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.components.shell-component
2 | (:require [com.stuartsierra.component :as component]
3 | [clojure.string :as str]))
4 |
5 | (defrecord ShellComponent [command]
6 | component/Lifecycle
7 | (start [this]
8 | (when-not (:running this)
9 | (println "Shell command:" (str/join " " command))
10 | (future (apply clojure.java.shell/sh command)))
11 | (assoc this :running true)))
12 |
13 | (defn shell-component [& cmd]
14 | (->ShellComponent cmd))
15 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/clj/chestnut/config.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.config
2 | (:require [environ.core :refer [env]]
3 | [ring.middleware.defaults :refer [wrap-defaults {{ring-defaults}}]]
4 | [ring.middleware.gzip :refer [wrap-gzip]]
5 | [ring.middleware.logger :refer [wrap-with-logger]]))
6 |
7 | (defn config []
8 | {:http-port (Integer. (or (env :port) 10555))
9 | :middleware [[wrap-defaults {{ring-defaults}}]
10 | wrap-with-logger
11 | wrap-gzip]})
12 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/clj/chestnut/routes.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.routes
2 | (:require [clojure.java.io :as io]
3 | {{#compojure?}}
4 | [compojure.core :refer [ANY GET PUT POST DELETE routes]]
5 | [compojure.route :refer [resources]]
6 | {{/compojure?}}
7 | {{#bidi?}}
8 | [ring.util.response :refer [resource-response]]
9 | [bidi.bidi :as bidi]
10 | [bidi.ring :refer [resources]]
11 | {{/bidi?}}
12 | [ring.util.response :refer [response]]))
13 | {{#compojure?}}
14 |
15 | (defn home-routes [endpoint]
16 | (routes
17 | (GET "/" _
18 | (-> "public/index.html"
19 | io/resource
20 | io/input-stream
21 | response
22 | (assoc :headers {"Content-Type" "text/html; charset=utf-8"})))
23 | (resources "/")))
24 | {{/compojure?}}
25 | {{#bidi?}}
26 |
27 | (defn index-handler [req]
28 | (assoc (resource-response "index.html" {:root "public"})
29 | :headers {"Content-Type" "text/html; charset=UTF-8"}))
30 |
31 | (def routes ["/" {"" {:get index-handler}
32 | "css" {:get (resources {:prefix "public/css/"})}
33 | "js" {:get (resources {:prefix "public/js/"})}}])
34 |
35 | (defn home-routes [endpoint]
36 | routes)
37 | {{/bidi?}}
38 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/clj/chestnut/styles.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.styles
2 | (:require [garden-watcher.def :refer [defstyles]]))
3 |
4 | (defstyles style
5 | [:h1 {:text-decoration "underline"}])
6 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljc/chestnut/common.cljc:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.common)
2 |
3 | (defn shared-fn
4 | "A function that is shared between clj and cljs"
5 | []
6 | (println "cljc!"))
7 |
8 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/components/ui.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.components.ui
2 | (:require [com.stuartsierra.component :as component]
3 | [{{project-ns}}.core :refer [render]]))
4 |
5 | (defrecord UIComponent []
6 | component/Lifecycle
7 | (start [component]
8 | (render)
9 | component)
10 | (stop [component]
11 | component))
12 |
13 | (defn new-ui-component []
14 | (map->UIComponent {}))
15 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/core_om_next.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.core
2 | (:require [om.next :as om :refer-macros [defui]]
3 | [om.dom :as dom]))
4 |
5 | (enable-console-print!)
6 |
7 | (defonce app-state (atom {:text "Hello Chestnut!"}))
8 |
9 | (defui RootComponent
10 | Object
11 | (render [this]
12 | (dom/div nil (dom/h1 nil (:text @app-state)))))
13 |
14 | (def root (om/factory RootComponent))
15 |
16 | (defn render []
17 | (js/ReactDOM.render (root) (js/document.getElementById "app")))
18 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/core_re_frame.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.core
2 | (:require [reagent.core :as reagent]
3 | [re-frame.core :as re-frame]
4 | [{{project-ns}}.events]
5 | [{{project-ns}}.subs]
6 | [{{project-ns}}.views :as views]
7 | [{{project-ns}}.config :as config]))
8 |
9 | (enable-console-print!)
10 |
11 | (defn dev-setup []
12 | (when config/debug?
13 | (enable-console-print!)
14 | (println "dev mode")))
15 |
16 | (defn mount-root []
17 | (re-frame/clear-subscription-cache!)
18 | (reagent/render [views/main-panel]
19 | (.getElementById js/document "app")))
20 |
21 | (defn render []
22 | (re-frame/dispatch-sync [:initialize-db])
23 | (dev-setup)
24 | (mount-root))
25 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/core_reagent.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.core
2 | (:require [reagent.core :as reagent :refer [atom]]))
3 |
4 | (enable-console-print!)
5 |
6 | (defonce app-state (atom {:text "Hello Chestnut!"}))
7 |
8 | (defn greeting []
9 | [:h1 (:text @app-state)])
10 |
11 | (defn render []
12 | (reagent/render [greeting] (js/document.getElementById "app")))
13 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/core_rum.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.core
2 | (:require [rum.core :as rum]))
3 |
4 | (enable-console-print!)
5 |
6 | (defonce app-state (atom {:text "Hello Chestnut!"}))
7 |
8 | (rum/defc greeting < rum/reactive []
9 | [:h1 (:text (rum/react app-state))])
10 |
11 | (defn render []
12 | (rum/mount (greeting) (. js/document (getElementById "app"))))
13 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/core_vanilla.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.core)
2 |
3 | (enable-console-print!)
4 |
5 | (defn render []
6 | (set! (.-innerHTML (js/document.getElementById "app"))
7 | "Hello Chestnut!
"))
8 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/cljs/chestnut/system.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.system
2 | (:require [com.stuartsierra.component :as component]
3 | [{{project-ns}}.components.ui :refer [new-ui-component]]))
4 |
5 | (declare system)
6 |
7 | (defn new-system []
8 | (component/system-map
9 | :app-root (new-ui-component)))
10 |
11 | (defn init []
12 | (set! system (new-system)))
13 |
14 | (defn start []
15 | (set! system (component/start system)))
16 |
17 | (defn stop []
18 | (set! system (component/stop system)))
19 |
20 | (defn ^:export go []
21 | (init)
22 | (start))
23 |
24 | (defn reset []
25 | (stop)
26 | (go))
27 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/less/style.less:
--------------------------------------------------------------------------------
1 | h1 {
2 | text-decoration: underline;
3 | }
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/src/scss/style.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | h1 {
4 | text-decoration: underline;
5 | }
6 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/system.properties:
--------------------------------------------------------------------------------
1 | java.runtime.version=1.8
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/test/clj/chestnut/example_test.clj:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.example-test
2 | (:require [clojure.test :refer :all]))
3 |
4 | (deftest example-passing-test
5 | (is (= 1 1)))
6 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/test/cljc/chestnut/common_test.cljc:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.common-test
2 | #? (:cljs (:require-macros [cljs.test :refer (is deftest testing)]))
3 | (:require [{{project-ns}}.common :as sut]
4 | #?(:clj [clojure.test :refer :all]
5 | :cljs [cljs.test])))
6 |
7 | (deftest example-passing-test-cljc
8 | (is (= 1 1)))
9 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/test/cljs/chestnut/core_test.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.core-test
2 | (:require-macros [cljs.test :refer (is deftest testing)])
3 | (:require [cljs.test]))
4 |
5 | (deftest example-passing-test
6 | (is (= 1 1)))
7 |
--------------------------------------------------------------------------------
/src/leiningen/new/chestnut/test/cljs/chestnut/test_runner.cljs:
--------------------------------------------------------------------------------
1 | (ns {{project-ns}}.test-runner
2 | (:require
3 | [doo.runner :refer-macros [doo-tests]]
4 | [{{project-ns}}.core-test]
5 | [{{project-ns}}.common-test]))
6 |
7 | (enable-console-print!)
8 |
9 | (doo-tests '{{project-ns}}.core-test
10 | '{{project-ns}}.common-test)
11 |
--------------------------------------------------------------------------------
/src/mistletoe/process.clj:
--------------------------------------------------------------------------------
1 | (ns mistletoe.process
2 | (:import [java.nio ByteBuffer]
3 | [jnr.constants.platform Signal])
4 | (:require [clojure.core.async :refer [go-loop ! chan close!]]))
5 |
6 | (defn process [& args]
7 | (let [argsAry (into-array String args)
8 | process (jnr.process.ProcessBuilder. argsAry)]
9 | {:processBuilder process
10 | :inBuf (ByteBuffer/allocate 2048)
11 | :outBuf (ByteBuffer/allocate 2048)}))
12 |
13 | (defn directory [processMap dir]
14 | (.directory (:processBuilder processMap) dir)
15 | processMap)
16 |
17 | (defn start [processMap]
18 | (let [process (.start (:processBuilder processMap))]
19 | (merge
20 | processMap
21 | {:process process
22 | :in (.getIn process)
23 | :err (.getErr process)
24 | :out (.getOut process)})))
25 |
26 | (defn read-str [process & [stream]]
27 | (let [buf (:inBuf process)
28 | chan ((or stream :in) process)]
29 | (.clear buf)
30 | (.read chan buf)
31 | (let [len (.position buf)
32 | bytes (.array buf)]
33 | (if (> len 0)
34 | (String. (into-array Byte/TYPE (take len bytes)))))))
35 |
36 | (defn read-err [process]
37 | (read-str process :err))
38 |
39 | (defn write-str [process exp]
40 | (let [buf (:outBuf process)
41 | chan (:out process)]
42 | (.clear buf)
43 | (.put buf (into-array Byte/TYPE (str exp)))
44 | (.flip buf)
45 | (.write chan buf))
46 | process)
47 |
48 | (defn start-pipe [process & [stream]]
49 | (let [c (chan 1)
50 | stream (or stream :in)]
51 | (go-loop []
52 | (if-let [str (read-str process stream)]
53 | (>! c str)
54 | (close! c))
55 | (recur))
56 | (assoc process (keyword (str (name stream) "Chan")) c)))
57 |
58 | (defn kill [{process :process} & [signal]]
59 | (.kill process (or signal Signal/SIGKILL)))
60 |
61 | (defn posix []
62 | (jnr.posix.POSIXFactory/getPOSIX))
63 |
64 | (defn kill-process-group [{process :process} & [signal]]
65 | (.kill (posix)
66 | (- (.getPid process))
67 | (.intValue (or signal Signal/SIGKILL))))
68 |
69 | (defn wait-for [{process :process}]
70 | (.waitFor process))
71 |
72 | (defn chdir
73 | "Change the working directory of the running process (the JVM)"
74 | [dir]
75 | (.chdir (posix) dir))
76 |
--------------------------------------------------------------------------------
/src/mistletoe/test.clj:
--------------------------------------------------------------------------------
1 | (ns mistletoe.test
2 | (:import [java.util.concurrent TimeoutException])
3 | (:require [clojure.core.async :refer [go-loop ! chan
4 | alts!! timeout close!]]))
5 |
6 |
7 | (def ^:dynamic *expect-guard-for* #{})
8 |
9 | (defn log-chan [process prefix & [key]]
10 | (let [key (or key :inChan)
11 | in (key process)
12 | out (chan 2)]
13 | (go-loop []
14 | (let [v (! out v)
18 | (if (re-seq #"\n$" v)
19 | (print prefix v)
20 | (println prefix v))
21 | (recur))
22 | (close! out))))
23 | (assoc process key out)))
24 |
25 | (defn expect [process regex & [timeout-sec]]
26 | (loop []
27 | (let [chan (:inChan process)
28 | ms (* 1000 (or timeout-sec 30))
29 | timeout-chan (timeout ms)
30 | [v ch] (alts!! [chan timeout-chan])]
31 | (cond
32 | (= ch timeout-chan)
33 | (throw (TimeoutException. (str "Timeout waiting for " regex)))
34 | (nil? v)
35 | (throw (Exception. (str "Input channel closed, expecting " regex)))
36 | (re-seq regex v)
37 | (println "--> Got" v ", continuing.")
38 | (first (filter #(re-seq % v) *expect-guard-for*))
39 | (throw (Exception. (str "Got unexpected input: "
40 | (first (filter #(re-seq % v) *expect-guard-for*)) " in " v)))
41 | :default
42 | (recur))))
43 | process)
44 |
--------------------------------------------------------------------------------