OLD | NEW |
(Empty) | |
| 1 overview: | |
| 2 Inverted Section tags and End Section tags are used in combination to wrap a |
| 3 section of the template. |
| 4 |
| 5 These tags' content MUST be a non-whitespace character sequence NOT |
| 6 containing the current closing delimiter; each Inverted Section tag MUST be |
| 7 followed by an End Section tag with the same content within the same |
| 8 section. |
| 9 |
| 10 This tag's content names the data to replace the tag. Name resolution is as |
| 11 follows: |
| 12 1) Split the name on periods; the first part is the name to resolve, any |
| 13 remaining parts should be retained. |
| 14 2) Walk the context stack from top to bottom, finding the first context |
| 15 that is a) a hash containing the name as a key OR b) an object responding |
| 16 to a method with the given name. |
| 17 3) If the context is a hash, the data is the value associated with the |
| 18 name. |
| 19 4) If the context is an object and the method with the given name has an |
| 20 arity of 1, the method SHOULD be called with a String containing the |
| 21 unprocessed contents of the sections; the data is the value returned. |
| 22 5) Otherwise, the data is the value returned by calling the method with |
| 23 the given name. |
| 24 6) If any name parts were retained in step 1, each should be resolved |
| 25 against a context stack containing only the result from the former |
| 26 resolution. If any part fails resolution, the result should be considered |
| 27 falsey, and should interpolate as the empty string. |
| 28 If the data is not of a list type, it is coerced into a list as follows: if |
| 29 the data is truthy (e.g. `!!data == true`), use a single-element list |
| 30 containing the data, otherwise use an empty list. |
| 31 |
| 32 This section MUST NOT be rendered unless the data list is empty. |
| 33 |
| 34 Inverted Section and End Section tags SHOULD be treated as standalone when |
| 35 appropriate. |
| 36 tests: |
| 37 - name: Falsey |
| 38 desc: Falsey sections should have their contents rendered. |
| 39 data: { boolean: false } |
| 40 template: '"{{^boolean}}This should be rendered.{{/boolean}}"' |
| 41 expected: '"This should be rendered."' |
| 42 |
| 43 - name: Truthy |
| 44 desc: Truthy sections should have their contents omitted. |
| 45 data: { boolean: true } |
| 46 template: '"{{^boolean}}This should not be rendered.{{/boolean}}"' |
| 47 expected: '""' |
| 48 |
| 49 - name: Context |
| 50 desc: Objects and hashes should behave like truthy values. |
| 51 data: { context: { name: 'Joe' } } |
| 52 template: '"{{^context}}Hi {{name}}.{{/context}}"' |
| 53 expected: '""' |
| 54 |
| 55 - name: List |
| 56 desc: Lists should behave like truthy values. |
| 57 data: { list: [ { n: 1 }, { n: 2 }, { n: 3 } ] } |
| 58 template: '"{{^list}}{{n}}{{/list}}"' |
| 59 expected: '""' |
| 60 |
| 61 - name: Empty List |
| 62 desc: Empty lists should behave like falsey values. |
| 63 data: { list: [ ] } |
| 64 template: '"{{^list}}Yay lists!{{/list}}"' |
| 65 expected: '"Yay lists!"' |
| 66 |
| 67 - name: Doubled |
| 68 desc: Multiple inverted sections per template should be permitted. |
| 69 data: { bool: false, two: 'second' } |
| 70 template: | |
| 71 {{^bool}} |
| 72 * first |
| 73 {{/bool}} |
| 74 * {{two}} |
| 75 {{^bool}} |
| 76 * third |
| 77 {{/bool}} |
| 78 expected: | |
| 79 * first |
| 80 * second |
| 81 * third |
| 82 |
| 83 - name: Nested (Falsey) |
| 84 desc: Nested falsey sections should have their contents rendered. |
| 85 data: { bool: false } |
| 86 template: "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |" |
| 87 expected: "| A B C D E |" |
| 88 |
| 89 - name: Nested (Truthy) |
| 90 desc: Nested truthy sections should be omitted. |
| 91 data: { bool: true } |
| 92 template: "| A {{^bool}}B {{^bool}}C{{/bool}} D{{/bool}} E |" |
| 93 expected: "| A E |" |
| 94 |
| 95 - name: Context Misses |
| 96 desc: Failed context lookups should be considered falsey. |
| 97 data: { } |
| 98 template: "[{{^missing}}Cannot find key 'missing'!{{/missing}}]" |
| 99 expected: "[Cannot find key 'missing'!]" |
| 100 |
| 101 # Dotted Names |
| 102 |
| 103 - name: Dotted Names - Truthy |
| 104 desc: Dotted names should be valid for Inverted Section tags. |
| 105 data: { a: { b: { c: true } } } |
| 106 template: '"{{^a.b.c}}Not Here{{/a.b.c}}" == ""' |
| 107 expected: '"" == ""' |
| 108 |
| 109 - name: Dotted Names - Falsey |
| 110 desc: Dotted names should be valid for Inverted Section tags. |
| 111 data: { a: { b: { c: false } } } |
| 112 template: '"{{^a.b.c}}Not Here{{/a.b.c}}" == "Not Here"' |
| 113 expected: '"Not Here" == "Not Here"' |
| 114 |
| 115 - name: Dotted Names - Broken Chains |
| 116 desc: Dotted names that cannot be resolved should be considered falsey. |
| 117 data: { a: { } } |
| 118 template: '"{{^a.b.c}}Not Here{{/a.b.c}}" == "Not Here"' |
| 119 expected: '"Not Here" == "Not Here"' |
| 120 |
| 121 # Whitespace Sensitivity |
| 122 |
| 123 - name: Surrounding Whitespace |
| 124 desc: Inverted sections should not alter surrounding whitespace. |
| 125 data: { boolean: false } |
| 126 template: " | {{^boolean}}\t|\t{{/boolean}} | \n" |
| 127 expected: " | \t|\t | \n" |
| 128 |
| 129 - name: Internal Whitespace |
| 130 desc: Inverted should not alter internal whitespace. |
| 131 data: { boolean: false } |
| 132 template: " | {{^boolean}} {{! Important Whitespace }}\n {{/boolean}} | \n" |
| 133 expected: " | \n | \n" |
| 134 |
| 135 - name: Indented Inline Sections |
| 136 desc: Single-line sections should not alter surrounding whitespace. |
| 137 data: { boolean: false } |
| 138 template: " {{^boolean}}NO{{/boolean}}\n {{^boolean}}WAY{{/boolean}}\n" |
| 139 expected: " NO\n WAY\n" |
| 140 |
| 141 - name: Standalone Lines |
| 142 desc: Standalone lines should be removed from the template. |
| 143 data: { boolean: false } |
| 144 template: | |
| 145 | This Is |
| 146 {{^boolean}} |
| 147 | |
| 148 {{/boolean}} |
| 149 | A Line |
| 150 expected: | |
| 151 | This Is |
| 152 | |
| 153 | A Line |
| 154 |
| 155 - name: Standalone Indented Lines |
| 156 desc: Standalone indented lines should be removed from the template. |
| 157 data: { boolean: false } |
| 158 template: | |
| 159 | This Is |
| 160 {{^boolean}} |
| 161 | |
| 162 {{/boolean}} |
| 163 | A Line |
| 164 expected: | |
| 165 | This Is |
| 166 | |
| 167 | A Line |
| 168 |
| 169 - name: Standalone Line Endings |
| 170 desc: '"\r\n" should be considered a newline for standalone tags.' |
| 171 data: { boolean: false } |
| 172 template: "|\r\n{{^boolean}}\r\n{{/boolean}}\r\n|" |
| 173 expected: "|\r\n|" |
| 174 |
| 175 - name: Standalone Without Previous Line |
| 176 desc: Standalone tags should not require a newline to precede them. |
| 177 data: { boolean: false } |
| 178 template: " {{^boolean}}\n^{{/boolean}}\n/" |
| 179 expected: "^\n/" |
| 180 |
| 181 - name: Standalone Without Newline |
| 182 desc: Standalone tags should not require a newline to follow them. |
| 183 data: { boolean: false } |
| 184 template: "^{{^boolean}}\n/\n {{/boolean}}" |
| 185 expected: "^\n/\n" |
| 186 |
| 187 # Whitespace Insensitivity |
| 188 |
| 189 - name: Padding |
| 190 desc: Superfluous in-tag whitespace should be ignored. |
| 191 data: { boolean: false } |
| 192 template: '|{{^ boolean }}={{/ boolean }}|' |
| 193 expected: '|=|' |
OLD | NEW |