Amber is an elegant templating engine for Go Programming Language, inspired from HAML and Jade

amber GoDoc Build Status

Notice

While Amber is perfectly fine and stable to use, I've been working on a direct Pug.js port for Go. It is somewhat hacky at the moment but take a look at Pug.go if you are looking for a Pug.js compatible Go template engine.

Usage

import "github.com/eknkc/amber"

Amber is an elegant templating engine for Go Programming Language It is inspired from HAML and Jade

Tags

A tag is simply a word:

html

is converted to

<html></html>

It is possible to add ID and CLASS attributes to tags:

div#main
span.time

are converted to

<div id="main"></div>
<span class="time"></span>

Any arbitrary attribute name / value pair can be added this way:

a[href="http://www.google.com"]

You can mix multiple attributes together

a#someid[href="/"][title="Main Page"].main.link Click Link

gets converted to

<a id="someid" class="main link" href="/" title="Main Page">Click Link</a>

It is also possible to define these attributes within the block of a tag

a
    #someid
    [href="/"]
    [title="Main Page"]
    .main
    .link
    | Click Link

Doctypes

To add a doctype, use !!! or doctype keywords:

!!! transitional
// <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

or use doctype

doctype 5
// <!DOCTYPE html>

Available options: 5, default, xml, transitional, strict, frameset, 1.1, basic, mobile

Tag Content

For single line tag text, you can just append the text after tag name:

p Testing!

would yield

<p>Testing!</p>

For multi line tag text, or nested tags, use indentation:

html
    head
        title Page Title
    body
        div#content
            p
                | This is a long page content
                | These lines are all part of the parent p

                a[href="/"] Go To Main Page

Data

Input template data can be reached by key names directly. For example, assuming the template has been executed with following JSON data:

{
  "Name": "Ekin",
  "LastName": "Koc",
  "Repositories": [
    "amber",
    "dateformat"
  ],
  "Avatar": "/images/ekin.jpg",
  "Friends": 17
}

It is possible to interpolate fields using #{}

p Welcome #{Name}!

would print

<p>Welcome Ekin!</p>

Attributes can have field names as well

a[title=Name][href="/ekin.koc"]

would print

<a title="Ekin" href="/ekin.koc"></a>

Expressions

Amber can expand basic expressions. For example, it is possible to concatenate strings with + operator:

p Welcome #{Name + " " + LastName}

Arithmetic expressions are also supported:

p You need #{50 - Friends} more friends to reach 50!

Expressions can be used within attributes

img[alt=Name + " " + LastName][src=Avatar]

Variables

It is possible to define dynamic variables within templates, all variables must start with a $ character and can be assigned as in the following example:

div
    $fullname = Name + " " + LastName
    p Welcome #{$fullname}

If you need to access the supplied data itself (i.e. the object containing Name, LastName etc fields.) you can use $ variable

p $.Name

Conditions

For conditional blocks, it is possible to use if <expression>

div
    if Friends > 10
        p You have more than 10 friends
    else if Friends > 5
        p You have more than 5 friends
    else
        p You need more friends

Again, it is possible to use arithmetic and boolean operators

div
    if Name == "Ekin" && LastName == "Koc"
        p Hey! I know you..

There is a special syntax for conditional attributes. Only block attributes can have conditions;

div
    .hasfriends ? Friends > 0

This would yield a div with hasfriends class only if the Friends > 0 condition holds. It is perfectly fine to use the same method for other types of attributes:

div
    #foo ? Name == "Ekin"
    [bar=baz] ? len(Repositories) > 0

Iterations

It is possible to iterate over arrays and maps using each:

each $repo in Repositories
    p #{$repo}

would print

p amber
p dateformat

It is also possible to iterate over values and indexes at the same time

each $i, $repo in Repositories
    p
        .even ? $i % 2 == 0
        .odd ? $i % 2 == 1

Mixins

Mixins (reusable template blocks that accept arguments) can be defined:

mixin surprise
    span Surprise!
mixin link($href, $title, $text)
    a[href=$href][title=$title] #{$text}

and then called multiple times within a template (or even within another mixin definition):

div
	+surprise
	+surprise
    +link("http://google.com", "Google", "Check out Google")

Template data, variables, expressions, etc., can all be passed as arguments:

+link(GoogleUrl, $googleTitle, "Check out " + $googleTitle)

Imports

A template can import other templates using import:

a.amber
    p this is template a

b.amber
    p this is template b

c.amber
    div
        import a
        import b

gets compiled to

div
    p this is template a
    p this is template b

Inheritance

A template can inherit other templates. In order to inherit another template, an extends keyword should be used. Parent template can define several named blocks and child template can modify the blocks.

master.amber
    !!! 5
    html
        head
            block meta
                meta[name="description"][content="This is a great website"]

            title
                block title
                    | Default title
        body
            block content

subpage.amber
    extends master

    block title
        | Some sub page!

    block append meta
        // This will be added after the description meta tag. It is also possible
        // to prepend someting to an existing block
        meta[name="keywords"][content="foo bar"]

    block content
        div#main
            p Some content here

License

(The MIT License)

Copyright (c) 2012 Ekin Koc [email protected]

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Usage

var DefaultOptions = Options{true, false}
var DefaultDirOptions = DirOptions{".amber", true}

func Compile

func Compile(input string, options Options) (*template.Template, error)

Parses and compiles the supplied amber template string. Returns corresponding Go Template (html/templates) instance. Necessary runtime functions will be injected and the template will be ready to be executed.

func CompileFile

func CompileFile(filename string, options Options) (*template.Template, error)

Parses and compiles the contents of supplied filename. Returns corresponding Go Template (html/templates) instance. Necessary runtime functions will be injected and the template will be ready to be executed.

func CompileDir

func CompileDir(dirname string, dopt DirOptions, opt Options) (map[string]*template.Template, error)

Parses and compiles the contents of a supplied directory name. Returns a mapping of template name (extension stripped) to corresponding Go Template (html/template) instance. Necessary runtime functions will be injected and the template will be ready to be executed.

If there are templates in subdirectories, its key in the map will be it's path relative to dirname. For example:

templates/
   |-- index.amber
   |-- layouts/
         |-- base.amber
templates, err := amber.CompileDir("templates/", amber.DefaultDirOptions, amber.DefaultOptions)
templates["index"] // index.amber Go Template
templates["layouts/base"] // base.amber Go Template

By default, the search will be recursive and will match only files ending in ".amber". If recursive is turned off, it will only search the top level of the directory. Specified extension must start with a period.

type Compiler

type Compiler struct {
	// Compiler options
	Options
}

Compiler is the main interface of Amber Template Engine. In order to use an Amber template, it is required to create a Compiler and compile an Amber source to native Go template.

compiler := amber.New()
// Parse the input file
err := compiler.ParseFile("./input.amber")
if err == nil {
	// Compile input file to Go template
	tpl, err := compiler.Compile()
	if err == nil {
		// Check built in html/template documentation for further details
		tpl.Execute(os.Stdout, somedata)
	}
}

func New

func New() *Compiler

Create and initialize a new Compiler

func (*Compiler) Compile

func (c *Compiler) Compile() (*template.Template, error)

Compile amber and create a Go Template (html/templates) instance. Necessary runtime functions will be injected and the template will be ready to be executed.

func (*Compiler) CompileString

func (c *Compiler) CompileString() (string, error)

Compile template and return the Go Template source You would not be using this unless debugging / checking the output. Please use Compile method to obtain a template instance directly.

func (*Compiler) CompileWriter

func (c *Compiler) CompileWriter(out io.Writer) (err error)

Compile amber and write the Go Template source into given io.Writer instance You would not be using this unless debugging / checking the output. Please use Compile method to obtain a template instance directly.

func (*Compiler) Parse

