Coder Social home page Coder Social logo

snapframework / heist Goto Github PK

View Code? Open in Web Editor NEW
92.0 92.0 58.0 1.44 MB

An xhtml-based templating engine, allowing Haskell functions to be bound to XML tags.

Home Page: http://snapframework.com/

License: BSD 3-Clause "New" or "Revised" License

Haskell 94.53% Smarty 1.52% CSS 3.55% Shell 0.40%

heist's People

Contributors

23skidoo avatar alexanderkjeldaas avatar aluink avatar andreasabel avatar aslatter avatar bergmark avatar cdsmith avatar centromere avatar chowells79 avatar cydparser avatar duairc avatar gregorycollins avatar h-3-0 avatar hvr avatar imalsogreg avatar kaol avatar ludat avatar markwright avatar michaelxavier avatar mightybyte avatar norm2782 avatar ozataman avatar rahulmutt avatar schell avatar soiamsong avatar sol avatar sopvop avatar trofi avatar wiz avatar wlangstroth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

heist's Issues

Please provide a Changelog

snaplet-stripe currently doesn't build with the latest version of heist. I'd like to fix that, but I'm not a heist user. Unfortunately, there is no documentation that lets me learn where hcCompiledSplices has gone, and what I should be doing instead. This problem (and future problems) could be reduced if there was a Changelog document, which would document API changes, and ideally how one can fix parts that have changed.

