papercraft 2.23 → 3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +16 -0
 - data/README.md +15 -587
 - data/lib/papercraft/compiler.rb +33 -13
 - data/lib/papercraft/proc_ext.rb +12 -97
 - data/lib/papercraft/template.rb +19 -6
 - data/lib/papercraft/version.rb +1 -1
 - data/lib/papercraft.rb +127 -1
 - metadata +3 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: ac74fb8004af29f1b15e8ca36de8039d3e47c6642105032fa1a51ec46bda100a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 2b5fcf6bc6d472c33033381577b62e0875594a56e3a8f9f1d769b64d4a6ec2ce
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 390c81c371d17216134e931b26e1d6c9728c54e2c8db220b0d21761f9ed7d21b12f784b5642e7473e55c1f65f2bad4fe07f9afa09d78c04b7d54569ed7cc5ebf
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 9801c61a0a9788a563396bed4064b0b0f4aeacb82e43677c52bfc83ed1d25d7b001af4915c3bdb86b6191b1f5681bd1b54460fbaaa626bfde32e471cb12a830f
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,3 +1,19 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # 3.0.0 2025-10-19
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            - Improve implementation of `Papercraft.apply`
         
     | 
| 
      
 4 
     | 
    
         
            +
            - Add support for rendering self-closing XML tags
         
     | 
| 
      
 5 
     | 
    
         
            +
            - Streamline Papercraft API
         
     | 
| 
      
 6 
     | 
    
         
            +
            - Add support for `Papercraft.render { ... }`
         
     | 
| 
      
 7 
     | 
    
         
            +
            - Prefix internal Proc extensions with `__papercraft_`
         
     | 
| 
      
 8 
     | 
    
         
            +
            - Change API to use `Papercraft.html` instead of `Proc#render`. Same for
         
     | 
| 
      
 9 
     | 
    
         
            +
              `apple`, `render_xml` etc.
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
            # 2.24 2025-10-14
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            - Update gem links
         
     | 
| 
      
 14 
     | 
    
         
            +
            - Simplify `render_cache`, caller must provide cache key
         
     | 
| 
      
 15 
     | 
    
         
            +
            - Reduce surface area of Proc extensions
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
       1 
17 
     | 
    
         
             
            # 2.23 2025-10-12
         
     | 
| 
       2 
18 
     | 
    
         | 
| 
       3 
19 
     | 
    
         
             
            - Update ERB to version 5.1.1
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -18,603 +18,31 @@ 
     | 
|
| 
       18 
18 
     | 
    
         
             
              </a>
         
     | 
| 
       19 
19 
     | 
    
         
             
            </p>
         
     | 
| 
       20 
20 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
            <p align="center">
         
     | 
| 
       22 
     | 
    
         
            -
              <a href="https://www.rubydoc.info/gems/papercraft">API reference</a>
         
     | 
| 
       23 
     | 
    
         
            -
            </p>
         
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
            ## What is Papercraft?
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
21 
     | 
    
         
             
            ```ruby
         
     | 
| 
       28 
22 
     | 
    
         
             
            require 'papercraft'
         
     | 
| 
       29 
23 
     | 
    
         | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
               
     | 
| 
       32 
     | 
    
         
            -
                 
     | 
| 
       33 
     | 
    
         
            -
                body { render_children **props }
         
     | 
| 
      
 24 
     | 
    
         
            +
            Papercraft.html {
         
     | 
| 
      
 25 
     | 
    
         
            +
              div {
         
     | 
| 
      
 26 
     | 
    
         
            +
                h1 "Hello from Papercraft!"
         
     | 
| 
       34 
27 
     | 
    
         
             
              }
         
     | 
| 
       35 
28 
     | 
    
         
             
            }
         
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
              p 'foo'
         
     | 
| 
       38 
     | 
    
         
            -
            }
         
     | 
| 
       39 
     | 
    
         
            -
            #=> "<html><head><title>Title</title></head><body><p>foo</p></body></html>"
         
     | 
| 
      
 29 
     | 
    
         
            +
            #=> "<div><h1>Hello from Papercraft</h1></div>"
         
     | 
| 
       40 
30 
     | 
    
         
             
            ```
         
     | 
| 
       41 
31 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
            Papercraft is a templating engine for dynamically producing HTML in Ruby apps. 
     | 
| 
       43 
     | 
    
         
            -
            templates are expressed as Ruby procs, leading to easier debugging, 
     | 
| 
       44 
     | 
    
         
            -
            protection against HTML injection attacks, and better code reuse.
         
     | 
| 
      
 32 
     | 
    
         
            +
            Papercraft is a templating engine for dynamically producing HTML in Ruby apps.
         
     | 
| 
      
 33 
     | 
    
         
            +
            Papercraft templates are expressed as Ruby procs, leading to easier debugging,
         
     | 
| 
      
 34 
     | 
    
         
            +
            better protection against HTML injection attacks, and better code reuse.
         
     | 
| 
       45 
35 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
            Papercraft templates can be composed in a variety of ways, facilitating the 
     | 
| 
       47 
     | 
    
         
            -
            layout templates, and enabling a component-oriented approach to 
     | 
| 
       48 
     | 
    
         
            -
            interfaces of arbitrary complexity.
         
     | 
| 
      
 36 
     | 
    
         
            +
            Papercraft templates can be composed in a variety of ways, facilitating the
         
     | 
| 
      
 37 
     | 
    
         
            +
            usage of layout templates, and enabling a component-oriented approach to
         
     | 
| 
      
 38 
     | 
    
         
            +
            building web interfaces of arbitrary complexity.
         
     | 
| 
       49 
39 
     | 
    
         | 
| 
       50 
40 
     | 
    
         
             
            In Papercraft, dynamic data is passed explicitly to the template as block/lambda
         
     | 
| 
       51 
     | 
    
         
            -
            arguments, making the data flow easy to follow and understand. Papercraft also 
     | 
| 
       52 
     | 
    
         
            -
            developers create derivative templates using full or partial parameter
         
     | 
| 
      
 41 
     | 
    
         
            +
            arguments, making the data flow easy to follow and understand. Papercraft also
         
     | 
| 
      
 42 
     | 
    
         
            +
            lets developers create derivative templates using full or partial parameter
         
     | 
| 
       53 
43 
     | 
    
         
             
            application.
         
     | 
| 
       54 
44 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
            require 'papercraft'
         
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
            page = ->(**props) {
         
     | 
| 
       59 
     | 
    
         
            -
              html {
         
     | 
| 
       60 
     | 
    
         
            -
                head { title 'My Title' }
         
     | 
| 
       61 
     | 
    
         
            -
                body { render_children **props }
         
     | 
| 
       62 
     | 
    
         
            -
              }
         
     | 
| 
       63 
     | 
    
         
            -
            }
         
     | 
| 
       64 
     | 
    
         
            -
            page.render {
         
     | 
| 
       65 
     | 
    
         
            -
              p(class: 'big') 'foo'
         
     | 
| 
       66 
     | 
    
         
            -
            }
         
     | 
| 
       67 
     | 
    
         
            -
            #=> "<html><head><title>Title</title></head><body><p class="big">foo</p></body></html>"
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
            hello_page = page.apply ->(name:, **) {
         
     | 
| 
       70 
     | 
    
         
            -
              h1 "Hello, #{name}!"
         
     | 
| 
       71 
     | 
    
         
            -
            }
         
     | 
| 
       72 
     | 
    
         
            -
            hello.render(name: 'world')
         
     | 
| 
       73 
     | 
    
         
            -
            #=> "<html><head><title>Title</title></head><body><h1>Hello, world!</h1></body></html>"
         
     | 
| 
       74 
     | 
    
         
            -
            ```
         
     | 
| 
       75 
     | 
    
         
            -
             
     | 
| 
       76 
     | 
    
         
            -
            Papercraft features:
         
     | 
| 
       77 
     | 
    
         
            -
             
     | 
| 
       78 
     | 
    
         
            -
            - Express HTML using plain Ruby procs.
         
     | 
| 
       79 
     | 
    
         
            -
            - Automatic compilation for super-fast execution (about as
         
     | 
| 
       80 
     | 
    
         
            -
              [fast](https://github.com/digital-fabric/papercraft/blob/master/examples/perf.rb) as
         
     | 
| 
       81 
     | 
    
         
            -
              compiled ERB/ERubi).
         
     | 
| 
       82 
     | 
    
         
            -
            - Deferred rendering using `defer`.
         
     | 
| 
       83 
     | 
    
         
            -
            - Simple and easy template composition (for uses such as layouts, or modular
         
     | 
| 
       84 
     | 
    
         
            -
              templates).
         
     | 
| 
       85 
     | 
    
         
            -
            - Markdown rendering using [Kramdown](https://github.com/gettalong/kramdown/).
         
     | 
| 
       86 
     | 
    
         
            -
            - Rudimentary support for generating XML.
         
     | 
| 
       87 
     | 
    
         
            -
            - Support for extensions.
         
     | 
| 
       88 
     | 
    
         
            -
            - Simple caching API for caching the rendering result.
         
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
            ## Table of Content
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
            - [Getting Started](#getting-started)
         
     | 
| 
       93 
     | 
    
         
            -
            - [Basic Markup](#basic-markup)
         
     | 
| 
       94 
     | 
    
         
            -
            - [Builtin Methods](#builtin-methods)
         
     | 
| 
       95 
     | 
    
         
            -
            - [Template Parameters](#template-parameters)
         
     | 
| 
       96 
     | 
    
         
            -
            - [Template Logic](#template-logic)
         
     | 
| 
       97 
     | 
    
         
            -
            - [Template Blocks](#template-blocks)
         
     | 
| 
       98 
     | 
    
         
            -
            - [Template Composition](#template-composition)
         
     | 
| 
       99 
     | 
    
         
            -
            - [Parameter and Block Application](#parameter-and-block-application)
         
     | 
| 
       100 
     | 
    
         
            -
            - [Higher-Order Templates](#higher-order-templates)
         
     | 
| 
       101 
     | 
    
         
            -
            - [Layout Template Composition](#layout-template-composition)
         
     | 
| 
       102 
     | 
    
         
            -
            - [Rendering Markdown](#rendering-markdown)
         
     | 
| 
       103 
     | 
    
         
            -
            - [Deferred Evaluation](#deferred-evaluation)
         
     | 
| 
       104 
     | 
    
         
            -
            - [Cached Rendering](#cached-rendering)
         
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
            A typical example for a dashboard-type app markup can be found here:
         
     | 
| 
       107 
     | 
    
         
            -
            https://github.com/digital-fabric/papercraft/blob/master/examples/dashboard.rb
         
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
            ## Getting Started
         
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
            In Papercraft, an HTML template is expressed as a proc:
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       114 
     | 
    
         
            -
            html = -> {
         
     | 
| 
       115 
     | 
    
         
            -
              div(id: 'greeter') { p 'Hello!' }
         
     | 
| 
       116 
     | 
    
         
            -
            }
         
     | 
| 
       117 
     | 
    
         
            -
            ```
         
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
            Rendering a template is done using `Proc#render`:
         
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       122 
     | 
    
         
            -
            require 'papercraft'
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
            html.render #=> "<div id="greeter"><p>Hello!</p></div>"
         
     | 
