Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sbsoftware/js.cr
Experimental tool to generate JavaScript code from Crystal
https://github.com/sbsoftware/js.cr
Last synced: 3 months ago
JSON representation
Experimental tool to generate JavaScript code from Crystal
- Host: GitHub
- URL: https://github.com/sbsoftware/js.cr
- Owner: sbsoftware
- Created: 2023-10-01T17:50:23.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-06-17T14:13:18.000Z (7 months ago)
- Last Synced: 2024-06-17T15:50:30.271Z (7 months ago)
- Language: Crystal
- Size: 60.5 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# `js.cr`
An experimental tool to generate JavaScript code from Crystal code.
## Contents
* [Goals](#goals)
* [Examples](#examples)
* [Code Snippets](#javascript-code)
* [`_call`](#_call)
* [Functions](#javascript-functions)
* [Classes](#javascript-classes)
* [Files](#javascript-files)
* [Aliases](#aliases)
* [Modules](#javascript-modules)
* [Loops](#loops)## Goals
The most important idea behind this project is to create the ability to reference JavaScript functions, classes and modules in Cystal code using typechecked entities instead of strings.
Initially I wanted to leverage Crystal's type system to have my JavaScript code typechecked at compile time, but that turned out to be too much to start with. It remains a goal to reintroduce that feature at some point, but for now you can generate _invalid_ JavaScript with this library.
Please note that this is still very experimental and probably lacks essential features to be genuinely used. So far I am employing it to generate stimulus controllers which toggle some classes of HTML elements.
Also, I skipped any whitespacing for now as I wanted to have my proof of concept as fast as possible. Not sure if I will ever deem it necessary to add it. The specs are still quite readable because I include whitespace in the examples and only remove it before comparing to the results.
## Examples
### JavaScript Code
Just want to output some loose snippet of JavaScript code? Use the `JS::Code` base class. You can print your code directly into a `` tag of your favorite template engine via `.to_js` if you want.
```crystal
require "js"class MyCode < JS::Code
def_to_js do
console.log("Hello World!")
end
endputs MyCode.to_js
```#### `_call`
In Crystal, there are no object properties but just method calls. Without any type information about the JS code you are calling, `js.cr` cannot know whether you want to reference a property or call a function without any arguments on an object.
It therefore always assumes a property reference. If you need a function call instead, just append `._call` to it.
Note that this isn't necessary if your call has arguments.```crystal
require "js"class MyCallCode < JS::Code
def_to_js do
a = SomeUnknownJSConstant.somePropertyOfIt
b = SomeUnknownJSConstant.someFunctionOfIt._call
c = SomeUnknownJSConstant.someOtherFunctionOfIt("foo")
end
end# => var a = SomeUnknownJSConstant.somePropertyOfIt;
# => var b = SomeUnknownJSConstant.someFunctionOfIt();
# => var c = SomeUnknownJSConstant.someOtherFunctionOfIt("foo");
puts MyCallCode.to_js
```### JavaScript Functions
If you were wondering how to define a function within `JS::Code.def_to_js` - that's not possible. Well, technically it is via a `_literal_js` call but that's dirty and there is a better way:
```crystal
require "js"class MyFunction < JS::Function
def_to_js do |foo|
console.log(foo)
end
endputs MyFunction.to_js
```You _could_ have that printed into a `<script>` tag again via `.to_js` and reference it in an `onclick` attribute by calling `.to_js_call`. Not sure how hip that is anymore.
```ecr
<html>
<head>
<title>JavaScript!</title>
<script><%= MyFunction.to_js %>
">Print "test" to the console!