Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://gitlab.com/DevelopmentDuck/rose

A website compiler allowing the use of Go alongside HTML
https://gitlab.com/DevelopmentDuck/rose

compiler golang html website

Last synced: 11 days ago
JSON representation

A website compiler allowing the use of Go alongside HTML

Lists

README

        

# Rose
Rose is a Go-based website compiler designed to enable using Go on a website similar to how PHP works. Rose files may be created with a mix of HTML/JS/CSS and Go, then when a specific web page is requested from the server the compiled website will execute the Go and display HTML/JS/CSS.

The goal is to allow for an easy use of Go on the web without requiring users to learn complicated templating systems and instead just use what they already know: Go and HTML.

The basic format for a file looks like this:

```go
--{@
"packageToImport"
@}--


<@
// Go code goes here
if condition == true {
write("Title A")
} else {
write("Title B")
}
@>



Whatever HTML you want here will show up exactly as you would expect HTML to work

Let's add some Go in the body as well:
<@

sum := 1
for sum < 1000 {
sum += sum
}

write(sum)
@>

```
All Go shows up between `<@` and `@>` similar to PHP's ?> or ASP's <% %>. Anything that is valid in regular Go can show up between `<@ @>` and it will work as it would in any other Go app. You can even define complete functions within these code blocks and they will act as you would expect. Currently, defined functions are accessible by all parts of the application, even if the function is defined in another Rose file.

Any required imports show up between `--{@` and `@}--` without indenting.

All of the Rose files get compiled into a single binary including a web server that allows for immediate cross-platform deployment and connectivity.

## Overview
### Features
* Execute Go on websites
* Use standard Go and standard HTML/JS/CSS, no unique syntax needed
* Single-file binary
* Built-in webserver (via net/http)
* Websocket Support (via gorilla/websocket)
* Authentication
- Basic HTTP Authentication
- Basic HTTP Authentication Challenged Against Active Directory
- JSON Web Tokens
* File includes
* Hot reloading
* Easy-to-use SQL querying and execution

### Requirements
All Rose-powered websites need the following parts:
* Gardener.go - The parser and compiler
* Seed - Website configuration file
* Roses - Individual pages of the website

### Optional
In addition to the required parts, Rose-powered websites may also include:
* Static file directory for non-compiled portions of the website that get served directly to users

## Design
Rose will check for Roses (.rose files) in a specified directory and then parses and combines all of the Roses into a single .go file including a web server and other desired features as supported by Rose

This is done in the following order:
1. Read configuration file (Seed)
2. Add built-in functions as called by Seed
3. Detect source files (Roses) and iterate through them
1. Check if they should ignore authentication rules
2. Add required imports
3. Parse defined functions and structs
4. Check for included files
5. Parse Go code
6. Parse HTML/JS/CSS
7. Add all code to final server binary

## Status
Experimental, however stable enough for production use. Breaking changes may happen at this phase. All breaking changes will be documented at [CHANGES.md](CHANGES.md)

## Usage
See [examples](examples/simple/) for a basic example of how to set up a Rose project

First compile the compiler for your platform:
`go build gardener.go`

Then, to compile a website, simply run:
`gardener seedfilename`

For a Seed named "website.seed" you would run `gardener website`

## Seed File Configuration
The seed dictates how the Roses are compiled and parsed. This also becomes very useful when wanting to have multiple versions of an application, such as for development, validation, and production environments.

In addition to basic configuration and activating Rose features, you may also add global variables which will be incorporated into your program.

### Basic Configuration
See the [example seed](examples/simple/simple.seed) for proper formatting