When parsing attribute substitutions, a single $ stops regular "text gobbling", whereas Heist should look for the full ${ pattern

Example:

Try putting the following regular html code (imagine the HTML braces there; github has issues with them)

<input type='text' value='This is just a value that has $ in it. But this part will never show, as $ will trigger attribute substitution and remove this entire part of this text'>

The resulting input node will only contain:

"This is just a value that has " in its value attribute.

Stack overflow when using attribute substitution inside apply tag

Using an attribute substitution in an apply tag leads to a stack overflow in the latest version of snap / heist.
Two Heist templates which produce the issue are:

attrsubtest1.tpl:

<content />

attrsubtest2.tpl:

<bind tag="test">asdf</bind>
<apply template="attrsubtest1">
    <a href="${test}">link</a>
</apply>

And the output when requesting attrsubtest2.tpl is:

A web handler threw an exception. Details:
stack overflow

Cannot contain child elements or comments

I built up a [Node] manually using only xmlhtml. Let's refer to it as myNodes. If I do

main = BC8.putStrLn $ Blaze.toByteString $ renderXmlFragment UTF8 myNodes

Then it renders fine. But, it is just an XML fragment, so I need to splice this into a template. This seems like it should be simple. It's a constant [Node]. So, I tried this:

main = do
  let heist = hcTemplateLocations  .~ [ loadTemplates "templates" ]
            $ hcNamespace .~ ""
            $ hcCompiledSplices .~ ("report" ## return (yieldPure (nodeSplice (const $ myNodes) ())))
            $ emptyHeistConfig
  heistState <- do
    res <- runEitherT $ initHeist heist
    case res of
      Left err -> error $ unlines err
      Right a -> return a
  builder <- maybe (error "oops") fst $
    renderTemplate heistState "report"
  BC8.putStrLn . Blaze.toByteString $ builder

But now I get this:

sheets: style:style cannot contain child elements or comments

Which seems bad because it's an exception thrown from pure code in xmlhtml (src/Text/XmlHtml/HTML/Render.hs). Also, if I just remove the line for using compiled splices, then it runs fine (but without replacing <report/> of course). So, something in heist is messing up the rendering of the otherwise alright node list. In case this is helpful:

Correct rendering of myNodes:

<office:automatic-styles><style:style style:name='basic-column-style' style:family='table-column'><style:table-column-properties fo:break-before='auto' style:column-width='0.9in'/></style:style><style:style style:name='basic-row-style' style:family='table-row'><style:table-row-properties fo:break-before='auto' style:row-height='0.178in' style:use-optimal-row-height='true'/></style:style><style:style style:name='basic-table-style' style:family='table' style:master-page-name='Default'><style:table-properties table:display='true' style:writing-mode='lr-tb'/></style:style><style:style style:name='foo11' style:family='table-cell'><style:table-cell-properties fo:border-top='none' fo:border-bottom='none' fo:border-left='none' fo:border-right='none'/></style:style></office:automatic-styles><office:body><office:spreadsheet><table:table table:name='Sheet1' table:style-name='basic-table-style'><table:table-column table:number-columns-repeated='1' table:style-name='basic-column-style'/><table:table-row table:style-name='basic-row-style'><table:table-cell table:style-name='foo11'><text:p>Hello There</text:p></table:table-cell></table:table-row></table:table></office:spreadsheet></office:body>

report.tpl

<?xml version="1.0" encoding="UTF-8"?>
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:presentation="urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2">
  <office:scripts/>
  <office:font-face-decls>
    <style:font-face style:name="Liberation Sans" svg:font-family="'Liberation Sans'" style:font-family-generic="swiss" style:font-pitch="variable"/>
    <style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
    <style:font-face style:name="Droid Sans Fallback" svg:font-family="'Droid Sans Fallback'" style:font-family-generic="system" style:font-pitch="variable"/>
    <style:font-face style:name="FreeSans" svg:font-family="FreeSans" style:font-family-generic="system" style:font-pitch="variable"/>
  </office:font-face-decls>
  <report/>
</office:document-content>

GHC 8.10.1 support

The current version on hackage, 1.1.0.1 doesn't support base 4.14. Any plans to make a point release with the bounds bumped?

Incorrect alignment in resulting HTML

Consider this .tpl file:

<html>
<head>
    <apply template="meta"/>
</head>
</html>

With this meta.tpl file:

<meta http-equiv='content-type' content='text/html; charset=utf-8' />
<meta name='robots' content='noarchive' />

Then this is the result:

<html>
<head>
    <meta http-equiv='content-type' content='text/html; charset=utf-8' />
<meta name='robots' content='noarchive' />
</head>
</html>

Note the misalignment of the second line.

Can this be fixed? (I like my websites to have beautiful HTML.)

Add an example of a simple HeistConfig value

So I'm trying to use this library on it's own (without Snap's heist snaplet), but it doesn't appear to be a simple process to create a HeistConfig value. Perhaps it would be useful to demonstrate such an example?

heist cabal file revision in nixos (and on hackage)?

By running
nix-prefetch-url http://hackage.haskell.org/package/heist-1.0.1.0/revision/6.cabal
I can see the store path to the heist.cabal that, in turn, seems to be old. (The above link seems to show it, too.)

There is aeson upper bound < 1.2 while here on the github it seems to be < 1.3. Also hackage seems to refer to old version, see heist on hackage.

The nixpkgs seems to refer to heist-1.0.1.0 and revision 6. See the lines around line 98640 in
hackage-packages.

There is possibly some other revisions/changes made after aeson upper bound change? If so, it would mean that those changes are also not available at nixos.

Any chances to get a new version 1.0.1.1 that would certainly have the latest changes?

Expose more of RuntimeSplice

We have a MonadReader-like typeclass that we'd like to implement for RuntimeSplice m. Currently this is not possible, since you can't implement local. One option is to expose the RuntimeSplice constructor and unRS deconstructor. Then we could do something like:

instance OurReader m => OurReader (RuntimeSplice m) where
  ourAsk = lift ourAsk
  ourLocal f = RuntimeSplice . ourLocal f . unRT 

Another option is to provide an instance of MonadTransControl for RuntimeSplice. This could be used to write ourLocal and would also allow use of the functions from lifted-base, like catch.

I could send a pull request for either option, if you let me know which (if any) you prefer.

Barely malformed XML

So, when I use heist for XML (or HTML, but I assume that it probably leads to correct behaviors in that case), the end of the resulting document looks like this:

</office:body>&#10;</office:document-content>&#10;

When I run this file through xmllint, I get:

andrew@webapps-test:~/projects/sheets$ xmllint --format sheet.xml                                                                                                                                            
sheet.xml:6: parser error : Extra content at the end of the document
</table:table></office:spreadsheet></office:body>&#10;</office:document-content>
                                                                               ^

Other linters give similar complaints. This is because you aren't supposed to have any content after closing the root tag in an XML document. Is there something that I have missed (ie- rendering it the wrong way), or is this case not correctly handled?

Can't pass-through full JSON object to template

Maybe I don't understand the point of bindJson at all, but I expected the following to be possible:

Bind a JSON splice, for example using:

bindSplice "foo" (bindJson $ object [ "bar" .= 1, "baz" .= 2 ])

(having object and (.=) imported from Data.Aeson, and then in the template using

<foo><value/></foo>

but this only produces an error message saying var should be specified for value. While the docs say that this is the intended behavior, I do not understand the rationale for this limitation and would like to see it lifted.

Not compatible with attoparsec 0.12

I haven't released 0.12 yet, but you can find it at the expected place.

Failed to install heist-0.11.1
Last 10 lines of the build log ( /Users/bryano/Downloads/t/.cabal-sandbox/logs/heist-0.11.1.log ):
    In the first argument of `numToText', namely `n'
    In the second argument of `($)', namely `numToText n'
    In the expression: txt $ numToText n

src/Heist/Splices/Json.hs:158:40:
    Couldn't match expected type `Number'
                with actual type `scientific-0.3.2.1:Data.Scientific.Scientific'
    In the first argument of `numToText', namely `n'
    In the second argument of `($)', namely `numToText n'
    In the expression: goText $ numToText n

Performance issues with large / many templates (though they're not rendered)

So I've been trying to figure out why a simple template is taking a very long time to render (nearly a second). I realized my heist config was trying to compile the templates - I've prevented that.

However it's still taking 0.2s, upon further investigation if I add a bunch of large templates into my templates directory - the performance drops. I'm not rendering those templates so I don't see why any processing is being done on them.

Here is my function I use to render:

renderHeistTemplatePath :: TemplateName -> HeistBind -> IO (Either Text Text)
renderHeistTemplatePath fileName hsBinding = do
  let emptyI = return () :: MapSyntax Text (I.Splice IO)
  let emptyC = return () :: MapSyntax Text (HeistCom.Splice IO)
  let emptyA = return () :: MapSyntax Text (AttrSplice IO)
  let templateLocations = [Heist.loadTemplates "templates/"]
  let spliceConfig = SpliceConfig emptyI emptyI emptyC emptyA templateLocations (\_ -> False):: SpliceConfig IO
  heist <- Heist.initHeist (HeistConfig spliceConfig "" True)
  case heist of
    Right heist' -> do
      rendered <- I.renderTemplate (hsBinding heist') $ convertString fileName
      case (rendered) of
        Just (builder, _) -> return . return . convertString $ toLazyByteString builder
        Nothing -> return . Left $ "Heist render error. No further information"
    Left a -> return . Left . convertString . show $ a

Any ideas would greatly be appreciated.

When callTemplate is used in conjunction with withSplices, templates throw namespace errors when they shouldn't.

There's a problem with how compiled Heist loads templates in compileTemplates'. It processes all the templates, including ones starting with an underscore, even though those aren't meant to be used directly. This causes problems when namespaces are also used, since subtemplates potentially have tags that are only bound with withSplices.

https://github.com/kaol/heist/tree/nsbindcall has the fix and https://github.com/kaol/heist/tree/nsbindcall-test has a test for calling underscored template with namespaces. The new test should work with master and my branch but the code in master fails with the added underscored template in the nsbinderr test.

Heist cannot parse "well formed" comments

HTML comments have the following format:

<!-- foo -->

This is fine, however, the number of - characters used is not correctly specified in Heist. HTML does not make a distinction between <!-- and <!--- or --> and ------>. Any hyphens after the opening two and preceding the ending two are not significant. Heist will throw a parse error in this situation.

Please add support for errors 1.4.0

Heist won't compile against the latest version of the errors package. If there is a chance, could you please release a quick update that remedies this issue? The error message I get trying to compile Heist is:

src/Heist.hs:140:30:
    Not in scope: type constructor or class `EitherT'
    Perhaps you meant one of these:
      `Either' (imported from Prelude),
      `EitherR' (imported from Control.Error),
      `EitherRT' (imported from Control.Error)

"Apply"ing a missing template gives no warning

My use case was something like:

<apply template="path/to/outer"><apply template="path/to/inner"/></apply>

Which causes heist to look for "inner" in /path/to/path/to/inner, because there is no leading /. I have no opinion on whether this behavior is correct or not, but it did surprise me as a newbie. It would help even out the learning curve if file-not-found conditions issued some kind of warning message (or maybe I just don't know how to turn warnings on).

Add `<else />` support for bindJson

I'm parsing YAML into a Aeson.Value and passing it straight to the template using bindJson, for using like this (tags would be a YAML field with list value):

            <with var="tags">
              <a title="Tag" class="px-1 bg-gray-100 rounded">
                <value />
              </a>
            </with>

This however doesn't work when the YAML has no fields named "tag"; Heist throws: expression error: can't find "tags" in JSON object (<with> tag)

I'd like to be able to specify a "else" case to render if there is no such field, based on the similar behaviour if the IfElse splice, i.e.

            <with var="tags">
              <a title="Tag" class="px-1 bg-gray-100 rounded">
                <value />
              </a>
              <else />
              <p>This note is not tagged</p>  <!-- Can also be empty -->
            </with>

What do you folks think of this feature? It may be extended to <value> and <snippet> as well.

Incorrect DOCTYPE for XML documents.

I built a template for establishing an RSS feed at https://github.com/justindthomas/blog/blob/master/snaplets/heist/templates/rss.xtpl

Despite trying to direct Snap to render that as "application/rss+xml", it insists on removing the ?xml directives and prepending a at the top (see https://ser.endipito.us/rss.xml for an example). That breaks all RSS readers that I've tried (and the validator at https://validator.w3.org/feed/ just aborts immediately when the document is pasted in, saying it's a web page, not an RSS feed).

RSS 2.0 specifies that there should/can be no DOCTYPE. Any mechanism for dropping that from the parser should solve this issue. Also refraining from stripping the ?xml directives for xtpl files would be nice.

Interpreted splices don't work in attributes

If you bind an interpreted splice (e.g. ("foo", textSplice "bar")) and use it in an attribute, it doesn't work. The following template:

<foo/>
<a class="${foo}">bla</a>

will render as

bar
<a class="${foo}">bla</a>

Even nastier, the following template

<bind tag=bar><foo/></bind>
<a class="${bar}">bla</a>

will render as

<a class>bla</a>

This is because the bind expands to <foo/> at compile time, and heist then takes the text content, which is empty.

The right fix seems to be to compile attributes to Chunks as well, but that looked like a rather invasive fix. Any ideas?

Attribute Minimization

To my knowledge, heist doesn't provide a way to enable/disable minimized attributes. I saw a reddit question where someone gave this example of a template they had written:

<select>
  <for-stylesheets>
    <if-equal a="${key}" b="${active-stylesheet}">
      <option value="${key}" selected><name/></option>
    </if-equal>
    <if-not-equal a="${key}" b="${active-stylesheet}">
      <option value="${key}"><name/></option>
    </if-not-equal>
  </for-stylesheets>
</select>

What's bad is that the if-equal and if-not-equal splices only differ in whether the option element has the selected attribute enabled. Ideally, it would be possible to write something like this:

<option value="${key}" selected="${is-selected}"><name/></option>

Except that this makes selected appear in all cases. Is there a workaround for this (possibly one that generates non-compliant HTML5 that all browsers still understand)?

stopRecursion does not properly stop recursion in attribute substitutions

I was not able to dig the exact source of this error in Heist code, but if I put a $ value within a bound splice and use it as an attribute substitute, the attribute substitution process seems to continue recursion into the initial substitute and further try to replace the inner text. I was unable to stop this using stopRecursion.

For example:

sampleSplice = do
  stopRecursion
  textSplice ("Here is a text splice with $ in it. But this part will not be seen, as Heist will keep recursing and look to replace anything after $.")

Interpreted Splices and Adding Templates

I'm using interpreted splices and trying to add templates to the HeistState at runtime. However, I can't get any of the templates to use the default splices. What I have right now will render the template exactly as it is loaded, without applying bind or apply tags.

The relevant parts of my code (I think) are the heistConfig function and the line that reads mrendered <- I.renderTemplate newHs title. I will post it all in case it is somehow helpful. However, you will not be able to run this.

Let me know if I can do anything to clarify the issue further.

{-# LANGUAGE ScopedTypeVariables #-}
module Microsite.Functions
  ( renderPage
  ) where

import           Lens.Family (set)

import qualified Heist             as H
import qualified Heist.Interpreted as I
import           Heist (HeistConfig, HeistT, HeistState)
import qualified Microsite.Types as MS
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import           Control.Monad.Trans.Either (runEitherT)
import           Control.Monad.IO.Class (MonadIO, liftIO)
import           Data.ByteString (ByteString)
import           System.IO.Unsafe (unsafePerformIO)
import           Text.XmlHtml (parseHTML, docContent)
import           Blaze.ByteString.Builder as Blaze

renderPage :: forall m. MonadIO m => MS.Interface m -> MS.MicrositeId -> MS.ResourceName -> m (Either String ByteString)
renderPage interface theId name = do
  markupText <- MS.loadResourceMarkup interface theId MS.Page name
  let markupByteString = TE.encodeUtf8 markupText
  hs <- liftIO (baseHeistState :: IO (HeistState m))
  let res = parseHTML (MS.resourceNameToString name) markupByteString
  case res of
    Left errMsg -> return $ Left errMsg
    Right document -> do
      let nodes = docContent document
          title = TE.encodeUtf8 $ MS.unResourceName name
          newHs = I.addTemplate title nodes Nothing hs
      mrendered <- I.renderTemplate newHs title
      case mrendered of
        Just (builder, _) -> return $ Right $ Blaze.toByteString builder
        Nothing           -> return $ Left "Something in heist messed up"

baseHeistState :: MonadIO m => IO (HeistState m)
baseHeistState = do
  res <- runEitherT $ H.initHeist heistConfig
  return $ either (error "heist state has broken in microsite") id res

heistConfig :: MonadIO m => HeistConfig m
heistConfig = set H.hcNamespace (T.pack "h") $
              set H.hcInterpretedSplices H.defaultInterpretedSplices $
              set H.hcErrorNotBound True $
              H.emptyHeistConfig

getDoc makes no diff with getXMLDoc

Around line 660 at Text.Templating.Heist.Internal.hs

Both getDoc and getXMLDoc leverage parseHTML from xmlhtml and I suspect getXMLDoc is expected to use parseXML.

Thanks.

Mock out pandoc in the test suite if the executable doesn't exist

Is there a reason pandoc isn't listed as a dependency?

This is causing heist builds to fail over in nixpkgs. Without an official dependency on pandoc, cabal2nix doesn't correctly set up an environment so heist tests can run.

I decided to open this issue instead of going directly for a PR so we can discuss the correct fix.

Test suite failure

  heist/fsLoad: [OK]
  heist/renderNoName: [OK]
  heist/doctype: [OK]
  heist/attributeSubstitution: [OK]
  heist/bindAttribute: [OK]
  heist/markdown: [OK]
  heist/pandoc: [Failed]
ERROR: user error (Pattern match failure in do expression at test/suite/Heist/Interpreted/Tests.hs:319:9-21)
  heist/pandoc_div: [Failed]
ERROR: user error (Pattern match failure in do expression at test/suite/Heist/Interpreted/Tests.hs:319:9-21)
  heist/title_expansion: [OK]
  heist/textarea_expansion: [OK]
  heist/div_expansion: [OK]
  heist/bind_param: [OK]
  heist/markdownText: [OK]
  heist/apply: [OK]
  heist/ignore: [OK]
  heist/lookupTemplateContext: [OK]
  heist/attrSpliceContext: [OK]
  heist/json/values: [OK]
  heist/json/object: [OK]
  heist/renderXML: [Failed]
ERROR: user error (Pattern match failure in do expression at test/suite/Heist/Interpreted/Tests.hs:319:9-21)
Heist.Compiled.Tests:
  compiled/simple: [OK]
  compiled/people: [OK]
  compiled/namespace1: [Failed]
namespace test 1
expected: Right "Alpha\naoeu\nBeta\n<h:foo aoeu='htns'>Inside h:foo</h:foo>\nEnd\n"
 but got: Left ["Error rendering"]
  compiled/namespace2: [Failed]
namespace test 2
expected: Right "Alpha\naoeu\nBeta\n<h:foo aoeu='htns'>Inside h:foo</h:foo>\nEnd\n"
 but got: Left ["Error rendering"]
  compiled/namespace3: [Failed]

href="" gets turned into href (="" goes away)

This Heist code

<a href="" onclick="return false;" id="abt">About</a>

turns into this HTML

<a href onclick='return false;' id='abt'>About</a>

This is not good, because the W3 Validator spits out a warning about it:

Warning: Attribute href without an explicit value seen. The attribute may be dropped by IE7.

I want my HTML to pass all validations.

Can you make ="" not disappear?

HTML entities are not being preserved

All HTML entities found in my templates are being converted to the actual character (eg. &amp; becomes &, &copy; becomes ©). For most characters, this doesn't matter a whole lot, but a raw ampersand causes HTML validation to fail.

Template source:

<p class="copyright">&copy;2013 Company Name here</p>

Rendered document's source:

<p class='copyright'>©2013 Company Name here</p>

How to pass raw HTML as template variable?

textSplice cannot obviously be used to inject raw HTML (say, those coming from Pandoc rendered HTML) into heist template, as they will be automatically escaped.

One solution is to parse the raw HTML using Text.XmlHtml but this is obviously both unnecessary and waste of CPU usage.

Does heist support injecting raw HTML?


A related question: if I'm to build HTML from some AST (say Pandoc AST), how does the performance of Text.XmlHtml compare to others (such as blaze-html)?

passing bound names to splices

When trying the following

<bind tag="foo">5</bind>
<fact><foo/></fact>

(here fact is bound to factSplice from the tutorial)

it seems that <foo/> is not expanded before the splice is evaluated (which in this case leads to an exception).

Do we want to support the above example? If no, is there a way to do something similar with heist? In particular I'd like to bind some name inside my code with bindString and pass it to a splice.

Odd escaping of whitespace if the first thing in a template is a bind-tag

If the first thing in a template is a bind-tag and that bind tag is followed by a whitespace then, for some reason, the whitespace is replaced by a numeric character reference (e.g. \n becomes &#10;). Is this a bug or a feature?

I can supply a test case that demonstrates this behaviour, if that helps.

Update documentation - be explicit that .tpl extension is not needed to "render" call

Hey,

I'll edit the docs when I have the time, but I wanted to record this for future reference.

For a heist template, to render a given template, say, index.tpl, the corresponding call in handler should be like this:

handleIndex :: Handler App App ()
handleIndex = render "index"

That is, the name should be index, not index.tpl

This isn't explicitly documented anywhere I looked, and it took me an hour to figure out :)

Build failure with 1.0.1.3

I'm getting the following build error when performing an LTS Haskell build:

[ 9 of 20] Compiling Heist.Internal.Types ( src/Heist/Internal/Types.hs, dist/build/Heist/Internal/Types.o )

src/Heist/Internal/Types.hs:161:21: error:
    • No instance for (Semigroup (Splices (I.Splice m)))
        arising from a use of ‘<>’
    • In the first argument of ‘SpliceConfig’, namely ‘(a1 <> a2)’
      In the expression:
        SpliceConfig
          (a1 <> a2)
          (b1 <> b2)
          (c1 <> c2)
          (d1 <> d2)
          (e1 <> e2)
          (\ x -> f1 x && f2 x)
      In an equation for ‘<>’:
          SpliceConfig a1 b1 c1 d1 e1 f1 <> SpliceConfig a2 b2 c2 d2 e2 f2
            = SpliceConfig
                (a1 <> a2)
                (b1 <> b2)
                (c1 <> c2)
                (d1 <> d2)
                (e1 <> e2)
                (\ x -> f1 x && f2 x)
    |
161 |       SpliceConfig (a1 <> a2) (b1 <> b2) (c1 <> c2)
    |                     ^^^^^^^^

src/Heist/Internal/Types.hs:161:32: error:
    • No instance for (Semigroup (Splices (I.Splice IO)))
        arising from a use of ‘<>’
    • In the second argument of ‘SpliceConfig’, namely ‘(b1 <> b2)’
      In the expression:
        SpliceConfig
          (a1 <> a2)
          (b1 <> b2)
          (c1 <> c2)
          (d1 <> d2)

Namespacing gets ignored with compiled Heist for withSplices/callTemplate

Namespacing gets ignored for a template introduced with withSplices and codeGen.

{-# LANGUAGE OverloadedStrings #-}
module Bug where

import qualified Data.ByteString as B
import Blaze.ByteString.Builder
import Control.Monad.Trans.Either
import Heist
import Heist.Compiled as C
import qualified Data.Text as T
import Control.Lens
import Heist.Compiled.LowLevel as C

dummy :: Monad m => RuntimeSplice m ()
dummy = return ()

mainSplices :: Monad m => Splices (C.Splice m)
mainSplices = "one" ## (oneRender dummy)

oneRender :: Monad m => RuntimeSplice m () -> C.Splice m
oneRender = const $ do
  tpl <- C.withSplices (C.callTemplate "sub") oneSplices dummy
  return $ C.yieldRuntime $ C.codeGen tpl

oneSplices :: Monad m => Splices (RuntimeSplice m () -> C.Splice m)
oneSplices = mapV (pureSplice . textSplice) $
  "two" ## const "should not be spliced in"

heistConfig = emptyHeistConfig
              & hcCompiledSplices .~ mainSplices
              & hcTemplateLocations .~ [loadTemplates "."]

main = do
  initState <- runEitherT $ initHeist heistConfig
  case initState of
   Left errs -> print errs
   Right heistState -> do
     builder <- maybe (error "oops") fst $
                C.renderTemplate heistState "main"
     toByteStringIO B.putStr builder

main.tpl:

One.
<h:one/>

sub.tpl:

Two.
<two/>

<!-- using <h:two/> results error "./sub.tpl: No splice bound for h:two" -->


The output for this is

One.
Two.
should not be spliced in

Expected output would be

One.
Two.
<two/>

Tags incorrectly made self-closing when compiled

Rendering the following template

<a href="${a}"></a>

produces this output:

<a href="${a}" />

According to the HTML5 spec, this means the same as

<a href="${a}">

This has a different meaning, and will break your HTML.

The reason this happens is that in Heist.Compiled.Internal.compileNode, a tag is 'self-closed' like this if it contains no children. This should only be done for tags that must be empty in HTML5, like br and img. In Text.XmlHtml.HTML.Meta, there is a set of voidTags that can be used to check if the tag should be self-closed. However, that module isn't exported (yet), which is why I couldn't easily send a pull request. Should I just expose the module and use that in heist? That's how I fixed it locally.

Generalize to any load time monad m rather than fixing it to IO

Fixing to IO was the wrong decision here. First, I don't think most use cases even use IO. And second, there are good reasons to want to initialize Heist in monads other than IO.

This isn't a very substantive change, but it ends up affecting a lot of code because the compiled splice type alias gets an additional type variable. If anyone wants to help out with a pull request here, it would be much appreciated.

Tests fails when built with nix

nix build
builder for '/nix/store/2y56639fzrr25xfn62a21a46rkyy8znn-heist-1.1.0.1.drv' failed with exit code 1; last 10 log lines:
  CallStack (from HasCallStack):
    error, called at test/suite/Heist/TestCommon.hs:67:13 in main:Heist.TestCommon
  
           Properties  Test Cases   Total       
   Passed  2           15           17          
   Failed  0           32           32          
   Total   2           47           49          
  Test suite testsuite: FAIL
  Test suite logged to: dist/test/heist-1.1.0.1-testsuite.log
  0 of 1 test suites (0 of 1 test cases) passed.
[0 built (1 failed)]
error: build of '/nix/store/2y56639fzrr25xfn62a21a46rkyy8znn-heist-1.1.0.1.drv' failed

I'm not sure how to get that log out unfortunately.

default.nix file used:

{
  nixpkgs ? import <nixpkgs> {}
, sources ? import ./nix/sources.nix
, compiler ? "ghc864" } :
let
  niv = import sources.nixpkgs {
    overlays = [
      (_ : _ : { niv = import sources.niv {}; })
    ] ;
    # config = { allowBroken = true; };
    config = { };
  };
  pkgs = niv.pkgs;
  myHaskellPackages = pkgs.haskell.packages.${compiler}.override {
    overrides = self: super: rec {
      map-syntax  = self.callCabal2nix "map-syntax" (builtins.fetchGit {
        url = "[email protected]:mightybyte/map-syntax.git";
        rev = "e5f9b431525b8670d59c96f477f174cb976e99c6";
      })
          {};
    };
  };
in
(myHaskellPackages.callCabal2nix "heist" (./.) {})

MonadFail passthrough instance for HeistT?

With MonadFailDesugaring as default landing in GHC 8.6, the lack of a MonadFail instance for HeistT may become more acute, and will probably cause code breakage. It's easy and I think most sensible to add a simple pass-through instance:

instance MonadFail m => MonadFail (HeistT n m) where fail = lift . fail

However, this would differ from the legacy fail, which is not defined for HeistT and thus falls to the default implementation, which is just a regular error. So for pure compatibility that could be done instead, although my feeling is that pass-through is a better design.

Documentation code snippet incorrect

The documentation for Heist show a call to emptyHeistState but no such function exists.

I think you meant emptyTemplateState? Which meant that something got renamed. Which is cool, except that right after emptyTemplateState is documentation for defaultHeistState. Seems a bit inconsistent.

AfC

Reduce support window for heist to GHC >= 7.4

I noticed this while making heist GHC 8.2-ready; CI currently tests only w/ GHC >= 7.4, so the following failure with GHC 7.0.4 wasn't detected (while testing GHC 7.2.2 is messy due to its incomplete SafeHaskell impl which harms more than it helps):

Configuring library for heist-1.0.1.0..
Preprocessing library for heist-1.0.1.0..
Building library for heist-1.0.1.0..
[ 1 of 20] Compiling Data.HeterogeneousEnvironment ( src/Data/HeterogeneousEnvironment.hs, /tmp/heist-1.0.1.0/dist-newstyle/build/x86_64-linux/ghc-7.0.4/heist-1.0.1.0/build/Data/HeterogeneousEnvironment.o )
[ 2 of 20] Compiling Heist.Internal.Types.HeistState ( src/Heist/Internal/Types/HeistState.hs, /tmp/heist-1.0.1.0/dist-newstyle/build/x86_64-linux/ghc-7.0.4/heist-1.0.1.0/build/Heist/Internal/Types/HeistState.o )

src/Heist/Internal/Types/HeistState.hs:427:35:
    Not in scope: `liftM'

src/Heist/Internal/Types/HeistState.hs:429:35:
    Not in scope: `liftM'

I think we should adapt the lower bound on base to reflect the actively CI-tested base range, (i.e. build-depends: base >= 4.5 ..)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.