func (c *Compiler) Parse(input string) (err error)

Parse given raw amber template string.

func (*Compiler) ParseFile

func (c *Compiler) ParseFile(filename string) (err error)

Parse the amber template file in given path

type Options

type Options struct {
	// Setting if pretty printing is enabled.
	// Pretty printing ensures that the output html is properly indented and in human readable form.
	// If disabled, produced HTML is compact. This might be more suitable in production environments.
	// Defaukt: true
	PrettyPrint bool
	// Setting if line number emitting is enabled
	// In this form, Amber emits line number comments in the output template. It is usable in debugging environments.
	// Default: false
	LineNumbers bool
}

type DirOptions

// Used to provide options to directory compilation
type DirOptions struct {
	// File extension to match for compilation
	Ext string
	// Whether or not to walk subdirectories
	Recursive bool
}
Owner
Ekin Koc
kovan.io -- also co founder of onedio.com
Ekin Koc
Comments
  • Support for virtual filesystems

    Support for virtual filesystems

    I needed to add support for virtual filesystems (ex. implementing net/http.FileSystem interface) for a project I am working on which then compiles to a single standalone binary without any external resources so I am opening this PR to get suggestions what to improve and eventually merge it into master.

  • Input close tag

    Input close tag

    I have asked in the golang g+ forum about this issue, i can't generate output like this using amber: <input type="text" name="email" size="30" />

    they are always give result like this <input type="text" name="email" size="30"></input> so what i want is just that simple. my question: is it by design or not yet implemented? thanks

  • Do not evaluate conditional attributes until condition is satisfied

    Do not evaluate conditional attributes until condition is satisfied

    Template:

    input
        [value=row.Value] ? row != nil
    

    Produces error, if row is nil:

    template: .:1:20: executing "." at <.row.Value>: can't evaluate field Value in type interface {}
    

    row.Value should not be evaluated until row != nil is satisfied.

  • Inconsistent order of attribute iteration

    Inconsistent order of attribute iteration

    Currently attributes are put into a map in Compiler.visitTag() method. Since Go uses randomized order of iteration for maps - this results in different HTML files generated from the same amber file every time you compile them.

    This implies that one can't keep compiled HTMLs under version control because amber compilation is not reproducible. Also, one can't test amber templates because the HTML output is always random, so you can't compare it to a certain expected value.

    A possible fix would be to keep attributes in a slice and use a special node pointer for the special class attribute.

    P.S. On a side note, is this project still alive? Most open issues are half a year old.. Amber seems to be the only sane lightweight HTML markup compiler for Go, it would be a big loss if it's not under development anymore.

  • Incorrect inline-style

    Incorrect inline-style

    One item in style is fine: p[style="color:black"] => <p style="color:black"></p>

    However, with multiple items there, the output is wired: p[style="color:black; background:write"] => <p style="ZgotmplZ"></p>

    Even with a semicolon appended, the output is not correct: p[style="color:black;"] => <p style="ZgotmplZ"></p>

    The same style in Jade and Slim are fine. Am I missing any document about this?

  • Cannot import templates in nested directory, is it supported?

    Cannot import templates in nested directory, is it supported?

    +templates +components --test.amber -main.amber

    test.amber
    div#somid hello
    
    main.amber
    ....
    body 
         import test.amber
    

    does not work.

    How would you import templates from a directory?

  • Parsing data without converting to string

    Parsing data without converting to string

    Making it possible to read the contents of a file and providing both the contents and the filename to Amber, as an alternative to Amber reading the file (or a string, without a filename).

    This avoids a conversion from []byte to string in algernon and also makes it possible to manipulate the bytes before sending them to Amber, while keeping the functionality that is available when the Amber parser has been given a filename.

    Please accept, reject or ask me to make changes to the pull request.

    Best regards, Alexander F Rødseth

  • Command-line version

    Command-line version

    I just saw amber, and from the readme, it looks absolutely awesome!

    One thing that I wish you'd add is a standalone command line for amber, so you could compile amber files without having to write a script that does that.

  • "Import"ing header.amber issue

    Hi there,

    I'm finding that when I have header.amber:

    !!! 5
    html
        head
            title #{title}
            link[href="assets/build/app.css"][rel="stylesheet"]
        body
    

    ...and a whatever.amber:

    import header
        h1 foobar!
    

    ...the resulting HTML is invalid:

    <!DOCTYPE html>
    <html>
        <head>
            <title>Baz</title>
            <link href="assets/build/app.css" rel="stylesheet" />
        </head>
        <body></body>
    </html>
    <h1>foobar!</h1>
    

    Whenever a "child" amber file is "import"ed, valid markup results (as seen in the README). The use-case I've described above seems to result in invalid markup, however (child "import"ing parent file). Just for reference, I have a convenience "AmberParser" struct (I plan on open sourcing this soon!) that takes an amber file and JSON options and then uses amber's ParseFile(), Compile(), and tpl.Execute().

    Is this use-case simply not supported or am I missing something?

    Thanks and I enjoy using Amber! At the moment, it's the closest thing to actual Jade in the Golang world!

    -Matthew Vita

  • HTML5 self-closing tags really are self-closing

    HTML5 self-closing tags really are self-closing

    In HTML5, the / should be omitted from self-closing tags. e.g. <br/> should just be <br>.

    https://github.com/eknkc/amber/blob/a714b9e68ad80f05c05d60e1dce218192c2f7325/compiler.go#L399-L400 is what would be changed.

  • Export funcMap or provide it as an Option

    Export funcMap or provide it as an Option

    It would be nice if you provided a means to add functions to the template via the funcMap. At the moment, the funcMap variable is private (in runtime.go). A simple way to be open to extensions would be to make this variable public, although package users could remove/replace the existing, required runtime functions (can be seen both as a feature or a bug, really).

    Another (more controlled) way to provide this flexibility would be to add a template.FuncMap field in the Options, and this map would extend the internal funcMap.

    My basic need for this is to provide a function to format a time.Time value, but this seems like a nice generic feature to add (which obviously is present with the native Go functions). I wanted to discuss it first, but if you're ok with one of the proposals, I'd be happy to send a PR.

  • render: template * does not exist

    render: template * does not exist

    Hi, I got this message: image

    and this is my code: image

    and I have imported these 2 packages:

    "github.com/gofiber/fiber/v2" "github.com/gofiber/template/amber"

    Am I doing something wrong?

  • How to use safeURL in amber img src base64 data?

    How to use safeURL in amber img src base64 data?

    block content h1 #{Title} img[src=LogoBase64Data] h2 #{SubTitle} p #{Description} hr each $com in Components import partials/component

    OUTPUT

    <img src="#ZgotmplZ">

  • Added Power Support ppc64le

    Added Power Support ppc64le

    Added power support for the travis.yml file with ppc64le. This is part of the Ubuntu distribution for ppc64le. This helps us simplify testing later when distributions are re-building and re-releasing. Thank you.

  • runtime error: invalid memory address or nil pointer dereference

    runtime error: invalid memory address or nil pointer dereference

    We are experiencing issues compiling our templates. Any help or recommendations will be extremely useful and appreciated. the error gotten is " runtime error: invalid memory address or nil pointer dereference - Line: 41, Column: 5, Length: 3 STACK:"

    The script being compiled contains the following code, I cant seem to solve the issue.

    **`extends ./../layout

    block menu +topMenu("items")

    block left_menu +leftMenu("items")

    block content $selectedPage = Page $selectedCity = CityID $selectedCategory = CategoryID $selectedShippingTo = ShippingTo $selectedShippingFrom = ShippingFrom $viewUser = ViewUser $sortby = SortBy $account = Account $l = Localization div.ui.grid.stackable.divided div.three.wide.column.t-left-menu-items if EnableStoreStaffUI if ViewUserStore.VerificationRequired a.ui.button.red.fluid[href="/verification/encryption"] #{Localization.Auth.VerifyAccount} div.ui.section.divider.left-menu if !HideAdvertisings import ./../advertising/partial_advertising import C:\Users\user\go\src\marketplaceproject-clone\student-free-market\deploy\package\templates\mixin_right_menu.amber $SelectedPackageType = SelectedPackageType $Localization = Localization $ShippingFrom = ShippingFrom $ShippingFromList = ShippingFromList $ShippingTo = ShippingTo $ShippingToList = ShippingToList $City = City $GeoCities = GeoCities $SortBy = SortBy $Category = Category $SubCategory = SubCategory $Query = Query +RightMenu($SelectedPackageType, $Localization, $ShippingFrom, $ShippingFromList, $ShippingTo, $ShippingToList, $SelectedPackageType, $City, $GeoCities, $SortBy, $Category, $SubCategory, $Query) div.thirteen.wide.column form.ui.input.icon.fluid[method="GET"][action="/marketplace"] input[type="hidden"][name="category"][value=0] input[type="hidden"][name="subcategory"][value=0] input[type="text"][name="query"][placeholder=Localization.Items.LookingFor][value=Query] i.icon.search div.ui.four.item.menu.secondary.pointing a.item[href="/marketplace/"] [class="active"] ? SelectedPackageType == "all" i.icon.filter | #{Localization.Items.AllTypes} a.item[href="/marketplace/mail/"] [class="active"] ? SelectedPackageType == "mail" i.icon.envelope.open.outline | #{Localization.Items.Mail} a.item[href="/marketplace/drop/"] [class="active"] ? SelectedPackageType == "drop" i.icon.sticky.note.outline | #{Localization.Items.Drop} a.item[href="/marketplace/drop preorder/"] [class="active"] ? SelectedPackageType == "drop preorder" i.icon.warehouse | #{Localization.Items.DropPreorder} if len(ViewSerpItems) > 0 div.ui.grid.stackable each $item in ViewSerpItems div.four.wide.column import ./mixin_item_row $i = $item $u = $viewUser +itemRow($i, $u, $l) if len(ViewSerpItems) == 0 div.ui.icon.message i.icon.cart div.content div.header #{Localization.Items.NoItems} if len(Pages) > 1 $query = Query div.ui.section.divider div.ui.pagination.menu.mini each $page in Pages div.item .active ? $page == $selectedPage a[href="?page="+$page + "&city="+$selectedCity + "&category="+$selectedCategory + "&sortby="+$sortby + "&account="+$account + "&shipping-to="+$selectedShippingTo + "&shipping-from="+$selectedShippingFrom + "&query=" + $query] #{$page} `**

  • variables not work with extends and import

    variables not work with extends and import

    eg. _layout.amber:

    !!! 5
    html
        body
            import inc/_sidebar
    

    inc/_sidebar.amber:

    div.test #{$activePage}
    

    and rendered page is home.amber:

    extends _layout
    $activePage = "dashboard"
    

    this won't work, with err: undefined variable "$activePage"

  • Small typo in README.md

    Small typo in README.md

    type Options

    type Options struct {
    	// Setting if pretty printing is enabled.
    	// Pretty printing ensures that the output html is properly indented and in human readable form.
    	// If disabled, produced HTML is compact. This might be more suitable in production environments.
    	// Defaukt: true
    	PrettyPrint bool
    	// Setting if line number emitting is enabled
    	// In this form, Amber emits line number comments in the output template. It is usable in debugging environments.
    	// Default: false
    	LineNumbers bool
    }
    

    Typo in text // Defaukt: true

