eknkc / amber Goto Github PK
View Code? Open in Web Editor NEWAmber is an elegant templating engine for Go Programming Language, inspired from HAML and Jade
License: MIT License
Amber is an elegant templating engine for Go Programming Language, inspired from HAML and Jade
License: MIT License
The documentation appears to be wrong. The keyword to bring in an external file seems to be "import", not "include"
works
{{foo}}
fails
[data-colour="{{foo}}"]
It looks like you have a fix in place for the text parser that converts {{foo}} to {{"{{"}}foo{{"}}"}}. However, if you attempt to use angular brackets on a tags attribute, it will cause the template package to throw an error.
When the tag parser loops through the attributes, would it be possible to have it call the same regex replace as the text parser?
Or do you have another work around?
I did try moving the regex replace into it's own function and then having the visitText use it, as well as the attribute loop right at the end to replace the value. It fixed my particular issue, but does cause 1 test to fail. Test_FuncCall.
I tried just using the compiler to output a string via CompileString() and then using a new template, changing the delimiter, but then because of the visitText regex, it's producing invalid angularjs as the template ignores the {{"{{"}} etc. as the delimiter has changed. So while that fixes the attribute issue, it introduces an issue with the text parser.
if i pass a struct into an amber template, i can't seem to access the variables inside of an iteration block:
let's say i have this struct:
type Foo struct {
ID string
OK bool
Bar []string
}
// initialized here
f = Foo{ID: "abc", OK: true, Bar: make([]string){"ddd", "eee"}}
passed into the template.Execute function:
template.Execute(w, f)
i can do the following without any issues:
h3 #{ID} // h3 abc
but if i do this:
each $i in Bar
h3 #{$i} // works fine
h3 #{ID} // causes an Amber Error <>: Unable to parse expression
exact error is:
Amber Error in <static/templates/viewteam.amber>: Unable to parse expression. - Line: 62, Column: 21, Length: 2
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}
`**
amber 0.3.12 when rendering a page shows a lot of
/var/lib/gems/2.5.0/gems/tilt-2.0.8/lib/tilt/haml.rb:77: warning: Haml::Engine#precompiled_method_return_value at /usr/lib/ruby/2.5.0/forwardable.rb:157 forwarding to private method Haml::Compiler#precompiled_method_return_value
It's probably benign but spoils the output.
!!! 5
html[manifest="/index.appcache"]
leads to identical output as
!!! 5
html
which means that the manifest
attribute is silently, and incorrectly, dropped from the html
tag.
I am seeing some issues with how templates are parsed when blank lines are present.
This:
div.content
div.inner-content Hello!
will generate:
<div class="content"></div>
<div class="inner-content">Hello!</div>
whereas this:
div.content
div.inner-content Hello!
will generate:
<div class="content">
<div class="inner-content">Hello!</div>
</div>
Along these same lines, I've noticed that a blank line immediately following an each
statement will lose the variable scope:
each $x in Collection
div.row #{$x.Name}
This will throw an error undefined variable "$x"
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.
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
EDIT: Nevermind. You can close/delete it. That was extremely stupid. Shame to me.
Hello,
I'm sorry to bother, but I can't seem to make some code work. I have the following:
package main
import (
"net/http"
"os"
"github.com/eknkc/amber"
)
func root(w http.ResponseWriter, r *http.Request) {
compiler := amber.New()
err := compiler.ParseFile("tem.amber")
if err == nil {
tpl, err := compiler.Compile()
if err == nil {
tpl.Execute(os.Stdout, nil)
}
}
}
func main() {
http.HandleFunc("/", root)
http.ListenAndServe(":9999", nil)
}
I've also tried writting "./tem.amber" when parsing the file, and same result. Changing "nil" for some text doesn't do anything, either.
And in the same directory, a standard amber file (tem.amber):
!!! 5
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
What am I doing wrong? When I open localhost:9999, I get a blank page. I've been playing with go for a few days, so I'm pretty new with it, so my apologizes if it's a really stupid mistake. Thank you for open sourcing amber.
Sincerely,
Adria
Hi,
I'm using Amber for Algernon, and it works well.
However, I need some advice on how to best format this page:
https://github.com/xyproto/algernon/blob/master/examples/gcss/index.amber
<br>
to each line?I considered using <pre>
, but I suspect that Amber may offer an even better way.
Thanks for creating Amber!
Best regards,
Alexander F Rødseth
I've tried to use the printf function but I just get panics:
#{printf "%s:%s" $a $b}
{{printf "%s:%s" $a $b}}
Are html/template
builtin functions allowed somehow? If so, how?
!!!5
html
import ./partials/header.amber
body.ma0.min-vh-100
p #{Site.BaseURL}
div.min-vh-100.cover[style="background-image:url(#{Site.BaseURL}/img/flower.jpg); background-position: center;"]
From the above,
p #{Site.BaseURL}
Results in http://localhost:1313/stephandjohn/
But
div.min-vh-100.cover[style="background-image:url(#{Site.BaseURL}/img/flower.jpg); background-position: center;"]
Results in (#{Site.BaseURL}/img/flower.jpg)
instead of (http://localhost:1313/stephandjohn//img/flower.jpg)
.
I am using Hugo by the way, I'm not sure if this matters.
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.
Is there a way to set/pass in global variables for use in templates without passing them in to each individual template?
// I could pass the variable through the Execute, but would have to do that everywhere in my code.
tpl := config.Globals.Templates["root/login"]
tpl.Execute(w, map[string]interface{}{
"Identity": identity,
"Error": err.Error(),
})
// it would be nice to be able to pass some global variables to the compiler itself, for global vars.
templates, err := amber.CompileDir("app/views/", amber.DefaultDirOptions, amber.DefaultOptions)
example.
I have a global variable which determines if it is production or development mode
when in development mode within the master template ( that all others extend from ) I would like to add livereload.js as one of my included javascript tags
but when in production mode, not have livereload.js compiled into the template.
I understand that access to global variables outside of the templates may not be possible, but would there be a way to pass in a map of interface or something to the Options passed to the Amber Compiler which the template would then have access to?
Thanks in advance, love this package!
I'm trying to achieve something using Amber that I regularly used in Pug. It would be best described as an example from the Pug documentation:
Mixins can also take a block of Pug to act as the content:
mixin article(title)
.article
.article-wrapper
h1= title
if block
block
else
p No content provided
+article('Hello world')
+article('Hello world')
p This is my
p Amazing article
The resulting HTML:
<div class="article">
<div class="article-wrapper">
<h1>Hello world</h1>
<p>No content provided</p>
</div>
</div>
<div class="article">
<div class="article-wrapper">
<h1>Hello world</h1>
<p>This is my</p>
<p>Amazing article</p>
</div>
</div>
I tried the same code with Amber but it just ignores it.
I also tried sending mixins as parameters of a mixin. This also doesn't seem possible:
+header("Header Text")
+twocolumns(+header, +header)
Any workaround for this?
Hello.
I have some questions to a several things :)
-- main.go
...
data := []string{ "qwe", "rty", "uio"}
tmpl["test"].Execute(res, data)
-- test.amber
each $word in .
p #{$word}
I tried use .
#{}
#{.}
and blank - but it's not working.
I need to create attribute with an empty value. <a testattr=""></a>
for example.
a[testattr]
- creates <a testattr></a>
a[testattr=""]
- submits "Unable to parse expression".
Thanks in advance, and thanks for a great package :)
Template:
div[style` = "px;bottom:" + "aaa" + "px"]
Expected result:
<div style="px;bottom:aaapx"></div>
Real result:
<div style="ZgotmplZ"></div>
There is no error being displayed.
In HTML5, the /
should be omitted from self-closing tags. e.g. <br/>
should just be <br>
.
Lines 399 to 400 in a714b9e
empty string attribute values are not accepted, i get a generic error: Unable to parse expression
sample template:
a[href=""] // those are double quotes
if i put something in the double quotes then it works:
a[href="/"] // this compiles
in general, i can't really think of a use case where an empty string for the value of an attribute makes sense, but since i'm trying to convert jade/haml to amber, i think it might be a bit of an incompatibility. obviously there are incompatibilities, but this one's not so complicated.
!!! 5
html
body
iframe[src="/frame.html"]
leads to
Amber Error in <t.amber>: Unable to parse expression. - Line: 4, Column: 5, Length: 25
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
Special chars in attribute value, though quoted, breaks the parser:
input
[pattern="(\d{3}- )?\d{3}-\d{4}"]
panic: Unable to parse expression. [recovered]
Would it be possible to add syntax for importing Markdown pages? Or having blocks of Markdown? This could be useful for making Amber templates, but then add content with separate Markdown files.
I've had good experiences with this Markdown module: https://github.com/russross/blackfriday
@eknkc Good to know that Iris web framework has build'n support for amber template engine, if you want add a section like 'Projects using amber' and put Iris on it, I have put amber on the README, e-book and history.md also :)
Good job and continue hard!
I wanna change the markup for tag attributes to
a(href="", style="")
Using a[href=""][style=""]
would have no highlight on any editor.
I've tried your Pug package but there are numerous errors.
Any chance?
Hi Sorry for such question because i am new to templates can any one tell me how to add Javascript functions in template.
Pasted the code and error
main.go
package main
import (
"log"
"github.com/eknkc/amber"
)
func main() {
res, err := amber.CompileDir("./views", amber.DefaultDirOptions, amber.DefaultOptions)
if err != nil {
log.Print(err)
}
log.Print(res)
}
views/a.amber
mixin a
foo
views/b.amber
+a
err:
2014/10/17 17:22:56 Amber Error in <views/b.amber>: runtime error: invalid memory address or nil pointer dereference - Line: 1, Column: 1, Length: 2
Any idea?
beego
for k, v := range amber.FuncMap {
beego.AddFuncMap(k, v)
}
beego.AddTemplateEngine("amber", func(root, path string, funcs template.FuncMap) (*template.Template, error) {
amber.FuncMap = funcs
options := amber.Options{true, true}
//options := &amber.FuncMap
filePath := filepath.Join(root, path)
fmt.Println("path", filePath)
tpl, err := amber.CompileFile(filePath, options)
if err != nil {
return nil, fmt.Errorf("error loading amber template: %v", err)
}
return tpl, nil
})
template
!!! 5
html
head
block meta
//re this error
meta[name="description"][content="This is a great website"]
title
block title
| Default title
body
block content
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?
Bug 1:
Whenever there are no default classes being included on a tag and all the included classes are with conditional values, the template is not rendered according to the expectations.
Reproduction guide:
Run the following template:
$var_1 = 20
div
.foo ? $var_1 == 10
.bar ? $var_1 == 20
Compiled template:
{{$var_1 := 20}}{{$__amber_1 := __amber_eql $var_1 10}}{{$__amber_2 := __amber_eql $var_1 20}}
<div{{if $__amber_1}} class="{{if $__amber_1}}foo{{end}} {{if $__amber_2}}bar{{end}}"{{end}}></div>
Expected result:
<div class="bar"></div>
Real result:
<div></div>
Bug 2:
Whenever adding attributes to a tag, if the same attribute appears multiple times with different conditions, just the latest one is considered.
Reproduction guide:
Run the following template:
$var_1 = 10
div
[foo="bar"] ? $var_1 == 10
[foo="zaz"] ? $var_1 == 20
Compiled template:
{{$var_1 := 20}}{{$__amber_1 := __amber_eql $var_1 10}}{{$__amber_2 := __amber_eql $var_1 20}}
<div{{if $__amber_2}} foo="zaz"{{end}}></div>
Expected result:
<div foo="bar"></div>
Real result:
<div></div>
Version: Latest
+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?
for example :
a[href="path?id="+$repo.ID];
the value of href will be messy code
i want to know how to solve it
I tried the sample code on inheritance but it compiles as a tag element.
For example:
extends master
generates:
<extends>master</extends>
I used a 32-bit Windows Vista running go1.0.3
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.
How would you iterate. The following pseudo-code with dot format will convey what I am trying to achieve
each $row in .
tr
td $row.Firstcol
td $row.Secondcol
Is there a way to print unescaped HTML text? I pass some text through blackfriday (markdown library) to generate HTML, and try to print it in an amber template using the #{variable} notation, but I always get it escaped (it prints the tags and all in the rendered document, instead of interpreting the HTML).
I know this is possible in Jade, the "inspiration" for amber, but I haven't found anything about such a feature in the docs or a quick look at the code.
Thanks,
Martin
I am using Sublime 3 and would like to have syntax highlight if I used Amber. Do you know of anything of the sort? I noticed the syntax deviates from Jade, so a Jade plugin won't work.
Using this code:
package main
import (
"log"
"os"
"github.com/eknkc/amber"
)
func hasData() bool {
return true
}
var tmpl = `p
.has-data ? hasData()`
func main() {
amber.FuncMap["hasData"] = hasData
compiler := amber.New()
compiler.Parse(tmpl)
c, err := compiler.Compile()
if err != nil {
log.Fatal(err)
}
err = c.Execute(os.Stdout, nil)
if err != nil {
log.Fatal(err)
}
}
Results in this error:
reflect: call of reflect.Value.Type on zero Value
I've been looking at this for days. Am I plugging the function in wrong? Are (non-builtin) functions disallowed in conditional argument conditions? Or is this just a bug?
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"
Hello, please see https://github.com/jaschaephraim/amber/tree/handlebars where I've added support for using Amber to write handlebars templates. The main changes are:
type="text/x-handlebars"
, then its contents is compiled instead of being treated as raw textunescapedJS
, like unescaped
but using template.JS
instead of template.HTML
unescapedJS
. This keeps html/template
from escaping {{
and }}
only when the contents of the script
tag is being compiledSo...
h1 {{hello}}
script
h1 {{hello}}
script[type="text/x-handlebars"]
h1 {{hello}}
becomes:
<!-- behavior unchanged -->
<h1>{{hello}}</h1>
<!-- behavior unchanged -->
<script>
h1 "{{"hello"}}"
</script>
<!-- new behavior -->
<script type="text/x-handlebars">
<h1>{{hello}}</h1>
</script>
Let me know if this is something you'd like to merge and I can fix the import paths and submit a pull request. Thanks!
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
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.
Hello,
Is it possible to include a separate file with the license text? It makes redistributing amber easier for some projects (like in distros).
Thank you!
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.