realistschuckle / gohaml

An implementation of the popular XHTML Abstraction Markup Language using the Go language.
MIT License
95 stars 13 forks source link

Needs CDATA blocks (perhaps haml filters) #4

Closed bmatsuo closed 12 years ago

bmatsuo commented 12 years ago

Haml has special blocks for outputting javascript/css (and generic CDATA) blocks.

Bundled with these features is the ability to embed other markup styles.

Embedding other markup isn't very important, but CDATA blocks are nice in some circumstances where page-specific javascript is used. So, filter blocks might as well be implemented anyway.

I'd be willing to help implement this. I imagine an interface

type Filter interface{
    // content is indented and ends with "\n".
    // output should be indented and end with "\n".
    Filter(content, indent string) string
}

And so CDATA, css, and javascript blocks can all be implemented is simple functions

func cdataHelper(pre, post, content, indent string) string {
    return fmt.Sprintf("%s%s<![CDATA[%s\n%s\n%s%s]]>%s\n",indent, pre, post, content, indent, pre, post)
}

func cdata(content, indent string) string { return cdataHelper("", "", content, indent) }
func css(content, indent string) string {
    return fmt.Sprintf(`%s<style type="text/css">\n%s\n%s</style>\n`, indent, cdataHelper("", "", content, indent), indent)
}
func javascript(content, indent string) string {
    return fmt.Sprintf(`%s<script type="text/javascript">\n%s\n%s</script>\n`, indent, cdataHelper("", "", content, indent), indent)
}

The parsers could be usable in the parser via a map.

type FilterMap map[string]func(input, indent string) string

Note: I haven't actually compiled any of this, so there could be some small errors.

bmatsuo commented 12 years ago

Oh yea, there was a bug. I never used the Filter type...

Make FilterMap have type

type FilterMap map[string]Filter

And, there should be a type

type filterFunc func(content, indent string) string

func (fn filterFunc) Filter(content, indent string) string { return fn(content, indent) }

Then, the filter map available to parsers looks something like

var defaultFilters = FilterMap{
    "cdata": filterFunc(cdata),
    "css": filterFunc(css),
    "javascript": filterFunc(javascript),
    // ...
}
bmatsuo commented 12 years ago

I started a branch where filters are implemented. https://github.com/bmatsuo/gohaml/tree/filters

It has working implementations of the filters I described above. They turned out to be more complex than I'd thought originally. But still, not bad.

Because filter input is plain text (not haml markup) they only need to be executed once. So I'm executing them in the parse method right after the block is out of scope.

It has unit tests that you can check out in the file lib/haml_filter_test.go

Before I issue a pull request, I just want another day or so to work out kinks and sloppiness in my mods to

func (self *hamlParser) parse(input string) (output *tree, err os.Error)

Any thoughts?

realistschuckle commented 12 years ago

Thanks for doing this, bmatsuo. I, too, have felt the inspiration to implement it. If I can get it in leaner, I'll commit. Otherwise, I'll wait for your pull request.

bmatsuo commented 12 years ago

I ended up getting all caught up with custom indentation strings for filter output and not finishing when I thought I would.

Then school and life got in the way of progress, like always.

But things are pretty good, I think, when you check out the branch diff https://github.com/bmatsuo/gohaml/compare/master...filters (sorry there are scattered tiny changes that gofmt made w/o me realising)

The parse method is cleaned up a good amount. I moved everything into helper methods/functions. I think I'll split that code off into a new file parse_filter.go.

But overall, I think this code is working and stable enough to open a pull request. I think it can still be improved substantially. But, I don't think it has to be done immediately.

Any thoughts? If you think its good, then I'll just clean it up a little bit (like splitting off the new file I mentioned) and open the pull request.

realistschuckle commented 12 years ago

Hey, yeah, that looks nice! Waiting for the pull request.

bmatsuo commented 12 years ago

Pull request here. Closing this issue to move any discussion there. Didn't end up splitting filter parsing off into a new file, just organized it a little better. Also, some final fixes and things.

Anyway, sorry it took so long. Other things in life taking priority. THis is just a side-project for me. Anyway, look it over, test it out, and enjoy.