├── .gitignore
├── CHANGES.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── boot.properties
├── build.boot
├── circle.yml
├── docs
├── cljs.edn.md
├── compiler-options.md
└── integration-with-other-tasks.md
├── src
└── adzerk
│ ├── boot_cljs.clj
│ └── boot_cljs
│ ├── impl.clj
│ ├── js_deps.clj
│ ├── middleware.clj
│ └── util.clj
└── test
├── adzerk
├── boot_cljs
│ ├── impl_test.clj
│ ├── middleware_test.clj
│ └── util_test.clj
└── boot_cljs_test.clj
└── demo
├── core.cljs
├── index.cljs.edn
├── index.html
├── other.cljs
├── other.cljs.edn
└── other.html
/.gitignore:
--------------------------------------------------------------------------------
1 | ### BOOT #######################################################################
2 |
3 | /.boot/
4 |
5 | ### LEININGEN ##################################################################
6 |
7 | .lein-*
8 |
9 | ### MAVEN (include pom.xml in /base) ###########################################
10 |
11 | *.jar
12 | *.war
13 | pom.xml
14 | pom.xml.asc
15 |
16 | ### NREPL ######################################################################
17 |
18 | .repl-*
19 | .nrepl-*
20 |
21 | ### JAVA #######################################################################
22 |
23 | /hs_err_pid*.log
24 |
25 | ### OSX ########################################################################
26 |
27 | .DS_Store
28 |
29 | ### EMACS ######################################################################
30 |
31 | [#]*[#]
32 |
33 | ### VIM ########################################################################
34 |
35 | *.swn
36 | *.swo
37 | *.swp
38 |
39 | ### PROJECT ####################################################################
40 |
41 | /zzz/
42 | /target/
43 |
--------------------------------------------------------------------------------
/CHANGES.md:
--------------------------------------------------------------------------------
1 | ## 2.1.5 (2018-10-25)
2 |
3 | - Try handling exceptions in a way that serialization errors are less likely
4 | - Handle exceptions where ex-data can't be serialized
5 | - This should print real exceptions for problematic cases, but the exceptions won't be
6 | formatted perfectly.
7 |
8 | ## 2.1.4 (2017-09-25)
9 |
10 | - Fix setting `:modules` `:output-to` automatically ([#174](https://github.com/boot-clj/boot-cljs/issues/174))
11 | - Fix using Node packages and native requires with Node.js ([#175](https://github.com/boot-clj/boot-cljs/issues/175))
12 | - Uses `java.util.Base64` instead of `javax.xml.bind.DatatypeConverter`, to support Java 9 ([#178](https://github.com/boot-clj/boot-cljs/issues/178))
13 | - Breaks Java 1.7
14 | - Somehow fixes NPE when using `:infer-externs` (not sure what caused this...) ([#172](https://github.com/boot-clj/boot-cljs/issues/172))
15 |
16 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/2.1.3...master)**
17 |
18 | ## 2.1.3 (2017-08-29)
19 |
20 | - Fix `:source-map` option logic to allow disabling the option when doing optimized build.
21 | - If `:source-map` is string (i.e. path), use value as is, instead of setting new value based on `:output-to`.
22 |
23 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/2.1.2...2.1.3)**
24 |
25 | ## 2.1.2 (2017-08-17)
26 |
27 | - Fix missing exception message
28 | - Handle new exception location format
29 | - Escape `%` in exception messages if using Boot <2.7.2 ([Boot fix](https://github.com/boot-clj/boot/commit/c07b08751ad195e6e6349cb7c2f826c95a8e8186))
30 |
31 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/2.1.1...2.1.2)**
32 |
33 | ## 2.1.1 (29.7.2017)
34 |
35 | - Fix `:modules` `:output-to` handling
36 |
37 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/2.1.0...2.1.1)**
38 |
39 | ## 2.1.0 (29.7.2017)
40 |
41 | - Require `:main` namespace in our shim ns requires ([#139](https://github.com/boot-clj/boot-cljs/issues/139))
42 | - Don't set `:source-map-path` automatically ([#157](https://github.com/boot-clj/boot-cljs/pull/157), [#136](https://github.com/boot-clj/boot-cljs/issues/136))
43 | - Use relative path of `.cljs.edn` for asset-path instead of name of the file ([#156](https://github.com/boot-clj/boot-cljs/pull/156), [#152](https://github.com/boot-clj/boot-cljs/issues/152))
44 | - Use provided `:output-dir` and `:output-to` and set default values based on path of `.cljs.edn`, like previously ([#104](https://github.com/boot-clj/boot-cljs/issues/104))
45 | - Drop support for `.cljs.edn` `:modules` option (with warning) and instead handle `:output-to` paths in
46 | `:modules` under `:compiler-options`
47 | - If project dependencies have changed, add new dependencies to Boot-cljs pods ([#95](https://github.com/boot-clj/boot-cljs/issues/95))
48 | - E.g. `(boot.core/set-env! :dependencies #(conj % '[com.andrewmcveigh/cljs-time "0.4.0"]))`
49 | can be used to add `cljs-time` dependency and Boot-cljs will find this without restarting
50 | the whole Boot process.
51 | - Add validation for Boot-cljs `.cljs.edn` options ([#148](https://github.com/boot-clj/boot-cljs/issues/148))
52 | - During `:advanced` compilation set the `:output-wrapper` option to `true`.
53 | This is not the ClojureScript compiler default but more friendly for regular use.
54 | This makes `boot-cljs` behave similar to `lein-cljsbuild` as well. ([#64](https://github.com/boot-clj/boot-cljs/issues/64))
55 |
56 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/2.0.0...2.1.0)**
57 |
58 | ## 2.0.0 (10.3.2017)
59 |
60 | - Stop following ClojureScript compiler version number
61 | - Boot-cljs uses the [public compiler API](https://github.com/clojure/clojurescript/blob/master/src/main/clojure/cljs/build/api.clj)
62 | - The API is static and should not change between versions
63 | - ClojureScript compiler versions since [1.7.28](https://github.com/clojure/clojurescript/blob/master/changes.md#1728)
64 | which included change [CLJS-1367](https://github.com/clojure/clojurescript/commit/9e662c3ea5b9f536f303e9084415e988bf5d0878), should work.
65 | - Expose ClojureScript compiler options in `.cljs.edn` Boot fileset metadata for
66 | others tasks (e.g. boot-reload)
67 | - Hide stacktraces for Cljs compiler exceptions (reader exception, analysis error)
68 |
69 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.228-2...2.0.0)**
70 |
71 | ## 1.7.228-2 (18.10.2016)
72 |
73 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.228-1...1.7.228-2)**
74 |
75 | - Changed the order compiler-options are merged. Task-options are now merged on top of
76 | options from .cljs.edn. This allows overriding options per build task invocation.
77 |
78 | ## 1.7.228-1 (11.1.2016)
79 |
80 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.228-0...1.7.228-1)**
81 |
82 | - Fixed optimization none builds ([#115](https://github.com/adzerk-oss/boot-cljs/pull/115))
83 |
84 | ## 1.7.228-0 (10.1.2016)
85 |
86 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.170-3...1.7.228-0)**
87 |
88 | - Update default ClojureScript release to 1.7.228
89 | - Improved exception messages in some cases. ([#110](https://github.com/adzerk-oss/boot-cljs/issues/110))
90 | - Added *experimental* support for Closure Modules using `:modules` option on
91 | `.cljs.edn` files. ([#113](https://github.com/adzerk-oss/boot-cljs/issues/113))
92 |
93 | ## 1.7.170-3 (8.11.2015)
94 |
95 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.170-2...1.7.170-3)**
96 |
97 | - Fixed critical bug introduced in the previous release
98 | - Second compilation broke the main shim
99 |
100 | ## 1.7.170-2 (8.11.2015)
101 |
102 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.170-1...1.7.170-2)**
103 |
104 | - Read `.cljs.edn` always instead of only once
105 | - This allows editing `:require` and `:compiler-options` in without
106 | restarting the build process.
107 |
108 | ## 1.7.170-1 (6.11.2015)
109 |
110 | **[compare](https://github.com/adzerk-oss/boot-cljs/compare/1.7.166-1...1.7.170-1)**
111 |
112 | - Update to match latest ClojureScript release
113 |
114 | ## 1.7.166-1 (4.11.2015)
115 |
116 | - Removed workaround related to recompile-dependents which is made unncessary
117 | by [CLJS-1437](https://github.com/clojure/clojurescript/commit/409d1eca4fcf776be1f7b28f759d6f36f7a83ec8).
118 | - Fixed source-map options when `optimizations` is not explicitly set.
119 |
120 | ## 1.7.48-6 (16.10.2015)
121 |
122 | - Fixed problem where default main (no `.cljs.edn` files) tried to compile
123 | `deps.cljs` files in the fileset.
124 |
125 | ## 1.7.48-5 (4.10.2015)
126 |
127 | - Warning messages now display file path without tmp-dir path
128 | - Adds information about warnings and exceptions to fileset so that
129 | [boot-reload](https://github.com/adzerk-oss/boot-reload) can use the
130 | information to display HUD.
131 | - Cljs exceptions are now always rethrown, this is to allow other tasks to
132 | catch the exceptions and to see when build failed
133 |
134 | ## 1.7.48-4 (19.9.2015)
135 |
136 | - Improved ClojureScript dependency check logic
137 | 1. If ClojureScript dependency is specific in build.boot, use that
138 | 2. If no dependency is found but ClojureScript is available in classpath,
139 | display a warning
140 | 3. If no dependency is found and ClojureScript is not available, add dependency
141 |
142 | ## 1.7.48-3 (24.8.2015)
143 |
144 | - **BREAKING**: Changed the way `:ids` option selects the files. Instead of looking only at the basename of file, it looks at the paths. E.g. to use `src/js/main.cljs.edn` use `--ids js/main` instead of just `--ids main`.
145 | - Fixed advanced optimization caused by generated main namespace not being on
146 | classpath
147 | - Fixed where advanced optimization was broken with multiple builds
148 | [#92](https://github.com/adzerk-oss/boot-cljs/pull/92).
149 |
150 | ## 1.7.48-2 (20.8.2015)
151 |
152 | - Display reader exceptions in pretty format
153 | - Fix [#89](https://github.com/adzerk-oss/boot-cljs/issues/89).
154 |
155 | ## 1.7.48-1 (20.8.2015)
156 |
157 | - Fix Cljs version assertion
158 | - Add Cljs output files as resources so they'll be available in classpath
159 |
160 | ## 1.7.48-0 (20.8.2015)
161 |
162 | - Support reloading macro namespaces
163 | - Use ClojureScript API
164 | - Builds specified by `.cljs.edn` files are now run parallel in separated
165 | environments.
166 | - Add `:ids` option to select used `.cljs.edn` files
167 | - Bug fixes
168 |
169 | ## 0.0-3308-0 (13.6.2015)
170 |
171 | - Updated to latest ClojureScript version
172 |
173 | ## 0.0-3269-4 (13.6.2015)
174 |
175 | - Instead automatically adding or updating Clojure 1.7 dependency,
176 | display a warning and link to [Boot wiki](https://github.com/boot-clj/boot/wiki/Setting-Clojure-version)
177 | page about setting the Clojure version.
178 |
179 | ## 0.0-3269-3 (13.6.2015)
180 |
181 | - Broken release
182 |
183 | ## 0.0-3269-2 (30.5.2015)
184 |
185 | - Path->js fix fir cljc namespaces
186 |
187 | ## 0.0-3269-1 (23.5.2015)
188 |
189 | - Automatically add Clojure 1.7 dependency to Cljs pod if project
190 | is not yet using it.
191 |
192 | ## 0.0-3269-0 (17.5.2015)
193 |
194 | - **Probably breaks stuff**: Updated to latest ClojureScript compiler
195 | - **Might break stuff**: Uses shim created by cljs compiler
196 | - **Breaking**: Removed \*.inc.js, \*.ext.js, \*.lib.js handling
197 | - Most of use cases are covered by [cljsjs](http://cljsjs.github.io/)
198 | - If you still need to add local js files to the build, you can add deps.cljs
199 | file to your local project
200 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to contribute
2 |
3 | Contributions are welcome.
4 |
5 | Please file bug reports and feature requests to https://github.com/adzerk-oss/boot-cljs/issues.
6 |
7 | ## Hacking
8 |
9 | Check [development guide](https://github.com/adzerk-oss/boot-cljs/wiki/Development) on wiki for how
10 | to build and test boot-cljs locally.
11 |
12 | ## Making changes
13 |
14 | * Fork the repository on Github
15 | * Create a topic branch from where you want to base your work (usually the master branch)
16 | * Check the formatting rules from existing code (no trailing whitepace, mostly default indentation)
17 | * Ensure any new code is well-tested, and if possible, any issue fixed is covered by one or more new tests
18 | * Verify that all tests pass using ```boot run-tests``` and test the changes manually as our test suite is not very comprehesive
19 | * Push your code to your fork of the repository
20 | * Make a Pull Request
21 |
22 | ## Commit messages
23 |
24 | 1. Separate subject from body with a blank line
25 | 2. Limit the subject line to 50 characters
26 | 3. Capitalize the subject line
27 | 4. Do not end the subject line with a period
28 | 5. Use the imperative mood in the subject line
29 | - "Add x", "Fix y", "Support z", "Remove x"
30 | 6. Wrap the body at 72 characters
31 | 7. Use the body to explain what and why vs. how
32 |
33 |
--------------------------------------------------------------------------------
/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 Washington 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 | # boot-cljs [](https://clojars.org/adzerk/boot-cljs) [](https://circleci.com/gh/boot-clj/boot-cljs) [](https://jarkeeper.com/adzerk/boot-cljs)
2 |
3 | [Boot](http://boot-clj.com/) task to compile ClojureScript applications.
4 |
5 | * Provides the `cljs` task for compiling ClojureScript to JavaScript
6 | * Requirements
7 | * Supports [ClojureScript versions](https://github.com/clojure/clojurescript/blob/master/changes.md) since 1.7.28
8 | * Boot version 2.6.0 but 2.7.0 is recommended for better error reporting
9 | * Java 8+
10 | * Docs
11 | * [.cljs.edn files](docs/cljs.edn.md)
12 | * [Compiler options](docs/compiler-options.md), Boot-cljs modified and automatically sets some options
13 | * **Related projects:** [boot-reload](https://github.com/adzerk-oss/boot-reload) and [boot-cljs-repl](https://github.com/adzerk-oss/boot-cljs-repl)
14 |
15 | ## Quick start
16 |
17 | Add ClojureScript and `boot-cljs` to your `build.boot` dependencies and `require` the namespace:
18 |
19 | ```clj
20 | (set-env! :dependencies '[[adzerk/boot-cljs "X.Y.Z" :scope "test"]])
21 | (require '[adzerk.boot-cljs :refer [cljs]])
22 | ```
23 |
24 | You can see the options available on the command line:
25 |
26 | ```bash
27 | boot cljs --help
28 | ```
29 |
30 | Or the same in the REPL:
31 |
32 | ```clj
33 | boot.user=> (doc cljs)
34 | ```
35 |
36 | ### Further Reading
37 |
38 | - [boot-cljs-example](https://github.com/adzerk/boot-cljs-example) - An example project with a local web server, CLJS REPL, and live-reload.
39 | - [Saapas example project](https://github.com/Deraen/saapas) - Opinionated example project for Boot.
40 | - [Tenzing project template](https://github.com/martinklepsch/tenzing) - ClojureScript application template.
41 | - [Modern ClojureScript](https://github.com/magomimmo/modern-cljs) - Series of tutorials for ClojureScript. Uses Boot.
42 |
43 |
44 | ## License
45 |
46 | Copyright © 2014 Adzerk
47 | Copyright © 2015-2017 Juho Teperi
48 |
49 | Distributed under the Eclipse Public License either version 1.0 or (at
50 | your option) any later version.
51 |
--------------------------------------------------------------------------------
/boot.properties:
--------------------------------------------------------------------------------
1 | #https://github.com/boot-clj/boot
2 | #Wed Jul 08 20:50:42 EEST 2015
3 | BOOT_CLOJURE_VERSION=1.8.0
4 | BOOT_VERSION=2.7.1
5 |
--------------------------------------------------------------------------------
/build.boot:
--------------------------------------------------------------------------------
1 | (set-env!
2 | :resource-paths #{"src"}
3 | :source-paths #{"test"}
4 | :dependencies '[[org.clojure/clojure "1.8.0" :scope "provided"]
5 | [adzerk/boot-test "1.1.0" :scope "test"]
6 | [pandeiro/boot-http "0.7.0" :scope "test"]
7 | [org.clojure/clojurescript "1.7.228" :scope "test"]
8 | [ns-tracker "0.3.1" :scope "test"]])
9 |
10 | (require '[adzerk.boot-test]
11 | '[adzerk.boot-cljs :refer [cljs]]
12 | '[pandeiro.boot-http :refer [serve]])
13 |
14 | (def +version+ "2.1.5")
15 |
16 | (task-options!
17 | pom {:project 'adzerk/boot-cljs
18 | :version +version+
19 | :description "Boot task to compile ClojureScript applications."
20 | :url "https://github.com/adzerk/boot-cljs"
21 | :scm {:url "https://github.com/adzerk/boot-cljs"}
22 | :license {"EPL" "http://www.eclipse.org/legal/epl-v10.html"}})
23 |
24 | (ns-unmap *ns* 'test)
25 |
26 | (deftask test
27 | [O optimizations LEVEL kw "Compiler optimization level."
28 | j junit-output-to JUNIT str "Test report destination."]
29 | (comp (serve)
30 | (cljs :optimizations (or optimizations :whitespace))
31 | (adzerk.boot-test/test
32 | :namespaces #{'adzerk.boot-cljs-test 'adzerk.boot-cljs.util-test}
33 | :junit-output-to junit-output-to)))
34 |
35 | (deftask build []
36 | (comp
37 | (pom)
38 | (jar)
39 | (install)))
40 |
41 | (deftask dev []
42 | (comp
43 | (watch)
44 | (build)
45 | (repl :server true)))
46 |
47 | (deftask deploy []
48 | (comp
49 | (build)
50 | (push :repo "clojars" :gpg-sign (not (.endsWith +version+ "-SNAPSHOT")))))
51 |
--------------------------------------------------------------------------------
/circle.yml:
--------------------------------------------------------------------------------
1 | machine:
2 | java:
3 | version: oraclejdk8
4 | environment:
5 | _JAVA_OPTIONS: "-Xms512m -Xmx1024m"
6 | dependencies:
7 | cache_directories:
8 | - "~/.boot/cache/lib"
9 | - "~/.boot/cache/bin"
10 | pre:
11 | - curl -L https://github.com/boot-clj/boot-bin/releases/download/latest/boot.sh -o ~/bin/boot
12 | - chmod +x ~/bin/boot
13 | override:
14 | - boot show -d
15 | test:
16 | override:
17 | - boot test -j junit
18 | - mkdir -p $CIRCLE_TEST_REPORTS/junit/
19 | - find . -type f -regex ".*/target/junit/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
20 |
--------------------------------------------------------------------------------
/docs/cljs.edn.md:
--------------------------------------------------------------------------------
1 | # `.cljs.edn` files
2 |
3 | `.cljs.edn` files are configuration files for Boot-cljs which allow options
4 | being set in a separate file instead of in `build.boot` task call.
5 |
6 | There are several benefits to providing configuration in separate files:
7 |
8 | Using separate file is that the options can be changed
9 | without restarting the whole Boot process.
10 |
11 | It is possible to calculate some options based on the
12 | relative path of `.cljs.edn` file inside the fileset. If user doesn't
13 | provide `:output-dir` or `:output-to` options, the values are set up using
14 | relative path of the `.cljs.edn` file.
15 |
16 | Perhaps the most important feature of `.cljs.edn` files is that other tasks
17 | can modify this configuration. For example Boot-reload and Boot-cljs-repl
18 | use this set up their code using `:require`.
19 |
20 | Boot-cljs is able to run several Cljs compiler parallel if multiple
21 | `.cljs.edn` files are present.
22 |
23 | > NOTE: This might change.
24 | > Cljs compiler can now work parallel itself, if `:parallel-build` option is enabled.
25 | > For cases there the application should be split to several JS files, `:modules`
26 | > is probably better fit as that way the shared code is not duplicated to every
27 | > output file.
28 | > For cases where separate builds, like app and tests, are needed, it might be
29 | > simpler to just run two cljs tasks.
30 |
31 | ## `:compiler-options`
32 |
33 | [Compiler options](./compiler-options.md) can be provided here.
34 |
35 | ## `:require`
36 |
37 | Collection of namespaces to require in Boot-cljs generated main namespace.
38 |
39 | ## `:init-fns`
40 |
41 | Collection of functions (namespaced symbols) to call from Boot-cljs main namespace,
42 | called after all the `:require` namespaces are loaded.
43 | Namespaces of these symbols are automatically added to `:require`.
44 |
--------------------------------------------------------------------------------
/docs/compiler-options.md:
--------------------------------------------------------------------------------
1 | # Boot-cljs compiler options
2 |
3 | Boot-cljs does some special handling with some of [ClojureScript compiler options](https://clojurescript.org/reference/compiler-options),
4 | these cases are either related to Boot temp dir and fileset architecture, or to
5 | support some additional features of Boot-cljs.
6 |
7 | Example of first case is `:output-to` and `:output-dir`. These filepaths need to
8 | be under temp directory managed by Boot-cljs.
9 |
10 | Example of second case is `:main` namespace. Boot-cljs writes it's own main namespace
11 | because we need to support multiple `:require` namespaces from `.cljs.edn` files. This
12 | is important because other tools ([boot-reload](https://github.com/adzerk-oss/boot-reload))
13 | use `:require` to initialize themselves.
14 |
15 | ## Merge order
16 |
17 | 1. `:compiler-options` in `.cljs.edn` file
18 | 2. `:compiler-options` task option
19 | 3. `:optimizations` and `:source-map` task options
20 | 4. options automatically set by boot-cljs (`:output-dir`, `:output-to`, `:main`)
21 |
22 | TODO: add support for merging `:closure-defines` and other map options [#135](https://github.com/boot-clj/boot-cljs/issues/135)
23 |
24 | ## `:output-dir` & `:output-to`
25 |
26 | If these options are set, path of Boot-cljs temp dir is prepended into these.
27 |
28 | If values are not set, default value is created based on relative path of the `.cljs.edn` file.
29 |
30 | - `resources/js/main.cljs.edn`
31 | - `:resource-paths #{"resources"}`
32 | - relative path of the file inside fileset is `js/main.cljs.edn`
33 | - `:output-dir` is set to `js/main.out`
34 | - `:output-to` is set to `js/main.js`
35 |
36 | ## `:main`
37 |
38 | This value is always set to namespace generated by Boot-cljs, e.g. `boot.cljs.main31649`,
39 | where the number is generated with `gensym`.
40 |
41 | If user provides `:main` option, the namespace is appended to `:require` `.cljs.edn`
42 | option, and is thus required by the Boot-cljs main namespace. This should usually
43 | work nearly the same as without Boot-cljs main namespace, but this keeps the support
44 | for Boot-reload and others to use `:require`.
45 |
46 | Note: It would be possible for Boot-reload to use `:preloads` instead of `:require`, but
47 | that would change the loading order and cause problems with current implementation
48 | of Boot-reload (check [#143](https://github.com/boot-clj/boot-cljs/pull/143) for some
49 | information.)
50 |
51 | ## `:source-map`
52 |
53 | This option can be provided task option or as compiler-option. If `:optimizations` is
54 | not `:none` and `:modules` is not used, `:source-map` is automatically set to
55 | `:output-to` with `.map` prepended.
56 |
57 | ## `:modules`
58 |
59 | Should work similar to `:output-to`. If user provides a value, it is prepended with
60 | path to Boot-cljs temp dir, else default value is created based on relative path of `.cljs.edn`
61 | file and name of the module.
62 |
63 | ## `:output-wrapper`
64 |
65 | When doing `:optimization :advanced` build, if `:output-wrapper` is `nil` it is set enabled. This follows Lein-cljsbuild.
66 |
67 | See more: [#64](https://github.com/boot-clj/boot-cljs/issues/64)
68 |
--------------------------------------------------------------------------------
/docs/integration-with-other-tasks.md:
--------------------------------------------------------------------------------
1 | # Integration with other tasks
2 |
3 | ## `.cljs.edn`
4 |
5 | Other tasks can modify the Cljs build options by modifying `.cljs.edn` files
6 | in the fileset. For example boot-reload and boot-cljs-repl add their
7 | client namespaces to `:require` vector in `.cljs.edn` files.
8 |
9 | Examples:
10 |
11 | - https://github.com/adzerk-oss/boot-reload/blob/master/src/adzerk/boot_reload.clj#L84-L89
12 | - https://github.com/adzerk-oss/boot-reload/blob/master/src/adzerk/boot_reload.clj#L138-L148
13 |
14 | ## Without `.cljs.edn` files
15 |
16 | FIXME:
17 |
18 | If tasks don't find `.cljs.edn` files, they don't currently have way to
19 | define which namespaces to include in build. This works for now,
20 | as Boot-cljs will create default `.cljs.edn` file, which has `:require`
21 | in any `.cljs` files in fileset. However, this causes the main file to
22 | require all the namespaces, even those that are unused.
23 |
24 | ## Related
25 |
26 | - [Boot-reload HUD messages](https://github.com/adzerk-oss/boot-reload/blob/master/doc/hud-messages.md)
27 |
--------------------------------------------------------------------------------
/src/adzerk/boot_cljs.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs
2 | {:boot/export-tasks true}
3 | (:refer-clojure :exclude [compile])
4 | (:require [adzerk.boot-cljs.js-deps :as deps]
5 | [adzerk.boot-cljs.middleware :as wrap]
6 | [adzerk.boot-cljs.util :as util]
7 | [boot.core :as core]
8 | [boot.pod :as pod]
9 | [boot.file :as file]
10 | [boot.util :refer [dbug info warn guard]]
11 | [clojure.java.io :as io]
12 | [clojure.pprint :as pp]
13 | [clojure.string :as string])
14 | (:import [java.util.concurrent ExecutionException]))
15 |
16 | (def cljs-version "1.7.228")
17 |
18 | (defn- cljs-dependency []
19 | (let [proj-deps (core/get-env :dependencies)
20 | cljs-dep? (first (filter (comp #{'org.clojure/clojurescript} first) proj-deps))
21 | cljs-exists? (io/resource "cljs/build/api.clj")]
22 | (cond
23 | ; org.clojure/clojurescript in project (non-transitive) deps - do nothing
24 | cljs-dep? nil
25 | ; cljs.core on classpath, org.clojure/clojurescript not in project deps
26 | cljs-exists? (do (warn "WARNING: No ClojureScript in project dependencies but ClojureScript was found in classpath. Adding direct dependency is advised.\n") nil)
27 | ; no cljs on classpath, no project dep, add cljs dep to pod
28 | :else ['org.clojure/clojurescript cljs-version])))
29 |
30 | (def ^:private deps
31 | "ClojureScript dependency to load in the pod if
32 | none is provided via project"
33 | (delay (filter identity [(cljs-dependency)
34 | ['ns-tracker "0.3.0"]])))
35 |
36 | (def ^:private QUALIFIERS
37 | "Order map for well-known Clojure version qualifiers."
38 | { "alpha" 0 "beta" 1 "rc" 2 "" 3})
39 |
40 | (defn- assert-clojure-version!
41 | "Warn user if Clojure 1.7 or greater is not found"
42 | [pod]
43 | (let [{:keys [major minor incremental qualifier]} (pod/with-eval-in pod *clojure-version*)
44 | [qualifier-part1 qualifier-part2] (if-let [[_ w d] (re-find #"(\w+)(\d+)" (or qualifier ""))]
45 | [(get QUALIFIERS w) (Integer/parseInt d)]
46 | [3 0])]
47 | (when-not (>= (compare [major minor incremental qualifier-part1 qualifier-part2] [1 7 0 3 0]) 0)
48 | (warn "ClojureScript requires Clojure 1.7 or greater.\nSee https://github.com/boot-clj/boot/wiki/Setting-Clojure-version.\n"))))
49 |
50 | (defn- read-cljs-edn
51 | [tmp-file]
52 | (let [file (core/tmp-file tmp-file)
53 | path (core/tmp-path tmp-file)]
54 | ;; FIXME: Better to use edn/read-string instead?
55 | (assoc (read-string (slurp file))
56 | :path (.getPath file)
57 | :rel-path path
58 | :id (string/replace (.getName file) #"\.cljs\.edn$" ""))))
59 |
60 | (defn- compile
61 | "Given a compiler context and a pod, compiles CLJS accordingly. Returns a
62 | seq of all compiled JS files known to the CLJS compiler in dependency order,
63 | as paths relative to the :output-to compiled JS file."
64 | [{:keys [tmp-src tmp-out main opts] :as ctx} macro-changes pod]
65 | (let [{:keys [output-dir]} opts
66 | rel-path #(.getPath (file/relative-to tmp-out %))]
67 | (pod/with-call-in pod
68 | (adzerk.boot-cljs.impl/reload-macros!))
69 | (pod/with-call-in pod
70 | (adzerk.boot-cljs.impl/backdate-macro-dependants! ~output-dir ~macro-changes))
71 | (let [{:keys [warnings exception] :as result}
72 | (pod/with-call-in pod
73 | (adzerk.boot-cljs.impl/compile-cljs ~(.getPath tmp-src) ~opts))]
74 | (swap! core/*warnings* + (or (count warnings) 0))
75 | (when exception
76 | (throw (util/deserialize-object exception)))
77 | (-> result
78 | (update-in [:dep-order] #(->> (conj % (:output-to opts)) (map rel-path)))
79 | (assoc :opts opts)))))
80 |
81 | (defn- macro-files-changed
82 | [diff]
83 | (->> (core/input-files diff)
84 | (core/by-ext [".clj" ".cljc"])
85 | (map core/tmp-path)))
86 |
87 | (defn main-files [fileset ids]
88 | (let [re-pat #(re-pattern (str "^\\Q" % "\\E\\.cljs\\.edn$"))
89 | select (if (seq ids)
90 | #(core/by-re (map re-pat ids) %)
91 | #(core/by-ext [".cljs.edn"] %))]
92 | (->> fileset
93 | core/input-files
94 | select
95 | (sort-by :path))))
96 |
97 | (defn- new-env [tmp-src]
98 | (-> (core/get-env)
99 | (update-in [:dependencies] into @deps)
100 | (update-in [:directories] conj (.getPath tmp-src))) )
101 |
102 | (defn- make-compiler
103 | [cljs-edn-content]
104 | (let [tmp-src (core/tmp-dir!)
105 | env (new-env tmp-src)]
106 | {:initial-ctx {:tmp-src tmp-src
107 | :tmp-out (core/tmp-dir!)
108 | :main-ns-name (name (gensym "main"))}
109 | :pod (future
110 | (doto (pod/make-pod env)
111 | (assert-clojure-version!)))}))
112 |
113 | (defn assert-cljs-edn!
114 | "Validate boot-cljs specific .cljs.edn options.
115 |
116 | Check https://github.com/boot-clj/boot-cljs/blob/master/docs/cljs.edn.md
117 | for documentation about options."
118 | [{:keys [main] :as ctx}]
119 | (assert (and (every? (fn [v]
120 | (and (symbol? v) (not (namespace v))))
121 | (:require main)))
122 | (str "Every .cljs.edn :require item should be a symbol referring to a namespace, "
123 | "i.e. symbol should only have a name:\n"
124 | (:require main)))
125 |
126 | (assert (and (every? (fn [v]
127 | (and (symbol? v) (and (namespace v) (name v))))
128 | (:init-fns main)))
129 | (str "Every .cljs.edn :init-fns item should a be symbol referring to a function, "
130 | "i.e. symbol should have both a namespace and a name:\n"
131 | (:init-fns main)))
132 |
133 | ctx)
134 |
135 | (defn- compile-1
136 | [compilers task-opts macro-changes write-main? {:keys [path] :as cljs-edn} deps-changed?]
137 | (let [cljs-edn-content (read-cljs-edn cljs-edn)
138 | _ (swap! compilers (fn [compilers]
139 | (if (contains? compilers path)
140 | compilers
141 | (assoc compilers path (make-compiler cljs-edn-content)))))
142 |
143 | {:keys [pod initial-ctx]} (get @compilers path)
144 | ctx (-> initial-ctx
145 | (assoc :main cljs-edn-content)
146 | (assert-cljs-edn!)
147 | (wrap/compiler-options task-opts)
148 | (wrap/main write-main?)
149 | (wrap/modules)
150 | wrap/source-map
151 | wrap/non-standard-defaults)
152 | tmp (:tmp-out initial-ctx)
153 | out (.getPath (file/relative-to tmp (-> ctx :opts :output-to)))]
154 |
155 | (when deps-changed?
156 | (pod/add-dependencies-in @pod (new-env (:tmp-src initial-ctx))))
157 |
158 | (info "• %s\n" out)
159 | (dbug "CLJS options:\n%s\n" (with-out-str (pp/pprint (:opts ctx))))
160 | (future (compile ctx macro-changes @pod))))
161 |
162 | (core/deftask ^:private default-main
163 | "Private task.
164 |
165 | If no .cljs.edn exists with given id, creates one. This default .cljs.edn file
166 | will :require all CLJS namespaces found in the fileset."
167 | [i ids IDS #{str} ""]
168 | (let [tmp-main (core/tmp-dir!)]
169 | (core/with-pre-wrap fileset
170 | (core/empty-dir! tmp-main)
171 | (if (seq (main-files fileset ids))
172 | fileset
173 | (let [remove-deps-cljs #(core/by-name ["deps.cljs"] % true)
174 | cljs (->> fileset core/input-files (core/by-ext [".cljs" ".cljc"]) remove-deps-cljs (sort-by :path))
175 | out-main (str (or (first ids) "main") ".cljs.edn")
176 | out-file (io/file tmp-main out-main)]
177 | (info "Writing %s...\n" (.getName out-file))
178 | (doto out-file
179 | (io/make-parents)
180 | (spit {:require (mapv (comp symbol util/path->ns core/tmp-path) cljs)}))
181 | (-> fileset (core/add-source tmp-main) core/commit!))))))
182 |
183 | (defn- remove-previous-cljs-output
184 | [fileset]
185 | (core/rm fileset (filter ::output (core/ls fileset))))
186 |
187 | (defn- cljs-output-meta
188 | [dir]
189 | (-> (file-seq dir)
190 | (->> (filter #(.isFile %))
191 | (map #(.getPath (file/relative-to dir %))))
192 | (zipmap (repeat {::output true}))))
193 |
194 | (defn- cljs-warnings-meta
195 | [cljs-edns results]
196 | (zipmap (map :path cljs-edns)
197 | (map (fn [r] {::warnings (:warnings r)})
198 | results)))
199 |
200 | (defn- cljs-opts-meta
201 | [cljs-edns results]
202 | (zipmap (map :path cljs-edns)
203 | (map (fn [r] {::opts (:opts r)})
204 | results)))
205 |
206 | (core/deftask cljs
207 | "Compile ClojureScript applications.
208 |
209 | Multiple builds can be compiled parallel. To define builds use .cljs.edn
210 | files. ID of build is the name of .cljs.edn file without the extension.
211 | To compile only specific builds, use ids option to select .cljs.edn files
212 | by name. Output files of build will be put below id.out folder in fileset.
213 |
214 | If no .cljs.edn files exists, default one is created. It will depend on
215 | all .cljs files in fileset.
216 |
217 | Available --optimizations levels (default 'none'):
218 |
219 | * none No optimizations. Bypass the Closure compiler completely.
220 | * whitespace Remove comments, unnecessary whitespace, and punctuation.
221 | * simple Whitespace + local variable and function parameter renaming.
222 | * advanced Simple + aggressive renaming, inlining, dead code elimination.
223 |
224 | Source maps can be enabled via the --source-map flag. This provides what the
225 | browser needs to map locations in the compiled JavaScript to the corresponding
226 | locations in the original ClojureScript source files.
227 |
228 | The --compiler-options option can be used to set any other options that should
229 | be passed to the Clojurescript compiler. A full list of options can be found
230 | here: https://github.com/clojure/clojurescript/wiki/Compiler-Options.
231 |
232 | Cljs compiler options are merged in this order:
233 |
234 | 1. :compiler-options in .cljs.edn file
235 | 2. :compiler-options task option
236 | 3. :optimizations and :source-map task options
237 | 4. options automatically set by boot-cljs (:output-dir, :output-to, :main)"
238 |
239 | [i ids IDS #{str} ""
240 | O optimizations LEVEL kw "The optimization level."
241 | s source-map bool "Create source maps for compiled JS."
242 | c compiler-options OPTS edn "Options to pass to the Clojurescript compiler."]
243 |
244 | (let [tmp-result (core/tmp-dir!)
245 | compilers (atom {})
246 | prev (atom nil)
247 | prev-deps (atom (core/get-env :dependencies))]
248 | (comp
249 | (default-main :ids ids)
250 | (core/with-pre-wrap fileset
251 | (info "Compiling ClojureScript...\n")
252 | ;; If there are any output files from other instances of the cljs
253 | ;; task in the pipeline we need to remove them from the classpath
254 | ;; or the cljs compiler will try to use them during compilation.
255 | (-> fileset remove-previous-cljs-output core/commit!)
256 | (let [diff (core/fileset-diff @prev fileset)
257 | macro-changes (macro-files-changed diff)
258 | cljs-edns (main-files fileset ids)
259 | changed-cljs-edns (->> diff core/input-files (core/by-ext [".cljs.edn"]) set)
260 |
261 | ;; Check if the dependencies have changed since last time
262 | new-deps (core/get-env :dependencies)
263 | deps-changed? (not= @prev-deps new-deps)
264 | _ (when deps-changed?
265 | (info "Project dependencies have changed, updating Boot-cljs pods...\n"))
266 | _ (reset! prev-deps new-deps)
267 |
268 | ;; Force realization to start compilation
269 | futures (doall (map (fn [cljs-edn]
270 | (let [write-main? (contains? changed-cljs-edns cljs-edn)]
271 | (compile-1 compilers *opts* macro-changes write-main? cljs-edn deps-changed?)))
272 | cljs-edns))
273 | ;; Wait for all compilations to finish
274 | ;; Remove unnecessary layer of cause stack added by futures
275 | results (try (doall (map deref futures))
276 | (catch ExecutionException e
277 | (throw (.getCause e))))
278 | ;; Since each build has its own :output-dir we don't need to do
279 | ;; anything special to merge dependency ordering of files across
280 | ;; builds. Each :output-to js file will depend only on compiled
281 | ;; namespaces in its own :output-dir, including goog/base.js etc.
282 | dep-order (reduce into [] (map :dep-order results))]
283 | (reset! prev fileset)
284 | (->> (vals @compilers)
285 | (map #(get-in % [:initial-ctx :tmp-out]))
286 | (apply core/sync! tmp-result))
287 | (-> fileset
288 | (core/add-resource tmp-result)
289 | ;; Add warnings to .cljs.edn files metadata so other tasks
290 | ;; can use this information and report it to users
291 | (core/add-meta (cljs-warnings-meta cljs-edns results))
292 | (core/add-meta (cljs-opts-meta cljs-edns results))
293 | ;; Add metadata to mark the output of this task so subsequent
294 | ;; instances of the cljs task can remove them before compiling.
295 | (core/add-meta (cljs-output-meta tmp-result))
296 | (core/add-meta (deps/compiled fileset dep-order))
297 | core/commit!))))))
298 |
--------------------------------------------------------------------------------
/src/adzerk/boot_cljs/impl.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.impl
2 | (:require [boot.file :as file]
3 | [boot.kahnsort :as kahn]
4 | [boot.pod :as pod]
5 | [boot.util :as butil]
6 | [clojure.string :as str]
7 | [clojure.edn :as edn]
8 | [cljs.analyzer :as ana]
9 | [cljs.env :as env]
10 | [cljs.analyzer.api :as ana-api :refer [warning-enabled?]]
11 | [cljs.build.api :as build-api :refer [build inputs target-file-for-cljs-ns]]
12 | [clojure.java.io :as io]
13 | [adzerk.boot-cljs.util :as util]
14 | [ns-tracker.core :refer [ns-tracker]]))
15 |
16 | ; Because this ns is loaded in pod, it's private to one cljs task.
17 | ; Compiler env is a atom.
18 | (def ^:private stored-env (atom nil))
19 |
20 | (defn ns-dependencies
21 | "Given a namespace as a symbol return list of namespaces required by the namespace."
22 | ; ([ns] (ns-dependencies env/*compiler* ns))
23 | ([state ns]
24 | (vals (:requires (ana-api/find-ns state ns)))))
25 |
26 | (defn cljs-dependency-graph [state]
27 | (let [all-ns (ana-api/all-ns state)
28 | all-ns-set (set all-ns)]
29 | (->> all-ns
30 | (reduce (fn [acc n]
31 | (assoc acc n (->> (ns-dependencies state n)
32 | (keep all-ns-set)
33 | (set))))
34 | {}))))
35 |
36 | (defn dep-order [env opts]
37 | (->> (cljs-dependency-graph env)
38 | (kahn/topo-sort)
39 | reverse
40 | (map #(.getPath (target-file-for-cljs-ns % (:output-dir opts))))
41 | vec))
42 |
43 | ;; Checks if https://github.com/boot-clj/boot/commit/c07b08751ad195e6e6349cb7c2f826c95a8e8186
44 | ;; is present.
45 | ;; The change will preserve %% as % are escapted before format, and will add newline.
46 | (def new-boot?
47 | (try
48 | (let [message (with-out-str
49 | (binding [*err* *out*]
50 | (butil/print-ex (ex-info "%%s" {:boot.util/omit-stacktrace? true}))))]
51 | (and message
52 | (.contains message "%%")
53 | (.contains message "\n")))
54 | (catch Throwable _
55 | false)))
56 |
57 | (defn- ensure-ends-in-newline [s]
58 | (if s
59 | (if (.endsWith s "\n")
60 | s
61 | (str s "\n"))))
62 |
63 | (defn- escape-format-string [s]
64 | (str/replace s #"%" "%%"))
65 |
66 | (defn handle-ex
67 | "Rethrows an interesting exception if possible or the original exception.
68 |
69 | Exception is interesting when it has either type or tag ex-data set by cljs compiler.
70 |
71 | If ex-data has file property, it is changed to contain path in original source-paths.
72 | Exceptino message is rewriten to contain fixed path."
73 | [e source-paths dirs]
74 | (let [{:keys [type tag file line] :as data} (util/merge-cause-ex-data e)
75 | column (or (:col data) (:column data))
76 |
77 | ; Get the message without location info
78 | message (util/last-cause-message e)
79 | ; Sometimes filepath is a URI
80 | file (if file (str/replace file #"^file:" ""))
81 | real-file (util/find-original-path source-paths dirs file)
82 | ; Replace tmpdir path with real file path
83 | message (if (and message file real-file)
84 | (.replace message file real-file)
85 | message)
86 | file real-file
87 | ; Add file info if message doesn't contain it but it is available
88 | message (if (and message file (not (str/includes? message file)))
89 | (str
90 | (if file (str file " "))
91 | (if (or line column)
92 | (str "["
93 | (if line (str "line " line))
94 | (if column (str ", col " column))
95 | "] "))
96 | message)
97 | message)
98 | ;; E.g. (defmacro foo [] (+ nil nil)) will cause exception where
99 | ;; message is only " at line ..."
100 | message (if (str/starts-with? message " at line ")
101 | (str "Compilation failed" message)
102 | message)
103 | ;; NOTE: This probably matches any errors from macro compilation
104 | cljs-error? (or (= :reader-exception type)
105 | (= :cljs/analysis-error tag))]
106 |
107 | (ex-info
108 | ;; For now, when Boot shows the message with omit-stacktrace, no newline is automatically appended
109 | (if new-boot?
110 | message
111 | (-> message ensure-ends-in-newline escape-format-string))
112 | (if cljs-error?
113 | ;; Skip ex-data if it won't even be shown. This will avoid some serialization errors,
114 | ;; as compiler or spec errors from macros only really need the message anyway.
115 | {:boot.util/omit-stacktrace? true}
116 | (-> data
117 | (assoc :from :boot-cljs)
118 | (cond->
119 | file (assoc :file file)))))))
120 |
121 | (defn compile-cljs
122 | "Given a seq of directories containing CLJS source files and compiler options
123 | opts, compiles the CLJS to produce JS files."
124 | [input-path {:keys [optimizations] :as opts}]
125 | ;; So directories need to be passed to cljs compiler when compiling in dev
126 | ;; or there are stale namespace problems with tests. However, if compiling
127 | ;; with optimizations other than :none adding directories will break the
128 | ;; build and defeat tree shaking and :main option.
129 | (let [dirs (:directories pod/env)
130 | ; Includes also some tmp-dirs passed to this pod, but shouldn't matter
131 | source-paths (concat (:source-paths pod/env) (:resource-paths pod/env))
132 | warnings (atom [])
133 | handler (fn [warning-type env extra]
134 | (when (warning-enabled? warning-type)
135 | (when-let [s (ana/error-message warning-type extra)]
136 | (let [path (if (= (-> env :ns :name) 'cljs.core)
137 | "cljs/core.cljs"
138 | (util/find-original-path source-paths dirs ana/*cljs-file*))
139 | warning-data {:line (:line env)
140 | :column (:column env)
141 | :ns (-> env :ns :name)
142 | :file path
143 | :type warning-type
144 | :message s
145 | ;; :fn-deprecated warning contains the whole
146 | ;; analyze result as extra data, and :env value
147 | ;; of that is unprintable.
148 | :extra (cond-> extra
149 | (:fexpr extra) (update :fexpr dissoc :env))}]
150 | (butil/warn (str "WARNING: "
151 | s
152 | (if (:line env)
153 | (str " at line " (:line env) " " path)
154 | (when path
155 | (str " in file " path)))
156 | "\n"))
157 | (butil/dbug* "%s\n" (butil/pp-str warning-data))
158 | (swap! warnings conj warning-data)))))]
159 | ;; ana-api/empty-state doesn't take options, so need to use this instead
160 | (swap! stored-env #(or % (env/default-compiler-env opts)))
161 | (try
162 | (build
163 | (inputs input-path)
164 | (assoc opts :warning-handlers [handler])
165 | @stored-env)
166 | {:warnings @warnings
167 | :dep-order (dep-order @stored-env opts)}
168 | (catch Exception e
169 | (let [ex (handle-ex e source-paths dirs)]
170 | (try
171 | {:exception (util/serialize-object ex)}
172 | (catch Exception e
173 | (butil/warn "Exception couldn't be serialized properly: %s, rethrowing original exception but it won't formatted perfectly. Please report this bug.\n" (.getMessage e))
174 | (throw ex))))))))
175 |
176 |
177 | (def tracker (atom nil))
178 |
179 | (defn reload-macros! []
180 | (let [dirs (:directories pod/env)]
181 | (when (nil? @tracker)
182 | (reset! tracker (ns-tracker (vec dirs))))
183 | ; Reload only namespaces which are already loaded
184 | ; As opposed to :reload-all, ns-tracker only reloads namespaces which are really changed.
185 | (doseq [s (filter find-ns (@tracker))]
186 | (butil/dbug "Reload macro ns: %s\n" s)
187 | (require s :reload))))
188 |
189 | (defn backdate-macro-dependants!
190 | [output-dir changed-files]
191 | (if @stored-env
192 | (doseq [cljs-ns (->> changed-files
193 | (map (comp symbol util/path->ns))
194 | (build-api/cljs-dependents-for-macro-namespaces @stored-env))]
195 | ; broken
196 | ; (build-api/mark-cljs-ns-for-recompile! cljs-ns output-dir)
197 | (let [f (build-api/target-file-for-cljs-ns cljs-ns output-dir)]
198 | (when (.exists f)
199 | (butil/dbug "Backdate macro dependant cljs ns: %s\n" cljs-ns)
200 | (.setLastModified f 5000))))))
201 |
--------------------------------------------------------------------------------
/src/adzerk/boot_cljs/js_deps.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.js-deps)
2 |
3 | (defn- max* [& args] (apply max (or (seq args) [0])))
4 |
5 | (defn- start-dep-order
6 | "Returns the next dependency order index, one greater than the maximum dep
7 | order index in the given metadata map (path => {:dependency-order n})."
8 | [maps]
9 | (->> maps (keep :dependency-order) (apply max*) inc))
10 |
11 | (defn compiled
12 | "Given a dep order metadata map (path => {:dependency-order n}) and a seq of
13 | fileset paths in dependency order, creates a new metadata map adding entries
14 | for the paths such that the paths depend on the preexisting entries."
15 | [dep-order-meta paths]
16 | (let [start (->> dep-order-meta vals start-dep-order)]
17 | (->> paths
18 | (map-indexed (fn [a b] [b {:dependency-order (+ start a)}]))
19 | (into dep-order-meta))))
20 |
21 | (defn analyzed
22 | [analysis-meta]
23 | (reduce-kv (fn [xs k v] (assoc xs k {:cljs-analysis v})) {} analysis-meta))
24 |
--------------------------------------------------------------------------------
/src/adzerk/boot_cljs/middleware.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.middleware
2 | (:require [adzerk.boot-cljs.util :as util]
3 | [boot.file :as file]
4 | [boot.util :as butil]
5 | [clojure.java.io :as io]
6 | [clojure.string :as string]))
7 |
8 | ;; helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 |
10 | (defn- main-ns-forms
11 | "Given a namespace symbol, ns-sym, a sorted set of namespace symbols this
12 | namespace will :require, requires, and a vector of namespace-qualified
13 | symbols, init-fns, constructs the forms for a namespace named ns-sym that
14 | :requires the namespaces in requires and calls the init-fns with no arguments
15 | at the top level."
16 | [ns-sym requires init-fns]
17 | (apply list
18 | (list 'ns ns-sym (apply list :require requires))
19 | (map list init-fns)))
20 |
21 | (defn- format-ns-forms
22 | "Given a sequence of forms, formats them nicely as a string."
23 | [forms]
24 | (->> forms (map pr-str) (string/join "\n\n") (format "%s\n")))
25 |
26 | (defn- cljs-edn-path->output-dir-path
27 | [cljs-edn-path]
28 | (str (.replaceAll cljs-edn-path "\\.cljs\\.edn$" "") ".out"))
29 |
30 | (defn- cljs-edn-path->js-path
31 | [cljs-edn-path]
32 | (str (.replaceAll cljs-edn-path "\\.cljs\\.edn$" "") ".js"))
33 |
34 | ;; middleware ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
35 |
36 | (defn compiler-options
37 | [{:keys [opts main] :as ctx}
38 | {:keys [compiler-options] :as task-options}]
39 | (assoc ctx :opts (merge (:compiler-options main)
40 | compiler-options
41 | (select-keys task-options [:optimizations :source-map]))))
42 |
43 | (defn set-option [ctx k value]
44 | (when-let [current-value (get-in ctx [:opts k])]
45 | (butil/warn "WARNING: Replacing ClojureScript compiler option %s with automatically set value.\n" k))
46 | (assoc-in ctx [:opts k] value))
47 |
48 | (defn main
49 | "Middleware to create the CLJS namespace for the build's .cljs.edn file and
50 | set the compiler :output-to option accordingly. The :output-to will be derived
51 | from the path of the .cljs.edn file (e.g. foo/bar.cljs.edn will produce the
52 | foo.bar CLJS namespace with output to foo/bar.js)."
53 | [{:keys [tmp-src tmp-out main main-ns-name] :as ctx} write-main?]
54 | (let [out-rel-path (if-let [output-dir (:output-dir (:opts ctx))]
55 | output-dir
56 | (cljs-edn-path->output-dir-path (:rel-path main)))
57 | asset-path out-rel-path
58 | out-file (io/file tmp-out out-rel-path)
59 | out-path (.getPath out-file)
60 | js-path (if-let [output-to (:output-to (:opts ctx))]
61 | (util/path tmp-out output-to)
62 | (util/path tmp-out (cljs-edn-path->js-path (:rel-path main))))
63 |
64 | cljs-path (util/path "boot" "cljs" (str main-ns-name ".cljs"))
65 | cljs-file (io/file tmp-src cljs-path)
66 | cljs-ns (symbol (util/path->ns cljs-path))
67 | init-fns (:init-fns main)
68 | requires (into (sorted-set) (:require main))
69 | ;; We set out own shim ns as :main, but if user provides :main,
70 | ;; include that in our shim ns requires
71 | requires (if-let [main (:main (:opts ctx))]
72 | (conj requires (symbol main))
73 | requires)
74 | init-nss (into requires (->> init-fns (keep namespace) (map symbol)))]
75 | (.mkdirs out-file)
76 | (when write-main?
77 | (doto cljs-file
78 | (io/make-parents)
79 | (spit (format-ns-forms (main-ns-forms cljs-ns init-nss init-fns)))))
80 | (-> ctx
81 | (update-in [:opts :asset-path] #(if % % asset-path))
82 | (assoc-in [:opts :output-dir] out-path)
83 | (assoc-in [:opts :output-to] js-path)
84 | (assoc-in [:opts :main] cljs-ns))))
85 |
86 | (defn modules
87 | "Updates :modules :output-to paths under :compiler-options
88 |
89 | If module declaration has :output-to, the path is prepended with
90 | path to Boot-cljs temp directory.
91 |
92 | If :output-to is not set, default value is created based on
93 | the temp directory, relative path of the .cljs.edn file and module name."
94 | [{:keys [tmp-out main] :as ctx}]
95 | (when (:modules main)
96 | (butil/warn "WARNING: .cljs.edn :modules option is no longer supported, please set :modules under :compiler-options.\n"))
97 | (if (contains? (:opts ctx) :modules)
98 | (update-in ctx [:opts :modules]
99 | (fn [modules]
100 | (into (empty modules)
101 | (map (fn [[k v]]
102 | [k (if-let [output-to (:output-to v)]
103 | (assoc v :output-to (util/path tmp-out output-to))
104 | (assoc v :output-to (util/path (-> ctx :opts :output-dir) (str (name k) ".js"))))])
105 | modules))))
106 | ctx))
107 |
108 | (defn source-map
109 | "Middleware to configure source map related CLJS compiler options."
110 | [{:keys [opts] :as ctx}]
111 | (if (contains? opts :source-map)
112 | (let [optimizations (:optimizations opts :none)
113 | ; Under :none optimizations only true and false are valid values
114 | ; Same if :modules is used.
115 | ; https://github.com/clojure/clojurescript/wiki/Compiler-Options#source-map
116 | sm (if (or (= optimizations :none) (:modules opts))
117 | (boolean (:source-map opts))
118 | ;; If path is already provided, use that
119 | (if (string? (:source-map opts))
120 | (:source-map opts)
121 | ;; If non-path is provided, generate path, if the given value is truthy
122 | (and (:source-map opts) (-> opts :output-to (str ".map")))))]
123 | (assoc-in ctx [:opts :source-map] sm))
124 | ctx))
125 |
126 | (defn non-standard-defaults
127 | "Sets defaults differing from the ones provided by the ClojureScript compiler."
128 | [{:keys [opts] :as ctx}]
129 | (let [advanced? (= :advanced (:optimizations opts))]
130 | (cond-> ctx
131 | (and advanced? (nil? (:output-wrapper opts)))
132 | (assoc-in [:opts :output-wrapper] true))))
133 |
--------------------------------------------------------------------------------
/src/adzerk/boot_cljs/util.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.util
2 | (:require [clojure.java.io :as io]
3 | [clojure.string :as string]
4 | [boot.file :as file])
5 | (:import [java.util Base64]
6 | [java.io ObjectInputStream ObjectOutputStream ByteArrayOutputStream ByteArrayInputStream]))
7 |
8 | (defn path->js
9 | "Given a path to a CLJS namespace source file, returns the corresponding
10 | Google Closure namespace name for goog.provide() or goog.require()."
11 | [path]
12 | (-> path
13 | (string/replace #"\.clj([s|c])?$" "")
14 | (string/replace #"[/\\]" ".")))
15 |
16 | (defn path->ns
17 | "Given a path to a CLJS namespace source file, returns the corresponding
18 | CLJS namespace name."
19 | [path]
20 | (-> (path->js path) (string/replace #"_" "-")))
21 |
22 | (defn get-name
23 | [path-or-file]
24 | (-> path-or-file io/file .getName))
25 |
26 | (defn path [& parts]
27 | (.getPath (apply io/file parts)))
28 |
29 | (defn find-relative-path [dirs filepath]
30 | (if-let [file (io/file filepath)]
31 | (let [parent (->> dirs
32 | (map io/file)
33 | (some (fn [x] (if (file/parent? x file) x))))]
34 | (if parent (.getPath (file/relative-to parent file))))))
35 |
36 | (defn find-original-path [source-paths dirs filepath]
37 | (if-let [rel-path (find-relative-path dirs filepath)]
38 | (or (some (fn [source-path]
39 | (let [f (io/file source-path rel-path)]
40 | (if (.exists f)
41 | (.getPath f))))
42 | source-paths)
43 | rel-path)
44 | filepath))
45 |
46 | ;;
47 | ;; Object serialization
48 | ;;
49 |
50 | (defn serialize-object
51 | "Serialize given Object to String using Object Streams and encode the bytes
52 | as Base64 string."
53 | [e]
54 | (with-open [bos (ByteArrayOutputStream.)
55 | out (ObjectOutputStream. bos)]
56 | (.writeObject out e)
57 | (.encodeToString (Base64/getEncoder) (.toByteArray bos))))
58 |
59 | (defn deserialize-object
60 | "Deserialize given Base64 encoding string using Object Streams and return the
61 | Object."
62 | [ba]
63 | (with-open [bis (ByteArrayInputStream. (.decode (Base64/getDecoder) ba))
64 | in (ObjectInputStream. bis)]
65 | (.readObject in)))
66 |
67 | (defn merge-cause-ex-data
68 | "Merges ex-data from all exceptions in cause stack. First value for a key is
69 | used."
70 | [ex]
71 | (loop [ex ex
72 | data {}]
73 | (if-let [c (.getCause ex)]
74 | (recur c (merge (ex-data ex) data))
75 | (merge (ex-data ex) data))))
76 |
77 | (defn last-cause [ex]
78 | (loop [ex ex]
79 | (if (.getCause ex)
80 | (recur (.getCause ex))
81 | ex)))
82 |
83 | (defn last-cause-message [ex]
84 | (loop [ex ex
85 | last-msg (.getMessage ex)]
86 | (if-let [c (.getCause ex)]
87 | (recur c (or (.getMessage c) last-msg))
88 | last-msg)))
89 |
--------------------------------------------------------------------------------
/test/adzerk/boot_cljs/impl_test.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.impl-test
2 | (:require [clojure.test :refer :all]
3 | [adzerk.boot-cljs.impl :refer :all]
4 | [clojure.java.io :as io]
5 | [clojure.string :as string]
6 | [boot.from.io.aviso.exception :as pretty]
7 | [boot.from.io.aviso.ansi :as ansi]
8 | [boot.util :as util :refer [*verbosity* fail]]))
9 |
10 | (defn delete-dir [dir]
11 | (doseq [f (file-seq dir)
12 | :when (.isFile f)]
13 | (.delete f))
14 | (doseq [f (file-seq dir)
15 | :when (.isDirectory f)]
16 | (.delete f))
17 | (.delete dir))
18 |
19 | (deftest handle-ex-test
20 | (with-redefs [adzerk.boot-cljs.impl/new-boot? true]
21 | (let [source-dir (io/file "boot-cljs-handle-ex-test")
22 | core-cljs-file (io/file source-dir "frontend" "core.cljs")]
23 | (delete-dir source-dir)
24 |
25 | ;; Setup mock source for finding the original source path
26 | (io/make-parents core-cljs-file)
27 | (spit core-cljs-file "")
28 |
29 | (testing "old error format"
30 | (let [e (handle-ex (ex-info "Unmatched delimiter )"
31 | {:type :reader-exception
32 | :file "/home/juho/.boot/cache/tmp/home/juho/Source/saapas/obh/uanrg/frontend/core.cljs"
33 | :line 30
34 | :column 67})
35 | [(.getPath source-dir)]
36 | ["/home/juho/.boot/cache/tmp/home/juho/Source/saapas/obh/uanrg"])]
37 | (is (= "boot-cljs-handle-ex-test/frontend/core.cljs [line 30, col 67] Unmatched delimiter )" (.getMessage e)))
38 | (is (= "boot-cljs-handle-ex-test/frontend/core.cljs" (:file (ex-data e))))))
39 |
40 | (testing "new error format"
41 | (let [e (handle-ex (ex-info "/home/juho/.boot/cache/tmp/home/juho/Source/saapas/obh/uanrg/frontend/core.cljs [line 30, col 67] Unmatched delimiter )."
42 | {:type :reader-exception
43 | :ex-kind :reader-error
44 | :file "/home/juho/.boot/cache/tmp/home/juho/Source/saapas/obh/uanrg/frontend/core.cljs"
45 | :line 30
46 | :col 67})
47 | [(.getPath source-dir)]
48 | ["/home/juho/.boot/cache/tmp/home/juho/Source/saapas/obh/uanrg"])]
49 | (is (= "boot-cljs-handle-ex-test/frontend/core.cljs [line 30, col 67] Unmatched delimiter )." (.getMessage e)))
50 | (is (= "boot-cljs-handle-ex-test/frontend/core.cljs" (:file (ex-data e))))))
51 |
52 | (delete-dir source-dir))))
53 |
54 | ;; From 2.7.1
55 | (defn old-print-ex
56 | [ex]
57 | (cond
58 | (= 0 @*verbosity*) nil
59 | (::omit-stacktrace? (ex-data ex)) (fail (.getMessage ex))
60 | (= 1 @*verbosity*) (pretty/write-exception *err* ex nil)
61 | (= 2 @*verbosity*) (pretty/write-exception *err* ex {:filter nil})
62 | :else (binding [*out* *err*] (.printStackTrace ex))))
63 |
64 | ;; From 2.7.2
65 | (defn- ensure-ends-in-newline [s]
66 | (if s
67 | (if (.endsWith s "\n")
68 | s
69 | (str s "\n"))))
70 |
71 | (defn- escape-format-string [s]
72 | (string/replace s #"%" "%%"))
73 |
74 | (defn new-print-ex
75 | [ex]
76 | (cond
77 | (= 0 @*verbosity*) nil
78 | (::omit-stacktrace? (ex-data ex)) (fail (-> (.getMessage ex) escape-format-string ensure-ends-in-newline))
79 | (= 1 @*verbosity*) (pretty/write-exception *err* ex nil)
80 | (= 2 @*verbosity*) (pretty/write-exception *err* ex {:filter nil})
81 | :else (binding [*out* *err*] (.printStackTrace ex))))
82 |
83 | (deftest ex-message-print-test
84 | (is (= "Missing symbol foo%asd\n"
85 | (ansi/strip-ansi
86 | (with-out-str
87 | (binding [*err* *out*]
88 | (old-print-ex (ex-info "Missing symbol foo%%asd\n" {::omit-stacktrace? true})))))))
89 |
90 | (is (= "Missing symbol foo%asd\n"
91 | (ansi/strip-ansi
92 | (with-out-str
93 | (binding [*err* *out*]
94 | (new-print-ex (ex-info "Missing symbol foo%asd" {::omit-stacktrace? true}))))))))
95 |
--------------------------------------------------------------------------------
/test/adzerk/boot_cljs/middleware_test.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.middleware-test
2 | (:require [clojure.test :refer :all]
3 | [adzerk.boot-cljs.middleware :refer :all]
4 | [clojure.java.io :as io]
5 | [clojure.stacktrace :as st]
6 | [clojure.string :as string]))
7 |
8 | (deftest source-map-test
9 | (is (= {:opts {:source-map true}}
10 | (source-map {:opts {:source-map true}})))
11 |
12 | (is (= {:opts {:source-map true
13 | :optimizations :none}}
14 | (source-map {:opts {:source-map true
15 | :optimizations :none}})))
16 |
17 | (testing "source-map boolean is replaced with path when doing optimized build"
18 | (is (= {:opts {:source-map "main.js.map"
19 | :output-to "main.js"
20 | :optimizations :advanced}}
21 | (source-map {:opts {:source-map true
22 | :optimizations :advanced
23 | :output-to "main.js"}}))))
24 |
25 | (testing "if source-map disabled, not path added for optimized builds"
26 | (is (= {:opts {:source-map false
27 | :output-to "main.js"
28 | :optimizations :advanced}}
29 | (source-map {:opts {:source-map false
30 | :optimizations :advanced
31 | :output-to "main.js"}})))
32 |
33 | (is (= {:opts {:source-map false
34 | :output-to "main.js"
35 | :optimizations :simple}}
36 | (source-map {:opts {:source-map false
37 | :optimizations :simple
38 | :output-to "main.js"}}))))
39 |
40 | (testing "if source-map path is provided, use that"
41 | (is (= {:opts {:source-map "hello.js.map"
42 | :output-to "main.js"
43 | :optimizations :simple}}
44 | (source-map {:opts {:source-map "hello.js.map"
45 | :optimizations :simple
46 | :output-to "main.js"}})))))
47 |
--------------------------------------------------------------------------------
/test/adzerk/boot_cljs/util_test.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs.util-test
2 | (:require [clojure.test :refer :all]
3 | [adzerk.boot-cljs.util :refer :all]
4 | [clojure.java.io :as io]
5 | [clojure.stacktrace :as st]
6 | [clojure.string :as string]))
7 |
8 | (deftest find-relative-path-test
9 | (is (= "src/foo/bar.clj" (find-relative-path ["/foo" "/bar"] "/foo/src/foo/bar.clj")))
10 | (is (= nil (find-relative-path ["/foo" "/bar"] nil))))
11 |
12 | (def pwd (.getAbsolutePath (io/file "")))
13 |
14 | (deftest find-original-path-test
15 | (testing "file doesn't exist in source-paths - returns relative path"
16 | (is (= "foo/bar.clj" (find-original-path ["src" "test"] ["/foo" "/bar"] "/foo/foo/bar.clj"))))
17 | (testing "existing file - returns path with original source-path"
18 | (is (= "src/adzerk/boot_cljs.clj" (find-original-path ["src" "test"] ["/foo" "/bar"] "/foo/adzerk/boot_cljs.clj")))))
19 |
20 | (deftest basic-exception-test
21 | (let [original (Exception. "foo")
22 | a (deserialize-object (serialize-object original))]
23 | (is (= "foo" (.getMessage a)))))
24 |
25 | (deftest ex-data-test
26 | (let [original (ex-info "foo" {:a 1})
27 | a (deserialize-object (serialize-object original))]
28 | (is (= "foo" (.getMessage a)))
29 | (is (= {:a 1} (ex-data a)))))
30 |
31 | (deftest cause-test
32 | (let [original (Exception. "foo" (Exception. "bar"))
33 | a (deserialize-object (serialize-object original))]
34 | (is (= "bar" (.getMessage (.getCause a))))))
35 |
36 | (defn drop-first-line [s]
37 | (-> s
38 | (string/split #"\n")
39 | rest
40 | (->> (string/join "\n"))))
41 |
42 | (deftest stack-trace-test
43 | (let [original (Exception. "foo")
44 | a (deserialize-object (serialize-object original))]
45 | (is (= (with-out-str (st/print-stack-trace original))
46 | (with-out-str (st/print-stack-trace a))))))
47 |
48 | (deftest merge-cause-ex-data-test
49 | (is (= {:a 1 :b 2} (merge-cause-ex-data (ex-info "a" {:a 1} (ex-info "b" {:b 2}))))))
50 |
51 | (deftest last-cause-message-test
52 | (is (= "a" (last-cause-message (Exception. "a"))))
53 | (is (= "b" (last-cause-message (Exception. "a" (Exception. "b")))))
54 | (is (= "c" (last-cause-message (Exception. "a" (Exception. "b" (Exception. "c"))))))
55 | (is (= "b" (last-cause-message (Exception. "a" (Exception. "b" (Exception.))))))
56 | (is (= "b" (last-cause-message (Exception. "a" (Exception. (Exception. "b"))))))
57 | )
58 |
--------------------------------------------------------------------------------
/test/adzerk/boot_cljs_test.clj:
--------------------------------------------------------------------------------
1 | (ns adzerk.boot-cljs-test
2 | (:require
3 | [boot.pod :as pod]
4 | [clojure.test :refer :all]))
5 |
6 | (def pod-env
7 | '{:dependencies [[net.sourceforge.htmlunit/htmlunit "2.18"]]})
8 |
9 | (def hunit-pod
10 | (delay (doto (pod/make-pod pod-env)
11 | (pod/with-eval-in
12 | (import
13 | [java.util.logging Logger Level]
14 | [com.gargoylesoftware.htmlunit WebClient])
15 | (-> (Logger/getLogger "com.gargoylesoftware")
16 | (.setLevel (Level/-OFF)))
17 | (def client (WebClient.))))))
18 |
19 | (defn hunit-page
20 | [path]
21 | (pod/with-eval-in @hunit-pod
22 | (.asText (.getPage client ~(format "http://localhost:3000%s" path)))))
23 |
24 | (deftest a-test
25 | (testing "Compiling with .cljs.edn"
26 | (is (= "test passed" (hunit-page "/demo/index.html")))))
27 |
--------------------------------------------------------------------------------
/test/demo/core.cljs:
--------------------------------------------------------------------------------
1 | (ns demo.core)
2 |
3 | (.appendChild (.-body js/document) (.createTextNode js/document "test passed"))
4 |
--------------------------------------------------------------------------------
/test/demo/index.cljs.edn:
--------------------------------------------------------------------------------
1 | {:require [demo.core]}
2 |
--------------------------------------------------------------------------------
/test/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |