Git Product home page Git Product logo

handlebars-objc's Introduction

Build Status

handlebars-objc

handlebars-objc is a feature complete implementation of Handlebars.js v2.0 for Objective-C that is and will remain 100% compatible with the Javascript version.

What is Handlebars?

(Please see the main Handlebars site for a more thorough description of what Handlebars is).

In general, you should use handlebars if you need to generate text documents (HTML documents, for instance) and you want to maintain a clean separation between your views (the templates) and your model.

An increasingly popular option is to use Mustache for this purpose. Mustache is a very simple templating language available in most languages.

Unfortunately, using Mustache rapidly becomes an implementation nightmare when trying to implement localization, formatting of dates, and many other basic user interface needs. Developers quickly find themselves adding view-specific data into their model to circumvent the limitations of their templating system.

Handlebars is a pragmatic superset of Mustache that addresses most shortcomings of its ancestor with the addition of helpers and block helpers.

Helpers are small rendering functions provided by the hosting application that can be used in templates.

Helpers generally help formatting raw data from your models (think iso 8601 dates), while block helpers provide support for custom iterators and conditional constructs.

Block helpers have even been used to implement a clean cache-compatible compositional view system in Ruby on Rails at Fotonauts: the Reporter application (http://www.fotopedia.com/reporter) uses a compositional view system and is able to render its page exactly the same way server-side and client-side. It is written in Ruby, renders server-side templates within a Java front end using Handlebars.java and renders the exact same templates client-side using Handlebars.js.

All this thanks to Handlebars and a handful of very simple helpers shared between the Java and Javascript implementation.

Handlebars implementations are available for Javascript, Java, Ruby (via therubyracer) and PHP.

In short, if you're looking for a templating system with a clean view/model separation and want to render them in Objective-C and in Javascript (or Java), Handlebars is probably what you need.

Please note that some implementations of Mustache provide extensions similar to Handlebars, and if you intend to render your templates only on a Mac or an iPhone, I strongly suggest you take a look at GRMustache. GRMustache is a fantastic library.

Getting Started

Integrate handlebars-objc into your project

You have 3 options:

Render your first template

Add this import clause to your objective-C implementation:

#import <HBHandlebars/HBHandlebars.h>

Then add:

NSError* error = nil;
NSString* result = [HBHandlebars renderTemplateString:@"Hello {{value}}!" 
                                          withContext:@{ @"value" : @"Bertrand"} 
                                                error:&error]; 
NSLog(@"handlebars template evaluated to : %@", result); 

Run your application, and in your logs you should see "Hello Bertrand!".

Congratulations! You've just rendered your first Handlebars template.

Going Further

If you like to read reference documentation, read the Handlebars public API reference documentation.

Since handlebars-objc if fully compatible with handlebars.js, please refer to handlebars.js documentation for a complete description of handlebars syntax.

The doc folder contains some guides that will help you learn how to use handlebars-objc step by step:

handlebars-objc's People

Contributors

azu avatar bertrand avatar guillaumealgis avatar jonfriskics avatar luketheobscure avatar nicolas-cherel avatar psclcosta avatar randomsequence 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

handlebars-objc's Issues

Memory leaks

Hi,

Love handlebars-objc. But we're having issues that are causing our app to crash. The app makes extensive use of Handlebars and memory usage keeps climbing until it quits.

The screenshot from Xcode Instruments below is not of the app, but of about 100 Handlebars unit tests. As you can see, there's a leak somewhere!

screen shot 2014-06-17 at 1 30 33 pm

Note that the list is sorted by the objects with the greatest number of leaks.

Having a hard time finding the issue, so I thought I'd alert you to it. We're in a bit of a bind, as a deadline approaches, so anything you can do would be appreciated!

Thanks...

Parsing without escaping embedded text... is it possible?

I have an application where the results I want to produce are not pure html, but actually Slash (or maybe Markdown) that will then be turned into NSAttributedString objects.

Slash, for instance uses and HTML like syntax for making NSAttributedStrings. I can in theory take the output of handlebars-objc and run it thru slash.

The issue I expect to have, though, is whether handlebars will HTML Escape the text that's being processed (the data from the database.) I don't want to turn every instance of & into &amp in my text!

Is it possible to turn this off?

I know GRMustache has a mode for this, but I need data handlers to transform the info coming from the database (localization and unit conversions) so I can't use GRMustache.

If this isn't supported I'd consider adding it, but would like your advice as to whether this can be easily done by adding a setting and then changing the code that does the escaping to check that setting-- or is escaping done in many places?

Thanks.

Difficulty writing a specific type of helper

Hi,

Really enjoying this library - thanks!

I've written a few good helpers, but am having trouble implementing something like this:

http://stackoverflow.com/a/16315366/869838

I know it breaks compatibility with other handlebars implementations, but is it possible?

Trying something like:

{{#ifCond var1 '==' var2}} and passing it into a helper throws an exception due to the equals sign. I can't figure out if it's possible to just get the whole string that's passed to the helper (in this case var1 '==' var2).

Thanks...

Will handlebars-objc loop through an NSSet?

I'm working with Core Data and the 'to-many' aspect of a managed object is expressed as an NSSet. I'll keep plugging away, but I don't think handlebars-objc will loop through an NSSet? I can work around this, just curious.

Not really an issue either way, but I don't know how else to be sure about this.

Build fails with Xcode 9.3

handlebars-objc/src/handlebars-objc/helpers/HBBuiltinHelpersRegistry.m:168:65: error: expected method to read dictionary element not found on object of type 'id<NSFastEnumeration>'
                id statementEvaluation = callingInfo.statements(dictionaryLike[key], dictionaryData);
                                                                ^

Xcode 9.3, version 1.4.4

ARC restriction errors even with -fno-objc-arc

It seems I'm getting ARC restriction errors even when the files involved are being compiled with -fno-objc-arc. I'm guessing some other related files also need to be compiled with -fno-objc-arc.

screenshot 2015-05-01 10 44 28

Changing scope from 'this'

I have a handlebars loop that looks something like the one below. The problem is that I can't seem to switch scope within the loop. See the comments in the code for clarification:

{{#collection}}

    {
        "img": {

            {{! Can't access 'global' object }}
            "width": "{{global.img-w}}",
            "height": "{{global.img-h}}",

            {{! 'this' works fine }}
            "url": "{{this.url}}"
        }
    }
},

{{/collection}}

{{! 'global' object can be accessed ok here...}}
"someOtherProperty" : {{global.someOtherValue}}

I'm using Handlebars all over the place in my app, and it works beautifully except for this issue. I always pass a number of objects to the parser. In the case of a collection to be iterated, I obviously pass the collection. But I also pass 'global' which is just a dictionary of properties, and a few other things. Again, all of it works everywhere (except here) without exception - the problem only occurs when iterating. I don't think I'm using your library incorrectly... Perhaps this is a limitation?

My current workaround is to add 'global' as a property on the object being iterated. So {{this.global.img-w}} inside the loop works. But that's obviously not ideal.

Thanks for handlebars-objc. It is a wonderful thing!

Erroneous documentation on valid context objects?

The page https://github.com/Bertrand/handlebars-objc/blob/master/doc/ContextObjects.md states that

In most examples you'll find throughout handlebars-objc documentation, context objects are plist-compatible Foundation objects (NSDictionary, NSArray, NSString, NSNumber, etc.).

However, in HBContextRendering.m, line 45-52, nil is returned for any class other than NSString and NSNumber.

My point is, NSDate and NSData are valid plist-compatible objects, but are not supported by handlebars-objc. Am I missing something?

Lex error when including `inhibit_all_warnings!` in Podfile

When I Include inhibit_all_warnings! in my Podfile, I get a lex error on the handlebars-objc.lm file. This issue does not appear when I do not suppress the warnings.

Lex handlebars-objc/src/handlebars-objc/parser/handlebars-objc.lm
    cd /Users/mabbl/dev/projects/fortyip-ios/Pods
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lex -w -Xanalyzer -analyzer-disable-checker -o/Users/mabbl/Library/Developer/Xcode/DerivedData/fortyip-gxpqkofbpwiavrgdrxjrswfekilx/Build/Intermediates/Pods.build/Debug-iphoneos/Pods-handlebars-objc.build/DerivedSources/handlebars-objc.yy.m /Users/mabbl/dev/projects/fortyip-ios/Pods/handlebars-objc/src/handlebars-objc/parser/handlebars-objc.lm

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/flex: Unrecognized option `a'
Try `flex --help' for more information.
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lex failed with exit code 1

Bison/yacc error when using Cocoapods 0.35

So after migrating to Cocoapods 0.35, i'm experiencing some new issue with handlebars-objc.ym.
Probably it comes from the same place as #7, and flags on those files just incorrect by default and i think it is somehow related to CocoaPods/CocoaPods#2559

Yacc handlebars-objc/src/handlebars-objc/parser/handlebars-objc.ym
    cd /Users/alekseishevchenko/repositories/balluun365-ios/Balluun365/Pods
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/yacc -fno-objc-arc -d -b /Users/alekseishevchenko/Library/Developer/Xcode/DerivedData/BalluunPlatformApps-eauaqhqikuxfzwezgceqctfbhbqq/Build/Intermediates/Pods.build/Debug-iphonesimulator/Pods-handlebars-objc.build/DerivedSources/y /Users/alekseishevchenko/repositories/balluun365-ios/Balluun365/Pods/handlebars-objc/src/handlebars-objc/parser/handlebars-objc.ym

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison: invalid option -- f
Try `/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bison --help' for more information.
Command /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/yacc failed with exit code 1

Difficulty creating helper

Hi,

I've successfully created many helpers. This one is giving me trouble, probably because it runs counter to the philosophy behind handlebars....

I want to be able to iterate through objects whether they are arrays or dictionaries and whether I know their property names or not. Easiest to explain with an example:

{
    {{#each model}}

        "{{@key}}" : "{{print this}}",

    {{/each}}
}

This is all within a JSON object, so ideally, the print block would return a number or string if it encountered one, or would print out the values of an array or dictionary if it encountered those. This is what I've got so far for print:

HBHelperBlock printBlock = ^(HBHelperCallingInfo * callingInfo) {

    id expr = callingInfo[0];

    if ([expr isKindOfClass:NSArray.class] || [expr isKindOfClass:NSDictionary.class]) {

        //Return JSON string if array or dictionary
        NSError * error;
        NSData * jsonData = [NSJSONSerialization dataWithJSONObject:expr options:NSJSONWritingPrettyPrinted error:&error];
        return [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    }

    //Otherwise return as is
    return (NSString *)expr;
};
[HBHandlebars registerHelperBlock:printBlock forName:@"print"];

I think part of the problem is that "{{print this}}" only works at all if surrounded by quotes, but that causes everything to be quoted, whether it's a string or not.

Other helpers I've made have made use of things like this:

return result ?
       callingInfo.statements(callingInfo.context, callingInfo.data) :
       callingInfo.inverseStatements(callingInfo.context, callingInfo.data);

I found code like that in your built-in helpers and used it, frankly, without understanding it. Am I missing something like that here?

And that, basically, is my question. I'm not asking you to make this block work, just asking you for advice on how to work with your (excellent!) library so that a block like this might work.

Thanks!

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.