Skip to content

Commit

Permalink
guides wip
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Jan 26, 2012
1 parent 6aa657e commit 03d4645
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 43 deletions.
Empty file added guides/partials.md
Empty file.
50 changes: 10 additions & 40 deletions guides/runtime/booleans.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@

**TL;DR** Sections render or not, depending on the boolean value of the object they are attached to. Generally speaking, all objects are considered true, except:

- `nil`, and missing KVC keys
- `nil`, and missing keys
- `[NSNull null]`
- `[NSNumber numberWithBool:NO]`, aka `kCFBooleanFalse`
- the empty string `@""`

The most direct ways to provide sections with actual booleans are the explicit `[NSNumber numberWithBool:]` objects, and BOOL properties in your model objects.
The most direct ways to provide sections with actual booleans are the explicit `[NSNumber numberWithBool:]` objects, and `BOOL` properties in your model objects.

Beware zero (an NSNumber whose value is zero) is not considered false in GRMustache.
Beware zero (NSNumber whose value is zero) is not considered false in GRMustache.

---

Expand Down Expand Up @@ -44,20 +44,16 @@ For instance:

@interface Person: NSObject
@property BOOL pretty;
+ (id)person;
@end

Person *alice = [Person person];
Person *alice = [Person new];
alice.pretty = YES;

Person *bob = [Person person];
Person *bob = [Person new];
bob.pretty = NO;

// @"whistle"
[template renderObject:alice];

// @""
[template renderObject:bob];
[template renderObject:alice]; // @"whistle"
[template renderObject:bob]; // @""


## Other false values
Expand All @@ -69,31 +65,7 @@ GRMustache considers as false the following values, and only those:
- `[NSNumber numberWithBool:NO]`, aka `kCFBooleanFalse`
- the empty string `@""`

Each of those renderings return the empty string:

// @"foobar" has no `pretty` key
[template renderObject:@"foobar"];

// nil is false
[template renderObject:[NSDictionary dictionary]];

// [NSNull null] is false
[template renderObject:[NSDictionary dictionaryWithObject:[NSNull null]
forKey:@"pretty"]];

// [NSNumber numberWithBool:NO] is false
[template renderObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO]
forKey:@"pretty"]];

// @"" is false
[template renderObject:[NSDictionary dictionaryWithObject:@""
forKey:@"pretty"]];

Note that zero, as an explicit NSNumber whose value is zero, or as an int/float property, is not considered false in GRMustache:

// @"whistle"
[template renderObject:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:0]
forKey:@"pretty"]];
Note that zero, as an explicit NSNumber whose value is zero, or as an int/float property, is not considered false in GRMustache.


## Caveats
Expand All @@ -105,12 +77,11 @@ GRMustache handles properly BOOL properties, but not methods which return BOOL v
For instance, the following class would **not** render as expected:

@interface BadPerson: NSObject
+ (id)person;
- (void)setPretty:(BOOL)value;
- (BOOL)pretty;
@end

Person *carol = [BadPerson person];
Person *carol = [BadPerson new];
[carol setPretty:NO];

// @"whistle"
Expand All @@ -128,10 +99,9 @@ For the very same reason, you should not use your property getters in templates:

@interface Person: NSObject
@property (getter=isPretty) BOOL pretty;
+ (id)person;
@end

Person *dave = [Person person];
Person *dave = [Person new];
dave.pretty = NO;

// Note the use of the property getter, this time
Expand Down
4 changes: 2 additions & 2 deletions guides/runtime/helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,12 @@ And now the rendering is done as usual:

### Implementing helpers with classes conforming to the `GRMustacheHelper` protocol

Now that we have a nice working localizing helper, we may well want to reuse it in some other projects. Unfortunately, the two techniques seen above don't help us that much acheiving this goal:
Now that we have a nice working localizing helper, we may well want to reuse it in some other projects. Unfortunately, the two techniques seen above don't help us that much achieving this goal:

- the selector technique binds the helper code to the section name, thus making impossible to share the helper code between various sections of various templates.
- the block technique provides no way to cleanly encapsulate the helper code.

The `GRMustacheHelper` protocol aims at giving you a way to create classes which encapsulate a helper.
The `GRMustacheHelper` protocol aims at giving you a way to create helper classes, with all expected benefits: encapsulation and reusability.

In our case, here would be the implementation of our localizing helper:

Expand Down
2 changes: 1 addition & 1 deletion guides/runtime/loops.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Arrays of scalar values

The "implicit iterator" `{{.}}` tag will help you iterating arrays of strings or numbers, generally objects that don't have any dedicated key for rendering themselves.

For instance, the following template can render `{ items: ['ham', 'jam'] }`.
For instance, the following template can render `{ items: ['ham', 'jam'] }`:

<ul>
{{#items}}
Expand Down
135 changes: 135 additions & 0 deletions guides/templates.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
Templates
=========

You'll learn here how to load, and render templates. [guides/runtime.md](runtime.md) will talk about about what happens *during* the rendering itself.

**TL;DR** Let XCode autocompletion magic find the correct method for you: just type "`[GRMustacheTemplate render`" or "`[GRMustacheTemplate parse`".

The `render...` family parses and renders templates on-the-fly, from strings, bundle resources, or files. The `parse...` family parses only. You'll then have to invoke `renderObject:` on the generated GRMustacheTemplate instances:

// on-the-fly:
NSString *rendering = [GRMustacheTemplate renderObject:... from...];

// parse once, render many times:
GRMustacheTemplate *template = [GRMustacheTemplate parse...];
NSString *rendering = [template renderObject:...]

---

Errors
------

Not funny, but those happens.

Once and for all: GRMustache methods may return errors whose domain is `GRMustacheErrorDomain`, and error codes interpreted with the `GRMustacheErrorCode` enumeration:

extern NSString* const GRMustacheErrorDomain;

typedef enum {
GRMustacheErrorCodeParseError,
GRMustacheErrorCodeTemplateNotFound,
} GRMustacheErrorCode;

On-the-fly rendering methods
----------------------------

There are methods for rendering from strings, files, and bundle resources:

@interface GRMustacheTemplate

// Renders the provided templateString.
+ (NSString *)renderObject:(id)object
fromString:(NSString *)templateString
error:(NSError **)outError;

// Renders the template loaded from a url. (from MacOS 10.6 and iOS 4.0)
+ (NSString *)renderObject:(id)object
fromContentsOfURL:(NSURL *)url
error:(NSError **)outError;

// Renders the template loaded from a path.
+ (NSString *)renderObject:(id)object
fromContentsOfFile:(NSString *)path
error:(NSError **)outError;

// Renders the template loaded from a bundle resource of extension "mustache".
+ (NSString *)renderObject:(id)object
fromResource:(NSString *)name
bundle:(NSBundle *)bundle // nil stands for the main bundle
error:(NSError **)outError;

// Renders the template loaded from a bundle resource of provided extension.
+ (NSString *)renderObject:(id)object
fromResource:(NSString *)name
withExtension:(NSString *)ext
bundle:(NSBundle *)bundle // nil stands for the main bundle
error:(NSError **)outError;

Remember GRMustache supports two flavors of the Mustache language: check [guides/flavors.md](flavors.md)

Parse-once-and-render-many-times methods
----------------------------------------

It's efficient to parse a template once, and then render it as often as needed:

@interface GRMustacheTemplate

// Parses the templateString.
+ (id)parseString:(NSString *)templateString
error:(NSError **)outError;

// Loads and parses the template from url. (from MacOS 10.6 and iOS 4.0)
+ (id)parseContentsOfURL:(NSURL *)url
error:(NSError **)outError;

// Loads and parses the template from path.
+ (id)parseContentsOfFile:(NSString *)path
error:(NSError **)outError;

// Loads and parses the template from a bundle resource of extension "mustache".
+ (id)parseResource:(NSString *)name
bundle:(NSBundle *)bundle // nil stands for the main bundle
error:(NSError **)outError;

// Loads and parses the template from a bundle resource of provided extension.
+ (id)parseResource:(NSString *)name
withExtension:(NSString *)ext
bundle:(NSBundle *)bundle // nil stands for the main bundle
error:(NSError **)outError;

Those methods return GRMustacheTemplate instances, which render objects with the following methods:

- (NSString *)renderObject:(id)object;
- (NSString *)renderObjects:(id)object, ...; // nil-terminated list

The latter method, which takes several arguments, is helpful when several objects should feed the template.

Partials
--------

When a `{{>name}}` Mustache tags occurs in a template, GRMustache renders in place the content of another template, the *partial*, identified by its name.

Depending on the method which has been used to create the original template, partials will be looked for in different places :

- In the main bundle, with ".mustache" extension:
- `renderObject:fromString:error:`
- `parseString:error:`
- In the specified bundle, with ".mustache" extension:
- `renderObject:fromResource:bundle:error:`
- `parseResource:bundle:error:`
- In the specified bundle, with the provided extension:
- `renderObject:fromResource:withExtension:bundle:error:`
- `parseResource:withExtension:bundle:error:`
- Relatively to the URL of the including template, with the same extension:
- `renderObject:fromContentsOfURL:error:`
- `parseContentsOfURL:error:`
- Relatively to the path of the including template, with the same extension:
- `renderObject:fromContentsOfFile:error:`
- `parseContentsOfFile:error:`

You can write recursive partials. Just avoid infinite loops in your context objects.

More loading options
--------------------

All methods above load UTF8-encoded templates and partials from disk. If this does not fulfill your needs, check [guides/template_loaders.md](template_loaders.md)

0 comments on commit 03d4645

Please sign in to comment.