| 
       125 
     | 
    
         
            -
            ```
         
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
            ## Basic Markup
         
     | 
| 
       128 
     | 
    
         
            -
             
     | 
| 
       129 
     | 
    
         
            -
            Tags are added using unqualified method calls, and can be nested using blocks:
         
     | 
| 
       130 
     | 
    
         
            -
             
     | 
| 
       131 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       132 
     | 
    
         
            -
            -> {
         
     | 
| 
       133 
     | 
    
         
            -
              html {
         
     | 
| 
       134 
     | 
    
         
            -
                head {
         
     | 
| 
       135 
     | 
    
         
            -
                  title 'page title'
         
     | 
| 
       136 
     | 
    
         
            -
                }
         
     | 
| 
       137 
     | 
    
         
            -
                body {
         
     | 
| 
       138 
     | 
    
         
            -
                  article {
         
     | 
| 
       139 
     | 
    
         
            -
                    h1 'article title'
         
     | 
| 
       140 
     | 
    
         
            -
                  }
         
     | 
| 
       141 
     | 
    
         
            -
                }
         
     | 
| 
       142 
     | 
    
         
            -
              }
         
     | 
| 
       143 
     | 
    
         
            -
            }
         
     | 
| 
       144 
     | 
    
         
            -
            ```
         
     | 
| 
       145 
     | 
    
         
            -
             
     | 
| 
       146 
     | 
    
         
            -
            Tag methods accept a string argument, a block, or no argument at all:
         
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       149 
     | 
    
         
            -
            -> { p 'hello' }.render #=> "<p>hello</p>"
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
            -> { p { span '1'; span '2' } }.render #=> "<p><span>1</span><span>2</span></p>"
         
     | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
            -> { hr() }.render #=> "<hr/>"
         
     | 
| 
       154 
     | 
    
         
            -
            ```
         
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
            Tag methods also accept tag attributes, given as a hash:
         
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       159 
     | 
    
         
            -
            -> { img src: '/my.gif' }.render #=> "<img src=\"/my.gif\"/>"
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
            -> { p "foobar", class: 'important' }.render #=> "<p class=\"important\">foobar</p>"
         
     | 
| 
       162 
     | 
    
         
            -
            ```
         
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
            A `true` attribute value will emit a valueless attribute. A `nil` or `false`
         
     | 
| 
       165 
     | 
    
         
            -
            attribute value will emit nothing:
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       168 
     | 
    
         
            -
            -> { button disabled: nil }.render #=> "<button></button>"
         
     | 
| 
       169 
     | 
    
         
            -
            -> { button disabled: true }.render #=> "<button disabled></button>"
         
     | 
| 
       170 
     | 
    
         
            -
            ```
         
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
            An attribute value given as an array will be joined by space characters:
         
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       175 
     | 
    
         
            -
            -> { div class: [:foo, :bar] }.render #=> "<div class=\"foo bar\"></div>"
         
     | 
| 
       176 
     | 
    
         
            -
            ```
         
     | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
            ### Tag and Attribute Formatting
         
     | 
| 
       179 
     | 
    
         
            -
             
     | 
| 
       180 
     | 
    
         
            -
            Papercraft does not make any assumption about what tags and attributes you can use. You
         
     | 
| 
       181 
     | 
    
         
            -
            can mix upper and lower case letters, and you can include arbitrary characters
         
     | 
| 
       182 
     | 
    
         
            -
            in tag and attribute names. However, in order to best adhere to the HTML specs
         
     | 
| 
       183 
     | 
    
         
            -
            and common practices, tag names and attributes will be formatted according to
         
     | 
| 
       184 
     | 
    
         
            -
            the following rules, depending on the template type:
         
     | 
| 
       185 
     | 
    
         
            -
             
     | 
| 
       186 
     | 
    
         
            -
            - HTML: underscores are converted to dashes:
         
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
              ```ruby
         
     | 
| 
       189 
     | 
    
         
            -
              -> {
         
     | 
| 
       190 
     | 
    
         
            -
                foo_bar { p 'Hello', data_name: 'world' }
         
     | 
| 
       191 
     | 
    
         
            -
              }.render #=> '<foo-bar><p data-name="world">Hello</p></foo-bar>'
         
     | 
| 
       192 
     | 
    
         
            -
              ```
         
     | 
| 
      
 45 
     | 
    
         
            +
            ## Documentation
         
     | 
| 
       193 
46 
     | 
    
         | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
             
     | 
| 
       196 
     | 
    
         
            -
            normally used for tags:
         
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       199 
     | 
    
         
            -
            -> {
         
     | 
| 
       200 
     | 
    
         
            -
              tag 'cra_zy__:!tag', 'foo'
         
     | 
| 
       201 
     | 
    
         
            -
            }.render #=> '<cra_zy__:!tag>foo</cra_zy__:!tag>'
         
     | 
| 
       202 
     | 
    
         
            -
            ```
         
     | 
| 
       203 
     | 
    
         
            -
             
     | 
| 
       204 
     | 
    
         
            -
            ### Escaping Content
         
     | 
| 
       205 
     | 
    
         
            -
             
     | 
| 
       206 
     | 
    
         
            -
            Papercraft automatically escapes all text content emitted in a template. The specific
         
     | 
| 
       207 
     | 
    
         
            -
            escaping algorithm depends on the template type. To emit raw HTML, use the
         
     | 
| 
       208 
     | 
    
         
            -
            `#raw` method as [described below](#builtin-methods).
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
            ## Builtin Methods
         
     | 
| 
       211 
     | 
    
         
            -
             
     | 
| 
       212 
     | 
    
         
            -
            In addition to normal tags, Papercraft provides the following method calls for templates:
         
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
       214 
     | 
    
         
            -
            ### `#text` - emit escaped text
         
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
            `#text` is used for emitting text that will be escaped. This method can be used
         
     | 
| 
       217 
     | 
    
         
            -
            to emit text not directly inside an enclosing tag:
         
     | 
| 
       218 
     | 
    
         
            -
             
     | 
| 
       219 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       220 
     | 
    
         
            -
            -> {
         
     | 
| 
       221 
     | 
    
         
            -
              p {
         
     | 
| 
       222 
     | 
    
         
            -
                text 'The time is: '
         
     | 
| 
       223 
     | 
    
         
            -
                span(Time.now, id: 'clock')
         
     | 
| 
       224 
     | 
    
         
            -
              }
         
     | 
| 
       225 
     | 
    
         
            -
            }.render #=> <p>The time is: <span id="clock">XX:XX:XX</span></p>
         
     | 
| 
       226 
     | 
    
         
            -
            ```
         
     | 
| 
       227 
     | 
    
         
            -
             
     | 
| 
       228 
     | 
    
         
            -
            ### `#raw` - emit raw HTML
         
     | 
| 
       229 
     | 
    
         
            -
             
     | 
| 
       230 
     | 
    
         
            -
            `#raw` is used for emitting raw HTML, i.e. without escaping. You can use this to
         
     | 
| 
       231 
     | 
    
         
            -
            emit an HTML snippet:
         
     | 
| 
       232 
     | 
    
         
            -
             
     | 
| 
       233 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       234 
     | 
    
         
            -
            TITLE_HTML = '<h1>hi</h1>'
         
     | 
| 
       235 
     | 
    
         
            -
            -> {
         
     | 
| 
       236 
     | 
    
         
            -
              div {
         
     | 
| 
       237 
     | 
    
         
            -
                raw TITLE_HTML
         
     | 
| 
       238 
     | 
    
         
            -
              }
         
     | 
| 
       239 
     | 
    
         
            -
            }.render #=> <div><h1>hi</h1></div>
         
     | 
| 
       240 
     | 
    
         
            -
            ```
         
     | 
| 
       241 
     | 
    
         
            -
             
     | 
| 
       242 
     | 
    
         
            -
            ### `#render_children` - render the given block
         
     | 
| 
       243 
     | 
    
         
            -
             
     | 
| 
       244 
     | 
    
         
            -
            `#render_children` is used to emit a given block. If no block is given, a
         
     | 
| 
       245 
     | 
    
         
            -
            `LocalJumpError` exception is raised:
         
     | 
| 
       246 
     | 
    
         
            -
             
     | 
| 
       247 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       248 
     | 
    
         
            -
            Card = ->(**props) {
         
     | 
| 
       249 
     | 
    
         
            -
              card { render_children(**props) }
         
     | 
| 
       250 
     | 
    
         
            -
            }
         
     | 
| 
       251 
     | 
    
         
            -
             
     | 
| 
       252 
     | 
    
         
            -
            Card.render(foo: 'bar') { |foo|
         
     | 
| 
       253 
     | 
    
         
            -
              h1 foo
         
     | 
| 
       254 
     | 
    
         
            -
            } #=> <card><h1>bar</h1></card>
         
     | 
| 
       255 
     | 
    
         
            -
            ```
         
     | 
| 
       256 
     | 
    
         
            -
             
     | 
| 
       257 
     | 
    
         
            -
            `render_children` can be called with or without arguments, which are passed to the
         
     | 
| 
       258 
     | 
    
         
            -
            given block.
         
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
       260 
     | 
    
         
            -
            ### `#defer` - emit deferred HTML
         
     | 
| 
       261 
     | 
    
         
            -
             
     | 
| 
       262 
     | 
    
         
            -
            `#defer` is used to emit HTML in a deferred fashion - the deferred part will be
         
     | 
| 
       263 
     | 
    
         
            -
            evaluated only after processing the entire template:
         
     | 
| 
       264 
     | 
    
         
            -
             
     | 
| 
       265 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       266 
     | 
    
         
            -
            Layout = -> {
         
     | 
| 
       267 
     | 
    
         
            -
              head {
         
     | 
| 
       268 
     | 
    
         
            -
                defer {
         
     | 
| 
       269 
     | 
    
         
            -
                  title @title
         
     | 
| 
       270 
     | 
    
         
            -
                }
         
     | 
| 
       271 
     | 
    
         
            -
              }
         
     | 
| 
       272 
     | 
    
         
            -
              body {
         
     | 
| 
       273 
     | 
    
         
            -
                render_children
         
     | 
| 
       274 
     | 
    
         
            -
              }
         
     | 
| 
       275 
     | 
    
         
            -
            }
         
     | 
| 
       276 
     | 
    
         
            -
             
     | 
| 
       277 
     | 
    
         
            -
            Layout.render {
         
     | 
| 
       278 
     | 
    
         
            -
              @title = 'Foobar'
         
     | 
| 
       279 
     | 
    
         
            -
              h1 'hi'
         
     | 
| 
       280 
     | 
    
         
            -
            } #=> <head><title>Foobar</title></head><body><h1>hi</h1></body>
         
     | 
| 
       281 
     | 
    
         
            -
            ```
         
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
            ### `#render` - render the given template inline
         
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
       285 
     | 
    
         
            -
            `#render` is used to emit the given template. This can be used to compose
         
     | 
| 
       286 
     | 
    
         
            -
            templates:
         
     | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
       288 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       289 
     | 
    
         
            -
            partial = -> { p 'foo' }
         
     | 
| 
       290 
     | 
    
         
            -
            -> {
         
     | 
| 
       291 
     | 
    
         
            -
              div {
         
     | 
| 
       292 
     | 
    
         
            -
                render partial
         
     | 
| 
       293 
     | 
    
         
            -
              }
         
     | 
| 
       294 
     | 
    
         
            -
            }.render #=> <div><p>foo</p></div>
         
     | 
| 
       295 
     | 
    
         
            -
            ```
         
     | 
| 
       296 
     | 
    
         
            -
             
     | 
| 
       297 
     | 
    
         
            -
            Any argument following the given template is passed to the template for
         
     | 
| 
       298 
     | 
    
         
            -
            rendering:
         
     | 
| 
       299 
     | 
    
         
            -
             
     | 
| 
       300 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       301 
     | 
    
         
            -
            large_button = ->(title) { button(title, class: 'large') }
         
     | 
| 
       302 
     | 
    
         
            -
             
     | 
| 
       303 
     | 
    
         
            -
            -> {
         
     | 
| 
       304 
     | 
    
         
            -
              render large_button, 'foo'
         
     | 
| 
       305 
     | 
    
         
            -
            }.render #=> <button class="large">foo</button>
         
     | 
| 
       306 
     | 
    
         
            -
            ```
         
     | 
| 
       307 
     | 
    
         
            -
             
     | 
| 
       308 
     | 
    
         
            -
            ### `#html`/`#html5` - emit an HTML5 document type declaration and html tag
         
     | 
| 
       309 
     | 
    
         
            -
             
     | 
| 
       310 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       311 
     | 
    
         
            -
            -> {
         
     | 
| 
       312 
     | 
    
         
            -
              html5 {
         
     | 
| 
       313 
     | 
    
         
            -
                p 'hi'
         
     | 
| 
       314 
     | 
    
         
            -
              }
         
     | 
| 
       315 
     | 
    
         
            -
            } #=> <!DOCTYPE html><html><p>hi</p></html>
         
     | 
| 
       316 
     | 
    
         
            -
            ```
         
     | 
| 
       317 
     | 
    
         
            -
             
     | 
| 
       318 
     | 
    
         
            -
            ### `#markdown` emit markdown content
         
     | 
| 
       319 
     | 
    
         
            -
             
     | 
| 
       320 
     | 
    
         
            -
            `#markdown` is used for rendering markdown content. The call converts the given
         
     | 
| 
       321 
     | 
    
         
            -
            markdown to HTML and emits it into the rendered HTML:
         
     | 
| 
       322 
     | 
    
         
            -
             
     | 
| 
       323 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       324 
     | 
    
         
            -
            -> {
         
     | 
| 
       325 
     | 
    
         
            -
              div {
         
     | 
| 
       326 
     | 
    
         
            -
                markdown 'This is *markdown*'
         
     | 
| 
       327 
     | 
    
         
            -
              }
         
     | 
| 
       328 
     | 
    
         
            -
            }.render #=> <p>This is <em>markdown</em></p>
         
     | 
| 
       329 
     | 
    
         
            -
            ```
         
     | 
| 
       330 
     | 
    
         
            -
             
     | 
| 
       331 
     | 
    
         
            -
            ## Template Parameters
         
     | 
| 
       332 
     | 
    
         
            -
             
     | 
| 
       333 
     | 
    
         
            -
            In Papercraft, parameters are always passed explicitly. This means that template
         
     | 
| 
       334 
     | 
    
         
            -
            parameters are specified as block parameters, and are passed to the template on
         
     | 
| 
       335 
     | 
    
         
            -
            rendering:
         
     | 
| 
       336 
     | 
    
         
            -
             
     | 
| 
       337 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       338 
     | 
    
         
            -
            greeting = ->(name) { h1 "Hello, #{name}!" }
         
     | 
| 
       339 
     | 
    
         
            -
            greeting.render('world') #=> "<h1>Hello, world!</h1>"
         
     | 
| 
       340 
     | 
    
         
            -
            ```
         
     | 
| 
       341 
     | 
    
         
            -
             
     | 
| 
       342 
     | 
    
         
            -
            Templates can also accept named parameters:
         
     | 
| 
       343 
     | 
    
         
            -
             
     | 
| 
       344 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       345 
     | 
    
         
            -
            greeting = ->(name:) { h1 "Hello, #{name}!" }
         
     | 
| 
       346 
     | 
    
         
            -
            greeting.render(name: 'world') #=> "<h1>Hello, world!</h1>"
         
     | 
| 
       347 
     | 
    
         
            -
            ```
         
     | 
| 
       348 
     | 
    
         
            -
             
     | 
| 
       349 
     | 
    
         
            -
            ## Template Logic
         
     | 
| 
       350 
     | 
    
         
            -
             
     | 
| 
       351 
     | 
    
         
            -
            Since Papercraft templates are just a bunch of Ruby, you can easily embed your view
         
     | 
| 
       352 
     | 
    
         
            -
            logic right in the template:
         
     | 
| 
       353 
     | 
    
         
            -
             
     | 
| 
       354 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       355 
     | 
    
         
            -
            ->(user = nil) {
         
     | 
| 
       356 
     | 
    
         
            -
              if user
         
     | 
| 
       357 
     | 
    
         
            -
                span "Hello, #{user.name}!"
         
     | 
| 
       358 
     | 
    
         
            -
              else
         
     | 
| 
       359 
     | 
    
         
            -
                span "Hello, guest!"
         
     | 
| 
       360 
     | 
    
         
            -
              end
         
     | 
| 
       361 
     | 
    
         
            -
            }
         
     | 
| 
       362 
     | 
    
         
            -
            ```
         
     | 
| 
       363 
     | 
    
         
            -
             
     | 
| 
       364 
     | 
    
         
            -
            ## Template Blocks
         
     | 
| 
       365 
     | 
    
         
            -
             
     | 
| 
       366 
     | 
    
         
            -
            Templates can also accept and render blocks by using `render_children`:
         
     | 
| 
       367 
     | 
    
         
            -
             
     | 
| 
       368 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       369 
     | 
    
         
            -
            page = -> {
         
     | 
| 
       370 
     | 
    
         
            -
              html {
         
     | 
| 
       371 
     | 
    
         
            -
                body { render_children }
         
     | 
| 
       372 
     | 
    
         
            -
              }
         
     | 
| 
       373 
     | 
    
         
            -
            }
         
     | 
| 
       374 
     | 
    
         
            -
             
     | 
| 
       375 
     | 
    
         
            -
            # we pass the inner HTML
         
     | 
| 
       376 
     | 
    
         
            -
            page.render { h1 'hi' }
         
     | 
| 
       377 
     | 
    
         
            -
            ```
         
     | 
| 
       378 
     | 
    
         
            -
             
     | 
| 
       379 
     | 
    
         
            -
            ## Template Composition
         
     | 
| 
       380 
     | 
    
         
            -
             
     | 
| 
       381 
     | 
    
         
            -
            Papercraft makes it easy to compose multiple templates into a whole HTML document. A Papercraft
         
     | 
| 
       382 
     | 
    
         
            -
            template can contain other templates, as the following example shows.
         
     | 
| 
       383 
     | 
    
         
            -
             
     | 
| 
       384 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       385 
     | 
    
         
            -
            Title = ->(title) { h1 title }
         
     | 
| 
       386 
     | 
    
         
            -
             
     | 
| 
       387 
     | 
    
         
            -
            Item = ->(id:, text:, checked:) {
         
     | 
| 
       388 
     | 
    
         
            -
              li {
         
     | 
| 
       389 
     | 
    
         
            -
                input name: id, type: 'checkbox', checked: checked
         
     | 
| 
       390 
     | 
    
         
            -
                label text, for: id
         
     | 
| 
       391 
     | 
    
         
            -
              }
         
     | 
| 
       392 
     | 
    
         
            -
            }
         
     | 
| 
       393 
     | 
    
         
            -
             
     | 
| 
       394 
     | 
    
         
            -
            ItemList = ->(items) {
         
     | 
| 
       395 
     | 
    
         
            -
              ul {
         
     | 
| 
       396 
     | 
    
         
            -
                items.each { |i|
         
     | 
| 
       397 
     | 
    
         
            -
                  Item(**i)
         
     | 
| 
       398 
     | 
    
         
            -
                }
         
     | 
| 
       399 
     | 
    
         
            -
              }
         
     | 
| 
       400 
     | 
    
         
            -
            }
         
     | 
| 
       401 
     | 
    
         
            -
             
     | 
| 
       402 
     | 
    
         
            -
            page = ->(title, items) {
         
     | 
| 
       403 
     | 
    
         
            -
              html5 {
         
     | 
| 
       404 
     | 
    
         
            -
                head { Title(title) }
         
     | 
| 
       405 
     | 
    
         
            -
                body { ItemList(items) }
         
     | 
| 
       406 
     | 
    
         
            -
              }
         
     | 
| 
       407 
     | 
    
         
            -
            }
         
     | 
| 
       408 
     | 
    
         
            -
             
     | 
| 
       409 
     | 
    
         
            -
            page.render('Hello from composed templates', [
         
     | 
| 
       410 
     | 
    
         
            -
              { id: 1, text: 'foo', checked: false },
         
     | 
| 
       411 
     | 
    
         
            -
              { id: 2, text: 'bar', checked: true }
         
     | 
| 
       412 
     | 
    
         
            -
            ])
         
     | 
| 
       413 
     | 
    
         
            -
            ```
         
     | 
| 
       414 
     | 
    
         
            -
             
     | 
| 
       415 
     | 
    
         
            -
            In addition to using templates defined as constants, you can also use
         
     | 
| 
       416 
     | 
    
         
            -
            non-constant templates by invoking the `#render` method:
         
     | 
| 
       417 
     | 
    
         
            -
             
     | 
| 
       418 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       419 
     | 
    
         
            -
            greeting = -> { span "Hello, world" }
         
     | 
| 
       420 
     | 
    
         
            -
             
     | 
| 
       421 
     | 
    
         
            -
            -> {
         
     | 
| 
       422 
     | 
    
         
            -
              div {
         
     | 
| 
       423 
     | 
    
         
            -
                render greeting
         
     | 
| 
       424 
     | 
    
         
            -
              }
         
     | 
| 
       425 
     | 
    
         
            -
            }
         
     | 
| 
       426 
     | 
    
         
            -
            ```
         
     | 
| 
       427 
     | 
    
         
            -
             
     | 
| 
       428 
     | 
    
         
            -
            ## Parameter and Block Application
         
     | 
| 
       429 
     | 
    
         
            -
             
     | 
| 
       430 
     | 
    
         
            -
            Parameters and blocks can be applied to a template without it being rendered, by
         
     | 
| 
       431 
     | 
    
         
            -
            using `#apply`. This mechanism is what allows template composition and the
         
     | 
| 
       432 
     | 
    
         
            -
            creation of higher-order templates.
         
     | 
| 
       433 
     | 
    
         
            -
             
     | 
| 
       434 
     | 
    
         
            -
            The `#apply` method returns a new template which applies the given parameters
         
     | 
| 
       435 
     | 
    
         
            -
            and or block to the original template:
         
     | 
| 
       436 
     | 
    
         
            -
             
     | 
| 
       437 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       438 
     | 
    
         
            -
            # parameter application
         
     | 
| 
       439 
     | 
    
         
            -
            hello = -> { |name| h1 "Hello, #{name}!" }
         
     | 
| 
       440 
     | 
    
         
            -
            hello_world = hello.apply('world')
         
     | 
| 
       441 
     | 
    
         
            -
            hello_world.render #=> "<h1>Hello, world!</h1>"
         
     | 
| 
       442 
     | 
    
         
            -
             
     | 
| 
       443 
     | 
    
         
            -
            # block application
         
     | 
| 
       444 
     | 
    
         
            -
            div_wrap = -> { div { render_children } }
         
     | 
| 
       445 
     | 
    
         
            -
            wrapped_h1 = div_wrap.apply { h1 'hi' }
         
     | 
| 
       446 
     | 
    
         
            -
            wrapped_h1.render #=> "<div><h1>hi</h1></div>"
         
     | 
| 
       447 
     | 
    
         
            -
             
     | 
| 
       448 
     | 
    
         
            -
            # wrap a template
         
     | 
| 
       449 
     | 
    
         
            -
            wrapped_hello_world = div_wrap.apply(&hello_world)
         
     | 
| 
       450 
     | 
    
         
            -
            wrapped_hello_world.render #=> "<div><h1>Hello, world!</h1></div>"
         
     | 
| 
       451 
     | 
    
         
            -
            ```
         
     | 
| 
       452 
     | 
    
         
            -
             
     | 
| 
       453 
     | 
    
         
            -
            ## Higher-Order Templates
         
     | 
| 
       454 
     | 
    
         
            -
             
     | 
| 
       455 
     | 
    
         
            -
            Papercraft also lets you create higher-order templates, that is, templates that take
         
     | 
| 
       456 
     | 
    
         
            -
            other templates as parameters, or as blocks. Higher-order templates are handy
         
     | 
| 
       457 
     | 
    
         
            -
            for creating layouts, wrapping templates in arbitrary markup, enhancing
         
     | 
| 
       458 
     | 
    
         
            -
            templates or injecting template parameters.
         
     | 
| 
       459 
     | 
    
         
            -
             
     | 
| 
       460 
     | 
    
         
            -
            Here is a higher-order template that takes a template as parameter:
         
     | 
| 
       461 
     | 
    
         
            -
             
     | 
| 
       462 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       463 
     | 
    
         
            -
            div_wrap = -> { |inner| div { render inner } }
         
     | 
| 
       464 
     | 
    
         
            -
            greeter = -> { h1 'hi' }
         
     | 
| 
       465 
     | 
    
         
            -
            wrapped_greeter = div_wrap.apply(greeter)
         
     | 
| 
       466 
     | 
    
         
            -
            wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
         
     | 
| 
       467 
     | 
    
         
            -
            ```
         
     | 
| 
       468 
     | 
    
         
            -
             
     | 
| 
       469 
     | 
    
         
            -
            The inner template can also be passed as a block, as shown above:
         
     | 
| 
       470 
     | 
    
         
            -
             
     | 
| 
       471 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       472 
     | 
    
         
            -
            div_wrap = -> { div { render_children } }
         
     | 
| 
       473 
     | 
    
         
            -
            wrapped_greeter = div_wrap.apply { h1 'hi' }
         
     | 
| 
       474 
     | 
    
         
            -
            wrapped_greeter.render #=> "<div><h1>hi</h1></div>"
         
     | 
| 
       475 
     | 
    
         
            -
            ```
         
     | 
| 
       476 
     | 
    
         
            -
             
     | 
| 
       477 
     | 
    
         
            -
            ## Layout Template Composition
         
     | 
| 
       478 
     | 
    
         
            -
             
     | 
| 
       479 
     | 
    
         
            -
            One of the principal uses of higher-order templates is the creation of nested
         
     | 
| 
       480 
     | 
    
         
            -
            layouts. Suppose we have a website with a number of different layouts, and we'd
         
     | 
| 
       481 
     | 
    
         
            -
            like to avoid having to repeat the same code in the different layouts. We can do
         
     | 
| 
       482 
     | 
    
         
            -
            this by creating a `default` page template that takes a block, then use `#apply`
         
     | 
| 
       483 
     | 
    
         
            -
            to create the other templates:
         
     | 
| 
       484 
     | 
    
         
            -
             
     | 
| 
       485 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       486 
     | 
    
         
            -
            default_layout = -> { |**params|
         
     | 
| 
       487 
     | 
    
         
            -
              html5 {
         
     | 
| 
       488 
     | 
    
         
            -
                head {
         
     | 
| 
       489 
     | 
    
         
            -
                  title: params[:title]
         
     | 
| 
       490 
     | 
    
         
            -
                }
         
     | 
| 
       491 
     | 
    
         
            -
                body {
         
     | 
| 
       492 
     | 
    
         
            -
                  render_children(**params)
         
     | 
| 
       493 
     | 
    
         
            -
                }
         
     | 
| 
       494 
     | 
    
         
            -
              }
         
     | 
| 
       495 
     | 
    
         
            -
            }
         
     | 
| 
       496 
     | 
    
         
            -
             
     | 
| 
       497 
     | 
    
         
            -
            article_layout = default_layout.apply { |title:, body:|
         
     | 
| 
       498 
     | 
    
         
            -
              article {
         
     | 
| 
       499 
     | 
    
         
            -
                h1 title
         
     | 
| 
       500 
     | 
    
         
            -
                markdown body
         
     | 
| 
       501 
     | 
    
         
            -
              }
         
     | 
| 
       502 
     | 
    
         
            -
            }
         
     | 
| 
       503 
     | 
    
         
            -
             
     | 
| 
       504 
     | 
    
         
            -
            article_layout.render(
         
     | 
| 
       505 
     | 
    
         
            -
              title: 'This is a title',
         
     | 
| 
       506 
     | 
    
         
            -
              body: 'Hello from *markdown body*'
         
     | 
| 
       507 
     | 
    
         
            -
            )
         
     | 
| 
       508 
     | 
    
         
            -
            ```
         
     | 
| 
       509 
     | 
    
         
            -
             
     | 
| 
       510 
     | 
    
         
            -
            ## Rendering Markdown
         
     | 
| 
       511 
     | 
    
         
            -
             
     | 
| 
       512 
     | 
    
         
            -
            Markdown is rendered using the
         
     | 
| 
       513 
     | 
    
         
            -
            [Kramdown](https://kramdown.gettalong.org/index.html) gem. To emit Markdown, use
         
     | 
| 
       514 
     | 
    
         
            -
            `#markdown`:
         
     | 
| 
       515 
     | 
    
         
            -
             
     | 
| 
       516 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       517 
     | 
    
         
            -
            template = -> { |md| div { markdown md } }
         
     | 
| 
       518 
     | 
    
         
            -
            template.render("Here's some *Markdown*") #=> "<div><p>Here's some <em>Markdown</em><p>\n</div>"
         
     | 
| 
       519 
     | 
    
         
            -
            ```
         
     | 
| 
       520 
     | 
    
         
            -
             
     | 
| 
       521 
     | 
    
         
            -
            [Kramdown
         
     | 
| 
       522 
     | 
    
         
            -
            options](https://kramdown.gettalong.org/options.html#available-options) can be
         
     | 
| 
       523 
     | 
    
         
            -
            specified by adding them to the `#markdown` call:
         
     | 
| 
       524 
     | 
    
         
            -
             
     | 
| 
       525 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       526 
     | 
    
         
            -
            template = -> { |md| div { markdown md, auto_ids: false } }
         
     | 
| 
       527 
     | 
    
         
            -
            template.render("# title") #=> "<div><h1>title</h1></div>"
         
     | 
| 
       528 
     | 
    
         
            -
            ```
         
     | 
| 
       529 
     | 
    
         
            -
             
     | 
| 
       530 
     | 
    
         
            -
            You can also use `Papercraft.markdown` directly:
         
     | 
| 
       531 
     | 
    
         
            -
             
     | 
| 
       532 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       533 
     | 
    
         
            -
            Papercraft.markdown('# title') #=> "<h1>title</h1>"
         
     | 
| 
       534 
     | 
    
         
            -
            ```
         
     | 
| 
       535 
     | 
    
         
            -
             
     | 
| 
       536 
     | 
    
         
            -
            The default Kramdown options are:
         
     | 
| 
       537 
     | 
    
         
            -
             
     | 
| 
       538 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       539 
     | 
    
         
            -
            {
         
     | 
| 
       540 
     | 
    
         
            -
              entity_output: :numeric,
         
     | 
| 
       541 
     | 
    
         
            -
              syntax_highlighter: :rouge,
         
     | 
| 
       542 
     | 
    
         
            -
              input: 'GFM',
         
     | 
| 
       543 
     | 
    
         
            -
              hard_wrap: false
         
     | 
| 
       544 
     | 
    
         
            -
            }
         
     | 
| 
       545 
     | 
    
         
            -
            ```
         
     | 
| 
       546 
     | 
    
         
            -
             
     | 
| 
       547 
     | 
    
         
            -
            The deafult options can be configured by accessing
         
     | 
| 
       548 
     | 
    
         
            -
            `Papercraft.default_kramdown_options`, e.g.:
         
     | 
| 
       549 
     | 
    
         
            -
             
     | 
| 
       550 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       551 
     | 
    
         
            -
            Papercraft.default_kramdown_options[:auto_ids] = false
         
     | 
| 
       552 
     | 
    
         
            -
            ```
         
     | 
| 
       553 
     | 
    
         
            -
             
     | 
| 
       554 
     | 
    
         
            -
            ## Deferred Evaluation
         
     | 
| 
       555 
     | 
    
         
            -
             
     | 
| 
       556 
     | 
    
         
            -
            Deferred evaluation allows deferring the rendering of parts of a template until
         
     | 
| 
       557 
     | 
    
         
            -
            the last moment, thus allowing an inner template to manipulate the state of the
         
     | 
| 
       558 
     | 
    
         
            -
            outer template. To in order to defer a part of a template, use `#defer`, and
         
     | 
| 
       559 
     | 
    
         
            -
            include any markup in the provided block. This technique, in in conjunction with
         
     | 
| 
       560 
     | 
    
         
            -
            holding state in instance variables, is an alternative to passing parameters,
         
     | 
| 
       561 
     | 
    
         
            -
            which can be limiting in some situations.
         
     | 
| 
       562 
     | 
    
         
            -
             
     | 
| 
       563 
     | 
    
         
            -
            A few use cases for deferred evaulation come to mind:
         
     | 
| 
       564 
     | 
    
         
            -
             
     | 
| 
       565 
     | 
    
         
            -
            - Setting the page title.
         
     | 
| 
       566 
     | 
    
         
            -
            - Adding a flash message to a page.
         
     | 
| 
       567 
     | 
    
         
            -
            - Using templates that dynamically add static dependencies (JS and CSS) to the
         
     | 
| 
       568 
     | 
    
         
            -
              page.
         
     | 
| 
       569 
     | 
    
         
            -
             
     | 
| 
       570 
     | 
    
         
            -
            The last use case is particularly interesting. Imagine a `DependencyMananger`
         
     | 
| 
       571 
     | 
    
         
            -
            class that can collect JS and CSS dependencies from the different templates
         
     | 
| 
       572 
     | 
    
         
            -
            integrated into the page, and adds them to the page's `<head>` element:
         
     | 
| 
       573 
     | 
    
         
            -
             
     | 
| 
       574 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       575 
     | 
    
         
            -
            deps = DependencyMananger.new
         
     | 
| 
       576 
     | 
    
         
            -
             
     | 
| 
       577 
     | 
    
         
            -
            default_layout = -> { |**args|
         
     | 
| 
       578 
     | 
    
         
            -
              head {
         
     | 
| 
       579 
     | 
    
         
            -
                defer { render deps.head_markup }
         
     | 
| 
       580 
     | 
    
         
            -
              }
         
     | 
| 
       581 
     | 
    
         
            -
              body { render_children **args }
         
     | 
| 
       582 
     | 
    
         
            -
            }
         
     | 