| Variable | Type | Required | Description | Example |
| --- | --- | --- | --- | --- |
| static_dir | string (quotes) | No | Define directory used to serve static files | 'static' |
| roses | string | Yes | Define directory where Roses are stored | roses |
| port | int | Yes | Set port webserver will run on | 7673 |
| server_filename | string | Yes | Declare file name Gardener will create | server_dev |
| line_breaks | bool | No | Retains line breaks from source files in compiled server | true |
| reload_on_change | bool | No | Uses [fsnotify](https://github.com/fsnotify/fsnotify "fsnotify GitHub Page") to monitor rose directory for file changes and then automatically recompiles the server on changes. This must be set AFTER the roses directory is defined | true |
| auth | string | No | Allows selection of a built-in authentication option | basic |
| sql | bool | No | Add SQL connection, querying, and execution functions | true |
| sql_package | string | Yes if sql = true | Define what SQL driver package to use | github.com/denisenkom/go-mssqldb |
| mongodb | bool | No | Add imports for MongoDB use | true |
| anything | string (quotes) | No | Global variable to be used throughout your website | globalVar = 'value' |

### Authentication

There are four different types of authentication which can be selected by setting auth to one of these:

| Authentication Type | Description | Setting | Status |
| --- | --- | --- | --- |
| None | No authentication needed to access website | auth = none | Working |
| HTTP Basic Auth | Utilizes HTTP Basic Auth to verify users | auth = basic

realm = 'Website Name' | Accepts any user/pass combo, needs to be redone to allow definition of users/passes that are allowed |
| LDAP HTTP Basic Auth | Checks credentials against Active Directory using [go-ldap.v3](https://github.com/go-ldap/ldap/tree/v3.1.6 "Go LDAP V3 GitHub Page") to authenticate via HTTP Basic Auth | auth = basicLDAP

dc = 'active.directory.location'

adDomain = 'Domain\' | Working |
| Login Once with LDAP (LOL) | Logs into a central portal that checks credentials against Active Directory using [go-ldap.v3](https://github.com/go-ldap/ldap/tree/v3.1.6 "Go LDAP V3 GitHub Page") and then generates a JSON Web Token and sets it as a cookie to enable seamless authentication across a collection of websites.

Includes function to look retrieve the current logged in user (retrieveLoggedInUser) | auth = LOL | Partial; Everything works but a lot is hardcoded in |

Authentication is set across an entire website and you can only have one type of authentication enabled at a time.

There is the ability to exclude individual pages from the authentication checks by adding `/!\ignoreAuth/!\` to a file you want to allow anyone to access.

## Built-In Functions

Rose comes with some built-in functions to make common operations much easier and standard across applications.

### General Functions

These are available simply if using Rose

| Function Name | Description | Example |
| --- | --- | --- |
| write(string) | Similar to PHP's echo, this will write a string out to the website | x := "Hello"

write(x) |
| includeF(string) | Includes the contents of a file, without parsing, to the website. Useful for including repeated HTML | includeF("nav.html") |

### SQL Functions

Requires sql to be set to true in the Seed file. These SQL functions make working with SQL a breeze.

#### queryDB(driver string, dsn string, cmd string) map[string][]string

Uses database/sql and a SQL driver of your choice, along with dsn to create a connection to a server then executes a command (cmd) and returns the results as a map. This allows for selecting columns by name or row number in an efficient way.

Example:

```go
driver := "mssql"
dsn := "server=DBServer;user id=sqlUser;password=Pa$$w0rD;database=DatabaseName"
cmd := `SELECT * FROM Table`

results := queryDB(driver, dsn, cmd)

for i := 0; i < len(results["ColName"]); i++ {
log.Println(results["ColName"][i])
}

```

#### commandDB(driver string, dsn string, cmd string)

This is set up the same way as queryDB, however instead of assigning the output of commandDB to a variable (since it returns nothing), just call commandDB directly

## Global Variables and Structs

As with any normal Go application variables and structs work as you expect, however if you need to make something global there is a special way to do that with Rose.

Strings can be defined in the Seed file, just as another entry:
`variableName = 'default value'`

Structs when being defined in any file simply just need a @ placed in front of them so
`type Event struct` becomes `@type Event Struct`