A strongly typed HTML templating language that compiles to Go code, and has great developer tooling.
A strongly typed HTML templating language that compiles to Go code, and has great developer tooling.

A language, command line tool and set of IDE extensions that makes it easier to write HTML user interfaces and websites using Go.

Dec 29, 2022
pongo2 is a Django-syntax like templating-language

Django-syntax like template-engine for Go

Dec 27, 2022
An ERB-style templating language for Go.

Ego Ego is an ERb style templating language for Go. It works by transpiling templates into pure Go and including them at compile time. These templates

Jan 6, 2023
Templating system for HTML and other text documents - go implementation

FAQ What is Kasia.go? Kasia.go is a Go implementation of the Kasia templating system. Kasia is primarily designed for HTML, but you can use it for any

Mar 15, 2022
A sweet velvety templating package

Velvet Velvet is a templating package for Go. It bears a striking resemblance to "handlebars" based templates, there are a few small changes/tweaks, t

Nov 28, 2022
A maroto way to create PDFs. Maroto is inspired in Bootstrap and uses gofpdf. Fast and simple.
A maroto way to create PDFs. Maroto is inspired in Bootstrap and uses gofpdf. Fast and simple.

Maroto A Maroto way to create PDFs. Maroto is inspired in Bootstrap and uses Gofpdf. Fast and simple. Maroto definition: Brazilian expression, means a