| 
       583 
     | 
    
         
            -
             
     | 
| 
       584 
     | 
    
         
            -
            button = proc { |text, onclick|
         
     | 
| 
       585 
     | 
    
         
            -
              deps.js '/static/js/button.js'
         
     | 
| 
       586 
     | 
    
         
            -
              deps.css '/static/css/button.css'
         
     | 
| 
       587 
     | 
    
         
            -
             
     | 
| 
       588 
     | 
    
         
            -
              button text, onclick: onclick
         
     | 
| 
       589 
     | 
    
         
            -
            }
         
     | 
| 
       590 
     | 
    
         
            -
             
     | 
| 
       591 
     | 
    
         
            -
            heading = proc { |text|
         
     | 
| 
       592 
     | 
    
         
            -
              deps.js '/static/js/heading.js'
         
     | 
| 
       593 
     | 
    
         
            -
              deps.css '/static/css/heading.css'
         
     | 
| 
       594 
     | 
    
         
            -
             
     | 
| 
       595 
     | 
    
         
            -
              h1 text
         
     | 
| 
       596 
     | 
    
         
            -
            }
         
     | 
| 
       597 
     | 
    
         
            -
             
     | 
| 
       598 
     | 
    
         
            -
            page = default_layout.apply {
         
     | 
| 
       599 
     | 
    
         
            -
              render heading, "What's your favorite cheese?"
         
     | 
| 
       600 
     | 
    
         
            -
             
     | 
| 
       601 
     | 
    
         
            -
              render button, 'Beaufort', 'eat_beaufort()'
         
     | 
| 
       602 
     | 
    
         
            -
              render button, 'Mont d''or', 'eat_montdor()'
         
     | 
| 
       603 
     | 
    
         
            -
              render button, 'Époisses', 'eat_epoisses()'
         
     | 
| 
       604 
     | 
    
         
            -
            }
         
     | 
| 
       605 
     | 
    
         
            -
            ```
         
     | 
| 
       606 
     | 
    
         
            -
             
     | 
| 
       607 
     | 
    
         
            -
            ## Cached Rendering
         
     | 
| 
       608 
     | 
    
         
            -
             
     | 
| 
       609 
     | 
    
         
            -
            Papercraft provides a simple API for caching the result of a rendering. The cache stores
         
     | 
| 
       610 
     | 
    
         
            -
            renderings of a template respective to the given arguments. To automatically
         
     | 
| 
       611 
     | 
    
         
            -
            retrieve the cached rendered HTML, or generate it for the first time, use
         
     | 
| 
       612 
     | 
    
         
            -
            `Proc#render_cached`:
         
     | 
| 
       613 
     | 
    
         
            -
             
     | 
| 
       614 
     | 
    
         
            -
            ```ruby
         
     | 
| 
       615 
     | 
    
         
            -
            template = ->(title) { div { h1 title } }
         
     | 
| 
       616 
     | 
    
         
            -
            template.render_cached('foo') #=> <div><h1>foo</h1></div>
         
     | 
| 
       617 
     | 
    
         
            -
            template.render_cached('foo') #=> <div><h1>foo</h1></div> (from cache)
         
     | 
| 
       618 
     | 
    
         
            -
            template.render_cached('bar') #=> <div><h1>bar</h1></div>
         
     | 
| 
       619 
     | 
    
         
            -
            template.render_cached('bar') #=> <div><h1>bar</h1></div> (from cache)
         
     | 
| 
       620 
     | 
    
         
            -
            ```
         
     | 
