@danielx/civet 0.3.16 → 0.4.1-8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -55
- package/dist/browser.js +4400 -1215
- package/dist/esbuild-plugin.js +26 -19
- package/dist/esm.mjs +95 -30
- package/dist/main.js +4403 -1218
- package/package.json +20 -2
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ Code Sample
|
|
|
26
26
|
---
|
|
27
27
|
|
|
28
28
|
```typescript
|
|
29
|
-
|
|
29
|
+
ts, {CompilerOptions} from typescript
|
|
30
30
|
|
|
31
31
|
DefaultCompilerOptions : CompilerOptions :=
|
|
32
32
|
allowNonTsExtensions: true
|
|
@@ -41,29 +41,10 @@ fileCache : Record<string, any> := {}
|
|
|
41
41
|
|
|
42
42
|
createCompilerHost := (options: CompilerOptions, moduleSearchLocations : string[]) ->
|
|
43
43
|
fileExists := (fileName: string) : boolean ->
|
|
44
|
-
|
|
44
|
+
fileCache[fileName]?
|
|
45
45
|
|
|
46
46
|
readFile := (fileName: string) ->
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
ESBuild Plugin
|
|
51
|
-
---
|
|
52
|
-
|
|
53
|
-
```coffee
|
|
54
|
-
esbuild = require "esbuild"
|
|
55
|
-
civetPlugin = require "@danielx/civet/esbuild-plugin"
|
|
56
|
-
|
|
57
|
-
esbuild.build
|
|
58
|
-
entryPoints: ['source/main.civet']
|
|
59
|
-
bundle: true
|
|
60
|
-
platform: 'node'
|
|
61
|
-
outfile: 'dist/main.js'
|
|
62
|
-
plugins: [
|
|
63
|
-
civetPlugin
|
|
64
|
-
]
|
|
65
|
-
.catch -> process.exit 1
|
|
66
|
-
|
|
47
|
+
fileCache[fileName]
|
|
67
48
|
```
|
|
68
49
|
|
|
69
50
|
Things Kept from CoffeeScript
|
|
@@ -73,7 +54,7 @@ Things Kept from CoffeeScript
|
|
|
73
54
|
- `or` -> `||`
|
|
74
55
|
- `and` -> `&&`
|
|
75
56
|
- `loop` -> `while(true)`
|
|
76
|
-
- `unless`
|
|
57
|
+
- `unless exp` -> `if(!exp)`
|
|
77
58
|
- `until condition` -> `while(!condition)`
|
|
78
59
|
- Object literal syntax
|
|
79
60
|
```coffee
|
|
@@ -90,49 +71,82 @@ Things Kept from CoffeeScript
|
|
|
90
71
|
- `?=` null-coalescing assignment shorthand
|
|
91
72
|
- `@` `this` shorthand `@` -> `this`, `@id` -> `this.id`
|
|
92
73
|
- Prototype shorthand `X::` -> `X.prototype`, `X::a` -> `X.prototype.a`
|
|
93
|
-
-
|
|
74
|
+
- Class static shorthand `@`
|
|
75
|
+
- Chained comparisons `a < b < c` -> `a < b && b < c`
|
|
76
|
+
- Postfix `if/unless/while/until/for`
|
|
94
77
|
- Block Strings `"""` / `'''`
|
|
78
|
+
- `#{exp}` interpolation in `"""` strings
|
|
79
|
+
- `when` inside `switch` automatically breaks
|
|
80
|
+
- Multiple `,` separated `case`/`when` expressions
|
|
81
|
+
- `else` -> `default` in `switch`
|
|
82
|
+
- Array slices `list[0...2]` -> `list.slice(0, 2)`
|
|
83
|
+
- Slice assignment `numbers[3..6] = [-3, -4, -5, -6]` -> `numbers.splice(3, 4, ...[-3, -4, -5, -6])`
|
|
84
|
+
- Implicit returns
|
|
85
|
+
- Simplified number method calls `1.toFixed()` -> `1..toFixed()`
|
|
86
|
+
- `if`/`switch` expressions
|
|
87
|
+
- Destructuring object assignment doesn't require being wrapped in parens at the statement level `{a, b} = c` -> `({a, b} = c)`
|
|
95
88
|
- JSX 😿
|
|
96
|
-
- TODO
|
|
97
|
-
- [ ] `"""` String interpolation (for compatibility with existing .coffee code)
|
|
98
|
-
- [ ] Chained comparisons
|
|
99
89
|
|
|
100
90
|
Things Removed from CoffeeScript
|
|
101
91
|
---
|
|
102
92
|
|
|
103
|
-
- `
|
|
104
|
-
- `
|
|
105
|
-
- `
|
|
106
|
-
- `
|
|
107
|
-
- `
|
|
93
|
+
- Implicit `var` declarations (use `civet coffeeCompat` or `"civet autoVar"`)
|
|
94
|
+
- `on/yes/off/no` (use `true/false`, `"civet coffeeCompat"`, or `"civet coffeeBooleans"` to add them back)
|
|
95
|
+
- `isnt` (use `!==`, `"civet coffeeCompat"`, or `"civet coffeeIsnt"`)
|
|
96
|
+
- `not` (use `!`, `"civet coffeeCompat"`, or `"civet coffeeNot"`)
|
|
97
|
+
- `not instanceof` (use `!(a instanceof b)`)
|
|
98
|
+
- `not in`
|
|
99
|
+
- `not of`
|
|
100
|
+
- NOTE: CoffeeScript `not` precedence is dubious. `not a < b` should be equivalent to `!(a < b)` but it is in fact `!a < b`
|
|
101
|
+
- `do` keyword (replaced with JS `do`, invoke using existing `(-> ...)()` syntax)
|
|
102
|
+
- `for from` (use JS `for of`, `"civet coffeeCompat"`, or `"civet coffeeForLoops"`)
|
|
103
|
+
- `for own of` (use JS `for in` and check manually, switch to `Map#keys/values/entries`, or use `Object.create(null)`, or `"civet coffeeCompat"`, or `"civet coffeeForLoops"`)
|
|
104
|
+
- `for ... when <condition>` (use `continue if exp` inside loop, `"civet coffeeCompat"`, or `"civet coffeeForLoops"`)
|
|
108
105
|
- `and=`, `or=` (don't mix and match words and symbols)
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
- Ranges `[0...10]`
|
|
112
|
-
- Comprensions (a case could be made for keeping them)
|
|
106
|
+
- `a ? b` (use `a ?? b`, though it doesn't check for undeclared variables)
|
|
107
|
+
- `a of b` (use `a in b` matching JS, or `"civet coffeeCompat"`, or `"civet coffeeOf"`)
|
|
113
108
|
- Iteration expression results
|
|
114
|
-
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
-
|
|
118
|
-
-
|
|
119
|
-
-
|
|
109
|
+
- Backtick embedded JS (replaced by template literals)
|
|
110
|
+
- Will likely add later
|
|
111
|
+
- Optional assignment `x?.y = 3` -> `x != null ? x.y = 3 : undefined`
|
|
112
|
+
- Loop expressions (at least in compatibility mode)
|
|
113
|
+
- Conditional assignment `a?[x] = 3` -> `a ? a[x] = 3 : undefined`
|
|
114
|
+
- Might add later
|
|
115
|
+
- Braceless inline objects `x = coolStory: true`
|
|
116
|
+
- `///` Heregexp
|
|
117
|
+
- Ranges `[0...10]`
|
|
118
|
+
- Rest parameter in any assignment position
|
|
119
|
+
- Multiple slice assignment `otherNumbers[0...] = numbers[3..6] = [-3, -4, -5, -6]`
|
|
120
120
|
|
|
121
121
|
Things Changed from CoffeeScript
|
|
122
122
|
---
|
|
123
123
|
|
|
124
|
-
- `==` -> `==` rather than `===` (can be kept with `"
|
|
125
|
-
- `!=` -> `!=` rather than `!==` (can be kept with `"
|
|
124
|
+
- `==` -> `==` rather than `===` (can be kept with `"civet coffeeCompat"`)
|
|
125
|
+
- `!=` -> `!=` rather than `!==` (can be kept with `"civet coffeeCompat"`)
|
|
126
126
|
- `for in` and `for of` are no longer swapped and become their JS equivalents.
|
|
127
127
|
- `a...` is now `...a` just like JS
|
|
128
|
+
- `a in b` is now `a in b` rather than `b.indexOf(a) >= 0`
|
|
128
129
|
- `x?.y` now compiles to `x?.y` rather than the `if typeof x !== 'undefined' && x !== null` if check
|
|
129
130
|
- Existential `x?` -> `(x != null)` no longer checks for undeclared variables.
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
-
- No
|
|
131
|
+
- `x?()` -> `x?.()` instead of `if (typeof x === 'function') { x() }`
|
|
132
|
+
- Backtick embedded JS has been replaced with JS template literals.
|
|
133
|
+
- No longer allowing multiple postfix `if/unless` on the same line (use `&&` or `and` to combine conditions).
|
|
134
|
+
- `#{}` interpolation in `""` strings only when `"civet coffeeCompat"` or `"civet coffeeInterpolation"`
|
|
135
|
+
- Expanded chained comparisons to work on more operators `a in b instanceof C` -> `a in b && b instanceof C`
|
|
136
|
+
- Postfix iteration/conditionals always wrap the statement [#5431](https://github.com/jashkenas/coffeescript/issues/5431)
|
|
137
|
+
`try x() if y` -> `if (y) try x()`
|
|
133
138
|
- Civet tries to keep the transpiled output verbatim as much as possible.
|
|
134
139
|
In Coffee `(x)` -> `x;` but in Civet `(x)` -> `(x);`.
|
|
135
|
-
Also in Coffee
|
|
140
|
+
Also in Coffee
|
|
141
|
+
```coffee
|
|
142
|
+
x + 3
|
|
143
|
+
```
|
|
144
|
+
-> `x + 3` without the spacing
|
|
145
|
+
In Civet
|
|
146
|
+
```typescript
|
|
147
|
+
x + 3
|
|
148
|
+
```
|
|
149
|
+
remains as is.
|
|
136
150
|
|
|
137
151
|
Things Added that CoffeeScript didn't
|
|
138
152
|
---
|
|
@@ -157,19 +171,29 @@ Things Added that CoffeeScript didn't
|
|
|
157
171
|
- JS Compatability
|
|
158
172
|
- `var`, `let`, `const`
|
|
159
173
|
- JS Comment Syntax `//` and `/* */`
|
|
174
|
+
- `function` keyword
|
|
160
175
|
- Braced Blocks
|
|
161
|
-
- OptionalChain longhand
|
|
162
|
-
- ConditionalExpression
|
|
176
|
+
- `f?.(x)` function application and `a?.[x]` index OptionalChain longhand
|
|
177
|
+
- `a ? b : c` ConditionalExpression
|
|
163
178
|
- `case` statement
|
|
164
179
|
- `do`, `do { ... } until condition`
|
|
165
|
-
-
|
|
180
|
+
- `get`/`set` method definitions
|
|
181
|
+
- Private identifiers `#id`
|
|
166
182
|
- Convenience for ES6+ Features
|
|
167
|
-
-
|
|
183
|
+
- Const assignment shorthand `a := b` -> `const a = b`; `{a, b} := c` -> `const {a, b} = c`
|
|
168
184
|
- `@#id` -> `this.#id` shorthand for private identifiers
|
|
169
185
|
- `import` shorthand `x from ./x` -> `import x from "./x"`
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
186
|
+
- Triple backtick Template Strings remove leading indentation for clarity
|
|
187
|
+
- Class constructor shorthand `@( ... )`
|
|
188
|
+
- ClassStaticBlock `@ { ... }`
|
|
189
|
+
- `<` as `extends` shorthand
|
|
190
|
+
- Short function block syntax like [Ruby symbol to proc](https://ruby-doc.org/core-3.1.2/Symbol.html#method-i-to_proc), [Crystal](https://crystal-lang.org/reference/1.6/syntax_and_semantics/blocks_and_procs.html#short-one-parameter-syntax), [Elm record access](https://elm-lang.org/docs/records#access)
|
|
191
|
+
- access `x.map &.name` -> `x.map(a => a.name)`
|
|
192
|
+
- nested access + slices `x.map &.profile?.name[0...3]` -> `x.map(a => a.profile?.name.slice(0, 3))`
|
|
193
|
+
- function call `x.map &.callback a, b` -> `x.map($ => $.callback(a, b))`
|
|
194
|
+
- unary operators `x.map !!&`, -> `x.map($ => !!$)`
|
|
195
|
+
- binary operators `x.map &+1` -> `x.map($ => $+1)`
|
|
196
|
+
- Postfix loop `run() loop` -> `while(true) run()`
|
|
173
197
|
- Shebang line is kept unmodified in output
|
|
174
198
|
```civet
|
|
175
199
|
#!./node_modules/.bin/ts-node
|
|
@@ -179,7 +203,139 @@ Things Added that CoffeeScript didn't
|
|
|
179
203
|
Things Changed from ES6
|
|
180
204
|
---
|
|
181
205
|
|
|
206
|
+
- Implicit returns
|
|
182
207
|
- Disallow no parens on single argument arrow function. `x => ...` must become `(x) => ...`
|
|
183
208
|
The reasoning is `x -> ...` => `x(function() ...)` in CoffeeScript and having `->` and `=>`
|
|
184
209
|
behave more differently than they already do is bad. Passing an anonymous function to an
|
|
185
210
|
application without parens is also convenient.
|
|
211
|
+
- `for(i of x) ...` defaults to const declaration -> `for(const i of x) ...`
|
|
212
|
+
- Disallow comma operator in conditionals and many other places. `if x, y` is not allowed.
|
|
213
|
+
- Comma operator in `case`/`when` instead becomes multiple conditions.
|
|
214
|
+
- Numbers can't end with a dot (otherwise would be ambiguous with CoffeeScript slices `y[0..x]`). This also implies that you can't access properties
|
|
215
|
+
of numbers with `1..toString()` use `1.toString()` instead. When exponent follows a dot it is treated as a property access since an exponent
|
|
216
|
+
could be a valid property `1.e10` -> `1..e10`. The workaround is to add a trailing zero `1.0e10` or remove the dot before the exponent `1e10`.
|
|
217
|
+
- Additional reserved words `and`, `or`, `loop`, `until`, `unless`
|
|
218
|
+
- No whitespace between unary operators and operands. Mandatory whitespace between condition and ternary `?` ex. `x ? a : b` since `x?` is the unary existential operator.
|
|
219
|
+
|
|
220
|
+
CoffeeScript Compatibility
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
Civet provides a compatability prologue directive that aims to be 97+% compatible with existing CoffeeScript2 code (still a work in progress).
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
coffeeBooleans (yes/no/on/off)
|
|
227
|
+
coffeeComment (# single line comments)
|
|
228
|
+
coffeeEq (`==` -> `===`, `!=` -> `!==`)
|
|
229
|
+
coffeeInterpolation (`"a string with {myVar}"`)
|
|
230
|
+
coffeeIsnt (`isnt` -> `!==`)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
You can use these with `"civet coffeeCompat"` to opt in to all or use them bit by bit with `"civet coffeeComment coffeeEq coffeeInterpolation"`.
|
|
234
|
+
Another posibility is to slowly remove them to provide a way to migrate files a little at a time `"civet coffeeCompat -coffeeBooleans -coffeeComment -coffeeEq"`.
|
|
235
|
+
Both camel case and hyphens work when specifying options `"civet coffee-compat"`. More options will be added over time until 97+% compatibility is achieved.
|
|
236
|
+
|
|
237
|
+
Using Civet in your Node.js Environment
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
You have now been convinced that Civet is right for your current/next project. Here is how
|
|
241
|
+
to set up your environment to get productive right away and have a Good Time℠.
|
|
242
|
+
|
|
243
|
+
### Testing
|
|
244
|
+
|
|
245
|
+
Code coverage with [c8](https://github.com/bcoe/c8) "just works" thanks to their source map
|
|
246
|
+
integration and Civet's source maps.
|
|
247
|
+
|
|
248
|
+
Currently Civet's ESM loader depends on [ts-node](https://www.npmjs.com/package/ts-node)
|
|
249
|
+
|
|
250
|
+
#### c8 + Mocha
|
|
251
|
+
|
|
252
|
+
`package.json`
|
|
253
|
+
```json
|
|
254
|
+
"scripts": {
|
|
255
|
+
"test": "c8 mocha",
|
|
256
|
+
...
|
|
257
|
+
},
|
|
258
|
+
"c8": {
|
|
259
|
+
"extension": [
|
|
260
|
+
".civet"
|
|
261
|
+
]
|
|
262
|
+
},
|
|
263
|
+
"mocha": {
|
|
264
|
+
"extension": [
|
|
265
|
+
"civet"
|
|
266
|
+
],
|
|
267
|
+
"loader": [
|
|
268
|
+
"ts-node/esm",
|
|
269
|
+
"@danielx/civet/esm.mjs"
|
|
270
|
+
],
|
|
271
|
+
...
|
|
272
|
+
...
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
`ts-node` must be configured with `transpileOnly` (it can't resolve alternative extensions). Also I think `module` needs to be at least `ES2020` for the Civet ESM loader to work.
|
|
276
|
+
|
|
277
|
+
`tsconfig.json`
|
|
278
|
+
```json
|
|
279
|
+
...
|
|
280
|
+
"ts-node": {
|
|
281
|
+
"transpileOnly": true,
|
|
282
|
+
"compilerOptions": {
|
|
283
|
+
"module": "ES2020"
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
If you don't care for code coverage you can skip c8 (but it is so easy why not keep it?).
|
|
289
|
+
|
|
290
|
+
You can also add `.js` and `.ts` extensions if you want to mix and match! Even `.coffee` will work if you require `coffeescript/register` or add a loader for it.
|
|
291
|
+
|
|
292
|
+
Execute the tests
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
yarn test
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Step 4: Enjoy!
|
|
299
|
+
|
|
300
|
+
### Developing
|
|
301
|
+
|
|
302
|
+
Use the alpha version of [Civet Language Server](https://marketplace.visualstudio.com/items?itemName=DanielX.civet)
|
|
303
|
+
|
|
304
|
+
The language server provides syntax highlighting, completions, hover documentation, symbols outline, red squigglies, and go to definition.
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
*Q?* Why can't I just use the built-in VSCode TypeScript LSP?
|
|
309
|
+
|
|
310
|
+
*A:* VSCode's built in TypeScript LSP can't resolve non `.ts/.js`, not even with plugins. Maybe one day they'll allow for
|
|
311
|
+
plugins that let you adjust the resolver and insert a transpilation step but until then a separate language server is necessary.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
*Q?* Sometimes the file outline disappears and the red squigglies are all in the wrong place and maybe a notification pops up
|
|
316
|
+
about some kind of LSP error.
|
|
317
|
+
|
|
318
|
+
*A:* I'm sorry that happened to you but the Civet Language Server is still alpha and improving rapidly. Please let me know
|
|
319
|
+
exactly what happened and I'll try to do better next time.
|
|
320
|
+
|
|
321
|
+
It may happen when there is a syntax error in your Civet file. You can check and see if it compiles using the CLI tool in the meantime.
|
|
322
|
+
|
|
323
|
+
Please do submit bug reports / feature requests.
|
|
324
|
+
|
|
325
|
+
### Building
|
|
326
|
+
|
|
327
|
+
I strongly recommend using [esbuild](https://esbuild.github.io/) for building / packaging your Civet project.
|
|
328
|
+
|
|
329
|
+
```javascript
|
|
330
|
+
import esbuild from 'esbuild'
|
|
331
|
+
import civetPlugin from '@danielx/civet/esbuild-plugin'
|
|
332
|
+
|
|
333
|
+
esbuild.build({
|
|
334
|
+
...,
|
|
335
|
+
plugins: [
|
|
336
|
+
civetPlugin
|
|
337
|
+
]
|
|
338
|
+
}).catch(() => process.exit(1))
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
It's super fast and works great!
|