M .hgignore +1 -1
@@ 1,5 1,5 @@
^.yardoc/
-^doc/
+^docs/
^tags$
^manual/output/
^coverage/
M Examples.rdoc => Examples.md +120 -120
@@ 1,134 1,134 @@
-= Annotated Examples
+# Annotated Examples
This is a list of template examples with annotations explaining what each group of lines is doing.
-== Simple Examples
+## Simple Examples
...
-== Advanced Examples
+## Advanced Examples
-Here's a somewhat more complex example. At our company Spime-Thorpe from above, say we're creating a system that will handle mass layoffs without the need for management to handle all those messy personal interactions. We'll need a mass-mailer for the employees that will be afforded the chance to explore their career opportunities, right? So we create a template called +overboard-mail.tmpl+:
+Here's a somewhat more complex example. At our company Spime-Thorpe from above, say we're creating a system that will handle mass layoffs without the need for management to handle all those messy personal interactions. We'll need a mass-mailer for the employees that will be afforded the chance to explore their career opportunities, right? So we create a template called `overboard-mail.tmpl`:
- <?config debugging_comments: true ?>
- <?default grace_period to "7 days" ?>
-
- <?begin?>
- <p>Dear <?call employee.fullname ?>,</p>
- <?rescue DatabaseError ?>
- <p>Dear Valued Ex-Employee,</p>
- <?end begin?>
-
- <p>Congratulations! You have been selected by <?call failed_company.name ?>'s
- elite management team as one of the many lucky individuals that will
- enjoy the exciting challenge of pursuing other rewarding employment
- opportunities!</p>
-
- <p><em>Kudos!</em></p>
-
- <p>You will find your accounts have been disabled, your desk has been helpfully
- cleared out for you, and all of your personal effects packaged up and
- delivered to your address of record approximately
- <?timedelta tracking_info.delivery_date ?>:</p>
-
- <?for line in employee.address ?>
- <?attr line ?><br />
- <?end for ?>
-
- <p>Please visit your <a href="[?call config.overboard_url ?]/[?uriencode
- failed_company.id ?]/[?uriencode employee.id ?]">customized Man OverBoard
- transition site</a> immediately:</p>
-
- <p>This will acknowledge that you have received this message, and automatically
- disable your email account. Be sure and save this message!</p>
-
- <?if employee.severance_amount.nonzero? ?>
- <p>Failure to acknowledge this message within <?attr grace_period ?> could result
- in delay of your final severance pay, in the amount of
- <?call "$%0.2f" % employee.severance_amount ?>.</p>
- <?else?>
- <p>Failure to acknowledge this message within <?attr grace_period ?> will
- result in automatic forfeiture of your numerous Man Overboard package benefits.</p>
- <?end if?>
-
- <?comment Disabled at client request ?>
- If you have any questions or concerns, please don't hesitate to contact your
- friendly Spime-Thorpe <a href="mailto:salesteam2@spime-thorpe.com">representative</a>.
- <?end comment ?>
-
- <p>Good Luck,<br />
- Your friends at Spime-Thorpe, Inc!<br />
- <a href="http://www.spime-thorpe.com/">http://www.spime-thorpe.com/</a></p>
+ <?config debugging_comments: true ?>
+ <?default grace_period to "7 days" ?>
+
+ <?begin?>
+ <p>Dear <?call employee.fullname ?>,</p>
+ <?rescue DatabaseError ?>
+ <p>Dear Valued Ex-Employee,</p>
+ <?end begin?>
+
+ <p>Congratulations! You have been selected by <?call failed_company.name ?>'s
+ elite management team as one of the many lucky individuals that will
+ enjoy the exciting challenge of pursuing other rewarding employment
+ opportunities!</p>
+
+ <p><em>Kudos!</em></p>
+
+ <p>You will find your accounts have been disabled, your desk has been helpfully
+ cleared out for you, and all of your personal effects packaged up and
+ delivered to your address of record approximately
+ <?timedelta tracking_info.delivery_date ?>:</p>
+
+ <?for line in employee.address ?>
+ <?attr line ?><br />
+ <?end for ?>
+
+ <p>Please visit your <a href="[?call config.overboard_url ?]/[?uriencode
+ failed_company.id ?]/[?uriencode employee.id ?]">customized Man OverBoard
+ transition site</a> immediately:</p>
+
+ <p>This will acknowledge that you have received this message, and automatically
+ disable your email account. Be sure and save this message!</p>
+
+ <?if employee.severance_amount.nonzero? ?>
+ <p>Failure to acknowledge this message within <?attr grace_period ?> could result
+ in delay of your final severance pay, in the amount of
+ <?call "$%0.2f" % employee.severance_amount ?>.</p>
+ <?else?>
+ <p>Failure to acknowledge this message within <?attr grace_period ?> will
+ result in automatic forfeiture of your numerous Man Overboard package benefits.</p>
+ <?end if?>
+
+ <?comment Disabled at client request ?>
+ If you have any questions or concerns, please don't hesitate to contact your
+ friendly Spime-Thorpe <a href="mailto:salesteam2@spime-thorpe.com">representative</a>.
+ <?end comment ?>
+
+ <p>Good Luck,<br />
+ Your friends at Spime-Thorpe, Inc!<br />
+ <a href="http://www.spime-thorpe.com/">http://www.spime-thorpe.com/</a></p>
When wrapped with a layout template, here's what this renders as:
- <?example { language: xml, caption: "The rendered output for one lucky individual" } ?>
- <!DOCTYPE html>
- <!--
-
- Spime-Thorpe!
- $Id$
-
- -->
- <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
- <head>
- <title>Spime-Thorpe: Untitled</title>
-
- <link rel="stylesheet" src="/css/base.css" type="text/css" />
-
- <script type="text/javascript" src="/js/jquery-latest.min.js"></script>
-
- </head>
- <body>
-
- <header>
- <hgroup>
- <h1>Spime-Thorpe</h1>
- <h2></h2>
- </hgroup>
- </header>
-
- <section id="content">
- <p>Dear James Random,</p>
-
- <p>Congratulations! You have been selected by Widgets R Us's
- elite management team as one of the many lucky individuals that will
- enjoy the exciting challenge of pursuing other rewarding employment
- opportunities!</p>
-
- <p><em>Kudos!</em></p>
-
- <p>You will find your accounts have been disabled, your desk has been helpfully
- cleared out for you, and all of your personal effects packaged up and
- delivered to your address of record approximately
- 3 days ago:</p>
-
- 1213 NE. Winding Road<br />
- Syracuse, NY 100213<br />
-
- <p>Please visit your <a href="http://failedcompany.spime-thorpe.com/overboard/a18661/1881">
- customized Man OverBoard transition site</a> immediately:</p>
-
- <p>This will acknowledge that you have received this message, and automatically
- disable your email account. Be sure and save this message!</p>
-
- <p>Failure to acknowledge this message within 11 days could result
- in delay of your final severance pay, in the amount of
- $12.81.</p>
-
-
- <p>Good Luck,<br />
- Your friends at Spime-Thorpe, Inc!<br />
- <a href="http://www.spime-thorpe.com/">http://www.spime-thorpe.com/</a></p>
- </section>
-
- <footer>
- <section id="copyright">Copyright 2011, Spime-Thorpe</section>
- </footer>
-
- </body>
- </html>
+ <?example { language: xml, caption: "The rendered output for one lucky individual" } ?>
+ <!DOCTYPE html>
+ <!--
+
+ Spime-Thorpe!
+ $Id$
+
+ -->
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+ <head>
+ <title>Spime-Thorpe: Untitled</title>
+
+ <link rel="stylesheet" src="/css/base.css" type="text/css" />
+
+ <script type="text/javascript" src="/js/jquery-latest.min.js"></script>
+
+ </head>
+ <body>
+
+ <header>
+ <hgroup>
+ <h1>Spime-Thorpe</h1>
+ <h2></h2>
+ </hgroup>
+ </header>
+
+ <section id="content">
+ <p>Dear James Random,</p>
+
+ <p>Congratulations! You have been selected by Widgets R Us's
+ elite management team as one of the many lucky individuals that will
+ enjoy the exciting challenge of pursuing other rewarding employment
+ opportunities!</p>
+
+ <p><em>Kudos!</em></p>
+
+ <p>You will find your accounts have been disabled, your desk has been helpfully
+ cleared out for you, and all of your personal effects packaged up and
+ delivered to your address of record approximately
+ 3 days ago:</p>
+
+ 1213 NE. Winding Road<br />
+ Syracuse, NY 100213<br />
+
+ <p>Please visit your <a href="http://failedcompany.spime-thorpe.com/overboard/a18661/1881">
+ customized Man OverBoard transition site</a> immediately:</p>
+
+ <p>This will acknowledge that you have received this message, and automatically
+ disable your email account. Be sure and save this message!</p>
+
+ <p>Failure to acknowledge this message within 11 days could result
+ in delay of your final severance pay, in the amount of
+ $12.81.</p>
+
+
+ <p>Good Luck,<br />
+ Your friends at Spime-Thorpe, Inc!<br />
+ <a href="http://www.spime-thorpe.com/">http://www.spime-thorpe.com/</a></p>
+ </section>
+
+ <footer>
+ <section id="copyright">Copyright 2011, Spime-Thorpe</section>
+ </footer>
+
+ </body>
+ </html>
-This example can be found in the Inversion repository, in the +experiments+ directory.
+This example can be found in the Inversion repository, in the `experiments` directory.
M GettingStarted.rdoc => GettingStarted.md +30 -24
@@ 1,44 1,50 @@
-= Getting Started
+# Getting Started
+
+## Requirements
-== Requirements
+- Ruby 2.7.5 or later
-- Ruby 1.9.2 or later
+
+## Installation
-== Installation
+ $ gem install inversion
-$ gem install inversion
-== Basic Usage
+## Basic Usage
-Inversion, like most other templating systems, works by giving you a way of defining the static
-parts of your output, and then letting you combine that at a later point with the dynamic parts:
+Inversion, like most other templating systems, works by giving you a way of
+defining the static parts of your output, and then letting you combine that at
+a later point with the dynamic parts:
Create the template and use it to render an exciting message:
- tmpl = Inversion::Template.new( "Hello, <?attr name ?>!" )
- tmpl.name = "World"
- puts tmpl.render
+ tmpl = Inversion::Template.new( "Hello, <?attr name ?>!" )
+ tmpl.name = "World"
+ puts tmpl.render
-The +<?attr name ?>+ tag defines the _name_ accessor on the template[rdoc-ref:Templates]
-object, the value of which is substituted for any occurrences of +name+ in the template:
+The `<?attr name ?>` tag defines the _name_ accessor on the
+[template](rdoc-ref:Templates) object, the value of which is substituted for
+any occurrences of `name` in the template:
- Hello, World!
+ Hello, World!
-This by itself isn't fantastically useful, but it does illustrate one of the ways in which Inversion
-is different: the program and the template share data through an API, instead of through a complex
-data structure, which establishes a clear delineation between what responsibility is the program's
-and which is the template's. The program doesn't have to know how the view uses the data it's given,
-and tests of the controller can substitute a Mock Object for the template to test the interaction
-between the two instead of having to match patterns in the eventual output like an integration test.
+This by itself isn't fantastically useful, but it does illustrate one of the
+ways in which Inversion is different: the program and the template share data
+through an API, instead of through a complex data structure, which establishes
+a clear delineation between what responsibility is the program's and which is
+the template's. The program doesn't have to know how the view uses the data
+it's given, and tests of the controller can substitute a Mock Object for the
+template to test the interaction between the two instead of having to match
+patterns in the eventual output like an integration test.
You can also interact with the values set in the template:
- Name: <?attr employee.full_name ?>
+ Name: <?attr employee.full_name ?>
-This will call the #full_name method on whatever is set as the +employee+ attribute when
-rendered, and the result will take the place of the tag.
+This will call the #full_name method on whatever is set as the `employee`
+attribute when rendered, and the result will take the place of the tag.
-Inversion also comes with a collection of {other tags}[rdoc-ref:Tags] that
+Inversion also comes with a collection of [other tags](rdoc-ref:Tags) that
provide flow control, exception-handling, etc.
A => Guide.md +14 -0
@@ 0,0 1,14 @@
+# Inversion User's Guide
+
+Inversion is a templating system for Ruby. It uses the Inversion of Control principle to decouple
+the contents and structure of the template from the code that uses it, making it easier to use,
+test-friendly, and clean.
+
+[Getting Started](rdoc-ref:GettingStarted) goes over the requirements, installation, and basic usage of the library.
+
+The rdoc-ref:Templates topic has more details about how to load templates and control their behavior with options.
+
+When you're ready to start making your own templates, there's a quick-reference for the list of built-in rdoc-ref:Tags, too.
+
+Finally, there are a number of [Annotated Examples](rdoc-ref:Examples) that illustrate how to solve common problems while templating.
+
R Guide.rdoc => +0 -47
@@ 1,47 0,0 @@
-= Inversion User's Guide
-
-Inversion is a templating system for Ruby. It uses the Inversion of Control principle to decouple
-the contents and structure of the template from the code that uses it, making it easier to use,
-test-friendly, and clean.
-
-{Getting Started}[rdoc-ref:GettingStarted] goes over the requirements, installation, and basic usage of the library.
-
-The rdoc-ref:Templates topic has more details about how to load templates and control their behavior with options.
-
-When you're ready to start making your own templates, there's a quick-reference for the list of built-in rdoc-ref:Tags, too.
-
-Finally, there are a number of {Annotated Examples}[rdoc-ref:Examples] that illustrate how to solve common problems while templating.
-
-
-== Authors
-
-* Michael Granger
-* Mahlon E. Smith
-
-
-== License
-
-Copyright © 2011-2015, Michael Granger, Mahlon E. Smith
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, are
-permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this list of
- conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright notice, this list of
- conditions and the following disclaimer in the documentation and/or other materials
- provided with the distribution.
-* Neither the name of the authors nor contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
-TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
M History.rdoc => History.md +43 -43
@@ 1,8 1,8 @@
-= Release History for inversion
+# Release History for inversion
---
-== v1.3.1 [2020-09-29] Michael Granger <ged@faeriemud.org>
+## v1.3.1 [2020-09-29] Michael Granger <ged@faeriemud.org>
Improvements:
@@ 10,14 10,14 @@ Improvements:
- Handle HTML encoding for uriencoding tag ourselves
-== v1.3.0 [2020-04-08] Mahlon E. Smith <mahlon@martini.nu>
+## v1.3.0 [2020-04-08] Mahlon E. Smith <mahlon@martini.nu>
- Use safe_yaml when deserializing config tag contents.
- Un-hoeify.
- Updates for Ruby 2.7.
-== v1.2.0 [2019-05-14] Michael Granger <ged@FaerieMUD.org>
+## v1.2.0 [2019-05-14] Michael Granger <ged@FaerieMUD.org>
Enhancements:
@@ 26,14 26,14 @@ Enhancements:
'decorators' optional.
-== v1.1.1 [2017-11-13] Michael Granger <ged@FaerieMUD.org>
+## v1.1.1 [2017-11-13] Michael Granger <ged@FaerieMUD.org>
Bugfixes:
- Yield subarrays in `each` tags when there's only one block argument (#3).
-== v1.1.0 [2017-08-17] Mahlon E. Smith <mahlon@martini.nu>
+## v1.1.0 [2017-08-17] Mahlon E. Smith <mahlon@martini.nu>
Enhancements:
@@ 44,17 44,17 @@ Enhancements:
parents matcher patterns.
-== v1.0.0 [2017-01-16] Michael Granger <ged@FaerieMUD.org>
+## v1.0.0 [2017-01-16] Michael Granger <ged@FaerieMUD.org>
Mark as stable, update dependencies.
-== v0.18.0 [2015-10-01] Michael Granger <ged@FaerieMUD.org>
+## v0.18.0 [2015-10-01] Michael Granger <ged@FaerieMUD.org>
Add a `strict_attributes` option for templates.
-== v0.17.4 [2015-07-08] Michael Granger <ged@FaerieMUD.org>
+## v0.17.4 [2015-07-08] Michael Granger <ged@FaerieMUD.org>
Fixes:
@@ 62,14 62,14 @@ Fixes:
Galanakis <rob.galanakis@gmail.com>.
-== v0.17.3 [2015-02-16] Michael Granger <ged@FaerieMUD.org>
+## v0.17.3 [2015-02-16] Michael Granger <ged@FaerieMUD.org>
- Performance fix: Re-comment the #inspect logging message
in the RenderState
- Updated tag docs
-== v0.17.2 [2015-01-22] Michael Granger <ged@FaerieMUD.org>
+## v0.17.2 [2015-01-22] Michael Granger <ged@FaerieMUD.org>
- Fix a bug with the fragment tag.
@@ 77,35 77,35 @@ Fragments will now propagate to the cont
added by inner templates.
-== v0.17.1 [2015-01-15] Michael Granger <ged@FaerieMUD.org>
+## v0.17.1 [2015-01-15] Michael Granger <ged@FaerieMUD.org>
Re-push to fix a misbuilt gem.
-== v0.17.0 [2015-01-15] Michael Granger <ged@FaerieMUD.org>
+## v0.17.0 [2015-01-15] Michael Granger <ged@FaerieMUD.org>
Support snakecase tag names/tag filenames
-== v0.16.0 [2015-01-14] Michael Granger <ged@FaerieMUD.org>
+## v0.16.0 [2015-01-14] Michael Granger <ged@FaerieMUD.org>
Add support for loading templates from an alternate path
via :template_paths option to Inversion::Template.load.
-== v0.15.0 [2014-11-24] Michael Granger <ged@FaerieMUD.org>
+## v0.15.0 [2014-11-24] Michael Granger <ged@FaerieMUD.org>
Add a mechanism to allow tags to extend the template.
-== v0.14.0 [2014-11-05] Michael Granger <ged@FaerieMUD.org>
+## v0.14.0 [2014-11-05] Michael Granger <ged@FaerieMUD.org>
- Add the fragment tag and docs
- Remove old manual doc artifacts. Add documentation for the
'begin/rescue' and 'default' tags.
-== v0.13.0 [2014-04-23] Michael Granger <ged@FaerieMUD.org>
+## v0.13.0 [2014-04-23] Michael Granger <ged@FaerieMUD.org>
- Carry global configuration into instantiated template options.
- Documentation update.
@@ 113,90 113,90 @@ Add a mechanism to allow tags to extend
(Never released.)
-== v0.12.3 [2013-09-20] Michael Granger <ged@FaerieMUD.org>
+## v0.12.3 [2013-09-20] Michael Granger <ged@FaerieMUD.org>
- Don't deep_copy IOs or Tempfiles (bugfix).
-== v0.12.2 [2013-06-19] Michael Granger <ged@FaerieMUD.org>
+## v0.12.2 [2013-06-19] Michael Granger <ged@FaerieMUD.org>
- Fix propagation of config tags into subtemplates (fixes #1)
- Use replacement in transcoding instead of raising encoding errors
-== v0.12.1 [2013-03-05] Michael Granger <ged@FaerieMUD.org>
+## v0.12.1 [2013-03-05] Michael Granger <ged@FaerieMUD.org>
A bunch of optimization and inspect-encoding fixes.
-== v0.12.0 [2013-03-01] Michael Granger <ged@FaerieMUD.org>
+## v0.12.0 [2013-03-01] Michael Granger <ged@FaerieMUD.org>
- Make exceptions rendered as comments include the backtrace if
debugging comments are enabled.
-== v0.11.2 [2012-09-17] Michael Granger <ged@FaerieMUD.org>
+## v0.11.2 [2012-09-17] Michael Granger <ged@FaerieMUD.org>
- [bugfix] Don't cast enumerated values in for tags to Arrays.
-== v0.11.1 [2012-09-17] Michael Granger <ged@FaerieMUD.org>
+## v0.11.1 [2012-09-17] Michael Granger <ged@FaerieMUD.org>
- [bugfix] Make subscriptions get nodes that were already published
-== v0.11.0 [2012-07-06] Michael Granger <ged@FaerieMUD.org>
+## v0.11.0 [2012-07-06] Michael Granger <ged@FaerieMUD.org>
- Automatically transcode output according to the registered encoding
if the template is created with one
-== v0.10.2 [2012-06-27] Mahlon E. Smith <mahlon@martini.nu>
+## v0.10.2 [2012-06-27] Mahlon E. Smith <mahlon@martini.nu>
- Bugfix: Don't dup Classes and Modules in template attributes.
- Optimization: Don't needlessly duplicate the node tree on template
duplication.
-== v0.10.1 [2012-06-22] Michael Granger <ged@FaerieMUD.org>
+## v0.10.1 [2012-06-22] Michael Granger <ged@FaerieMUD.org>
- Bugfix: duplicated templates get distinct copies of their attributes.
-== v0.10.0 [2012-05-07] Michael Granger <ged@FaerieMUD.org>
+## v0.10.0 [2012-05-07] Michael Granger <ged@FaerieMUD.org>
- Added signature for changeset 9d9c49d532be
-== v0.10.0 [2012-05-07] Michael Granger <ged@FaerieMUD.org>
+## v0.10.0 [2012-05-07] Michael Granger <ged@FaerieMUD.org>
- Convert to Loggability for logging.
-== v0.9.0 [2012-04-24] Michael Granger <ged@FaerieMUD.org>
+## v0.9.0 [2012-04-24] Michael Granger <ged@FaerieMUD.org>
- Split the template path out from the config into a class instance variable.
- Documentation update.
-== v0.8.0 [2012-04-01] Michael Granger <ged@FaerieMUD.org>
+## v0.8.0 [2012-04-01] Michael Granger <ged@FaerieMUD.org>
- Optimization fixes
- Fixed rendering flow control to not use a begin/rescue.
-== v0.7.0 [2012-03-29] Michael Granger <ged@FaerieMUD.org>
+## v0.7.0 [2012-03-29] Michael Granger <ged@FaerieMUD.org>
- Switch to a much more flexible way to render tag bodies. This should
resolve most of the problems we've encountered with complex templates.
-== v0.6.1 [2012-03-16] Michael Granger <ged@FaerieMUD.org>
+## v0.6.1 [2012-03-16] Michael Granger <ged@FaerieMUD.org>
- Commented out some of the more expensive debug logging for an order
of magnitude increase in render speed.
-== v0.6.0 [2012-03-13] Michael Granger <ged@FaerieMUD.org>
+## v0.6.0 [2012-03-13] Michael Granger <ged@FaerieMUD.org>
- Fix a bug with "for" tag iteration over complex data structures
- Add a configurable delay for checking for changes on file-based
@@ 206,13 206,13 @@ A bunch of optimization and inspect-enco
- Handle Configurability's configure-with-defaults call.
-== v0.5.0 [2012-01-05] Michael Granger <ged@FaerieMUD.org>
+## v0.5.0 [2012-01-05] Michael Granger <ged@FaerieMUD.org>
Added an encoding option to Inversion::Template.load for
specifying the encoding of the template source.
-== v0.4.0 [2011-10-05] Michael Granger <ged@FaerieMUD.org>
+## v0.4.0 [2011-10-05] Michael Granger <ged@FaerieMUD.org>
Reworked render toggling so the before/after rendering hooks are
called immediately before and after the node *would* have been
@@ 223,14 223,14 @@ demark aren't even touched if rendering
Adjusted the other tags to account for the change.
-== v0.3.0 [2011-10-05] Michael Granger <ged@FaerieMUD.org>
+## v0.3.0 [2011-10-05] Michael Granger <ged@FaerieMUD.org>
- Fix require loop in if/elsif tags
- Fixing a problem with HTML escaping of objects other than Strings
- Added render timing (Inversion::RenderState#time_elapsed)
-== v0.2.0 [2011-09-27] Michael Granger <ged@FaerieMUD.org>
+## v0.2.0 [2011-09-27] Michael Granger <ged@FaerieMUD.org>
- Bugfixes (#1, #2)
- Renamed Inversion::Template::Parser to Inversion::Parser
@@ 238,18 238,18 @@ Adjusted the other tags to account for t
per-render basis.
-== v0.1.1 [2011-09-23] Michael Granger <ged@FaerieMUD.org>
+## v0.1.1 [2011-09-23] Michael Granger <ged@FaerieMUD.org>
- Bugfix for the Subscribe tag.
-== v0.1.0 [2011-09-23] Michael Granger <ged@FaerieMUD.org>
+## v0.1.0 [2011-09-23] Michael Granger <ged@FaerieMUD.org>
- Added template reloading via Inversion::Template#changed?
and #reload.
-== v0.0.4 [2011-09-21] Michael Granger <ged@FaerieMUD.org>
+## v0.0.4 [2011-09-21] Michael Granger <ged@FaerieMUD.org>
- Avoid Pathname#expand_path in Inversion::Template.load
[optimization]
@@ 258,17 258,17 @@ Adjusted the other tags to account for t
- Added a manual
-== v0.0.3 [2011-08-15] Michael Granger <ged@FaerieMUD.org>
+## v0.0.3 [2011-08-15] Michael Granger <ged@FaerieMUD.org>
- Dependency fix
-== v0.0.2 [2011-08-15] Michael Granger <ged@FaerieMUD.org>
+## v0.0.2 [2011-08-15] Michael Granger <ged@FaerieMUD.org>
- Packaging fix
-== v0.0.1 [2011-02-02] Michael Granger <ged@FaerieMUD.org>
+## v0.0.1 [2011-02-02] Michael Granger <ged@FaerieMUD.org>
Initial release.
M Manifest.txt +11 -10
@@ 1,18 1,19 @@
-Examples.rdoc
-GettingStarted.rdoc
-Guide.rdoc
-History.rdoc
-Manifest.txt
-README.rdoc
-Rakefile
-Tags.rdoc
+Examples.md
+GettingStarted.md
+Guide.md
+History.md
+README.md
+Tags.md
bin/inversion
lib/inversion.rb
-lib/inversion/command.rb
+lib/inversion/cli.rb
+lib/inversion/cli/api.rb
+lib/inversion/cli/tagtokens.rb
+lib/inversion/cli/tree.rb
lib/inversion/exceptions.rb
lib/inversion/mixins.rb
-lib/inversion/monkeypatches.rb
lib/inversion/parser.rb
+lib/inversion/refinements.rb
lib/inversion/renderstate.rb
lib/inversion/sinatra.rb
lib/inversion/template.rb
M README.rdoc => README.md +43 -34
@@ 1,12 1,19 @@
-= inversion
+# inversion
+
+home
+: https://hg.sr.ht/~ged/Inversion
-home:: https://hg.sr.ht/~ged/Inversion
-code:: https://hg.sr.ht/~ged/Inversion/browse
-github:: https://github.com/ged/inversion
-docs:: http://deveiate.org/code/Inversion
+code
+: https://hg.sr.ht/~ged/Inversion/browse
+
+github
+: https://github.com/ged/inversion
+
+docs
+: http://deveiate.org/code/Inversion
-== Description
+## Description
Inversion is a templating system for Ruby. It uses the "Inversion of Control"
principle to decouple the contents and structure of templates from the code
@@ 14,7 21,7 @@ that uses them, making it easier to sepa
and avoid polluting scopes with ephemeral data.
-=== Details
+### Details
Inversion, like most other templating systems, works by giving you a way of
defining the static parts of your output, and then letting you combine that at
@@ 22,12 29,12 @@ a later point with the dynamic parts:
Create the template and use it to render an exciting message:
- tmpl = Inversion::Template.new( "Hello, <?attr name ?>!" )
- tmpl.name = "World"
- puts tmpl.render
+ tmpl = Inversion::Template.new( "Hello, <?attr name ?>!" )
+ tmpl.name = "World"
+ puts tmpl.render
-The <tt><?attr name ?></tt> tag defines the _name_ accessor on the template
-object, the value of which is substituted for any occurrences of +name+ in the
+The `<?attr name ?>` tag defines the _name_ accessor on the template
+object, the value of which is substituted for any occurrences of `name` in the
template:
Hello, World!
@@ 45,15 52,15 @@ You can also interact with the values se
Name: <?attr employee.full_name ?>
-This will call the +#full_name+ method on whatever is set as the +employee+
+This will call the #full_name method on whatever is set as the `employee`
attribute when rendered, and the result will take the place of the tag.
-Inversion also comes with {a collection of other tags}[rdoc-ref:Tags] that
+Inversion also comes with [a collection of other tags](rdoc-ref:Tags) that
provide flow control, exception-handling, etc.
Here's a slightly more complex example: Say we have a layout template that
contains all the boilerplate, navigation, etc. for the site, and then an
-<code><?attr body ?></code> somewhere in the content area for the content specific to
+`<?attr body ?>` somewhere in the content area for the content specific to
each view:
layout = Inversion::Template.load( 'templates/layout.tmpl' )
@@ 70,8 77,8 @@ Then there's a view template that displa
</section>
Loading this template results in a Ruby object whose API contains one method:
-+#articles+. To render the view, we just call that accessor with instances of
-an +Article+ domain class we defined elsewhere, and then drop the +alist+
+`#articles`. To render the view, we just call that accessor with instances of
+an `Article` domain class we defined elsewhere, and then drop the `alist`
template into the layout and render them:
alist = Inversion::Template.load( 'templates/alist.tmpl' )
@@ 80,8 87,8 @@ template into the layout and render them
layout.body = alist
puts layout.render
-The +for+ tag in the alist will iterate over the enumerable Articles and
-generate an +<li>+ for each one. The resulting template object will be set as
+The `for` tag in the alist will iterate over the enumerable Articles and
+generate an `<li>` for each one. The resulting template object will be set as
the body of the layout template, and stringified when the enclosing template
is rendered. Templates can be nested this way as deeply as you like.
@@ 89,43 96,45 @@ For detailed tag documentation and examp
class in the API documentation.
-== References
+## References
-* {Inversion of Control}[http://en.wikipedia.org/wiki/Inversion_of_control]
-* {Passive View}[http://martinfowler.com/eaaDev/PassiveScreen.html]
-* {Supervising Controller}[http://martinfowler.com/eaaDev/SupervisingPresenter.html]
+* Inversion of Control - https://en.wikipedia.org/wiki/Inversion_of_control
+* Passive View - https://martinfowler.com/eaaDev/PassiveScreen.html
+* Supervising Controller - https://martinfowler.com/eaaDev/SupervisingPresenter.html
-== Installation
+## Installation
gem install inversion
-== Contributing
+## Contributing
You can check out the current development source
-{with Mercurial}[http://repo.deveiate.org/Inversion], or if you prefer Git, via the
-project's {Github mirror}[https://github.com/ged/Inversion].
+[with Mercurial](https://hg.sr.ht/~ged/Inversion), or if you prefer Git, via the
+project's [Github mirror](https://github.com/ged/Inversion).
You can submit bug reports, suggestions, and read more about future plans at
-{the project page}[http://deveiate.org/projects/Inversion].
+[the project page](https://hg.sr.ht/~ged/Inversion).
After checking out the source, run:
- $ rake newb
+ $ gem install -Ng
+ $ rake setup
-This task will install any missing dependencies, run the tests/specs,
-and generate the API documentation.
+This task will install any missing dependencies and do any necessary developer
+setup.
-== Authors
+
+## Authors
* Michael Granger <ged@faeriemud.org>
* Mahlon E. Smith <mahlon@martini.nu>
-== License
+## License
-Copyright © 2011-2020, Michael Granger and Mahlon E. Smith
+Copyright © 2011-2022, Michael Granger and Mahlon E. Smith
All rights reserved.
Redistribution and use in source and binary forms, with or without
M Rakefile +6 -1
@@ 2,5 2,10 @@
require 'rake/deveiate'
-Rake::DevEiate.setup( 'inversion' )
+Rake::DevEiate.setup( 'inversion' ) do |project|
+ project.publish_to = 'deveiate:/usr/local/www/public/code'
+ project.default_manifest.include( 'spec/data/**/*.inversion' )
+ project.default_manifest.include( 'spec/data/*.tmpl' )
+ project.rdoc_generator = :sixfish
+end
M Tags.rdoc => Tags.md +345 -350
@@ 1,94 1,93 @@
-= Built-In Tags
+# Built-In Tags
-Inversion's tags support the Pluggability[http://rubygems.org/gems/pluggability] API, allowing for the easy addition of {custom tags}[#label-Custom+Tags], but it comes with a number of built-in ones too.
+Inversion's tags support the [Pluggability](http://rubygems.org/gems/pluggability) API, allowing for the easy addition of [custom tags](#label-Custom+Tags), but it comes with a number of built-in ones too.
-== Tag Syntax
+## Tag Syntax
Tags can be in either of two formats:
-- XML Pre-processing instruction style: <code><?tagname tagdata ?></code>
-- or the same thing, but with square brackets instead: <code>[?tagname tagdata ?]</code>
+- XML Pre-processing instruction style: `<?tagname tagdata ?>`
+- or the same thing, but with square brackets instead: `[?tagname tagdata ?]`
The second form is especially useful if you're generating HTML and want to put an Inversion tag inside the attribute of an HTML tag, but still want the template to be well-formed:
-
- <a href="[?call article.permalink ?]">Permalink</a>
+ <a href="[?call article.permalink ?]">Permalink</a>
You can mix tag forms in a single document.
-== Placeholder Tags
+## Placeholder Tags
Placeholder tags represent the main functionality of Inversion; they create a placeholder in the output text which can be filled in via a method on the template object with the same name.
-=== attr
+### `attr`
-The +attr+ tag is the primary placeholder tag for injecting dynamic values into your templates. The most basic form is analogous to +attr_accessor+; it defines a method on the template object that, when set, replaces all occurrences of the tag in the template with the value:
+The `attr` tag is the primary placeholder tag for injecting dynamic values into your templates. The most basic form is analogous to `attr_accessor`; it defines a method on the template object that, when set, replaces all occurrences of the tag in the template with the value:
- Title: <?attr title ?>
+ Title: <?attr title ?>
-Calling the template object's +#title=+ method will inject the stringified value into that part of the output when it's rendered, e.g.,
+Calling the template object's `#title=` method will inject the stringified value into that part of the output when it's rendered, e.g.,
- template.title = "How to Breed Kangaroos for Milk and Meat"
- template.render
- # => "Title: How to Breed Kangaroos for Milk and Meat"
+ template.title = "How to Breed Kangaroos for Milk and Meat"
+ template.render
+ # => "Title: How to Breed Kangaroos for Milk and Meat"
-The rendered values of an +attr+ tag can also be the result of calling methods on the attr value:
+The rendered values of an `attr` tag can also be the result of calling methods on the attr value:
- ISBN: <?attr book.isbn ?>
+ ISBN: <?attr book.isbn ?>
Attributes can be sprintf formatted using Ruby's String#% method:
- Book price: <?attr "%0.2f" % book.price ?>
+ Book price: <?attr "%0.2f" % book.price ?>
Attributes can also contain other template objects, which allows templates to be nested within each other easily.
- layout = Inversion::Template.load( 'layout.tmpl' )
- content = Inversion::Template.load( 'content.tmpl' )
- content.caption = "Your kids will love their new Kangaroo family!"
- layout.body = content
- layout.render
+ layout = Inversion::Template.load( 'layout.tmpl' )
+ content = Inversion::Template.load( 'content.tmpl' )
+ content.caption = "Your kids will love their new Kangaroo family!"
+ layout.body = content
+ layout.render
-=== call
+### `call`
-+call+ is just an alias for +attr+. Use whichever strikes your fancy.
+`call` is just an alias for `attr`. Use whichever strikes your fancy.
-=== escape
+### `escape`
-+escape+ works just like +attr+, but it escapes the content inserted into the template, using the configured escaping behavior. The supported escaping behaviors are defined in a mixin called Inversion::Escaping. The behavior to use can be set using the {:escape_format}[Templates@Template+Options] option on the template or in a +config+ tag; it defaults to HTML escaping.
+`escape` works just like `attr`, but it escapes the content inserted into the template, using the configured escaping behavior. The supported escaping behaviors are defined in a mixin called Inversion::Escaping. The behavior to use can be set using the [:escape_format](Templates@Template`Options) option on the template or in a `config+ tag; it defaults to HTML escaping.
- <p>Company name: <?escape company.name ?></p>
+ <p>Company name: <?escape company.name ?></p>
-If the company was +"AT&T"+, the output would look like:
+If the company was `"AT&T"`, the output would look like:
- <p>Company name: AT&T</p>
+ <p>Company name: AT&T</p>
-=== uriencode
+### `uriencode`
-The +urlencode+ tag is another +attr+-like tag, but this one does URI encoding:
+The `urlencode` tag is another `attr`-like tag, but this one does URI encoding:
- <nav>Edit <a href="/profile?name=[?uriencode person.name ?]">your profile</a></nav>
+ <nav>Edit <a href="/profile?name=[?uriencode person.name ?]">your profile</a></nav>
-== Special Placeholders
+## Special Placeholders
-=== timedelta
+### `timedelta`
-If you need to automatically generate a human-readable description of the interval between two times, you can use the +timedelta+ tag:
+If you need to automatically generate a human-readable description of the interval between two times, you can use the `timedelta` tag:
- <article class="blogentry">
- <header>
- <p>Posted: <?timedelta entry.date_posted ?>.</p>
- </header>
- ...
- </article>
+ <article class="blogentry">
+ <header>
+ <p>Posted: <?timedelta entry.date_posted ?>.</p>
+ </header>
+ ...
+ </article>
-The tag supports any object which responds to the +#to_time+ method, so standard +Time+, +Date+, and +DateTime+ objects all work.
+The tag supports any object which responds to the `#to_time` method, so standard `Time`, `Date`, and `DateTime` objects all work.
Dates are compared against the current time, and render to approximate descriptions of the interval, e.g.,
@@ 98,462 97,458 @@ Dates are compared against the current t
* less than a minute from now
-== Inter-template Tags
+## Inter-template Tags
These tags operate on nested templates, allowing you to selectively use or send attributes or content from other templates.
-=== import
+### `import`
+
+Occasionally, you'll want to compose output from several different templates by nesting them, but you don't want to have to set common objects on all of them from code. The `import` tag lets you copy the values from a container template into one intended to be nested within it:
-Occasionally, you'll want to compose output from several different templates by nesting them, but you don't want to have to set common objects on all of them from code. The +import+ tag lets you copy the values from a container template into one intended to be nested within it:
+ <!-- layout.tmpl -->
+ Logged in as: <?attr request.authenticated_user ?>
+ <?attr body ?>
- <!-- layout.tmpl -->
- Logged in as: <?attr request.authenticated_user ?>
- <?attr body ?>
-
- <!-- body.tmpl -->
- <?import request ?>
- <p>You can check your balance using <a href="[?call request.path_info ?]/accounts">the
- accounts tool</a>.</p>
+ <!-- body.tmpl -->
+ <?import request ?>
+ <p>You can check your balance using <a href="[?call request.path_info ?]/accounts">the
+ accounts tool</a>.</p>
+
+When the content template is nested in the container, you only need to set the `request` attribute on the container to set it in both places:
-When the content template is nested in the container, you only need to set the +request+ attribute on the container to set it in both places:
+ layout = Inversion::Template.load( 'layout.tmpl' )
+ body = Inversion::Template.load( 'body.tmpl' )
- layout = Inversion::Template.load( 'layout.tmpl' )
- body = Inversion::Template.load( 'body.tmpl' )
-
- layout.body = body
- layout.request = request
-
- puts layout.render
+ layout.body = body
+ layout.request = request
+
+ puts layout.render
-Without the use of +import+, you'd need to similarly set the request attribute on the body template.
+Without the use of `import`, you'd need to similarly set the request attribute on the body template.
-The imported attribute's value is determined at render time, so you can also use it to import values from an iteration.
+The imported attribute's value is determined at render time, so you can also use it to import values from an iteration.
- <!-- Container template (table.tmpl)" -->
- <table>
- <thead>...</thead>
- <tbody>
- <?for user in assigned_users ?>
- <?attr row ?>
- <?end for ?>
- </tbody>
- </table>
- <?end?>
-
- <!-- Content template (row.tmpl)" -->
- <?import user ?>
- <tr>
- <th>Username:</th><td><?escape user.username ?></td>
- <th>UID:</th><td><?escape user.uid ?></td>
- <th>GID:</th><td><?escape user.gid ?></td>
- </tr>
- <?end?>
+ <!-- Container template (table.tmpl)" -->
+ <table>
+ <thead>...</thead>
+ <tbody>
+ <?for user in assigned_users ?>
+ <?attr row ?>
+ <?end for ?>
+ </tbody>
+ </table>
+ <?end?>
+
+ <!-- Content template (row.tmpl)" -->
+ <?import user ?>
+ <tr>
+ <th>Username:</th><td><?escape user.username ?></td>
+ <th>UID:</th><td><?escape user.uid ?></td>
+ <th>GID:</th><td><?escape user.gid ?></td>
+ </tr>
+ <?end?>
and the code:
- usertable = Inversion::Template.load( 'table.tmpl' )
- userrow = Inversion::Template.load( 'row.tmpl' )
-
- usertable.row = userrow
- usertable.assigned_users = User.assigned.all
-
- puts usertable.render
+ usertable = Inversion::Template.load( 'table.tmpl' )
+ userrow = Inversion::Template.load( 'row.tmpl' )
-When the +row.tmpl+ is rendered each time, its imported +user+ is set to whatever the +user+ in the container is, in this case the next object in +assigned_users+.
+ usertable.row = userrow
+ usertable.assigned_users = User.assigned.all
+
+ puts usertable.render
+
+When the `row.tmpl` is rendered each time, its imported `user` is set to whatever the `user` in the container is, in this case the next object in `assigned_users`.
You can import values into deeply-nested templates, provided each container imports it as well.
-=== publish/subscribe
+### `publish`/`subscribe`
-Often you'll want to set up a generic layout template to establish a global look-and-feel, and then modify it based on the content of an inner template.
+Often you'll want to set up a generic layout template to establish a global look-and-feel, and then modify it based on the content of an inner template.
+
+#### Look and feel template (`layout.tmpl`)
-==== Look and feel template (layout.tmpl)
- <!DOCTYPE HTML>
- <html lang="en">
- <head>
- <title><?subscribe title || Untitled ?></title>
- <link rel="stylesheet" href="/css/base.css" type="text/css" media="screen"
- title="Base Stylesheet" charset="utf-8" />
- <?subscribe stylesheets ?>
-
- <script defer="defer" src="/js/jquery-1.4.2.min.js"
- type="text/javascript" charset="utf-8"></script>
- <?subscribe scripts ?>
- </head>
-
- <body><?attr body ?></body>
- </html>
+ <!DOCTYPE HTML>
+ <html lang="en">
+ <head>
+ <title><?subscribe title || Untitled ?></title>
+ <link rel="stylesheet" href="/css/base.css" type="text/css" media="screen"
+ title="Base Stylesheet" charset="utf-8" />
+ <?subscribe stylesheets ?>
+
+ <script defer="defer" src="/js/jquery-1.4.2.min.js"
+ type="text/javascript" charset="utf-8"></script>
+ <?subscribe scripts ?>
+ </head>
+
+ <body><?attr body ?></body>
+ </html>
-==== A content template (content.tmpl)
- <?publish title ?>I make stuff up<?end publish?>
-
- <?publish stylesheets ?>
- <link rel="stylesheet" href="/css/content.css" type="text/css" media="screen"
- title="Content Style Overrides" charset="utf-8" />
- <?end publish?>
-
- <?publish scripts ?>
- <script defer="defer" src="/js/content.js" type="text/javascript" charset="utf-8"></script>
- <?end publish?>
-
- <div>Hi, there.</div>
+#### A content template (`content.tmpl`)
+
+ <?publish title ?>I make stuff up<?end publish?>
-==== Template setup
+ <?publish stylesheets ?>
+ <link rel="stylesheet" href="/css/content.css" type="text/css" media="screen"
+ title="Content Style Overrides" charset="utf-8" />
+ <?end publish?>
+
+ <?publish scripts ?>
+ <script defer="defer" src="/js/content.js" type="text/javascript" charset="utf-8"></script>
+ <?end publish?>
+
+ <div>Hi, there.</div>
+
+#### Template setup
- layout = Inversion::Template.load( 'layout.tmpl' )
- content = Inversion::Template.load( 'content.tmpl' )
-
- layout.body = content
-
- puts layout.render
+ layout = Inversion::Template.load( 'layout.tmpl' )
+ content = Inversion::Template.load( 'content.tmpl' )
+
+ layout.body = content
-+subscribe+ renders to an empty string if there is no matching +publish+, or to the value of a default if supplied (as in the HTML title example above.)
-In this fashion, you can dynamically switch out different content pages, with each having the ability to optionally override various HTML elements.
+ puts layout.render
-=== include
+`subscribe` renders to an empty string if there is no matching `publish`, or to the value of a default if supplied (as in the HTML title example above.)
+In this fashion, you can dynamically switch out different content pages, with each having the ability to optionally override various HTML elements.
-The +include+ tag allows inclusion of other template files from within a template. This supports separation of a template into several reusable components. The included template becomes a part of the including template, along with any defaults, attributes and configuration.
+### `include`
-==== Include setup
+The `include` tag allows inclusion of other template files from within a template. This supports separation of a template into several reusable components. The included template becomes a part of the including template, along with any defaults, attributes and configuration.
+
+#### `include` setup
- email = Inversion::Template.load( 'email.tmpl' )
-
- email.greeting = "Kudos"
- email.company = Company[ :spime_thorpe ]
- email.user = User[ :jrandom ]
-
- puts main.render
+ email = Inversion::Template.load( 'email.tmpl' )
+
+ email.greeting = "Kudos"
+ email.company = Company[ :spime_thorpe ]
+ email.user = User[ :jrandom ]
-==== Including template (email.tmpl)
+ puts main.render
+
+#### Including template (`email.tmpl`)
+
+ Subject: Great news, everybody!
+ From: <?attr company.email ?>
+ To: <?attr user.email ?>
+
+ <?attr greeting ?>, <?attr user.first_name ?>!
- Subject: Great news, everybody!
- From: <?attr company.email ?>
- To: <?attr user.email ?>
-
- <?attr greeting ?>, <?attr user.first_name ?>!
-
- We are excited to inform you that you have been selected to participate
- in a challenging and exciting career displacement opportunity!
-
- Please attend the mandatory Man Overboard (tm) session we have scheduled
- for you at 8:45AM on Thursday in the Sunshine Room. Light refreshments
- and computer-aided aptitude testing will be provided.
-
- <?include signature.tmpl ?>
+ We are excited to inform you that you have been selected to participate
+ in a challenging and exciting career displacement opportunity!
-==== Included template (signature.tmpl)
+ Please attend the mandatory Man Overboard (tm) session we have scheduled
+ for you at 8:45AM on Thursday in the Sunshine Room. Light refreshments
+ and computer-aided aptitude testing will be provided.
+
+ <?include signature.tmpl ?>
+
+#### Included template (`signature.tmpl`)
- Sincerely,
- Your Friends at <?attr company.name ?>!
+ Sincerely,
+ Your Friends at <?attr company.name ?>!
-==== The rendered output
+#### The rendered output
+
+ Subject: Great news, everybody!
+ From: "Spime-Thorpe, Inc." <salesteam2@spime-thorpe.com>
+ To: "James Random" <jrandom@compusa.com>
- Subject: Great news, everybody!
- From: "Spime-Thorpe, Inc." <salesteam2@spime-thorpe.com>
- To: "James Random" <jrandom@compusa.com>
-
- Kudos, James!
-
- We are excited to inform you that you have been selected to participate
- in a challenging and exciting career displacement opportunity!
-
- Please attend the mandatory Man Overboard (tm) session we have scheduled
- for you at 8:45AM on Thursday in the Sunshine Room. Light refreshments
- and computer-aided aptitude testing will be provided.
-
- Sincerely,
- Your Friends at Spime Thorpe!
+ Kudos, James!
+
+ We are excited to inform you that you have been selected to participate
+ in a challenging and exciting career displacement opportunity!
+
+ Please attend the mandatory Man Overboard (tm) session we have scheduled
+ for you at 8:45AM on Thursday in the Sunshine Room. Light refreshments
+ and computer-aided aptitude testing will be provided.
+
+ Sincerely,
+ Your Friends at Spime Thorpe!
-=== fragment
+### `fragment`
-A +fragment+ tag also sets an attribute from within the template, but under the
+A `fragment` tag also sets an attribute from within the template, but under the
scope of the global template itself. A fragment can use other Inversion tags,
and the attribute is both usable elsewhere in the template, and accessible from
calling code after rendering.
- template = Inversion::Template.new <<-TMPL
- <?fragment subject ?>Your order status (Order #<?call order.number ?>)<?end ?>
+ template = Inversion::Template.new <<-TMPL
+ <?fragment subject ?>Your order status (Order #<?call order.number ?>)<?end ?>
- Dear <?call order.customer.name ?>,
+ Dear <?call order.customer.name ?>,
- Your recent order was modified by our Order Fulfillment Team.
+ Your recent order was modified by our Order Fulfillment Team.
- After careful deliberation, it was decided that no one should have need for that many hot dogs
- with overnight shipping. Frankly, we're more than a little concerned for your health.
+ After careful deliberation, it was decided that no one should have need for that many hot dogs
+ with overnight shipping. Frankly, we're more than a little concerned for your health.
- Sincerely,
- Rowe's Meat Emporium
- (Buy! Sell! Consignment!)
- TMPL
+ Sincerely,
+ Rowe's Meat Emporium
+ (Buy! Sell! Consignment!)
+ TMPL
- template.order = order
- template.render
+ template.order = order
+ template.render
- template.fragments[ :subject ] #=> "Your order status (Order #3492)"
+ template.fragments[ :subject ] #=> "Your order status (Order #3492)"
-== Flow Control
+## Flow Control
The following tags are used to alter the flow of rendering from within templates.
-=== for
+### `for`
-The +for+ tag iterates over the objects in a collection, rendering its
+The `for` tag iterates over the objects in a collection, rendering its
template section once for each iteration. Its attribute can be set to anything
that responds to @#each@. The iteration variable(s) are scoped to the block,
and temporarily override any template attributes of the same name.
-==== 'For' tag setup
+#### `for` tag setup
- overhead_list = Inversion::Template.load( 'employee_list.tmpl' )
- overhead_list.users = User.
- filter { start_date < 6.months.ago }.
- filter { department = 'Information Technology' }
-
- puts overhead_list.render
+ overhead_list = Inversion::Template.load( 'employee_list.tmpl' )
+ overhead_list.users = User.
+ filter { start_date < 6.months.ago }.
+ filter { department = 'Information Technology' }
-The +for+ tag's iteration works just like Ruby's +for+; if the enumerated
+ puts overhead_list.render
+
+The `for` tag's iteration works just like Ruby's `for`; if the enumerated
value has more than one value, you can give a list of iteration variables to
be assigned to.
-==== Employee list using 'for'
+#### Employee list using `for`
- <table>
- <thead>...</thead>
- <tbody>
- <?for user, i in users.each_with_index ?>
- <tr class="[?if i.even? ?]even[?else?]odd[?end if?]-row">
- <td><?attr user.first_name ?></td>
- <td><?attr user.last_name ?></td>
- <td><?attr user.title ?></td>
- <td><?attr user.start_date ?></td>
- <td><?attr user.salary ?></td>
- </tr>
- <?end for ?>
- </tbody>
- </table>
+ <table>
+ <thead>...</thead>
+ <tbody>
+ <?for user, i in users.each_with_index ?>
+ <tr class="[?if i.even? ?]even[?else?]odd[?end if?]-row">
+ <td><?attr user.first_name ?></td>
+ <td><?attr user.last_name ?></td>
+ <td><?attr user.title ?></td>
+ <td><?attr user.start_date ?></td>
+ <td><?attr user.salary ?></td>
+ </tr>
+ <?end for ?>
+ </tbody>
+ </table>
-The example above uses a Ruby enumerator for the +#each_with_index+ method to set the class of the row to +'even-row'+ or +'odd-row'+.
+The example above uses a Ruby enumerator for the `#each_with_index` method to set the class of the row to `'even-row'` or `'odd-row'`.
This works with the keys and values of Hashes, too:
-==== Display hash of notes keyed by author using 'for'
+#### Display hash of notes keyed by author using `for`
- <?for user, content in user.notes ?>
- <section class="note">
- <header>
- Note by <?call user.username ?>
- </header>
- <p><?escape content ?></p>
- </section>
-
- <?end for ?>
+ <?for user, content in user.notes ?>
+ <section class="note">
+ <header>
+ Note by <?call user.username ?>
+ </header>
+ <p><?escape content ?></p>
+ </section>
+
+ <?end for ?>
Note that you can also use Ruby's "external iterator" syntax to iterate, too:
-==== Iterate over each byte of a string with an index using 'for'
+#### Iterate over each byte of a string with an index using `for`
- <section class="hexdump">
- <?for byte, index in frame.header.each_byte.with_index ?>
- <?if index.modulo(8).zero? ?>
- <?if index.nonzero? ?>
- </span><br />
+ <section class="hexdump">
+ <?for byte, index in frame.header.each_byte.with_index ?>
+ <?if index.modulo(8).zero? ?>
+ <?if index.nonzero? ?>
+ </span><br />
+ <?end if ?>
+ <span class="row"><?attr "0x%08x" % index ?>:
<?end if ?>
- <span class="row"><?attr "0x%08x" % index ?>:
- <?end if ?>
- <code><?attr "0x%02x" % byte ?></code>
- <?end for ?>
- </section>
+ `<?attr "0x%02x" % byte ?>`
+ <?end for ?>
+ </section>
-=== if/elsif/else
+### `if`/`elsif`/`else`
-The +if+ tag can be used to conditionally render a section of the template based on the value of an attribute or the value of a method called on it.
+The `if` tag can be used to conditionally render a section of the template based on the value of an attribute or the value of a method called on it.
-==== Conditional block
+#### Conditional block
- <?if user.has_stock_options? ?>
- You will have 21 days to exercise your stock options.
- <?else ?>
- You have a week to optionally take home a handful of supplies from the
- office cabinet.
- <?end if ?>
+ <?if user.has_stock_options? ?>
+ You will have 21 days to exercise your stock options.
+ <?else ?>
+ You have a week to optionally take home a handful of supplies from the
+ office cabinet.
+ <?end if ?>
-=== unless
+### `unless`
-Unless is like the +if+ tag, but with inverted logic. Note that an +unless+ can have an +else+ tag, but cannot have any +elsif+ tags within it.
+Unless is like the `if` tag, but with inverted logic. Note that an `unless` can have an `else` tag, but cannot have any `elsif` tags within it.
-=== yield
+### `yield`
-The +yield+ tag is used to defer rendering of some part of the template to the code that is calling render[rdoc-ref:Inversion::Template#render] on it. If a block is passed to +#render+, then the +yield+ tag will call it with the Inversion::RenderState object that is currently in effect, and will render the return value in its place.
+The `yield` tag is used to defer rendering of some part of the template to the code that is calling render[rdoc-ref:Inversion::Template#render] on it. If a block is passed to `#render`, then the `yield` tag will call it with the Inversion::RenderState object that is currently in effect, and will render the return value in its place.
-==== Using 'yield' to defer an expensive database lookup (report.tmpl)
+#### Using `yield` to defer an expensive database lookup (`report.tmpl`)
- <?if extra_details_enabled ?>
- <?yield ?>
- <?end if ?>
+ <?if extra_details_enabled ?>
+ <?yield ?>
+ <?end if ?>
- report = Inversion::Template.load( 'report.tmpl' )
- report.extra_details_enabled = true if $DEBUG
- puts report.render do
- report_table = Inversion::Template.load( 'table.tmpl' )
- report_table.rows = an_expensive_database_query()
- report_table
- end
+ report = Inversion::Template.load( 'report.tmpl' )
+ report.extra_details_enabled = true if $DEBUG
+ puts report.render do
+ report_table = Inversion::Template.load( 'table.tmpl' )
+ report_table.rows = an_expensive_database_query()
+ report_table
+ end
-This will insert the +report_table+ template in place of the yield, but only if $DEBUG is true.
+This will insert the `report_table` template in place of the yield, but only if $DEBUG is true.
-=== begin/rescue
+### `begin`/`rescue`
-These tags work as you'd expect from their ruby counterparts.
+These tags work as you'd expect from their ruby counterparts.
-The +begin+ section of the template to be rendered only if no exceptions are raised while it's
-being rendered. If an exception is raised, it is checked against any +rescue+ sections, and the
-first with a matching exception is rendered instead. If no +rescue+ block is found, the exception
+The `begin` section of the template to be rendered only if no exceptions are raised while it's
+being rendered. If an exception is raised, it is checked against any `rescue` sections, and the
+first with a matching exception is rendered instead. If no `rescue` block is found, the exception
is handled by the configured exception behavior for the template (see Inversion::Template@Template+Options).
- <?begin ?><?call employees.length ?><?end?>
-
- <?begin ?>
- <?for employee in employees.all ?>
- <?attr employee.name ?> --> <?attr employee.title ?>
- <?end for?>
- <?rescue DatabaseError => err ?>
- Oh no!! I can't talk to the database for some reason. The
- error was as follows:
- <pre>
- <?attr err.message ?>
- </pre>
- <?end?>
+ <?begin ?><?call employees.length ?><?end?>
+
+ <?begin ?>
+ <?for employee in employees.all ?>
+ <?attr employee.name ?> --> <?attr employee.title ?>
+ <?end for?>
+ <?rescue DatabaseError => err ?>
+ Oh no!! I can't talk to the database for some reason. The
+ error was as follows:
+ <pre>
+ <?attr err.message ?>
+ </pre>
+ <?end?>
-== Control Tags
+## Control Tags
There are a few tags that can be used to set values in the templating system itself.
-=== config
+### `config`
-The +config+ tag can be used to override template options[Templates@Template+Options]
+The `config` tag can be used to override template options[Templates@Template+Options]
on a per-template basis. It allows for convenient, inline settings from
within a template rather than from the code in which the template is
loaded.
For example, if you want to enable debugging comments on a single template:
- <?config debugging_comments: true ?>
+ <?config debugging_comments: true ?>
Multiple template options can be set simultaneously by using a YAML hash:
- <?config
- on_render_error: propagate
- debugging_comments: true
- comment_start: /*
- comment_end: */
- ?>
+ <?config
+ on_render_error: propagate
+ debugging_comments: true
+ comment_start: /*
+ comment_end: */
+ ?>
Note that this also allows you to set multiple options on a single line, if you wrap them in braces:
- <?config { comment_start: "/*", comment_end: "*/" } ?>
+ <?config { comment_start: "/*", comment_end: "*/" } ?>
-=== default
+### `default`
-The +default+ tag sets an attribute from within the template,
+The `default` tag sets an attribute from within the template,
and this value is used if the attribute is set to nil or otherwise unset.
- template = Inversion::Template.new <<-TMPL
- <?default adjective to "cruel" ?>
- <?default noun to "world" ?>
- Goodbye, <?attr adjective ?> <?attr noun ?>!
- TMPL
+ template = Inversion::Template.new <<-TMPL
+ <?default adjective to "cruel" ?>
+ <?default noun to "world" ?>
+ Goodbye, <?attr adjective ?> <?attr noun ?>!
+ TMPL
- template.render
+ template.render
- template.adjective = "delicious"
- template.render
+ template.adjective = "delicious"
+ template.render
- template.adjective = nil
- template.noun = "banana"
- template.render
+ template.adjective = nil
+ template.noun = "banana"
+ template.render
Would produce the output:
- Goodbye, cruel world!
- Goodbye, delicious world!
- Goodbye, cruel banana!
+ Goodbye, cruel world!
+ Goodbye, delicious world!
+ Goodbye, cruel banana!
-== Troubleshooting/Introspection
+## Troubleshooting/Introspection
-=== pp
+### `pp`
-The +pp+ tag uses the +PP+ library to output an escaped representation of its argument.
+The `pp` tag uses the `PP` library to output an escaped representation of its argument.
-==== Creating an object to inspect
+#### Creating an object to inspect
- content = Inversion::Template.load( 'content.tmpl' )
- content.file = File.stat( '/tmp/example.txt' )
-
- puts content.render
+ content = Inversion::Template.load( 'content.tmpl' )
+ content.file = File.stat( '/tmp/example.txt' )
+
+ puts content.render
-==== Inspecting an object from within a template (content.tmpl)
+#### Inspecting an object from within a template (`content.tmpl`)
- <div class="debugging">
- The file's stat attributes:
- <?pp file ?>
- </div>
+ <div class="debugging">
+ The file's stat attributes:
+ <?pp file ?>
+ </div>
-The output is escaped according to the current setting of the {:escape_format}[rdoc-ref:Templates@Template+Options] option.
+The output is escaped according to the current setting of the [:escape_format](rdoc-ref:Templates@Template+Options) option.
-==== The rendered result
+#### The rendered result
- <div class="debugging">
- The file's stat attributes:
- #<File::Stat
- dev=0xe000004,
- ino=3064556,
- mode=0100644 (file rw-r--r--),
- nlink=1,
- uid=501 (mahlon),
- gid=0 (wheel),
- rdev=0x0 (0, 0),
- size=0,
- blksize=4096,
- blocks=0,
- atime=2011-08-12 08:43:15 -0700 (1313163795),
- mtime=2011-08-12 08:43:15 -0700 (1313163795),
- ctime=2011-08-12 08:43:15 -0700 (1313163795)></div>
- </div>
+ <div class="debugging">
+ The file's stat attributes:
+ #<File::Stat
+ dev=0xe000004,
+ ino=3064556,
+ mode=0100644 (file rw-r--r--),
+ nlink=1,
+ uid=501 (mahlon),
+ gid=0 (wheel),
+ rdev=0x0 (0, 0),
+ size=0,
+ blksize=4096,
+ blocks=0,
+ atime=2011-08-12 08:43:15 -0700 (1313163795),
+ mtime=2011-08-12 08:43:15 -0700 (1313163795),
+ ctime=2011-08-12 08:43:15 -0700 (1313163795)></div>
+ </div>
-== Custom Tags
+## Custom Tags
We have a lot of documentation work to do for this still, but the basics are:
-* Create a file with the path <code>lib/inversion/template/«yourtagnametag».rb/code>
-
+* Create a file with the path `lib/inversion/template/«yourtagnametag».rb/code>
* Name your class Inversion::Template::«yourtagname.capitalize»Tag
-
* Subclass one of the abstract template tag types:
-
* If your tag body will contain code, subclass Inversion::Template::CodeTag
-
* Otherwise, subclass Inversion::Template::Tag
-
* If your tag is a container, include Inversion::Template::ContainerTag
-
-* Read the documentation for the tag type you're subclassing for the methods you're
- required to implement.
+* Read the documentation for the tag type you're subclassing for the methods
+ you're required to implement.
Unfortunately, the tag superclasses aren't currently documented very well, so
the best way to accomplish what you want is to find an existing tag that does
M certs/ged.pem +3 -3
@@ 4,17 4,17 @@ REM9RmFlcmllTVVEL0RDPW9yZzAeFw0yMjAxMDcy
MTRaMCIxIDAeBgNVBAMMF2dlZC9EQz1GYWVyaWVNVUQvREM9b3JnMIIBojANBgkq
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvyVhkRzvlEs0fe7145BYLfN6njX9ih5H
L60U0p0euIurpv84op9CNKF9tx+1WKwyQvQP7qFGuZxkSUuWcP/sFhDXL1lWUuIl
-M4uHbGCRmOshDrF4dgnBeOvkHr1fIhPlJm5FO+Vew8tSQmlDsosxLUx+VB7DrVFO
+M4uHbGCRmOshDrF4dgnBeOvkHr1fIhPlJm5FO`Vew8tSQmlDsosxLUx`VB7DrVFO
5PU2AEbf04GGSrmqADGWXeaslaoRdb1fu/0M5qfPTRn5V39sWD9umuDAF9qqil/x
Sl6phTvgBrG8GExHbNZpLARd3xrBYLEFsX7RvBn2UPfgsrtvpdXjsHGfpT3IPN+B
vQ66lts4alKC69TE5cuKasWBm+16A4aEe3XdZBRNmtOu/g81gvwA7fkJHKllJuaI
-dXzdHqq+zbGZVSQ7pRYHYomD0IiDe1DbIouFnPWmagaBnGHwXkDT2bKKP+s2v21m
+dXzdHqq`zbGZVSQ7pRYHYomD0IiDe1DbIouFnPWmagaBnGHwXkDT2bKKP`s2v21m
ozilJg4aar2okb/RA6VS87o+d7g6LpDDMMQjH4G9OPnJENLdhu8KnPw/ivSVvQw7
N2I4L/ZOIe2DIVuYH7aLHfjZDQv/mNgpAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYD
VR0PBAQDAgSwMB0GA1UdDgQWBBRyjf55EbrHagiRLqt5YAd3yb8k4DANBgkqhkiG
9w0BAQsFAAOCAYEASrm1AbEoxACZ9WXJH3R5axV3U0CA4xaETlL2YT+2nOfVBMQ9
0ZlkPx6j4ghKJgAIi1TMfDM2JyPJsppQh8tiNccDjWc62UZRY/dq26cMqf/lcI+a
-6YBuEYvzZfearwVs8tHnXtwYV3WSCoCOQaB+nq2lA1O+nkKNl41WOsVbNama5jx3
+6YBuEYvzZfearwVs8tHnXtwYV3WSCoCOQaB`nq2lA1O`nkKNl41WOsVbNama5jx3
8cQtVSEEmZy6jIDJ8c5TmBJ7BQUDEUEWA/A3V42Xyctoj7DvUXWE0lP+X6ypAVSr
lFh3TS64D7NTvxkmg7natUoCvobl6kGl4yMaqE4YRTlfuzhpf91TSOntClqrAOsS
K1s56WndQj3IoBocdY9mQhDZLtLHofSkymoP8btBlj5SsN24TiF0VMSZlctSCYZg
M certs/mahlon.pem +3 -3
@@ 3,11 3,11 @@ MIIENDCCApygAwIBAgIBATANBgkqhkiG9w0BAQsF
b24vREM9bWFydGluaS9EQz1udTAeFw0yMDAyMTkyMTU4NDBaFw0yMTAyMTgyMTU4
NDBaMCIxIDAeBgNVBAMMF21haGxvbi9EQz1tYXJ0aW5pL0RDPW51MIIBojANBgkq
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA3cz7ILM8n+Y5nvz7mVRVqE8LusWdT8NX
-nlnETynDndenI+a2S3j22DR+U4ooGUjuCHE3iR1CVmTDGbxFfNRfmnC1AN9Hybat
+nlnETynDndenI`a2S3j22DR`U4ooGUjuCHE3iR1CVmTDGbxFfNRfmnC1AN9Hybat
ewW+onvMBye7yfO0bJB5vkqaW5vd35rzquOffgBtJMo7rPRu6pX8RkL34Wnew4J7
POooUcYbWSAO934HSCUC8wVm6b4v/ejVF1Lk44Dz45jtMqtR7KTAtpipdbTXAarO
HQy3eVes/0oTqhk4CP50r1KP09nUHTn2lzVaCN9vmNE/Jwe0AuQ9ImvZXPpCsMMl
-V03/tuJ++48sVmOIusJkASPupXcdI6zqsjYw2vLMFtuYNskRSvwbn6Wm6x9hLWWj
+V03/tuJ``48sVmOIusJkASPupXcdI6zqsjYw2vLMFtuYNskRSvwbn6Wm6x9hLWWj
IRp5FvHPORLRCHFizXRmXZ3PyFHqbv6m4yG0SyfMzOXPk3Hn5dqqmK+BFCihTZIN
fqpBmuxyNEE21fSO9ALLlWeW9ffg9Ye5Sc1n3yEyv8rPb9VDvi1B5N6xIcDFMNVs
RiCamNbET4Sq9VIYwYtcB1f6EataqFEhAgMBAAGjdTBzMAkGA1UdEwQCMAAwCwYD
@@ 18,7 18,7 @@ 7NdIv8Bz4rpKAdhypy30xjukGLTOKBp1C0TjfHXo
K5IsyENen+YLeLfE8dguq5tHlfocbFilRGHt8BHHO9BpPpAYoPt/76SCC2NaU5vN
33YTCpaVP0raS6E4i+xtx5PNdKoeTdrgwCQtUBhGf3L9YbZy1UaSeAyng5keuOzV
Mu2osihEB0GE0pOZJNpI6ow+0emwN/XvBKHpN9D2bjbvKetyQSrm0OniaZBXIGzW
-Bg0JmajxUaGYWnz+QFADT+HLPmekxF3mB4+0ymZCHKPC+04h6RDjvkEOji6Jm+VB
+Bg0JmajxUaGYWnz`QFADT`HLPmekxF3mB4`0ymZCHKPC`04h6RDjvkEOji6Jm+VB
JHjnceUEejSXTkZAKAmiOAtnX4j1MM1DLiFMlZ5Wbt7hbiOiO5HoN9p9snZhYqSU
JyAQQloqY/KyzQqxPlKdMNmBxRU+Cdarp05lEI6Sfj9MdrndoIL6MT/f6PgoCWZQ
xEarK1Fn47yS4UZqRi6VgKc3JHscX9x4
M lib/inversion.rb +1 -1
@@ 39,8 39,8 @@ module Inversion
end
require 'inversion/exceptions'
+ require 'inversion/refinements'
require 'inversion/mixins'
- require 'inversion/monkeypatches'
require 'inversion/template'
end # module Inversion
M lib/inversion/cli.rb +16 -16
@@ 126,7 126,7 @@ class Inversion::CLI
end
- ### Add the specified +mod+ule containing subcommands to the 'inversion' command.
+ ### Add the specified `mod`ule containing subcommands to the 'inversion' command.
def self::register_subcommands( mod )
self.subcommand_modules ||= []
self.subcommand_modules.push( mod )
@@ 168,7 168,7 @@ class Inversion::CLI
end
- ### Set the global logging +level+ if it's defined.
+ ### Set the global logging `level` if it's defined.
def self::set_logging_level( level=nil )
if level
Loggability.level = level.to_sym
@@ 207,7 207,7 @@ class Inversion::CLI
end
- ### Set up the output levels and globals based on the associated +global+ options.
+ ### Set up the output levels and globals based on the associated `global` options.
def self::setup_output( global )
if global[:verbose]
@@ 246,13 246,13 @@ class Inversion::CLI
module_function
###############
- ### Exit with the specified +exit_code+ after printing the given +message+.
+ ### Exit with the specified `exit_code` after printing the given `message`.
def exit_now!( message, exit_code=1 )
raise GLI::CustomExit.new( message, exit_code )
end
- ### Exit with a helpful +message+ and display the usage.
+ ### Exit with a helpful `message` and display the usage.
def help_now!( message=nil )
exception = OptionParser::ParseError.new( message )
def exception.exit_code; 64; end
@@ 273,31 273,31 @@ class Inversion::CLI
end
- ### Return the specified +string+ in the 'headline' ANSI color.
+ ### Return the specified `string` in the 'headline' ANSI color.
def headline_string( string )
return hl.headline( string )
end
- ### Return the specified +string+ in the 'highlight' ANSI color.
+ ### Return the specified `string` in the 'highlight' ANSI color.
def highlight_string( string )
return hl.highlight( string )
end
- ### Return the specified +string+ in the 'success' ANSI color.
+ ### Return the specified `string` in the 'success' ANSI color.
def success_string( string )
return hl.success( string )
end
- ### Return the specified +string+ in the 'error' ANSI color.
+ ### Return the specified `string` in the 'error' ANSI color.
def error_string( string )
return hl.error( string )
end
- ### Output a table with the given +header+ (an array) and +rows+
+ ### Output a table with the given `header` (an array) and `rows`
### (an array of arrays).
def display_table( header, rows )
table = TTY::Table.new( header, rows )
@@ 323,7 323,7 @@ class Inversion::CLI
end
- ### Display the given list of +items+.
+ ### Display the given list of `items`.
def display_list( items )
items.flatten.each do |item|
self.prompt.say( "- %s" % [ self.highlight_string(item) ] )
@@ 332,14 332,14 @@ class Inversion::CLI
end
- ### Return the count of visible (i.e., non-control) characters in the given +string+.
+ ### Return the count of visible (i.e., non-control) characters in the given `string`.
def visible_chars( string )
return string.to_s.gsub(/\e\[.*?m/, '').scan( /\P{Cntrl}/ ).size
end
### In dry-run mode, output the description instead of running the provided block and
- ### return the +return_value+.
+ ### return the `return_value`.
### If dry-run mode is not enabled, yield to the block.
def unless_dryrun( description, return_value=true )
if $DRYRUN
@@ 353,8 353,8 @@ class Inversion::CLI
- ### Load the Inversion::Template from the specified +tmplpath+ and return it. If there
- ### is an error loading the template, output the error and return +nil+.
+ ### Load the Inversion::Template from the specified `tmplpath` and return it. If there
+ ### is an error loading the template, output the error and return `nil`.
def load_template( tmplpath )
template = Inversion::Template.load( tmplpath )
return template
@@ 384,7 384,7 @@ class Inversion::CLI
end
- ### Output a subheader with the given +caption+.
+ ### Output a subheader with the given `caption`.
def output_subheader( caption )
self.prompt.say( highlight_string caption )
end
M lib/inversion/cli/api.rb +1 -1
@@ 37,7 37,7 @@ module Inversion::CLI::ApiCommand
###############
- ### Output a description of the +template+'s attributes, subscriptions, etc.
+ ### Output a description of the `template`'s attributes, subscriptions, etc.
def describe_template_api( template )
attrs = template.attributes.keys.map( &:to_s )
return if attrs.empty?
M lib/inversion/cli/tree.rb +3 -3
@@ 36,7 36,7 @@ module Inversion::CLI::TreeCommand
module_function
###############
- ### Output the given +tree+ of nodes at the specified +indent+ level.
+ ### Output the given `tree` of nodes at the specified `indent` level.
def output_template_nodes( tree, indent=0 )
indenttxt = ' ' * indent
tree.each do |node|
@@ 46,7 46,7 @@ module Inversion::CLI::TreeCommand
end
- ### Dump the node tree of the given +templates+.
+ ### Dump the node tree of the given `templates`.
def dump_node_trees( templates )
templates.each do |path|
template = self.load_template( path )
@@ 57,7 57,7 @@ module Inversion::CLI::TreeCommand
end
- ### Output the given +tree+ of nodes at the specified +indent+ level.
+ ### Output the given `tree` of nodes at the specified `indent` level.
def output_template_nodes( tree, indent=0 )
indenttxt = ' ' * indent
tree.each do |node|
M lib/inversion/mixins.rb +10 -10
@@ 5,7 5,7 @@ require 'tempfile'
module Inversion
- # Hides your class's ::new method and adds a +pure_virtual+ method generator for
+ # Hides your class's ::new method and adds a `pure_virtual` method generator for
# defining API methods. If subclasses of your class don't provide implementations of
# "pure_virtual" methods, NotImplementedErrors will be raised if they are called.
#
@@ 66,7 66,7 @@ module Inversion
module_function
###############
- ### Return a version of the given +hash+ with its keys transformed
+ ### Return a version of the given `hash` with its keys transformed
### into Strings from whatever they were before.
###
### stringhash = stringify_keys( symbolhash )
@@ 86,7 86,7 @@ module Inversion
end
- ### Return a duplicate of the given +hash+ with its identifier-like keys
+ ### Return a duplicate of the given `hash` with its identifier-like keys
### transformed into symbols from whatever they were before.
###
### symbolhash = symbolify_keys( stringhash )
@@ 144,7 144,7 @@ module Inversion
end
- ### Escape the +output+ using the format specified by the given +render_state+'s config.
+ ### Escape the `output` using the format specified by the given `render_state`'s config.
def escape( output, render_state )
format = render_state.options[:escape_format] || DEFAULT_ESCAPE_FORMAT
return output if format == :none
@@ 159,7 159,7 @@ module Inversion
end
- ### Escape the given +output+ using HTML entity-encoding.
+ ### Escape the given `output` using HTML entity-encoding.
def escape_html( output )
return output.to_s.
gsub( /&/, '&' ).
@@ 168,7 168,7 @@ module Inversion
end
- ### Escape the given +output+ using the encoding specified in RFC3986 (URIs)
+ ### Escape the given `output` using the encoding specified in RFC3986 (URIs)
def escape_uri( output )
return output.to_s.gsub( URI_ENCODED_CHARACTERS ) do |m|
bytes = m[ 0 ].each_byte
@@ 194,7 194,7 @@ module Inversion
module MethodUtilities
### Creates instance variables and corresponding methods that return their
- ### values for each of the specified +symbols+ in the singleton of the
+ ### values for each of the specified `symbols` in the singleton of the
### declaring object (e.g., class instance variables and methods if declared
### in a Class).
def singleton_attr_reader( *symbols )
@@ 204,7 204,7 @@ module Inversion
end
### Creates methods that allow assignment to the attributes of the singleton
- ### of the declaring object that correspond to the specified +symbols+.
+ ### of the declaring object that correspond to the specified `symbols`.
def singleton_attr_writer( *symbols )
symbols.each do |sym|
singleton_class.__send__( :attr_writer, sym )
@@ 213,7 213,7 @@ module Inversion
### Creates readers and writers that allow assignment to the attributes of
### the singleton of the declaring object that correspond to the specified
- ### +symbols+.
+ ### `symbols`.
def singleton_attr_accessor( *symbols )
symbols.each do |sym|
singleton_class.__send__( :attr_accessor, sym )
@@ 230,7 230,7 @@ module Inversion
module_function
###############
- ### Recursively copy the specified +obj+ and return the result.
+ ### Recursively copy the specified `obj` and return the result.
def deep_copy( obj )
# self.log.debug "Deep copying: %p" % [ obj ]
M lib/inversion/parser.rb +5 -5
@@ 44,7 44,7 @@ class Inversion::Parser
}
- ### Create a new Inversion::Parser with the specified config +options+.
+ ### Create a new Inversion::Parser with the specified config `options`.
def initialize( template, options={} )
@template = template
@options = DEFAULT_OPTIONS.merge( options )
@@ 59,7 59,7 @@ class Inversion::Parser
attr_reader :options
- ### Parse the given +source+ into one or more Inversion::Template::Nodes and return
+ ### Parse the given `source` into one or more Inversion::Template::Nodes and return
### it as an Array.
def parse( source, inherited_state=nil )
state = nil
@@ 152,7 152,7 @@ class Inversion::Parser
private
#######
- ### Return at most +length+ characters long from the given +string+, appending +ellipsis+
+ ### Return at most `length` characters long from the given `string`, appending `ellipsis`
### at the end if it was truncated.
def abbrevstring( string, length=30, ellipsis='…' )
return string if string.length < length
@@ 267,7 267,7 @@ class Inversion::Parser
end
- ### Return the node that is currently being appended to, or +nil+ if there aren't any
+ ### Return the node that is currently being appended to, or `nil` if there aren't any
### opened container nodes.
def current_node
return self.node_stack.last
@@ 281,7 281,7 @@ class Inversion::Parser
end
- ### Load a subtemplate from the specified +path+, checking for recursive-dependency.
+ ### Load a subtemplate from the specified `path`, checking for recursive-dependency.
def load_subtemplate( path )
if self.include_stack.include?( path )
stack_desc = ( self.include_stack + [path] ).join( ' --> ' )
M lib/inversion/monkeypatches.rb => lib/inversion/refinements.rb +8 -10
@@ 4,17 4,15 @@
require 'inversion' unless defined?( Inversion )
require 'ripper'
-# Monkeypatch mixin to expose the 'tokens' instance variable of
-# Ripper::TokenPattern::MatchData. Included in Ripper::TokenPattern::MatchData.
-module Inversion::RipperAdditions
+# Expose the 'tokens' instance variable of Ripper::TokenPattern::MatchData.
+module Inversion::Refinements
- # the array of token tuples
- attr_reader :tokens
+ refine Ripper::TokenPattern::MatchData do
-end
+ # the array of token tuples
+ attr_reader :tokens
-# :stopdoc:
-class Ripper::TokenPattern::MatchData
- include Inversion::RipperAdditions
-end
+ end # refine Ripper::TokenPattern::MatchData
+end # module Inversion::Refinements
+
M lib/inversion/renderstate.rb +24 -24
@@ 20,26 20,26 @@ class Inversion::RenderState
class Scope < BasicObject
### Create a new RenderState::Scope with its initial tag locals set to
- ### +locals+.
+ ### `locals`.
def initialize( locals={}, fragments={} )
@locals = locals
@fragments = fragments
end
- ### Return the tag local with the specified +name+.
+ ### Return the tag local with the specified `name`.
def []( name )
return @locals[ name.to_sym ]
end
- ### Set the tag local with the specified +name+ to +value+.
+ ### Set the tag local with the specified `name` to `value`.
def []=( name, value )
@locals[ name.to_sym ] = value
end
- ### Return a copy of the receiving Scope merged with the given +values+,
+ ### Return a copy of the receiving Scope merged with the given `values`,
### which can be either another Scope or a Hash.
def +( values )
return Scope.new( self.__locals__.merge(values), self.__fragments__ )
@@ 74,9 74,9 @@ class Inversion::RenderState
### Create a new RenderState. If the template is being rendered inside another one, the
- ### containing template's RenderState will be passed as the +containerstate+. The
- ### +initial_attributes+ will be deep-copied, and the +options+ will be merged with
- ### Inversion::Template::DEFAULT_CONFIG. The +block+ is stored for use by
+ ### containing template's RenderState will be passed as the `containerstate`. The
+ ### `initial_attributes` will be deep-copied, and the `options` will be merged with
+ ### Inversion::Template::DEFAULT_CONFIG. The `block` is stored for use by
### template nodes.
def initialize( containerstate=nil, initial_attributes={}, options={}, &block )
@@ 164,7 164,7 @@ class Inversion::RenderState
end
- ### Evaluate the specified +code+ in the context of itself and
+ ### Evaluate the specified `code` in the context of itself and
### return the result.
def eval( code )
# self.log.debug "Evaling: %p" [ code ]
@@ 178,7 178,7 @@ class Inversion::RenderState
end
- ### Override the state's attributes with the given +overrides+, call the +block+, then
+ ### Override the state's attributes with the given `overrides`, call the `block`, then
### restore the attributes to their original values.
def with_attributes( overrides )
raise LocalJumpError, "no block given" unless block_given?
@@ 227,8 227,8 @@ class Inversion::RenderState
end
- ### Set the state's error handler to +handler+ for the duration of the block, restoring
- ### the previous handler after the block exits. +Handler+ must respond to #call, and will
+ ### Set the state's error handler to `handler` for the duration of the block, restoring
+ ### the previous handler after the block exits. `Handler` must respond to #call, and will
### be called with two arguments: the node that raised the exception, and the exception object
### itself.
def with_error_handler( handler )
@@ 250,7 250,7 @@ class Inversion::RenderState
### Returns a new RenderState containing the attributes and options of the receiver
- ### merged with those of the +otherstate+.
+ ### merged with those of the `otherstate`.
def merge( otherstate )
merged = self.dup
merged.merge!( otherstate )
@@ 258,7 258,7 @@ class Inversion::RenderState
end
- ### Merge the attributes and options of the +otherstate+ with those of the receiver,
+ ### Merge the attributes and options of the `otherstate` with those of the receiver,
### replacing any with the same keys.
def merge!( otherstate )
@scopes.push( @scopes.pop + otherstate.scope )
@@ 268,7 268,7 @@ class Inversion::RenderState
end
- ### Append operator -- add an node to the final rendered output. If the +node+ renders
+ ### Append operator -- add an node to the final rendered output. If the `node` renders
### as an object that itself responds to the #render method, #render will be called and
### the return value will be appended instead. This will continue until the returned
### object either doesn't respond to #render or #renders as itself.
@@ 311,7 311,7 @@ class Inversion::RenderState
end
- ### Publish the given +nodes+ to all subscribers to the specified +key+.
+ ### Publish the given `nodes` to all subscribers to the specified `key`.
def publish( key, *nodes )
key = key.to_sym
# self.log.debug "[0x%016x] Publishing %p nodes: %p" % [ self.object_id * 2, key, nodes ]
@@ 327,7 327,7 @@ class Inversion::RenderState
alias_method :publish_nodes, :publish
- ### Subscribe the given +node+ to nodes published with the specified +key+.
+ ### Subscribe the given `node` to nodes published with the specified `key`.
def subscribe( key, node )
key = key.to_sym
self.log.debug "Adding subscription to %p nodes for %p" % [ key, node ]
@@ 341,8 341,8 @@ class Inversion::RenderState
end
- ### Add one or more rendered +nodes+ to the state as a reusable fragment associated
- ### with the specified +name+.
+ ### Add one or more rendered `nodes` to the state as a reusable fragment associated
+ ### with the specified `name`.
def add_fragment( name, *nodes )
self.log.debug "Adding a %s fragment with %d nodes." % [ name, nodes.size ]
nodes.flatten!
@@ 360,7 360,7 @@ class Inversion::RenderState
end
- ### Handle an +exception+ that was raised while appending a node by calling the
+ ### Handle an `exception` that was raised while appending a node by calling the
### #errhandler.
def handle_render_error( node, exception )
self.log.error "%s while rendering %p: %s" %
@@ 385,7 385,7 @@ class Inversion::RenderState
end
- ### Default exception handler: Handle an +exception+ while rendering +node+ according to the
+ ### Default exception handler: Handle an `exception` while rendering `node` according to the
### behavior specified by the `on_render_error` option. Returns the string which should be
### appended to the output, if any.
def default_error_handler( state, node, exception )
@@ 413,7 413,7 @@ class Inversion::RenderState
end
- ### Return +true+ if rendered nodes are being saved for output.
+ ### Return `true` if rendered nodes are being saved for output.
def rendering_enabled?
return @rendering_enabled ? true : false
end
@@ 460,14 460,14 @@ class Inversion::RenderState
protected
#########
- ### Return the +node+ as a comment if debugging comments are enabled.
+ ### Return the `node` as a comment if debugging comments are enabled.
def make_node_comment( node )
comment_body = node.as_comment_body or return ''
return self.make_comment( comment_body )
end
- ### Return the specified +content+ inside of the configured comment characters.
+ ### Return the specified `content` inside of the configured comment characters.
def make_comment( content )
return [
self.options[:comment_start],
@@ 477,7 477,7 @@ class Inversion::RenderState
end
- ### Return the given +nodes+ as a String in the configured encoding.
+ ### Return the given `nodes` as a String in the configured encoding.
def stringify_nodes( nodes )
# self.log.debug "Rendering nodes: %p" % [ nodes ]
strings = nodes.flatten.map( &:to_s )
M lib/inversion/template.rb +18 -21
@@ 27,23 27,23 @@ end
#
# == Template Options
#
-# Inversion supports the {Configurability}[http://rubygems.org/gems/configurability]
-# API, and registers itself with the +templates+ key. This means you can either add
-# a +templates+ section to your Configurability config, or call
+# Inversion supports the [Configurability](http://rubygems.org/gems/configurability)
+# API, and registers itself with the `templates` key. This means you can either add
+# a `templates` section to your Configurability config, or call
# ::configure yourself with a config Hash (or something that quacks like one).
#
# To set options on a per-template basis, you can pass an options hash to either
# Inversion::Template::load or Inversion::Template::new, or set them from within the template
-# itself using the {config tag}[rdoc-ref:Tags@config].
+# itself using the [config tag](rdoc-ref:Tags@config).
#
# The available options are:
#
# [:ignore_unknown_tags]
# Setting to false causes unknown tags used in templates to raise an
-# Inversion::ParseError. Defaults to +true+.
+# Inversion::ParseError. Defaults to `true`.
#
# [:on_render_error]
-# Dictates the behavior of exceptions during rendering. Defaults to +:comment+.
+# Dictates the behavior of exceptions during rendering. Defaults to `:comment`.
#
# [:ignore]
# Exceptions are silently ignored.
@@ 54,7 54,7 @@ end
#
#
# [:debugging_comments]
-# Insert various Inversion parse and render statements while rendering. Defaults to +false+.
+# Insert various Inversion parse and render statements while rendering. Defaults to `false`.
#
# [:comment_start]
# When rendering debugging comments, the comment is started with these characters.
@@ 70,16 70,16 @@ end
# last checked member of this. Defaults to <code>[]</code>.
#
# [:escape_format]
-# The escaping used by tags such as +escape+ and +pp+. Default: +:html+.
+# The escaping used by tags such as `escape` and `pp`. Default: `:html`.
#
# [:strip_tag_lines]
# If a tag's presence introduces a blank line into the output, this option
-# removes it. Defaults to +true+.
+# removes it. Defaults to `true`.
#
# [:stat_delay]
# Templates know when they've been altered on disk, and can dynamically
# reload themselves in long running applications. Setting this option creates
-# a purposeful delay between reloads for busy servers. Defaults to +0+
+# a purposeful delay between reloads for busy servers. Defaults to `0`
# (disabled).
#
# [:strict_attributes]
@@ 110,9 110,6 @@ class Inversion::Template
require 'inversion/template/tag'
require 'inversion/renderstate'
- # Alias to maintain backward compatibility with <0.2.0 code
- Parser = Inversion::Parser
-
# Valid actions for 'on_render_error'
VALID_ERROR_ACTIONS = [
:ignore,
@@ 164,7 161,7 @@ class Inversion::Template
end
- ### Read a template object from the specified +path+.
+ ### Read a template object from the specified `path`.
def self::load( path, parsestate=nil, opts={} )
# Shift the options hash over if there isn't a parse state
@@ 209,10 206,10 @@ class Inversion::Template
end
- ### Add one or more extension +modules+ to Inversion::Template. This allows tags to decorate
+ ### Add one or more extension `modules` to Inversion::Template. This allows tags to decorate
### the template class with new functionality.
###
- ### Each one of the given +modules+ will be included as a mixin, and if it also
+ ### Each one of the given `modules` will be included as a mixin, and if it also
### contains a constant called ClassMethods and/or PrependedMethods, it will
### also be extended/prepended (respectively) with it.
###
@@ 259,7 256,7 @@ class Inversion::Template
end
- ### Create a new Inversion:Template with the given +source+.
+ ### Create a new Inversion:Template with the given `source`.
def initialize( source, parsestate=nil, opts={} )
if parsestate.is_a?( Hash )
# self.log.debug "Shifting template options: %p" % [ parsestate ]
@@ 324,7 321,7 @@ class Inversion::Template
end
- ### Returns +true+ if the template was loaded from a file and the file's mtime
+ ### Returns `true` if the template was loaded from a file and the file's mtime
### is after the time the template was created.
def changed?
return false unless file = self.source_file
@@ 407,7 404,7 @@ class Inversion::Template
end
- ### Parse the given +source+ into the template node tree.
+ ### Parse the given `source` into the template node tree.
def parse( source, parsestate=nil )
opts = self.class.config.merge( self.options )
parser = Inversion::Parser.new( self, opts )
@@ 441,7 438,7 @@ class Inversion::Template
end
- ### Add attributes for the given +node+'s identifiers.
+ ### Add attributes for the given `node`'s identifiers.
def add_attributes_from_node( node )
if node.respond_to?( :identifiers )
node.identifiers.each do |id|
@@ 452,7 449,7 @@ class Inversion::Template
end
- ### Install reader and writer methods for the attribute associated with the specified +key+.
+ ### Install reader and writer methods for the attribute associated with the specified `key`.
def install_accessors( key )
reader, writer = self.make_attribute_accessors( key )
M lib/inversion/template/attrtag.rb +7 -4
@@ 4,6 4,9 @@
require 'inversion/template' unless defined?( Inversion::Template )
require 'inversion/template/codetag'
+using Inversion::Refinements
+
+
# Inversion attribute tag.
#
# Attribute tags add an accessor to a template like 'attr_accessor' does for Ruby classes.
@@ 48,8 51,8 @@ class Inversion::Template::AttrTag < Inv
- ### Create a new AttrTag with the given +name+, which should be a valid
- ### Ruby identifier. The +linenum+ and +colnum+ should be the line and column of
+ ### Create a new AttrTag with the given `name`, which should be a valid
+ ### Ruby identifier. The `linenum` and `colnum` should be the line and column of
### the tag in the template source, if available.
def initialize( body, linenum=nil, colnum=nil )
@name = nil
@@ 78,7 81,7 @@ class Inversion::Template::AttrTag < Inv
attr_accessor :methodchain
- ### Render the tag attributes of the specified +renderstate+ and return them.
+ ### Render the tag attributes of the specified `renderstate` and return them.
def render( renderstate )
value = self.evaluate( renderstate ) # :FIXME: or return value # nil or false?
@@ 91,7 94,7 @@ class Inversion::Template::AttrTag < Inv
end
- ### Evaluate the body of the tag in the context of +renderstate+ and return the results.
+ ### Evaluate the body of the tag in the context of `renderstate` and return the results.
def evaluate( renderstate )
code = [ self.name.to_s, self.methodchain ].join( '' )
return renderstate.eval( code )
M lib/inversion/template/codetag.rb +38 -28
@@ 1,14 1,19 @@
# -*- ruby -*-
# vim: set noet nosta sw=4 ts=4 :
+require 'loggability'
+
require 'ripper'
require 'inversion/template' unless defined?( Inversion::Template )
require 'inversion/template/tag'
+using Inversion::Refinements
+
+
# The base class for Inversion tags that parse the body section of the tag using
# a Ruby parser.
#
-# It provides a +tag_pattern+ declarative method that is used to specify a pattern of
+# It provides a `tag_pattern` declarative method that is used to specify a pattern of
# tokens to match, and a block for handling tag instances that match the pattern.
#
# class Inversion::Template::MyTag < Inversion::Template::CodeTag
@@ 20,7 25,7 @@ require 'inversion/template/tag'
#
# end
#
-# The tokens in the +tag_pattern+ are Ruby token names used by the parser. If you're creating
+# The tokens in the `tag_pattern` are Ruby token names used by the parser. If you're creating
# your own tag, you can dump the tokens for a particular snippet using the 'inversion'
# command-line tool that comes with the gem:
#
@@ 35,49 40,53 @@ class Inversion::Template::CodeTag < Inv
include Inversion::AbstractClass
- ### A subclass of Ripper::TokenPattern that binds matches to the beginning and
- ### end of the matched string.
class TokenPattern < Ripper::TokenPattern
+ extend Loggability
- # the token pattern's source string
+ # Loggability API -- use Inversion's logger
+ log_to :inversion
+
+ # Expose the source attribute
attr_reader :source
- #########
- protected
- #########
- ### Compile the token pattern into a Regexp
+ ### Overloaded to generate a bound regex.
def compile( pattern )
+ self.log.debug "Compiling token pattern from: %p" % [ pattern ]
+
if m = /[^\w\s$()\[\]{}?*+\.]/.match( pattern )
- raise Ripper::TokenPattern::CompileError,
- "invalid char in pattern: #{m[0].inspect}"
+ raise Ripper::CompileError, "invalid char in pattern: #{m[0].inspect}"
end
- buf = String.new( '^' )
- pattern.scan( /(?:\w+|\$\(|[()\[\]\{\}?*+\.]+)/ ) do |tok|
+ buf = +'\\A'
+ pattern.scan(/(?:\w+|\$\(|[()\[\]\{\}?*+\.]+)/) do |tok|
case tok
when /\w/
- buf << map_token( tok )
+ buf.concat( map_token(tok) )
when '$('
- buf << '('
+ buf.concat( '(' )
when '('
- buf << '(?:'
+ buf.concat( '(?:' )
when /[?*\[\])\.]/
- buf << tok
+ buf.concat( tok )
else
- raise ScriptError, "invalid token in pattern: %p" % [ tok ]
+ raise 'must not happen'
end
end
- buf << '$'
+ buf.concat( '\z' )
- Regexp.compile( buf )
+ self.log.debug " resulting token pattern is: %p" % [ buf ]
+ return Regexp.compile( buf )
+
rescue RegexpError => err
- raise Ripper::TokenPattern::CompileError, err.message
+ raise Ripper::CompileError, err.message
end
+
end # class TokenPattern
+
#################################################################
### C L A S S M E T H O D S
#################################################################
@@ 90,10 99,10 @@ class Inversion::Template::CodeTag < Inv
end
- ### Declare a +token_pattern+ for tag bodies along with a +callback+ that will
- ### be called when a tag matching the pattern is instantiated. The +callback+ will
+ ### Declare a `token_pattern` for tag bodies along with a `callback` that will
+ ### be called when a tag matching the pattern is instantiated. The `callback` will
### be called with the tag instance, and the MatchData object that resulted from
- ### matching the input, and should set up the yielded +tag+ object appropriately.
+ ### matching the input, and should set up the yielded `tag` object appropriately.
def self::tag_pattern( token_pattern, &callback ) #:yield: tag, match_data
pattern = TokenPattern.compile( token_pattern )
@tag_patterns = [] unless defined?( @tag_patterns )
@@ 103,7 112,7 @@ class Inversion::Template::CodeTag < Inv
### Declarative that forces a tag to inherit existing patterns from
### its parent, rather than replacing them. Afterwards, you can use
- ### +tag_pattern+ regularly, appending to the list.
+ ### `tag_pattern` regularly, appending to the list.
def self::inherit_tag_patterns
raise ScriptError, "Patterns already exist for this tag." if defined?( @tag_patterns )
@tag_patterns = self.superclass.tag_patterns
@@ 114,8 123,8 @@ class Inversion::Template::CodeTag < Inv
### I N S T A N C E M E T H O D S
#################################################################
- ### Initialize a new tag that expects Ruby code in its +body+. Calls the
- ### tag's #parse_pi_body method with the specified +body+.
+ ### Initialize a new tag that expects Ruby code in its `body`. Calls the
+ ### tag's #parse_pi_body method with the specified `body`.
def initialize( body, linenum=nil, colnum=nil ) # :notnew:
super
@@ 145,12 154,13 @@ class Inversion::Template::CodeTag < Inv
protected
#########
- ### Match the given +body+ against one of the tag's tag patterns, calling the
+ ### Match the given `body` against one of the tag's tag patterns, calling the
### block associated with the first one that matches and returning the matching
### pattern.
def match_tag_pattern( body )
self.class.tag_patterns.each do |tp, callback|
+ self.log.debug "Testing for a match against %p" % [ tp ]
if match = tp.match( body.strip )
self.log.debug "Matched tag pattern: %p, match is: %p" % [ tp, match ]
callback.call( self, match )
M lib/inversion/template/configtag.rb +3 -3
@@ 31,7 31,7 @@ class Inversion::Template::ConfigTag < I
include Inversion::HashUtilities
- ### Create a new ConfigTag with the specified +body+.
+ ### Create a new ConfigTag with the specified `body`.
def initialize( body, linenum=nil, colnum=nil )
raise Inversion::ParseError, 'Empty config settings' if
body.nil? || body.strip.empty?
@@ 56,14 56,14 @@ class Inversion::Template::ConfigTag < I
attr_reader :options
- ### Override the options in the +parsestate+ when the config is appended to
+ ### Override the options in the `parsestate` when the config is appended to
### the tree.
def before_appending( parsestate )
parsestate.options.merge!( self.options )
end
- ### Override the options in the +renderstate+ when the config is rendered.
+ ### Override the options in the `renderstate` when the config is rendered.
def before_rendering( renderstate )
renderstate.options.merge!( self.options )
end
M lib/inversion/template/containertag.rb +1 -1
@@ 39,7 39,7 @@ module Inversion::Template::ContainerTag
end
- ### Append the container's subnodes to the +renderstate+.
+ ### Append the container's subnodes to the `renderstate`.
def render_subnodes( renderstate )
self.subnodes.each {|node| renderstate << node }
end
M lib/inversion/template/defaulttag.rb +1 -1
@@ 54,7 54,7 @@ class Inversion::Template::DefaultTag <
end
- ### Create a new DefaultTag with the given +name+, which should be a valid
+ ### Create a new DefaultTag with the given `name`, which should be a valid
### Ruby identifier.
def initialize( body, linenum=nil, colnum=nil )
@name = nil
M lib/inversion/template/endtag.rb +2 -2
@@ 7,7 7,7 @@ require 'inversion/template/tag'
# Closing tag class
class Inversion::Template::EndTag < Inversion::Template::Tag
- ### Overridden to provide a default +body+.
+ ### Overridden to provide a default `body`.
def initialize( body='', linenum=nil, colnum=nil )
super
@opener = nil
@@ 22,7 22,7 @@ class Inversion::Template::EndTag < Inve
attr_reader :opener
- ### Parser callback -- close the given +state+'s currently-open container node.
+ ### Parser callback -- close the given `state`'s currently-open container node.
def before_appending( state )
@opener = state.pop
self.log.debug "End tag for %s at %s" % [ @opener.tagname, @opener.location ]
M lib/inversion/template/escapetag.rb +1 -1
@@ 17,7 17,7 @@ require 'inversion/template/attrtag'
class Inversion::Template::EscapeTag < Inversion::Template::AttrTag
include Inversion::Escaping
- ### Render the method chains against the attributes of the specified +render_state+
+ ### Render the method chains against the attributes of the specified `render_state`
### and return them.
def render( render_state )
return self.escape( super, render_state )
M lib/inversion/template/fortag.rb +2 -2
@@ 58,7 58,7 @@ class Inversion::Template::ForTag < Inve
- ### Create a new ForTag with the specified +body+.
+ ### Create a new ForTag with the specified `body`.
def initialize( body, linenum=nil, colnum=nil )
@block_args = []
@enumerator = nil
@@ 79,7 79,7 @@ class Inversion::Template::ForTag < Inve
attr_accessor :enumerator
- ### Iterate over the enumerator in +state+ and render the tag's
+ ### Iterate over the enumerator in `state` and render the tag's
### contents for each iteration.
def render( state )
lvalue = state.eval( self.enumerator ) or return nil
M lib/inversion/template/fragmenttag.rb +1 -1
@@ 20,7 20,7 @@ class Inversion::Template::FragmentTag <
include Inversion::Template::ContainerTag
- ### Create a new FragmentTag with the given +body+.
+ ### Create a new FragmentTag with the given `body`.
def initialize( body, line=nil, column=nil )
super
M lib/inversion/template/iftag.rb +3 -0
@@ 6,6 6,9 @@ require 'inversion/template' unless defi
require 'inversion/template/attrtag'
require 'inversion/template/containertag'
+using Inversion::Refinements
+
+
# Inversion 'if' tag.
#
# This tag causes a section of the template to be rendered only if its methodchain or attribute
M lib/inversion/template/importtag.rb +2 -2
@@ 16,7 16,7 @@ require 'inversion/template/tag'
#
class Inversion::Template::ImportTag < Inversion::Template::Tag
- ### Create a new ImportTag with the given +name+, which should be a valid
+ ### Create a new ImportTag with the given `name`, which should be a valid
### Ruby identifier.
def initialize( body, linenum=nil, colnum=nil )
super
@@ 32,7 32,7 @@ class Inversion::Template::ImportTag < I
attr_reader :attributes
- ### Merge the inherited renderstate into the current template's +renderstate+.
+ ### Merge the inherited renderstate into the current template's `renderstate`.
def render( renderstate )
if (( cstate = renderstate.containerstate ))
# self.log.debug "Importing inherited attributes: %p from %p" %
M lib/inversion/template/includetag.rb +1 -1
@@ 19,7 19,7 @@ require 'inversion/template/tag'
#
class Inversion::Template::IncludeTag < Inversion::Template::Tag
- ### Create a new IncludeTag with the specified +path+.
+ ### Create a new IncludeTag with the specified `path`.
def initialize( path, linenum=nil, colnum=nil )
super
self.log.debug "Body is: %p" % [ @body ]
M lib/inversion/template/node.rb +4 -4
@@ 20,7 20,7 @@ class Inversion::Template::Node
log_to :inversion
- ### Create a new TextNode with the specified +source+.
+ ### Create a new TextNode with the specified `source`.
def initialize( body, linenum=nil, colnum=nil )
@body = body
@linenum = linenum
@@ 39,8 39,8 @@ class Inversion::Template::Node
attr_reader :colnum
- ### Render the node using the given +render_state+. By default, rendering a node
- ### returns +nil+.
+ ### Render the node using the given `render_state`. By default, rendering a node
+ ### returns `nil`.
def render( render_state )
return nil
end
@@ 52,7 52,7 @@ class Inversion::Template::Node
end
- ### Returns +true+ if the node introduces a new parsing/rendering scope.
+ ### Returns `true` if the node introduces a new parsing/rendering scope.
def is_container?
return false
end
M lib/inversion/template/pptag.rb +1 -1
@@ 16,7 16,7 @@ require 'inversion/template/calltag'
class Inversion::Template::PpTag < Inversion::Template::CallTag
include Inversion::Escaping
- ### Render the method chains against the attributes of the specified +render_state+
+ ### Render the method chains against the attributes of the specified `render_state`
### and return them.
def render( render_state )
raw = super
M lib/inversion/template/publishtag.rb +2 -2
@@ 30,7 30,7 @@ class Inversion::Template::PublishTag <
include Inversion::Template::ContainerTag
- ### Create a new PublishTag with the given +body+.
+ ### Create a new PublishTag with the given `body`.
def initialize( body, line=nil, column=nil )
super
@@ 49,7 49,7 @@ class Inversion::Template::PublishTag <
attr_reader :key
- ### Render the published subnodes in the context of the given +renderstate+, but
+ ### Render the published subnodes in the context of the given `renderstate`, but
### save them for publication after the render is done.
def render( renderstate )
self.log.debug "Publishing %d nodes as %s" % [ self.subnodes.length, self.key ]
M lib/inversion/template/rescuetag.rb +1 -1
@@ 71,7 71,7 @@ class Inversion::Template::RescueTag < I
private
#######
- ### Parse one or more exception classes from the given +rescuespec+ and return them.
+ ### Parse one or more exception classes from the given `rescuespec` and return them.
def parse_exception_types( rescuespec )
return [ ::RuntimeError ] if rescuespec.nil? || rescuespec == ''
M lib/inversion/template/subscribetag.rb +3 -3
@@ 28,7 28,7 @@ require 'inversion/template/tag'
#
class Inversion::Template::SubscribeTag < Inversion::Template::Tag
- ### Create a new SubscribeTag with the given +body+.
+ ### Create a new SubscribeTag with the given `body`.
def initialize( body, line=nil, column=nil )
super
@@ 59,7 59,7 @@ class Inversion::Template::SubscribeTag
attr_reader :content
- ### Tell the +renderstate+ that this tag is interested in nodes that are published with
+ ### Tell the `renderstate` that this tag is interested in nodes that are published with
### its key.
def before_rendering( renderstate )
@content.clear
@@ 73,7 73,7 @@ class Inversion::Template::SubscribeTag
end
- ### Pub/sub callback. Called from the RenderState when a PublishTag publishes +nodes+
+ ### Pub/sub callback. Called from the RenderState when a PublishTag publishes `nodes`
### with the same key as the current tag.
def publish( *nodes )
self.log.debug "Adding published nodes %p to %p" % [ nodes, @content ]
M lib/inversion/template/tag.rb +3 -3
@@ 104,7 104,7 @@ class Inversion::Template::Tag < Inversi
end
- ### Safely load the specified +tagfile+.
+ ### Safely load the specified `tagfile`.
def self::load( tagfile )
tagrequire = tagfile[ %r{inversion/template/\w+tag} ] or
raise "tag file %p doesn't look like a tag plugin" % [ tagfile ]
@@ 117,7 117,7 @@ class Inversion::Template::Tag < Inversi
end
- ### Create a new Inversion::Template::Tag from the specified +tagname+ and +body+.
+ ### Create a new Inversion::Template::Tag from the specified `tagname` and `body`.
def self::create( tagname, body, linenum=nil, colnum=nil )
tagname =~ /^(\w+)$/i or raise ArgumentError, "invalid tag name %p" % [ tagname ]
tagtype = $1.downcase
@@ 136,7 136,7 @@ class Inversion::Template::Tag < Inversi
### I N S T A N C E M E T H O D S
########################################################################
- ### Create a new Inversion::Template::Tag with the specified +body+.
+ ### Create a new Inversion::Template::Tag with the specified `body`.
def initialize( body, linenum=nil, colnum=nil )
super
@body = body.to_s.strip
M lib/inversion/template/textnode.rb +1 -1
@@ 7,7 7,7 @@ require 'inversion/template/node'
# Inversion text node class -- container for static content in templates between tags.
class Inversion::Template::TextNode < Inversion::Template::Node
- ### Create a new TextNode with the specified +source+.
+ ### Create a new TextNode with the specified `source`.
def initialize( body, linenum=nil, colnum=nil )
@body = body
super
M lib/inversion/template/timedeltatag.rb +1 -1
@@ 73,7 73,7 @@ class Inversion::Template::TimeDeltaTag
private
#######
- ### Return a string describing +seconds+ as an approximate interval of time.
+ ### Return a string describing `seconds` as an approximate interval of time.
def timeperiod( seconds )
return case
when seconds < MINUTES - 5
M lib/inversion/template/uriencodetag.rb +1 -1
@@ 18,7 18,7 @@ class Inversion::Template::UriencodeTag
include Inversion::Escaping
- ### Render the method chains against the attributes of the specified +render_state+
+ ### Render the method chains against the attributes of the specified `render_state`
### and return them.
def render( render_state )
raw = super
M lib/inversion/tilt.rb +1 -1
@@ 35,7 35,7 @@ if defined?( ::Tilt )
self.evaluate( *args )
end
- ### Tilt::Template API: render the template with the given +scope+, +locals+, and +block+.
+ ### Tilt::Template API: render the template with the given `scope`, `locals`, and `block`.
def evaluate( scope, locals, &block )
@template.attributes.merge!( scope.to_h ) if scope.respond_to?( :to_h )
@template.attributes.merge!( locals )
M spec/helpers.rb +4 -4
@@ 11,7 11,7 @@ require 'loggability/spechelpers'
require 'inversion'
-Inversion::Template::Tag.load_all
+# Inversion::Template::Tag.load_all
### RSpec helper functions.
@@ 21,14 21,14 @@ module Inversion::SpecHelpers
module_function
###############
- ### Make an easily-comparable version vector out of +ver+ and return it.
+ ### Make an easily-comparable version vector out of `ver` and return it.
def vvec( ver )
return ver.split('.').collect {|char| char.to_i }.pack('N*')
end
- ### Create a string containing an XML Processing Instruction with the given +name+
- ### and +data+.
+ ### Create a string containing an XML Processing Instruction with the given `name`
+ ### and `data`.
def create_pi( name, data )
return "<?#{name} #{data} ?>"
end