Cream

Getting started

Firstly, You have to install cream on your computer

You can install cream on linux or macOS by running this

$ curl https://raw.githubusercontent.com/tm-ahad/cream-installation/master/install.bash | bash 

On windows, you can run the following command

$ irm https://raw.githubusercontent.com/tm-ahad/cream-installation/master/install.ps1 | iex 

Creating Project

To create a cream project. run this command and answer the questions asked by cream cli

$ cream new <project_name> 

Building

After building the compiled html will be saved into /build/index.html (default) To build a cream project you can run this on windows (make sure you changed dir to the project):

$ powershell ./make.ps1 

Or, this command on linux or macos

$ bash ./make.sh 

Serving

To serve a cream project (You have yo build it first) on localhost you can run:

$ cream serve 

Hello world

Example of 'Hello World!' in cream:

src/app.js
----------
app {
    <temp>
        <h1>Hello, World!</h1>
    </temp>
}

Dynamic Rendering

Example of rendering element dynamically in cream:

src/app.js
----------
/*It is depended if your project is in js import 'map_concat.js' or if it's ts import 'map_concat.ts'
Same for every lib*/

import lib:map_concat.js

app {

    let fruits = {
        'apple': '2.00',
        'orange': '1.00',
        'banana': '1.50'
    }

    <temp>
        //Rendering elements of 'fruits'
        <div id="fruits"></div>

        $dyn:"fruits" innerHTML=mapConcat(Object.entries($todos), item => {
            const [fruit, price] = item

            return `<p>Price of a ${fruit} is ${price}</p>`
        })
    </temp>
}

Templates

Example of 'Hello World!' in cream:

src/app.js
----------

app {
    const content = 'Lorem ipsum'
    const clickHandler = () => console.log("Button clicked")

    <temp>
        //Rendering elements of 'fruits'
        <p id="pid"></p>
        $dyn:"pid" innerText=$content;

        <button id="bid">Click Me!</button>
        $dyn:"bid" onclick=$clickHandler;
    </temp>
}

States

Example of state managment in cream:

src/app.js
----------
    
app {
    let a = 0;

    let clickHandler = () => {
        //:= is the state operator
        a := $a + 1
    }
    
    <temp>
        <p id="pid"></p>
        $dyn:"pid" innerText=$a;

        <button id="bid">Click me!</button>
        $dyn:"bid" onclick=$clickHandler;
    </temp>
}

Components

Example of component in cream:

src/app.js
----------
import MyComponent from src/myComponent.js
    
app {
    <temp>
        <MyComponent />
    </temp>
}
src/myComponent.js
------------------

myComponent {
    <temp>
        <h1>Lorem ipsum</h1>
    </temp>
}

Passing data through component

Example of component in cream:

src/app.js
----------

import Item from src/item.js
import mod:src/store
    
app {
    const fruits = ['orange', 'banana', 'mango', 'apple']

    <temp>
        <div id="id1"></div>

        //using $fruits to handle state if fruits is updated id1 element will also be updated
        @temp:"id1" $mapConcat($fruits, item => {
            //setting data
            store.set("fruit", item)

            //rendering item
            //Make sure using template literals when dynamically rendering component
            return `<Item/>`
        })
        <Item />
    </temp>
}
src/item.js
-----------
    
Item {
    //getting data
    const fruit = store.get("fruit")

    <temp>
        <p>$fruit</p>
    </temp>
}
src/store.mod.cts
-----------------

//Initializing store
var store = new Map()

Router

Example of router in cream:

src/app.js
----------

app {
    <temp>
        <p>Index page</p>
    </temp>
}

Route 1

src/route1.js
-------------

Page {
    <temp>
        <p>Route 1</p>
    </temp>
}

Route 2

src/route2.js
-------------

Page {
    <temp>
        <p>Route 2</p>
    </temp>
}

Error page

src/error.js
------------

Page {
    <temp>
        <p>404 page not found</p>
    </temp>
}

Setting the routes:

src/routes.json
---------------
{
    "/route1": "src/route1.js",
    "/route2": "src/route2.js",

    //cream server will redirect to '/error' if page not found
    "/error": "src/error.js"
}

Static file serving

To serve static files, You have to set 'static_dir' to the path of static folder on the config file. Static files will be rendered on 'static_dir_render' Example of serving static files in cream:

src/config.dsp
-----------
routes$routes.json
//Static dir '/static'
static_dir$/static
//Dir '/static' will be rendered on '/static_files'
static_dir_render$/static_files

Generating id

Example of generating id in cream:

src/app.js
---------
        
app {
    const handleClick = () => console.log("Lorem ipsum")


    <temp>
        //generating id and saving it to variable name
        <div id=@gen:name;>Lorem ipsum<div>
        //Template
        $dyn:name onclick=$handleClick
    </temp>
}

Form handling

Example of form handling in cream (ts):

src/app.js
----------
import lib:get_by_name.ts
import mod:src/api_client
        
app {
    const handleClick = () => console.log("Lorem ipsum")

    //selecting elements
    const name_tag = GetByName<HTMLInputElement>("name_tag")
    const age_tag = GetByName<HTMLInputElement>("age")
    const email_tag = GetByName<HTMLInputElement>("email")

    //Submit function
    const submit = () => {
        const name = name_tag.value;
        const age = age_tag.value;
        const email = email_tag.value;

        const obj = {
            name,
            age,
            email
        }

        console.table(obj);
        //Posting data to api
        ApiClient.post("/createUser", JSON.stringify(obj))
    }

    <temp>
        <p>Name</p>
        <input type="text" id=@gen:name_tag;/>
        <p>Age</p>
        <input type="number" id=@gen:age;/>
        <p>Email</p>
        <input type="email" id=@gen:email;/>

        <button id="submit">Submit</button>
        $dyn:"submit" onclick=$submit;
    </temp>
}
src/api_client.mod.cts
----------------------
import lib:http_client.ts
const ApiClient = new HttpClient("api-link")

Intregating tailwindcss

Installation:

To install tailwindcss you first have to install css. If your project is a node project

You could install tailwindcss by this command

npm install -D tailwindcss
npx tailwindcss init 

Step 2 (Configuration):

You have to add this config to your config.dsp file

Don't change or remove other config

config.dsp
----------
pre_make$npx tailwindcss -i ./src/styles/style.css -o ./static/dist.css
static_dir$/static
static_dir_render$/static
    

After configuring config.dsp add this code to head_prefix.html

head_prefix.html
----------------
<link href="/static/dist.css" rel="stylesheet"/>

Now paste this code in tailwind.config.js

tailwind.config.js
------------------
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: ["./build/index.html", "./build/error.html"],
  theme: {
    extend: {},
  },
  plugins: [],
}

Let's create the input css file. which is essential

src/styles/style.css
--------------------
@tailwind base;
@tailwind components;
@tailwind utilities;

Now let's update your make file (make.ps1 or make.sh)

Append this command at the end of your make file (Don't forget to create src/styles/style.css)

npx tailwindcss -i ./src/styles/style.css -o ./build/output.css

Build your project then serve it & Voila tailwindcss intregated with cream

Compilation

As we said, after building cream the compiled html will be saved on build/index.html

Npm packages

Example of importing npm package in cream:

src/app.js
---------
import npm:<package_name>
        
app {
    <temp>
    </temp>
}