Jan 7, 2023
Article spinning and spintax/spinning syntax engine written in Go, useful for A/B, testing pieces of text/articles and creating more natural conversations

GoSpin Article spinning and spintax/spinning syntax engine written in Go, useful for A/B, testing pieces of text/articles and creating more natural co

Dec 22, 2022
Simple and fast template engine for Go

fasttemplate Simple and fast template engine for Go. Fasttemplate performs only a single task - it substitutes template placeholders with user-defined

Dec 30, 2022
A handy, fast and powerful go template engine.
A handy, fast and powerful go template engine.

Hero Hero is a handy, fast and powerful go template engine, which pre-compiles the html templates to go code. It has been used in production environme

Dec 27, 2022
The world’s most powerful template engine and Go embeddable interpreter.
The world’s most powerful template engine and Go embeddable interpreter.

The world’s most powerful template engine and Go embeddable interpreter

Dec 23, 2022
Competitive Programming Template for Golang

Go Competitive Programming Template How to use this repo? Check the commit histo

Dec 19, 2021
HTML template engine for Go

Ace - HTML template engine for Go Overview Ace is an HTML template engine for Go. This is inspired by Slim and Jade. This is a refinement of Gold. Exa

Jan 4, 2023
Jet template engine

Jet Template Engine for Go Jet is a template engine developed to be easy to use, powerful, dynamic, yet secure and very fast. simple and familiar synt