| 
      
 47 
     | 
    
         
            +
            For more information, please consult the [Papercraft
         
     | 
| 
      
 48 
     | 
    
         
            +
            website](https://papercraft.noteflakes.com/).
         
     | 
    
        data/lib/papercraft/compiler.rb
    CHANGED
    
    | 
         @@ -164,12 +164,23 @@ module Papercraft 
     | 
|
| 
       164 
164 
     | 
    
         
             
                  # adjust_whitespace(node.location)
         
     | 
| 
       165 
165 
     | 
    
         
             
                  is_void = is_void_element?(tag)
         
     | 
| 
       166 
166 
     | 
    
         
             
                  is_raw_inner_text = is_raw_inner_text_element?(tag)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  is_empty = !node.block && !node.inner_text
         
     | 
| 
       167 
168 
     | 
    
         | 
| 
       168 
     | 
    
         
            -
                  if is_void &&  
     | 
| 
      
 169 
     | 
    
         
            +
                  if is_void && !is_empty
         
     | 
| 
       169 
170 
     | 
    
         
             
                    raise Papercraft::Error, "Void element #{tag} cannot contain child nodes or inner text"
         
     | 
| 
       170 
171 
     | 
    
         
             
                  end
         
     | 
| 
       171 
172 
     | 
    
         | 
| 
       172 
     | 
    
         
            -
                   
     | 
| 
      
 173 
     | 
    
         
            +
                  if @mode == :xml && is_empty
         
     | 
| 
      
 174 
     | 
    
         
            +
                    emit_html(
         
     | 
| 
      
 175 
     | 
    
         
            +
                      node.tag_location, 
         
     | 
| 
      
 176 
     | 
    
         
            +
                      format_xml_tag_self_closing(node.tag_location, tag, node.attributes)
         
     | 
| 
      
 177 
     | 
    
         
            +
                    )
         
     | 
| 
      
 178 
     | 
    
         
            +
                    return
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
      
 181 
     | 
    
         
            +
                  emit_html(
         
     | 
| 
      
 182 
     | 
    
         
            +
                    node.tag_location, format_html_tag_open(node.tag_location, tag, node.attributes)
         
     | 
| 
      
 183 
     | 
    
         
            +
                  )
         
     | 
| 
       173 
184 
     | 
    
         
             
                  return if is_void
         
     | 
| 
       174 
185 
     | 
    
         | 
| 
       175 
186 
     | 
    
         
             
                  case node.block
         
     | 
| 
         @@ -178,7 +189,7 @@ module Papercraft 
     | 
|
| 
       178 
189 
     | 
    
         
             
                  when Prism::BlockArgumentNode
         
     | 
| 
       179 
190 
     | 
    
         
             
                    flush_html_parts!
         
     | 
| 
       180 
191 
     | 
    
         
             
                    adjust_whitespace(node.block)
         
     | 
| 
       181 
     | 
    
         
            -
                    emit("; #{format_code(node.block.expression)}. 
     | 
| 
      
 192 
     | 
    
         
            +
                    emit("; #{format_code(node.block.expression)}.__papercraft_compiled_proc.(__buffer__)")
         
     | 
| 
       182 
193 
     | 
    
         
             
                  end
         
     | 
| 
       183 
194 
     | 
    
         | 
| 
       184 
195 
     | 
    
         
             
                  if node.inner_text
         
     | 
| 
         @@ -213,7 +224,7 @@ module Papercraft 
     | 
|
| 
       213 
224 
     | 
    
         
             
                    emit(format_code(node.call_node.receiver))
         
     | 
| 
       214 
225 
     | 
    
         
             
                    emit('::')
         
     | 
| 
       215 
226 
     | 
    
         
             
                  end
         
     | 
| 
       216 
     | 
    
         
            -
                  emit("#{node.call_node.name}. 
     | 
| 
      
 227 
     | 
    
         
            +
                  emit("#{node.call_node.name}.__papercraft_compiled_proc.(__buffer__")
         
     | 
| 
       217 
228 
     | 
    
         
             
                  if node.call_node.arguments
         
     | 
| 
       218 
229 
     | 
    
         
             
                    emit(', ')
         
     | 
| 
       219 
230 
     | 
    
         
             
                    visit(node.call_node.arguments)
         
     | 
| 
         @@ -229,17 +240,17 @@ module Papercraft 
     | 
|
| 
       229 
240 
     | 
    
         
             
                  args = node.call_node.arguments.arguments
         
     | 
| 
       230 
241 
     | 
    
         
             
                  first_arg = args.first
         
     | 
| 
       231 
242 
     | 
    
         | 
| 
       232 
     | 
    
         
            -
                  block_embed = node.block && "&(->(__buffer__) #{format_code(node.block)}. 
     | 
| 
      
 243 
     | 
    
         
            +
                  block_embed = node.block && "&(->(__buffer__) #{format_code(node.block)}.__papercraft_compiled!)"
         
     | 
| 
       233 
244 
     | 
    
         
             
                  block_embed = ", #{block_embed}" if block_embed && node.call_node.arguments
         
     | 
| 
       234 
245 
     | 
    
         | 
| 
       235 
246 
     | 
    
         
             
                  flush_html_parts!
         
     | 
| 
       236 
247 
     | 
    
         
             
                  adjust_whitespace(node.location)
         
     | 
| 
       237 
248 
     | 
    
         | 
| 
       238 
249 
     | 
    
         
             
                  if args.length == 1
         
     | 
| 
       239 
     | 
    
         
            -
                    emit("; #{format_code(first_arg)}. 
     | 
| 
      
 250 
     | 
    
         
            +
                    emit("; #{format_code(first_arg)}.__papercraft_compiled_proc.(__buffer__#{block_embed})")
         
     | 
| 
       240 
251 
     | 
    
         
             
                  else
         
     | 
| 
       241 
252 
     | 
    
         
             
                    args_code = format_code_comma_separated_nodes(args[1..])
         
     | 
| 
       242 
     | 
    
         
            -
                    emit("; #{format_code(first_arg)}. 
     | 
| 
      
 253 
     | 
    
         
            +
                    emit("; #{format_code(first_arg)}.__papercraft_compiled_proc.(__buffer__, #{args_code}#{block_embed})")
         
     | 
| 
       243 
254 
     | 
    
         
             
                  end
         
     | 
| 
       244 
255 
     | 
    
         
             
                end
         
     | 
| 
       245 
256 
     | 
    
         | 
| 
         @@ -336,7 +347,7 @@ module Papercraft 
     | 
|
| 
       336 
347 
     | 
    
         
             
                def visit_extension_tag_node(node)
         
     | 
| 
       337 
348 
     | 
    
         
             
                  flush_html_parts!
         
     | 
| 
       338 
349 
     | 
    
         
             
                  adjust_whitespace(node.location)
         
     | 
| 
       339 
     | 
    
         
            -
                  emit("; Papercraft::Extensions[#{node.tag.inspect}]. 
     | 
| 
      
 350 
     | 
    
         
            +
                  emit("; Papercraft::Extensions[#{node.tag.inspect}].__papercraft_compiled_proc.(__buffer__")
         
     | 
| 
       340 
351 
     | 
    
         
             
                  if node.call_node.arguments
         
     | 
| 
       341 
352 
     | 
    
         
             
                    emit(', ')
         
     | 
| 
       342 
353 
     | 
    
         
             
                    visit(node.call_node.arguments)
         
     | 
| 
         @@ -367,7 +378,7 @@ module Papercraft 
     | 
|
| 
       367 
378 
     | 
    
         
             
                    end
         
     | 
| 
       368 
379 
     | 
    
         
             
                    block_params = block_params.empty? ? '' : ", #{block_params.join(', ')}"
         
     | 
| 
       369 
380 
     | 
    
         | 
| 
       370 
     | 
    
         
            -
                    emit(", &(proc { |__buffer__#{block_params}| #{block_body} }). 
     | 
| 
      
 381 
     | 
    
         
            +
                    emit(", &(proc { |__buffer__#{block_params}| #{block_body} }).__papercraft_compiled!")
         
     | 
| 
       371 
382 
     | 
    
         
             
                  end
         
     | 
| 
       372 
383 
     | 
    
         
             
                  emit(")")
         
     | 
| 
       373 
384 
     | 
    
         
             
                end
         
     | 
| 
         @@ -382,7 +393,7 @@ module Papercraft 
     | 
|
| 
       382 
393 
     | 
    
         
             
                  guard = @render_yield_used ?
         
     | 
| 
       383 
394 
     | 
    
         
             
                    '' : "; raise(LocalJumpError, 'no block given (render_yield)') if !__block__"
         
     | 
| 
       384 
395 
     | 
    
         
             
                  @render_yield_used = true
         
     | 
| 
       385 
     | 
    
         
            -
                  emit("#{guard}; __block__. 
     | 
| 
      
 396 
     | 
    
         
            +
                  emit("#{guard}; __block__.__papercraft_compiled_proc.(__buffer__")
         
     | 
| 
       386 
397 
     | 
    
         
             
                  if node.call_node.arguments
         
     | 
| 
       387 
398 
     | 
    
         
             
                    emit(', ')
         
     | 
| 
       388 
399 
     | 
    
         
             
                    visit(node.call_node.arguments)
         
     | 
| 
         @@ -398,7 +409,7 @@ module Papercraft 
     | 
|
| 
       398 
409 
     | 
    
         
             
                  flush_html_parts!
         
     | 
| 
       399 
410 
     | 
    
         
             
                  adjust_whitespace(node.location)
         
     | 
| 
       400 
411 
     | 
    
         
             
                  @render_children_used = true
         
     | 
| 
       401 
     | 
    
         
            -
                  emit("; __block__&. 
     | 
| 
      
 412 
     | 
    
         
            +
                  emit("; __block__&.__papercraft_compiled_proc&.(__buffer__")
         
     | 
| 
       402 
413 
     | 
    
         
             
                  if node.call_node.arguments
         
     | 
| 
       403 
414 
     | 
    
         
             
                    emit(', ')
         
     | 
| 
       404 
415 
     | 
    
         
             
                    visit(node.call_node.arguments)
         
     | 
| 
         @@ -410,7 +421,7 @@ module Papercraft 
     | 
|
| 
       410 
421 
     | 
    
         
             
                  flush_html_parts!
         
     | 
| 
       411 
422 
     | 
    
         
             
                  adjust_whitespace(node.location)
         
     | 
| 
       412 
423 
     | 
    
         | 
| 
       413 
     | 
    
         
            -
                  emit("; #{node.call_node.receiver.name}. 
     | 
| 
      
 424 
     | 
    
         
            +
                  emit("; #{node.call_node.receiver.name}.__papercraft_compiled_proc.(__buffer__")
         
     | 
| 
       414 
425 
     | 
    
         
             
                  if node.call_node.arguments
         
     | 
| 
       415 
426 
     | 
    
         
             
                    emit(', ')
         
     | 
| 
       416 
427 
     | 
    
         
             
                    visit(node.call_node.arguments)
         
     | 
| 
         @@ -418,7 +429,7 @@ module Papercraft 
     | 
|
| 
       418 
429 
     | 
    
         
             
                  if node.call_node.block
         
     | 
| 
       419 
430 
     | 
    
         
             
                    emit(", &(->")
         
     | 
| 
       420 
431 
     | 
    
         
             
                    visit(node.call_node.block)
         
     | 
| 
       421 
     | 
    
         
            -
                    emit("). 
     | 
| 
      
 432 
     | 
    
         
            +
                    emit(").__papercraft_compiled_proc")
         
     | 
| 
       422 
433 
     | 
    
         
             
                  end
         
     | 
| 
       423 
434 
     | 
    
         
             
                  emit(")")
         
     | 
| 
       424 
435 
     | 
    
         
             
                end
         
     | 
| 
         @@ -489,6 +500,15 @@ module Papercraft 
     | 
|
| 
       489 
500 
     | 
    
         
             
                  RAW_INNER_TEXT_TAGS.include?(tag.to_s)
         
     | 
| 
       490 
501 
     | 
    
         
             
                end
         
     | 
| 
       491 
502 
     | 
    
         | 
| 
      
 503 
     | 
    
         
            +
                def format_xml_tag_self_closing(loc, tag, attributes)
         
     | 
| 
      
 504 
     | 
    
         
            +
                  tag = convert_tag(tag)
         
     | 
| 
      
 505 
     | 
    
         
            +
                  if attributes && attributes&.elements.size > 0 || @@html_debug_attribute_injector
         
     | 
| 
      
 506 
     | 
    
         
            +
                    "<#{tag} #{format_html_attributes(loc, attributes)}/>"
         
     | 
| 
      
 507 
     | 
    
         
            +
                  else
         
     | 
| 
      
 508 
     | 
    
         
            +
                    "<#{tag}/>"
         
     | 
| 
      
 509 
     | 
    
         
            +
                  end
         
     | 
| 
      
 510 
     | 
    
         
            +
                end
         
     | 
| 
      
 511 
     | 
    
         
            +
             
     | 
| 
       492 
512 
     | 
    
         
             
                # Formats an open tag with optional attributes.
         
     | 
| 
       493 
513 
     | 
    
         
             
                #
         
     | 
| 
       494 
514 
     | 
    
         
             
                # @param loc [Prism::Location] tag location
         
     | 
    
        data/lib/papercraft/proc_ext.rb
    CHANGED
    
    | 
         @@ -5,122 +5,37 @@ require_relative './compiler' 
     | 
|
| 
       5 
5 
     | 
    
         
             
            module Papercraft
         
     | 
| 
       6 
6 
     | 
    
         
             
              # Extensions to the Proc class.
         
     | 
| 
       7 
7 
     | 
    
         
             
              module ProcExtensions
         
     | 
| 
       8 
     | 
    
         
            -
                # Returns the compiled form code for the proc.
         
     | 
| 
       9 
     | 
    
         
            -
                #
         
     | 
| 
       10 
     | 
    
         
            -
                # @return [String] compiled proc code
         
     | 
| 
       11 
     | 
    
         
            -
                def compiled_code
         
     | 
| 
       12 
     | 
    
         
            -
                  Papercraft::Compiler.compile_to_code(self).last
         
     | 
| 
       13 
     | 
    
         
            -
                end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                # Returns the source map for the compiled proc.
         
     | 
| 
       16 
     | 
    
         
            -
                #
         
     | 
| 
       17 
     | 
    
         
            -
                # @return [Array<String>] source map
         
     | 
| 
       18 
     | 
    
         
            -
                def source_map
         
     | 
| 
       19 
     | 
    
         
            -
                  loc = source_location
         
     | 
| 
       20 
     | 
    
         
            -
                  fn = compiled? ? loc.first : Papercraft::Compiler.source_location_to_fn(loc)
         
     | 
| 
       21 
     | 
    
         
            -
                  Papercraft::Compiler.source_map_store[fn]
         
     | 
| 
       22 
     | 
    
         
            -
                end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
                # Returns the AST for the proc.
         
     | 
| 
       25 
     | 
    
         
            -
                #
         
     | 
| 
       26 
     | 
    
         
            -
                # @return [Prism::Node] AST root
         
     | 
| 
       27 
     | 
    
         
            -
                def ast
         
     | 
| 
       28 
     | 
    
         
            -
                  Sirop.to_ast(self)
         
     | 
| 
       29 
     | 
    
         
            -
                end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
8 
     | 
    
         
             
                # Returns true if proc is marked as compiled.
         
     | 
| 
       32 
9 
     | 
    
         
             
                #
         
     | 
| 
       33 
10 
     | 
    
         
             
                # @return [bool] is the proc marked as compiled
         
     | 
| 
       34 
     | 
    
         
            -
                def  
     | 
| 
       35 
     | 
    
         
            -
                  @ 
     | 
| 
      
 11 
     | 
    
         
            +
                def __papercraft_compiled?
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @__papercraft_compiled
         
     | 
| 
       36 
13 
     | 
    
         
             
                end
         
     | 
| 
       37 
14 
     | 
    
         | 
| 
       38 
15 
     | 
    
         
             
                # Marks the proc as compiled, i.e. can render directly and takes a string
         
     | 
| 
       39 
16 
     | 
    
         
             
                # buffer as first argument.
         
     | 
| 
       40 
17 
     | 
    
         
             
                #
         
     | 
| 
       41 
18 
     | 
    
         
             
                # @return [self]
         
     | 
| 
       42 
     | 
    
         
            -
                def  
     | 
| 
       43 
     | 
    
         
            -
                  @ 
     | 
| 
      
 19 
     | 
    
         
            +
                def __papercraft_compiled!
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @__papercraft_compiled = true
         
     | 
| 
       44 
21 
     | 
    
         
             
                  self
         
     | 
| 
       45 
22 
     | 
    
         
             
                end
         
     | 
| 
       46 
23 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
                # Returns the compiled proc for the  
     | 
| 
      
 24 
     | 
    
         
            +
                # Returns the compiled proc for the proc. If marked as compiled, returns
         
     | 
| 
       48 
25 
     | 
    
         
             
                # self.
         
     | 
| 
       49 
26 
     | 
    
         
             
                #
         
     | 
| 
       50 
27 
     | 
    
         
             
                # @param mode [Symbol] compilation mode (:html, :xml)
         
     | 
| 
       51 
28 
     | 
    
         
             
                # @return [Proc] compiled proc or self
         
     | 
| 
       52 
     | 
    
         
            -
                def  
     | 
| 
       53 
     | 
    
         
            -
                  @ 
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                # Compiles the proc into the compiled form.
         
     | 
| 
       57 
     | 
    
         
            -
                #
         
     | 
| 
       58 
     | 
    
         
            -
                # @param mode [Symbol] compilation mode (:html, :xml)
         
     | 
| 
       59 
     | 
    
         
            -
                # @return [Proc] compiled proc
         
     | 
| 
       60 
     | 
    
         
            -
                def compile(mode: :html)
         
     | 
| 
       61 
     | 
    
         
            -
                  Papercraft::Compiler.compile(self, mode:).compiled!
         
     | 
| 
       62 
     | 
    
         
            -
                rescue Sirop::Error
         
     | 
| 
       63 
     | 
    
         
            -
                  raise Papercraft::Error, "Dynamically defined procs cannot be compiled"
         
     | 
| 
       64 
     | 
    
         
            -
                end
         
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                # Renders the proc to HTML with the given arguments.
         
     | 
| 
       67 
     | 
    
         
            -
                #
         
     | 
| 
       68 
     | 
    
         
            -
                # @return [String] HTML string
         
     | 
| 
       69 
     | 
    
         
            -
                def render(*a, **b, &c)
         
     | 
| 
       70 
     | 
    
         
            -
                  compiled_proc.(+'', *a, **b, &c)
         
     | 
| 
       71 
     | 
    
         
            -
                rescue Exception => e
         
     | 
| 
       72 
     | 
    
         
            -
                  e.is_a?(Papercraft::Error) ? raise : raise(Papercraft.translate_backtrace(e))
         
     | 
| 
       73 
     | 
    
         
            -
                end
         
     | 
| 
       74 
     | 
    
         
            -
             
     | 
| 
       75 
     | 
    
         
            -
                # Renders the proc to XML with the given arguments.
         
     | 
| 
       76 
     | 
    
         
            -
                #
         
     | 
| 
       77 
     | 
    
         
            -
                # @return [String] XML string
         
     | 
| 
       78 
     | 
    
         
            -
                def render_xml(*a, **b, &c)
         
     | 
| 
       79 
     | 
    
         
            -
                  compiled_proc(mode: :xml).(+'', *a, **b, &c)
         
     | 
| 
       80 
     | 
    
         
            -
                rescue Exception => e
         
     | 
| 
       81 
     | 
    
         
            -
                  e.is_a?(Papercraft::Error) ? raise : raise(Papercraft.translate_backtrace(e))
         
     | 
| 
       82 
     | 
    
         
            -
                end
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
                # Renders the proc to HTML with the given arguments into the given buffer.
         
     | 
| 
       85 
     | 
    
         
            -
                #
         
     | 
| 
       86 
     | 
    
         
            -
                # @param buf [String] buffer
         
     | 
| 
       87 
     | 
    
         
            -
                # @return [String] HTML string
         
     | 
| 
       88 
     | 
    
         
            -
                def render_to_buffer(buf, *a, **b, &c)
         
     | 
| 
       89 
     | 
    
         
            -
                  compiled_proc.(buf, *a, **b, &c)
         
     | 
| 
       90 
     | 
    
         
            -
                rescue Exception => e
         
     | 
| 
       91 
     | 
    
         
            -
                  raise Papercraft.translate_backtrace(e)
         
     | 
| 
       92 
     | 
    
         
            -
                end
         
     | 
| 
       93 
     | 
    
         
            -
             
     | 
| 
       94 
     | 
    
         
            -
                # Returns a proc that applies the given arguments to the original proc. The
         
     | 
| 
       95 
     | 
    
         
            -
                # returned proc calls the *compiled* form of the proc, merging the
         
     | 
| 
       96 
     | 
    
         
            -
                # positional and keywords parameters passed to `#apply` with parameters
         
     | 
| 
       97 
     | 
    
         
            -
                # passed to the applied proc. If a block is given, it is wrapped in a proc
         
     | 
| 
       98 
     | 
    
         
            -
                # that passed merged parameters to the block.
         
     | 
| 
       99 
     | 
    
         
            -
                #
         
     | 
| 
       100 
     | 
    
         
            -
                # @param *pos1 [Array<any>] applied positional parameters
         
     | 
| 
       101 
     | 
    
         
            -
                # @param **kw1 [Hash<any, any] applied keyword parameters
         
     | 
| 
       102 
     | 
    
         
            -
                # @return [Proc] applied proc
         
     | 
| 
       103 
     | 
    
         
            -
                def apply(*pos1, **kw1, &block)
         
     | 
| 
       104 
     | 
    
         
            -
                  compiled = compiled_proc
         
     | 
| 
       105 
     | 
    
         
            -
                  c_compiled = block&.compiled_proc
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
                  ->(__buffer__, *pos2, **kw2, &block2) {
         
     | 
| 
       108 
     | 
    
         
            -
                    c_proc = c_compiled && ->(__buffer__, *pos3, **kw3) {
         
     | 
| 
       109 
     | 
    
         
            -
                      c_compiled.(__buffer__, *pos3, **kw3, &block2)
         
     | 
| 
       110 
     | 
    
         
            -
                    }.compiled!
         
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
                    compiled.(__buffer__, *pos1, *pos2, **kw1, **kw2, &c_proc)
         
     | 
| 
       113 
     | 
    
         
            -
                  }.compiled!
         
     | 
| 
      
 29 
     | 
    
         
            +
                def __papercraft_compiled_proc(mode: :html)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @__papercraft_compiled_proc ||= @__papercraft_compiled ?
         
     | 
| 
      
 31 
     | 
    
         
            +
                    self : Papercraft.compile(self, mode:)
         
     | 
| 
       114 
32 
     | 
    
         
             
                end
         
     | 
| 
       115 
33 
     | 
    
         | 
| 
       116 
     | 
    
         
            -
                #  
     | 
| 
       117 
     | 
    
         
            -
                # arguments.
         
     | 
| 
      
 34 
     | 
    
         
            +
                # Returns the render cache for the proc.
         
     | 
| 
       118 
35 
     | 
    
         
             
                #
         
     | 
| 
       119 
     | 
    
         
            -
                # @return [ 
     | 
| 
       120 
     | 
    
         
            -
                def  
     | 
| 
       121 
     | 
    
         
            -
                  @ 
     | 
| 
       122 
     | 
    
         
            -
                  key = args.empty? && kargs.empty? && !block ? nil : [args, kargs, block&.source_location]
         
     | 
| 
       123 
     | 
    
         
            -
                  @render_cache[key] ||= render(*args, **kargs, &block)
         
     | 
| 
      
 36 
     | 
    
         
            +
                # @return [Hash] cache hash
         
     | 
| 
      
 37 
     | 
    
         
            +
                def __papercraft_render_cache
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @__papercraft_render_cache ||= {}
         
     | 
| 
       124 
39 
     | 
    
         
             
                end
         
     | 
| 
       125 
40 
     | 
    
         
             
              end
         
     | 
| 
       126 
41 
     | 
    
         
             
            end
         
     | 
    
        data/lib/papercraft/template.rb
    CHANGED
    
    | 
         @@ -8,21 +8,34 @@ module Papercraft 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                # @param proc [Proc] template proc
         
     | 
| 
       10 
10 
     | 
    
         
             
                # @param mode [Symbol] mode (:html, :xml)
         
     | 
| 
       11 
     | 
    
         
            -
                def initialize(proc, mode: :html)
         
     | 
| 
       12 
     | 
    
         
            -
                  @proc = proc
         
     | 
| 
      
 11 
     | 
    
         
            +
                def initialize(proc = nil, mode: :html, &block)
         
     | 
| 
      
 12 
     | 
    
         
            +
                  @proc = proc || block
         
     | 
| 
      
 13 
     | 
    
         
            +
                  raise ArgumentError, "No template proc given" if !@proc
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       13 
15 
     | 
    
         
             
                  @mode = mode
         
     | 
| 
       14 
16 
     | 
    
         
             
                end
         
     | 
| 
       15 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                # Renders the template.
         
     | 
| 
      
 19 
     | 
    
         
            +
                #
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @return [String] generated HTML
         
     | 
| 
       16 
21 
     | 
    
         
             
                def render(*, **, &)
         
     | 
| 
       17 
     | 
    
         
            -
                  (mode == :xml) ? @proc 
     | 
| 
      
 22 
     | 
    
         
            +
                  (mode == :xml) ? Papercraft.xml(@proc, *, **, &) : Papercraft.html(@proc, *, **, &)
         
     | 
| 
       18 
23 
     | 
    
         
             
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
                alias_method :call, :render
         
     | 
| 
       19 
25 
     | 
    
         | 
| 
      
 26 
     | 
    
         
            +
                # Applies the given parameters and block to the template, returning an
         
     | 
| 
      
 27 
     | 
    
         
            +
                # applied template.
         
     | 
| 
      
 28 
     | 
    
         
            +
                #
         
     | 
| 
      
 29 
     | 
    
         
            +
                # @return [Papercraft::Template] applied template
         
     | 
| 
       20 
30 
     | 
    
         
             
                def apply(*, **, &)
         
     | 
| 
       21 
     | 
    
         
            -
                  Template.new( 
     | 
| 
      
 31 
     | 
    
         
            +
                  Template.new(Papercraft.apply(@proc, *, **, &), mode: @mode)
         
     | 
| 
       22 
32 
     | 
    
         
             
                end
         
     | 
| 
       23 
33 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
                 
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
      
 34 
     | 
    
         
            +
                # Returns the compiled proc for the template.
         
     | 
| 
      
 35 
     | 
    
         
            +
                #
         
     | 
| 
      
 36 
     | 
    
         
            +
                # @return [Proc] compiled proc
         
     | 
| 
      
 37 
     | 
    
         
            +
                def __papercraft_compiled_proc
         
     | 
| 
      
 38 
     | 
    
         
            +
                  @proc.__papercraft_compiled_proc(mode: @mode)
         
     | 
| 
       26 
39 
     | 
    
         
             
                end
         
     | 
| 
       27 
40 
     | 
    
         
             
              end
         
     | 
| 
       28 
41 
     | 
    
         
             
            end
         
     | 
    
        data/lib/papercraft/version.rb
    CHANGED
    
    
    
        data/lib/papercraft.rb
    CHANGED
    
    | 
         @@ -114,10 +114,11 @@ module Papercraft 
     | 
|
| 
       114 
114 
     | 
    
         
             
              # @param opts [Hash] Kramdown option overrides
         
     | 
| 
       115 
115 
     | 
    
         
             
              # @return [Kramdown::Document] Kramdown document
         
     | 
| 
       116 
116 
     | 
    
         
             
              def markdown_doc(markdown, **opts)
         
     | 
| 
       117 
     | 
    
         
            -
                @markdown_deps_loaded ||=  
     | 
| 
      
 117 
     | 
    
         
            +
                @markdown_deps_loaded ||= begin
         
     | 
| 
       118 
118 
     | 
    
         
             
                  require 'kramdown'
         
     | 
| 
       119 
119 
     | 
    
         
             
                  require 'rouge'
         
     | 
| 
       120 
120 
     | 
    
         
             
                  require 'kramdown-parser-gfm'
         
     | 
| 
      
 121 
     | 
    
         
            +
                  true
         
     | 
| 
       121 
122 
     | 
    
         
             
                end
         
     | 
| 
       122 
123 
     | 
    
         | 
| 
       123 
124 
     | 
    
         
             
                opts = default_kramdown_options.merge(opts)
         
     | 
| 
         @@ -153,4 +154,129 @@ module Papercraft 
     | 
|
| 
       153 
154 
     | 
    
         
             
              def default_kramdown_options=(opts)
         
     | 
| 
       154 
155 
     | 
    
         
             
                @default_kramdown_options = opts
         
     | 
| 
       155 
156 
     | 
    
         
             
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              # Returns the compiled form code for the given proc.
         
     | 
| 
      
 159 
     | 
    
         
            +
              #
         
     | 
| 
      
 160 
     | 
    
         
            +
              # @param proc [Proc] template proc
         
     | 
| 
      
 161 
     | 
    
         
            +
              # @return [String] compiled proc code
         
     | 
| 
      
 162 
     | 
    
         
            +
              def compiled_code(proc)
         
     | 
| 
      
 163 
     | 
    
         
            +
                Papercraft::Compiler.compile_to_code(proc).last
         
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
              # Returns the source map for the given proc.
         
     | 
| 
      
 167 
     | 
    
         
            +
              #
         
     | 
| 
      
 168 
     | 
    
         
            +
              # @param proc [Proc] template proc
         
     | 
| 
      
 169 
     | 
    
         
            +
              # @return [Array<String>] source map
         
     | 
| 
      
 170 
     | 
    
         
            +
              def source_map(proc)
         
     | 
| 
      
 171 
     | 
    
         
            +
                loc = proc.source_location
         
     | 
| 
      
 172 
     | 
    
         
            +
                fn = proc.__papercraft_compiled? ? loc.first : Papercraft::Compiler.source_location_to_fn(loc)
         
     | 
| 
      
 173 
     | 
    
         
            +
                Papercraft::Compiler.source_map_store[fn]
         
     | 
| 
      
 174 
     | 
    
         
            +
              end
         
     | 
| 
      
 175 
     | 
    
         
            +
             
     | 
| 
      
 176 
     | 
    
         
            +
              # Returns the AST for the given proc.
         
     | 
| 
      
 177 
     | 
    
         
            +
              #
         
     | 
| 
      
 178 
     | 
    
         
            +
              # @param proc [Proc] template proc
         
     | 
| 
      
 179 
     | 
    
         
            +
              # @return [Prism::Node] AST root
         
     | 
| 
      
 180 
     | 
    
         
            +
              def ast(proc)
         
     | 
| 
      
 181 
     | 
    
         
            +
                Sirop.to_ast(proc)
         
     | 
| 
      
 182 
     | 
    
         
            +
              end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
              # Compiles the given template.
         
     | 
| 
      
 185 
     | 
    
         
            +
              #
         
     | 
| 
      
 186 
     | 
    
         
            +
              # @param proc [Proc] template proc
         
     | 
| 
      
 187 
     | 
    
         
            +
              # @param mode [Symbol] compilation mode (:html, :xml)
         
     | 
| 
      
 188 
     | 
    
         
            +
              # @return [Proc] compiled proc
         
     | 
| 
      
 189 
     | 
    
         
            +
              def compile(proc, mode: :html)
         
     | 
| 
      
 190 
     | 
    
         
            +
                Papercraft::Compiler.compile(proc, mode:).__papercraft_compiled!
         
     | 
| 
      
 191 
     | 
    
         
            +
              rescue Sirop::Error
         
     | 
| 
      
 192 
     | 
    
         
            +
                raise Papercraft::Error, "Can't compile eval'd template"
         
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
             
     | 
| 
      
 195 
     | 
    
         
            +
              # Renders the given template to HTML with the given arguments. The template
         
     | 
| 
      
 196 
     | 
    
         
            +
              # can be passed either as the first parameter, or as a block, if no parameter
         
     | 
| 
      
 197 
     | 
    
         
            +
              # is given.
         
     | 
| 
      
 198 
     | 
    
         
            +
              #
         
     | 
| 
      
 199 
     | 
    
         
            +
              # @param template [Proc] template proc
         
     | 
| 
      
 200 
     | 
    
         
            +
              # @return [String] HTML string
         
     | 
| 
      
 201 
     | 
    
         
            +
              def html(template = nil, *pos, **kw, &block)
         
     | 
| 
      
 202 
     | 
    
         
            +
                if !template
         
     | 
| 
      
 203 
     | 
    
         
            +
                  template = block
         
     | 
| 
      
 204 
     | 
    
         
            +
                elsif template.is_a?(Template)
         
     | 
| 
      
 205 
     | 
    
         
            +
                  template = template.proc
         
     | 
| 
      
 206 
     | 
    
         
            +
                end
         
     | 
| 
      
 207 
     | 
    
         
            +
                raise ArgumentError, "No template given" if !template
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                template.__papercraft_compiled_proc.(+'', *pos, **kw, &block)
         
     | 
| 
      
 210 
     | 
    
         
            +
              rescue Exception => e
         
     | 
| 
      
 211 
     | 
    
         
            +
                e.is_a?(Papercraft::Error) ? raise : raise(Papercraft.translate_backtrace(e))
         
     | 
| 
      
 212 
     | 
    
         
            +
              end
         
     | 
| 
      
 213 
     | 
    
         
            +
             
     | 
| 
      
 214 
     | 
    
         
            +
              # Renders the given template to XML with the given arguments. The template can
         
     | 
| 
      
 215 
     | 
    
         
            +
              # be passed either as the first parameter, or as a block, if no parameter is
         
     | 
| 
      
 216 
     | 
    
         
            +
              # given.
         
     | 
| 
      
 217 
     | 
    
         
            +
              #
         
     | 
| 
      
 218 
     | 
    
         
            +
              # @param template [Proc] template proc
         
     | 
| 
      
 219 
     | 
    
         
            +
              # @return [String] XML string
         
     | 
| 
      
 220 
     | 
    
         
            +
              def xml(template = nil, *pos, **kw, &block)
         
     | 
| 
      
 221 
     | 
    
         
            +
                if !template
         
     | 
| 
      
 222 
     | 
    
         
            +
                  template = block
         
     | 
| 
      
 223 
     | 
    
         
            +
                elsif template.is_a?(Template)
         
     | 
| 
      
 224 
     | 
    
         
            +
                  template = template.proc
         
     | 
| 
      
 225 
     | 
    
         
            +
                end
         
     | 
| 
      
 226 
     | 
    
         
            +
                raise ArgumentError, "No template given" if !template
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                template = template.proc if template.is_a?(Template)
         
     | 
| 
      
 229 
     | 
    
         
            +
                template.__papercraft_compiled_proc(mode: :xml).(+'', *pos, **kw, &block)
         
     | 
| 
      
 230 
     | 
    
         
            +
              rescue Exception => e
         
     | 
| 
      
 231 
     | 
    
         
            +
                e.is_a?(Papercraft::Error) ? raise : raise(Papercraft.translate_backtrace(e))
         
     | 
| 
      
 232 
     | 
    
         
            +
              end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
              # Returns a proc that applies the given arguments to the original proc. The
         
     | 
| 
      
 235 
     | 
    
         
            +
              # returned proc calls the *compiled* form of the proc, merging the
         
     | 
| 
      
 236 
     | 
    
         
            +
              # positional and keywords parameters passed to `#apply` with parameters
         
     | 
| 
      
 237 
     | 
    
         
            +
              # passed to the applied proc. If a block is given, it is wrapped in a proc
         
     | 
| 
      
 238 
     | 
    
         
            +
              # that passed merged parameters to the block.
         
     | 
| 
      
 239 
     | 
    
         
            +
              #
         
     | 
| 
      
 240 
     | 
    
         
            +
              # @param template [Proc] template proc
         
     | 
| 
      
 241 
     | 
    
         
            +
              # @param *pos1 [Array<any>] applied positional parameters
         
     | 
| 
      
 242 
     | 
    
         
            +
              # @param **kw1 [Hash<any, any] applied keyword parameters
         
     | 
| 
      
 243 
     | 
    
         
            +
              # @return [Proc] applied proc
         
     | 
| 
      
 244 
     | 
    
         
            +
              def apply(template, *pos1, **kw1, &block1)
         
     | 
| 
      
 245 
     | 
    
         
            +
                template = template.proc if template.is_a?(Template)
         
     | 
| 
      
 246 
     | 
    
         
            +
                compiled = template.__papercraft_compiled_proc
         
     | 
| 
      
 247 
     | 
    
         
            +
                block1_compiled = block1&.__papercraft_compiled_proc
         
     | 
| 
      
 248 
     | 
    
         
            +
             
     | 
| 
      
 249 
     | 
    
         
            +
                ->(__buffer__, *pos2, **kw2, &block2) {
         
     | 
| 
      
 250 
     | 
    
         
            +
                  if block2
         
     | 
| 
      
 251 
     | 
    
         
            +
                    block2_compiled = block1_compiled ?
         
     | 
| 
      
 252 
     | 
    
         
            +
                      ->(__buffer__, *pos3, **kw3) {
         
     | 
| 
      
 253 
     | 
    
         
            +
                        block1_compiled.(__buffer__, *pos3, **kw3, &block2)
         
     | 
| 
      
 254 
     | 
    
         
            +
                      }.__papercraft_compiled! :
         
     | 
| 
      
 255 
     | 
    
         
            +
                      block2.__papercraft_compiled_proc
         
     | 
| 
      
 256 
     | 
    
         
            +
                    compiled.(__buffer__, *pos1, *pos2, **kw1, **kw2, &block2_compiled)
         
     | 
| 
      
 257 
     | 
    
         
            +
                  else
         
     | 
| 
      
 258 
     | 
    
         
            +
                    compiled.(__buffer__, *pos1, *pos2, **kw1, **kw2, &block1_compiled)
         
     | 
| 
      
 259 
     | 
    
         
            +
                  end
         
     | 
| 
      
 260 
     | 
    
         
            +
                }.__papercraft_compiled!
         
     | 
| 
      
 261 
     | 
    
         
            +
              end
         
     | 
| 
      
 262 
     | 
    
         
            +
             
     | 
| 
      
 263 
     | 
    
         
            +
              # Caches and returns the rendered HTML for the template with the given
         
     | 
| 
      
 264 
     | 
    
         
            +
              # arguments.
         
     | 
| 
      
 265 
     | 
    
         
            +
              #
         
     | 
| 
      
 266 
     | 
    
         
            +
              # @param template [Proc] template proc
         
     | 
| 
      
 267 
     | 
    
         
            +
              # @param key [any] Cache key
         
     | 
| 
      
 268 
     | 
    
         
            +
              # @return [String] HTML string
         
     | 
| 
      
 269 
     | 
    
         
            +
              def cache_html(template, key, *, **, &)
         
     | 
| 
      
 270 
     | 
    
         
            +
                template.__papercraft_render_cache[key] ||= html(template, *, **, &)
         
     | 
| 
      
 271 
     | 
    
         
            +
              end
         
     | 
| 
      
 272 
     | 
    
         
            +
             
     | 
| 
      
 273 
     | 
    
         
            +
              # Caches and returns the rendered XML for the template with the given
         
     | 
| 
      
 274 
     | 
    
         
            +
              # arguments.
         
     | 
| 
      
 275 
     | 
    
         
            +
              #
         
     | 
| 
      
 276 
     | 
    
         
            +
              # @param template [Proc] template proc
         
     | 
| 
      
 277 
     | 
    
         
            +
              # @param key [any] Cache key
         
     | 
| 
      
 278 
     | 
    
         
            +
              # @return [String] XML string
         
     | 
| 
      
 279 
     | 
    
         
            +
              def cache_xml(template, key, *, **, &)
         
     | 
| 
      
 280 
     | 
    
         
            +
                template.__papercraft_render_cache[key] ||= xml(template, *, **, &)
         
     | 
| 
      
 281 
     | 
    
         
            +
              end
         
     | 
| 
       156 
282 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: papercraft
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: ' 
     | 
| 
      
 4 
     | 
    
         
            +
              version: '3.0'
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Sharon Rosner
         
     | 
| 
         @@ -142,8 +142,8 @@ homepage: http://github.com/digital-fabric/papercraft 
     | 
|
| 
       142 
142 
     | 
    
         
             
            licenses:
         
     | 
| 
       143 
143 
     | 
    
         
             
            - MIT
         
     | 
| 
       144 
144 
     | 
    
         
             
            metadata:
         
     | 
| 
       145 
     | 
    
         
            -
              homepage_uri: https:// 
     | 
| 
       146 
     | 
    
         
            -
               
     | 
| 
      
 145 
     | 
    
         
            +
              homepage_uri: https://papercraft.noteflakes.com/
         
     | 
| 
      
 146 
     | 
    
         
            +
              source_code_uri: https://github.com/digital-fabric/papercraft
         
     | 
| 
       147 
147 
     | 
    
         
             
              changelog_uri: https://github.com/digital-fabric/papercraft/blob/master/CHANGELOG.md
         
     | 
| 
       148 
148 
     | 
    
         
             
            rdoc_options:
         
     | 
| 
       149 
149 
     | 
    
         
             
            - "--title"
         
     |