Jan 4, 2023
A complete Liquid template engine in Go
A complete Liquid template engine in Go

Liquid Template Parser liquid is a pure Go implementation of Shopify Liquid templates. It was developed for use in the Gojekyll port of the Jekyll sta

Dec 15, 2022
Fast, powerful, yet easy to use template engine for Go. Optimized for speed, zero memory allocations in hot paths. Up to 20x faster than html/template

quicktemplate A fast, powerful, yet easy to use template engine for Go. Inspired by the Mako templates philosophy. Features Extremely fast. Templates

Dec 26, 2022
Razor view engine for go

gorazor gorazor is the Go port of the razor view engine originated from asp.net in 2011. In summary, gorazor is: Extremely Fast. Templates are convert

Dec 25, 2022
gtpl is a template engine for glang

gtpl 使用必读 gtpl is a HTML template engine for golang gtpl 是一个 go 语言模板引擎,它能以极快的速度进行模板语法分析。相比 go 语言官方库 html/template,gtpl 的语法有着简练、灵活、易用的特点。

Nov 28, 2022
This my project template for making fiber with SSR taste by empowered mustache engine.

SSR-FIBER-TEMPLATE This my project template for making fiber with SSR taste by empowered mustache engine. Folder Hierarchy Name Description configs Co

May 9, 2022
The mustache template language in Go

Overview mustache.go is an implementation of the mustache template language in Go. It is better suited for website templates than Go's native pkg/temp

Dec 22, 2022