express-hbs 2.4.2 → 2.5.1

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.
Files changed (269) hide show
  1. package/.claude/worktrees/node-20-26-migration-7de0c3/.editorconfig +8 -0
  2. package/.claude/worktrees/node-20-26-migration-7de0c3/.github/workflows/publish.yml +73 -0
  3. package/.claude/worktrees/node-20-26-migration-7de0c3/.github/workflows/test.yml +48 -0
  4. package/.claude/worktrees/node-20-26-migration-7de0c3/.jsbeautifyrc +17 -0
  5. package/.claude/worktrees/node-20-26-migration-7de0c3/.nvmrc +1 -0
  6. package/.claude/worktrees/node-20-26-migration-7de0c3/.nycrc.json +16 -0
  7. package/.claude/worktrees/node-20-26-migration-7de0c3/.oxfmtrc.json +19 -0
  8. package/.claude/worktrees/node-20-26-migration-7de0c3/.oxlintrc.json +32 -0
  9. package/.claude/worktrees/node-20-26-migration-7de0c3/AGENTS.md +40 -0
  10. package/.claude/worktrees/node-20-26-migration-7de0c3/LICENSE +21 -0
  11. package/.claude/worktrees/node-20-26-migration-7de0c3/README.md +333 -0
  12. package/.claude/worktrees/node-20-26-migration-7de0c3/SECURITY.md +9 -0
  13. package/.claude/worktrees/node-20-26-migration-7de0c3/example/app-layoutsDir.js +99 -0
  14. package/.claude/worktrees/node-20-26-migration-7de0c3/example/app.js +103 -0
  15. package/.claude/worktrees/node-20-26-migration-7de0c3/example/public/css/style.css +17 -0
  16. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/fruits/details-layoutsDir.hbs +3 -0
  17. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/fruits/details.hbs +4 -0
  18. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/fruits/index-layoutsDir.hbs +20 -0
  19. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/fruits/index.hbs +20 -0
  20. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/index.hbs +34 -0
  21. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/layout/default.hbs +13 -0
  22. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/layout/fruit-details.hbs +9 -0
  23. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/layout/fruits.hbs +6 -0
  24. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/layout/html-struct.hbs +21 -0
  25. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/layout/veggie-details.hbs +9 -0
  26. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/layout/veggie.hbs +6 -0
  27. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/partials/scripts.hbs +5 -0
  28. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/partials/sub/comment.hbs +1 -0
  29. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/partials-other/other.hbs +1 -0
  30. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/replace.hbs +6 -0
  31. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/tos.txt +3 -0
  32. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/veggies/details.hbs +1 -0
  33. package/.claude/worktrees/node-20-26-migration-7de0c3/example/views/veggies.hbs +17 -0
  34. package/.claude/worktrees/node-20-26-migration-7de0c3/index.js +1 -0
  35. package/.claude/worktrees/node-20-26-migration-7de0c3/lib/generate-id.js +16 -0
  36. package/.claude/worktrees/node-20-26-migration-7de0c3/lib/hbs.js +671 -0
  37. package/.claude/worktrees/node-20-26-migration-7de0c3/lib/resolver.js +59 -0
  38. package/.claude/worktrees/node-20-26-migration-7de0c3/package.json +61 -0
  39. package/.claude/worktrees/node-20-26-migration-7de0c3/pnpm-lock.yaml +3424 -0
  40. package/.claude/worktrees/node-20-26-migration-7de0c3/pnpm-workspace.yaml +6 -0
  41. package/.claude/worktrees/node-20-26-migration-7de0c3/renovate.json +13 -0
  42. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/async/index.js +139 -0
  43. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/async/views/failer.hbs +4 -0
  44. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/async/views/index.hbs +16 -0
  45. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/async/views/layout.hbs +1 -0
  46. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/i18n/index.js +57 -0
  47. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/i18n/locales/en.json +8 -0
  48. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/i18n/locales/fr.json +8 -0
  49. package/.claude/worktrees/node-20-26-migration-7de0c3/test/apps/i18n/views/index.hbs +3 -0
  50. package/.claude/worktrees/node-20-26-migration-7de0c3/test/asyncSpecs.js +69 -0
  51. package/.claude/worktrees/node-20-26-migration-7de0c3/test/cacheSpecs.js +135 -0
  52. package/.claude/worktrees/node-20-26-migration-7de0c3/test/customExtension.js +35 -0
  53. package/.claude/worktrees/node-20-26-migration-7de0c3/test/handlebarsSpecs.js +92 -0
  54. package/.claude/worktrees/node-20-26-migration-7de0c3/test/helperSpecs.js +58 -0
  55. package/.claude/worktrees/node-20-26-migration-7de0c3/test/helpers.js +24 -0
  56. package/.claude/worktrees/node-20-26-migration-7de0c3/test/i18nSpecs.js +36 -0
  57. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/144/index.hbs +1 -0
  58. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/153/index.hbs +3 -0
  59. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/21/views/index.hbs +1 -0
  60. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/21/views/layouts/default.hbs +1 -0
  61. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/21/views/layouts/sub/child.hbs +1 -0
  62. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/21/views/sub/relativeLayout.hbs +1 -0
  63. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/21/views/sub/sub.hbs +1 -0
  64. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/21/views/useLayoutInDir.hbs +1 -0
  65. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/22/layout1.hbs +1 -0
  66. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/22/layout2.hbs +1 -0
  67. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/22/template.hbs +1 -0
  68. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/empty.hbs +0 -0
  69. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/emptyComment.hbs +1 -0
  70. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/emptyPartial.hbs +1 -0
  71. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/index.hbs +4 -0
  72. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/layout.hbs +1 -0
  73. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/partials/custom/comment-only.hbs +1 -0
  74. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/partials/custom/empty.hbs +0 -0
  75. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/23/partials/hello.hbs +1 -0
  76. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/49/error.hbs +1 -0
  77. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/49/front/error.hbs +1 -0
  78. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/49/index.hbs +2 -0
  79. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/49/layouts/default.hbs +1 -0
  80. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/49/partial.hbs +1 -0
  81. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/49/partials/partial-error.hbs +1 -0
  82. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/53/default.hbs +15 -0
  83. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/53/index.hbs +7 -0
  84. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/53/partials/.gitkeep +0 -0
  85. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/59/index.hbs +2 -0
  86. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/62/basic.hbs +2 -0
  87. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/62/block.hbs +11 -0
  88. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/73/index.hbs +5 -0
  89. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/73/partials/partial.hbs +6 -0
  90. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/76/mypartial.hbs +0 -0
  91. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/84/index.hbs +1 -0
  92. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues/84/partials/abc/def/ghi/test.hbs +1 -0
  93. package/.claude/worktrees/node-20-26-migration-7de0c3/test/issues.js +490 -0
  94. package/.claude/worktrees/node-20-26-migration-7de0c3/test/layoutSpecs.js +146 -0
  95. package/.claude/worktrees/node-20-26-migration-7de0c3/test/localTemplateOptions/data-access-template.hbs +1 -0
  96. package/.claude/worktrees/node-20-26-migration-7de0c3/test/localTemplateOptions/template.hbs +1 -0
  97. package/.claude/worktrees/node-20-26-migration-7de0c3/test/localTemplateOptions.js +125 -0
  98. package/.claude/worktrees/node-20-26-migration-7de0c3/test/multiple.js +115 -0
  99. package/.claude/worktrees/node-20-26-migration-7de0c3/test/nonExpress.js +36 -0
  100. package/.claude/worktrees/node-20-26-migration-7de0c3/test/optionsSpecs.js +22 -0
  101. package/.claude/worktrees/node-20-26-migration-7de0c3/test/resolverSpecs.js +54 -0
  102. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/beautify/expected.hbs +9 -0
  103. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/beautify/index.hbs +2 -0
  104. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/customExtension/layout.server.view.html +1 -0
  105. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/customExtension/partialsDir/partial1.server.view.html +1 -0
  106. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/customExtension/partialsDir/partial2.server.view.html +1 -0
  107. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/customExtension/partialsDir/subs/subPartial1.server.view.html +1 -0
  108. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/customExtension/partialsDir/subs/subPartial2.server.view.html +1 -0
  109. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/customExtension/template.server.view.html +5 -0
  110. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/disableLayoutDirective/aside.hbs +1 -0
  111. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/disableLayoutDirective/index.hbs +2 -0
  112. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/disableLayoutDirective/layouts/default.hbs +1 -0
  113. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/helpers/home/async.hbs +6 -0
  114. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/helpers/home/index.hbs +3 -0
  115. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/helpers/layouts/default.hbs +1 -0
  116. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/multiple/views1/collide.hbs +1 -0
  117. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/multiple/views1/error.hbs +1 -0
  118. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/multiple/views1/test1.hbs +1 -0
  119. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/multiple/views2/collide.hbs +1 -0
  120. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/multiple/views2/error.hbs +1 -0
  121. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/multiple/views2/test2.hbs +1 -0
  122. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/viewsDir/layouts/default.hbs +1 -0
  123. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/viewsDir/sub/directive.hbs +2 -0
  124. package/.claude/worktrees/node-20-26-migration-7de0c3/test/views/viewsDir/sub/lay.hbs +1 -0
  125. package/.claude/worktrees/security-patches-review-c621ea/.editorconfig +8 -0
  126. package/.claude/worktrees/security-patches-review-c621ea/.github/workflows/publish.yml +73 -0
  127. package/.claude/worktrees/security-patches-review-c621ea/.github/workflows/test.yml +48 -0
  128. package/.claude/worktrees/security-patches-review-c621ea/.jsbeautifyrc +17 -0
  129. package/.claude/worktrees/security-patches-review-c621ea/.nvmrc +1 -0
  130. package/.claude/worktrees/security-patches-review-c621ea/.nycrc.json +16 -0
  131. package/.claude/worktrees/security-patches-review-c621ea/.oxfmtrc.json +19 -0
  132. package/.claude/worktrees/security-patches-review-c621ea/.oxlintrc.json +32 -0
  133. package/.claude/worktrees/security-patches-review-c621ea/AGENTS.md +40 -0
  134. package/.claude/worktrees/security-patches-review-c621ea/LICENSE +21 -0
  135. package/.claude/worktrees/security-patches-review-c621ea/README.md +333 -0
  136. package/.claude/worktrees/security-patches-review-c621ea/SECURITY.md +9 -0
  137. package/.claude/worktrees/security-patches-review-c621ea/example/app-layoutsDir.js +99 -0
  138. package/.claude/worktrees/security-patches-review-c621ea/example/app.js +103 -0
  139. package/.claude/worktrees/security-patches-review-c621ea/example/public/css/style.css +17 -0
  140. package/.claude/worktrees/security-patches-review-c621ea/example/views/fruits/details-layoutsDir.hbs +3 -0
  141. package/.claude/worktrees/security-patches-review-c621ea/example/views/fruits/details.hbs +4 -0
  142. package/.claude/worktrees/security-patches-review-c621ea/example/views/fruits/index-layoutsDir.hbs +20 -0
  143. package/.claude/worktrees/security-patches-review-c621ea/example/views/fruits/index.hbs +20 -0
  144. package/.claude/worktrees/security-patches-review-c621ea/example/views/index.hbs +34 -0
  145. package/.claude/worktrees/security-patches-review-c621ea/example/views/layout/default.hbs +13 -0
  146. package/.claude/worktrees/security-patches-review-c621ea/example/views/layout/fruit-details.hbs +9 -0
  147. package/.claude/worktrees/security-patches-review-c621ea/example/views/layout/fruits.hbs +6 -0
  148. package/.claude/worktrees/security-patches-review-c621ea/example/views/layout/html-struct.hbs +21 -0
  149. package/.claude/worktrees/security-patches-review-c621ea/example/views/layout/veggie-details.hbs +9 -0
  150. package/.claude/worktrees/security-patches-review-c621ea/example/views/layout/veggie.hbs +6 -0
  151. package/.claude/worktrees/security-patches-review-c621ea/example/views/partials/scripts.hbs +5 -0
  152. package/.claude/worktrees/security-patches-review-c621ea/example/views/partials/sub/comment.hbs +1 -0
  153. package/.claude/worktrees/security-patches-review-c621ea/example/views/partials-other/other.hbs +1 -0
  154. package/.claude/worktrees/security-patches-review-c621ea/example/views/replace.hbs +6 -0
  155. package/.claude/worktrees/security-patches-review-c621ea/example/views/tos.txt +3 -0
  156. package/.claude/worktrees/security-patches-review-c621ea/example/views/veggies/details.hbs +1 -0
  157. package/.claude/worktrees/security-patches-review-c621ea/example/views/veggies.hbs +17 -0
  158. package/.claude/worktrees/security-patches-review-c621ea/index.js +1 -0
  159. package/.claude/worktrees/security-patches-review-c621ea/lib/generate-id.js +16 -0
  160. package/.claude/worktrees/security-patches-review-c621ea/lib/hbs.js +665 -0
  161. package/.claude/worktrees/security-patches-review-c621ea/lib/resolver.js +59 -0
  162. package/.claude/worktrees/security-patches-review-c621ea/package.json +57 -0
  163. package/.claude/worktrees/security-patches-review-c621ea/pnpm-lock.yaml +3424 -0
  164. package/.claude/worktrees/security-patches-review-c621ea/pnpm-workspace.yaml +6 -0
  165. package/.claude/worktrees/security-patches-review-c621ea/renovate.json +6 -0
  166. package/.claude/worktrees/security-patches-review-c621ea/test/apps/async/index.js +139 -0
  167. package/.claude/worktrees/security-patches-review-c621ea/test/apps/async/views/failer.hbs +4 -0
  168. package/.claude/worktrees/security-patches-review-c621ea/test/apps/async/views/index.hbs +16 -0
  169. package/.claude/worktrees/security-patches-review-c621ea/test/apps/async/views/layout.hbs +1 -0
  170. package/.claude/worktrees/security-patches-review-c621ea/test/apps/i18n/index.js +57 -0
  171. package/.claude/worktrees/security-patches-review-c621ea/test/apps/i18n/locales/en.json +8 -0
  172. package/.claude/worktrees/security-patches-review-c621ea/test/apps/i18n/locales/fr.json +8 -0
  173. package/.claude/worktrees/security-patches-review-c621ea/test/apps/i18n/views/index.hbs +3 -0
  174. package/.claude/worktrees/security-patches-review-c621ea/test/asyncSpecs.js +69 -0
  175. package/.claude/worktrees/security-patches-review-c621ea/test/cacheSpecs.js +135 -0
  176. package/.claude/worktrees/security-patches-review-c621ea/test/customExtension.js +35 -0
  177. package/.claude/worktrees/security-patches-review-c621ea/test/handlebarsSpecs.js +92 -0
  178. package/.claude/worktrees/security-patches-review-c621ea/test/helperSpecs.js +58 -0
  179. package/.claude/worktrees/security-patches-review-c621ea/test/helpers.js +24 -0
  180. package/.claude/worktrees/security-patches-review-c621ea/test/i18nSpecs.js +36 -0
  181. package/.claude/worktrees/security-patches-review-c621ea/test/issues/144/index.hbs +1 -0
  182. package/.claude/worktrees/security-patches-review-c621ea/test/issues/153/index.hbs +3 -0
  183. package/.claude/worktrees/security-patches-review-c621ea/test/issues/21/views/index.hbs +1 -0
  184. package/.claude/worktrees/security-patches-review-c621ea/test/issues/21/views/layouts/default.hbs +1 -0
  185. package/.claude/worktrees/security-patches-review-c621ea/test/issues/21/views/layouts/sub/child.hbs +1 -0
  186. package/.claude/worktrees/security-patches-review-c621ea/test/issues/21/views/sub/relativeLayout.hbs +1 -0
  187. package/.claude/worktrees/security-patches-review-c621ea/test/issues/21/views/sub/sub.hbs +1 -0
  188. package/.claude/worktrees/security-patches-review-c621ea/test/issues/21/views/useLayoutInDir.hbs +1 -0
  189. package/.claude/worktrees/security-patches-review-c621ea/test/issues/22/layout1.hbs +1 -0
  190. package/.claude/worktrees/security-patches-review-c621ea/test/issues/22/layout2.hbs +1 -0
  191. package/.claude/worktrees/security-patches-review-c621ea/test/issues/22/template.hbs +1 -0
  192. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/empty.hbs +0 -0
  193. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/emptyComment.hbs +1 -0
  194. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/emptyPartial.hbs +1 -0
  195. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/index.hbs +4 -0
  196. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/layout.hbs +1 -0
  197. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/partials/custom/comment-only.hbs +1 -0
  198. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/partials/custom/empty.hbs +0 -0
  199. package/.claude/worktrees/security-patches-review-c621ea/test/issues/23/partials/hello.hbs +1 -0
  200. package/.claude/worktrees/security-patches-review-c621ea/test/issues/49/error.hbs +1 -0
  201. package/.claude/worktrees/security-patches-review-c621ea/test/issues/49/front/error.hbs +1 -0
  202. package/.claude/worktrees/security-patches-review-c621ea/test/issues/49/index.hbs +2 -0
  203. package/.claude/worktrees/security-patches-review-c621ea/test/issues/49/layouts/default.hbs +1 -0
  204. package/.claude/worktrees/security-patches-review-c621ea/test/issues/49/partial.hbs +1 -0
  205. package/.claude/worktrees/security-patches-review-c621ea/test/issues/49/partials/partial-error.hbs +1 -0
  206. package/.claude/worktrees/security-patches-review-c621ea/test/issues/53/default.hbs +15 -0
  207. package/.claude/worktrees/security-patches-review-c621ea/test/issues/53/index.hbs +7 -0
  208. package/.claude/worktrees/security-patches-review-c621ea/test/issues/53/partials/.gitkeep +0 -0
  209. package/.claude/worktrees/security-patches-review-c621ea/test/issues/59/index.hbs +2 -0
  210. package/.claude/worktrees/security-patches-review-c621ea/test/issues/62/basic.hbs +2 -0
  211. package/.claude/worktrees/security-patches-review-c621ea/test/issues/62/block.hbs +11 -0
  212. package/.claude/worktrees/security-patches-review-c621ea/test/issues/73/index.hbs +5 -0
  213. package/.claude/worktrees/security-patches-review-c621ea/test/issues/73/partials/partial.hbs +6 -0
  214. package/.claude/worktrees/security-patches-review-c621ea/test/issues/76/mypartial.hbs +0 -0
  215. package/.claude/worktrees/security-patches-review-c621ea/test/issues/84/index.hbs +1 -0
  216. package/.claude/worktrees/security-patches-review-c621ea/test/issues/84/partials/abc/def/ghi/test.hbs +1 -0
  217. package/.claude/worktrees/security-patches-review-c621ea/test/issues.js +490 -0
  218. package/.claude/worktrees/security-patches-review-c621ea/test/layoutSpecs.js +116 -0
  219. package/.claude/worktrees/security-patches-review-c621ea/test/localTemplateOptions/data-access-template.hbs +1 -0
  220. package/.claude/worktrees/security-patches-review-c621ea/test/localTemplateOptions/template.hbs +1 -0
  221. package/.claude/worktrees/security-patches-review-c621ea/test/localTemplateOptions.js +125 -0
  222. package/.claude/worktrees/security-patches-review-c621ea/test/multiple.js +115 -0
  223. package/.claude/worktrees/security-patches-review-c621ea/test/nonExpress.js +36 -0
  224. package/.claude/worktrees/security-patches-review-c621ea/test/optionsSpecs.js +22 -0
  225. package/.claude/worktrees/security-patches-review-c621ea/test/resolverSpecs.js +54 -0
  226. package/.claude/worktrees/security-patches-review-c621ea/test/views/beautify/expected.hbs +9 -0
  227. package/.claude/worktrees/security-patches-review-c621ea/test/views/beautify/index.hbs +2 -0
  228. package/.claude/worktrees/security-patches-review-c621ea/test/views/customExtension/layout.server.view.html +1 -0
  229. package/.claude/worktrees/security-patches-review-c621ea/test/views/customExtension/partialsDir/partial1.server.view.html +1 -0
  230. package/.claude/worktrees/security-patches-review-c621ea/test/views/customExtension/partialsDir/partial2.server.view.html +1 -0
  231. package/.claude/worktrees/security-patches-review-c621ea/test/views/customExtension/partialsDir/subs/subPartial1.server.view.html +1 -0
  232. package/.claude/worktrees/security-patches-review-c621ea/test/views/customExtension/partialsDir/subs/subPartial2.server.view.html +1 -0
  233. package/.claude/worktrees/security-patches-review-c621ea/test/views/customExtension/template.server.view.html +5 -0
  234. package/.claude/worktrees/security-patches-review-c621ea/test/views/disableLayoutDirective/aside.hbs +1 -0
  235. package/.claude/worktrees/security-patches-review-c621ea/test/views/disableLayoutDirective/index.hbs +2 -0
  236. package/.claude/worktrees/security-patches-review-c621ea/test/views/disableLayoutDirective/layouts/default.hbs +1 -0
  237. package/.claude/worktrees/security-patches-review-c621ea/test/views/helpers/home/async.hbs +6 -0
  238. package/.claude/worktrees/security-patches-review-c621ea/test/views/helpers/home/index.hbs +3 -0
  239. package/.claude/worktrees/security-patches-review-c621ea/test/views/helpers/layouts/default.hbs +1 -0
  240. package/.claude/worktrees/security-patches-review-c621ea/test/views/multiple/views1/collide.hbs +1 -0
  241. package/.claude/worktrees/security-patches-review-c621ea/test/views/multiple/views1/error.hbs +1 -0
  242. package/.claude/worktrees/security-patches-review-c621ea/test/views/multiple/views1/test1.hbs +1 -0
  243. package/.claude/worktrees/security-patches-review-c621ea/test/views/multiple/views2/collide.hbs +1 -0
  244. package/.claude/worktrees/security-patches-review-c621ea/test/views/multiple/views2/error.hbs +1 -0
  245. package/.claude/worktrees/security-patches-review-c621ea/test/views/multiple/views2/test2.hbs +1 -0
  246. package/.claude/worktrees/security-patches-review-c621ea/test/views/viewsDir/layouts/default.hbs +1 -0
  247. package/.claude/worktrees/security-patches-review-c621ea/test/views/viewsDir/sub/directive.hbs +2 -0
  248. package/.claude/worktrees/security-patches-review-c621ea/test/views/viewsDir/sub/lay.hbs +1 -0
  249. package/README.md +3 -2
  250. package/example/app-layoutsDir.js +2 -1
  251. package/example/app.js +2 -1
  252. package/lib/hbs.js +24 -4
  253. package/lib/resolver.js +10 -3
  254. package/package.json +2 -2
  255. package/test/apps/async/index.js +2 -1
  256. package/test/apps/i18n/index.js +2 -1
  257. package/test/asyncSpecs.js +60 -0
  258. package/test/customExtension.js +2 -1
  259. package/test/handlebarsSpecs.js +19 -0
  260. package/test/helperSpecs.js +4 -2
  261. package/test/issues.js +48 -20
  262. package/test/layoutSpecs.js +48 -0
  263. package/test/localTemplateOptions.js +12 -4
  264. package/test/multiple.js +3 -1
  265. package/test/nonExpress.js +4 -2
  266. package/test/optionsSpecs.js +1 -1
  267. package/test/resolverSpecs.js +70 -0
  268. package/test/views/asyncPrefix/body.hbs +1 -0
  269. package/test/views/asyncPrefix/index.hbs +1 -0
@@ -5,6 +5,7 @@ var assert = require('assert');
5
5
  var hbs = require('..');
6
6
  var asyncApp = require('./apps/async');
7
7
  var resolver = require('../lib/resolver');
8
+ var H = require('./helpers');
8
9
 
9
10
  function makeUserRequest(app, user, cb) {
10
11
  request(app)
@@ -66,4 +67,63 @@ describe('async', function() {
66
67
  done();
67
68
  });
68
69
  });
70
+
71
+ describe('literal async id prefix in data', function () {
72
+ var dirname = __dirname + '/views/asyncPrefix';
73
+
74
+ function createRender() {
75
+ var hb = hbs.create();
76
+ hb.registerAsyncHelper('async', function (s, cb) {
77
+ setTimeout(function () {
78
+ cb(new hb.SafeString('async-' + s));
79
+ }, 1);
80
+ });
81
+ return hb.express4({ viewsDir: dirname });
82
+ }
83
+
84
+ function renderValue(file, locals, cb) {
85
+ var render = createRender();
86
+ render(dirname + '/' + file, H.createLocals('express4', dirname, locals), cb);
87
+ }
88
+
89
+ it('renders prefix text in the middle of data verbatim', function (done) {
90
+ renderValue('body.hbs', { body: 'x __aSyNcId__ y' }, function (err, html) {
91
+ if (err) return done(err);
92
+ assert.equal(html.trim(), 'hello x __aSyNcId__ y');
93
+ done();
94
+ });
95
+ });
96
+
97
+ [
98
+ '__aSyNcId__',
99
+ '__aSyNcId__ start',
100
+ 'middle __aSyNcId__ text',
101
+ '__aSyNcId__<_abcdefgh__',
102
+ 'x __aSyNcId__<_abcdefgh__ y',
103
+ ].forEach(function (value) {
104
+ it('renders ' + JSON.stringify(value) + ' escaped and unescaped', function (done) {
105
+ renderValue('index.hbs', { value: value }, function (err, html) {
106
+ if (err) return done(err);
107
+ var escaped = hbs.Utils.escapeExpression(value);
108
+ assert.equal(html.trim(), 'hello ' + escaped + '|' + value + '|async-a');
109
+ done();
110
+ });
111
+ });
112
+ });
113
+
114
+ it('renders prefix text in data alongside nested async helpers', function (done) {
115
+ var app = asyncApp.create(hbs.create(), 'production');
116
+ request(app)
117
+ .get('/')
118
+ .set('Cookie', 'user=__aSyNcId__')
119
+ .end(function (err, res) {
120
+ if (err) return done(err);
121
+ assert.notEqual(res.text.indexOf('Hello, __aSyNcId__'), -1);
122
+ assert.notEqual(res.text.indexOf('This should welcome __aSyNcId__.'), -1);
123
+ assert.notEqual(res.text.indexOf('Title 1 Comment 1'), -1);
124
+ assert.equal(res.text.indexOf('This should not show!'), -1);
125
+ done();
126
+ });
127
+ });
128
+ });
69
129
  });
@@ -11,7 +11,8 @@ describe('custom extension for partials view', function() {
11
11
  var dirname = path.join(__dirname, 'views/customExtension');
12
12
  var render = hbs.create().express4({
13
13
  extname: '.server.view.html',
14
- partialsDir: dirname + '/partialsDir'
14
+ partialsDir: dirname + '/partialsDir',
15
+ restrictLayoutsTo: dirname
15
16
  });
16
17
 
17
18
  it('should allow rendering multiple partials with custom extension', function(done) {
@@ -92,4 +92,23 @@ describe('express-hbs', function() {
92
92
  assert(hbs !== hbs2 && hbs !== hbs3 && hbs2 !== hbs3);
93
93
  });
94
94
  });
95
+
96
+ describe('compile', function () {
97
+ it('should pad a template that ends with its only closing tag', function () {
98
+ var hb = hbs.create();
99
+ hb.onCompile = function (exhbs, source) {
100
+ return source;
101
+ };
102
+ assert.equal(hb.compile('{{! comment }}'), '{{! comment }} ');
103
+ });
104
+
105
+ it('should not pad a one-character template', function () {
106
+ var hb = hbs.create();
107
+ hb.onCompile = function (exhbs, source) {
108
+ return source;
109
+ };
110
+ assert.equal(hb.compile('x'), 'x');
111
+ assert.equal(hb.compile(''), '');
112
+ });
113
+ });
95
114
  });
@@ -15,7 +15,8 @@ describe('helpers', function() {
15
15
  var hb = hbs.create();
16
16
  hb.registerHelper("sync", sync);
17
17
  var render = hb.express3({
18
- viewsDir: dirname
18
+ viewsDir: dirname,
19
+ restrictLayoutsTo: dirname
19
20
  });
20
21
  var locals = H.createLocals('express3', dirname);
21
22
 
@@ -38,7 +39,8 @@ describe('helpers', function() {
38
39
  hb.registerAsyncHelper("async", async);
39
40
 
40
41
  var render = hb.express3({
41
- viewsDir: dirname
42
+ viewsDir: dirname,
43
+ restrictLayoutsTo: dirname
42
44
  });
43
45
  var locals = H.createLocals('express3', dirname);
44
46
 
package/test/issues.js CHANGED
@@ -9,7 +9,9 @@ describe('issue-22 template', function() {
9
9
  var dirname = path.join(__dirname, 'issues/22');
10
10
 
11
11
  it('should use multiple layouts with caching', function(done) {
12
- var render = hbs.create().express3({});
12
+ var render = hbs.create().express3({
13
+ restrictLayoutsTo: dirname
14
+ });
13
15
  var locals1 = H.createLocals('express3', dirname, { layout: 'layout1', cache: true });
14
16
  var locals2 = H.createLocals('express3', dirname, { layout: 'layout2', cache: true });
15
17
 
@@ -30,7 +32,8 @@ describe('issue-23', function() {
30
32
 
31
33
  it('should not pass an empty or missing partial to handlebars', function(done) {
32
34
  var render = hbs.create().express3({
33
- partialsDir: [dirname + '/partials']
35
+ partialsDir: [dirname + '/partials'],
36
+ restrictLayoutsTo: dirname
34
37
  });
35
38
 
36
39
  function check(err, html) {
@@ -43,7 +46,8 @@ describe('issue-23', function() {
43
46
 
44
47
  it('should handle empty string', function(done) {
45
48
  var render = hbs.create().express3({
46
- partialsDir: [dirname + '/partials']
49
+ partialsDir: [dirname + '/partials'],
50
+ restrictLayoutsTo: dirname
47
51
  });
48
52
 
49
53
  function check(err, html) {
@@ -58,7 +62,8 @@ describe('issue-23', function() {
58
62
  it('should register empty partial', function(done) {
59
63
  var hb = hbs.create();
60
64
  var render = hb.express3({
61
- partialsDir: [dirname + '/partials']
65
+ partialsDir: [dirname + '/partials'],
66
+ restrictLayoutsTo: dirname
62
67
  });
63
68
  hb.handlebars.registerPartial('emptyPartial', '');
64
69
 
@@ -82,7 +87,8 @@ describe('issue-23', function() {
82
87
  it('should register partial that results in empty string (comment)', function(done) {
83
88
  var hb = hbs.create();
84
89
  var render = hb.express3({
85
- partialsDir: [dirname + '/partials']
90
+ partialsDir: [dirname + '/partials'],
91
+ restrictLayoutsTo: dirname
86
92
  });
87
93
  // this fails
88
94
  //hb.handlebars.registerPartial('emptyComment', '{{! just a comment}}');
@@ -110,7 +116,8 @@ describe('issue-23', function() {
110
116
  describe('issue-21', function() {
111
117
  var dirname = path.join(__dirname, 'issues/21');
112
118
  var render = hbs.create().express3({
113
- layoutsDir: dirname + '/views/layouts'
119
+ layoutsDir: dirname + '/views/layouts',
120
+ restrictLayoutsTo: dirname
114
121
  });
115
122
 
116
123
  it('should allow specifying layouts without the parent dir', function(done) {
@@ -158,7 +165,9 @@ describe('issue-21', function() {
158
165
 
159
166
  it('should treat layouts relative to views directory if layoutsDir is not passed', function(done) {
160
167
  var dirname = path.join(__dirname, 'issues/21');
161
- var render = hbs.create().express3();
168
+ var render = hbs.create().express3({
169
+ restrictLayoutsTo: dirname
170
+ });
162
171
 
163
172
  function check(err, html) {
164
173
  assert.ifError(err);
@@ -177,7 +186,9 @@ describe('issue-49', function() {
177
186
 
178
187
  it('should report filename with error', function(done) {
179
188
  var hb = hbs.create()
180
- var render = hb.express3({});
189
+ var render = hb.express3({
190
+ restrictLayoutsTo: dirname
191
+ });
181
192
  var locals = H.createLocals('express3', dirname, {});
182
193
  render(dirname + '/error.hbs', locals, function(err, html) {
183
194
  assert(err.stack.indexOf('[error.hbs]') > 0);
@@ -187,7 +198,9 @@ describe('issue-49', function() {
187
198
 
188
199
  it('should report relative filename with error', function(done) {
189
200
  var hb = hbs.create()
190
- var render = hb.express3({});
201
+ var render = hb.express3({
202
+ restrictLayoutsTo: dirname
203
+ });
191
204
  var locals = H.createLocals('express3', dirname, {});
192
205
  render(dirname + '/front/error.hbs', locals, function(err, html) {
193
206
  assert(err.stack.indexOf('[front/error.hbs]') > 0);
@@ -198,7 +211,8 @@ describe('issue-49', function() {
198
211
  it('should report filename with partial error', function(done) {
199
212
  var hb = hbs.create()
200
213
  var render = hb.express3({
201
- partialsDir: dirname + '/partials'
214
+ partialsDir: dirname + '/partials',
215
+ restrictLayoutsTo: dirname
202
216
  });
203
217
  var locals = H.createLocals('express3', dirname, {});
204
218
  render(dirname + '/partial.hbs', locals, function(err, html) {
@@ -210,7 +224,8 @@ describe('issue-49', function() {
210
224
  it('should report filename with layout error', function(done) {
211
225
  var hb = hbs.create()
212
226
  var render = hb.express3({
213
- partialsDir: dirname + '/partials'
227
+ partialsDir: dirname + '/partials',
228
+ restrictLayoutsTo: dirname
214
229
  });
215
230
  var locals = H.createLocals('express3', dirname, {});
216
231
  render(dirname + '/index.hbs', locals, function(err, html) {
@@ -231,7 +246,9 @@ describe('issue-53', function() {
231
246
  resultcb(++res);
232
247
  }, 1)
233
248
  });
234
- var render = hb.express3({});
249
+ var render = hb.express3({
250
+ restrictLayoutsTo: dirname
251
+ });
235
252
  var locals = H.createLocals('express3', dirname, {});
236
253
  render(dirname + '/index.hbs', locals, function(err, html) {
237
254
  assert.ifError(err);
@@ -253,7 +270,8 @@ describe('issue-59', function() {
253
270
  hb.registerAsyncHelper("async", async);
254
271
 
255
272
  var render = hb.express3({
256
- viewsDir: dirname
273
+ viewsDir: dirname,
274
+ restrictLayoutsTo: dirname
257
275
  });
258
276
  var locals = H.createLocals('express3', dirname);
259
277
 
@@ -272,7 +290,8 @@ describe('issue-59', function() {
272
290
  hb.registerAsyncHelper('async', async);
273
291
 
274
292
  var render = hb.express3({
275
- viewsDir: dirname
293
+ viewsDir: dirname,
294
+ restrictLayoutsTo: dirname
276
295
  });
277
296
  var locals = H.createLocals('express3', dirname);
278
297
 
@@ -290,6 +309,7 @@ describe('issue-73', function() {
290
309
  var render = hb.express3({
291
310
  viewsDir: dirname,
292
311
  partialsDir: dirname + '/partials',
312
+ restrictLayoutsTo: dirname,
293
313
  onCompile: function(eh, source, filename) {
294
314
  var options;
295
315
  if (filename && filename.indexOf('partials')) {
@@ -329,7 +349,8 @@ describe('issue-62', function() {
329
349
  hb.registerAsyncHelper("async", async);
330
350
 
331
351
  var render = hb.express3({
332
- viewsDir: dirname
352
+ viewsDir: dirname,
353
+ restrictLayoutsTo: dirname
333
354
  });
334
355
  var locals = H.createLocals('express3', dirname);
335
356
 
@@ -359,7 +380,8 @@ describe('issue-62', function() {
359
380
  hb.registerAsyncHelper("async", async);
360
381
 
361
382
  var render = hb.express3({
362
- viewsDir: dirname
383
+ viewsDir: dirname,
384
+ restrictLayoutsTo: dirname
363
385
  });
364
386
  var locals = H.createLocals('express3', dirname);
365
387
 
@@ -380,7 +402,8 @@ describe('issue-76', function() {
380
402
  var hb = hbs.create();
381
403
 
382
404
  var render = hb.express3({
383
- partialsDir: dirname
405
+ partialsDir: dirname,
406
+ restrictLayoutsTo: dirname
384
407
  });
385
408
 
386
409
  hb.cachePartials(function (err) {
@@ -396,7 +419,8 @@ describe('issue-84', function () {
396
419
 
397
420
  it('should render deeply nested partials', function (done) {
398
421
  var render = hbs.create().express3({
399
- partialsDir: [dirname + '/partials']
422
+ partialsDir: [dirname + '/partials'],
423
+ restrictLayoutsTo: dirname
400
424
  });
401
425
 
402
426
  function check(err, html) {
@@ -421,7 +445,9 @@ describe('issue-144', function() {
421
445
  resultcb(new hbs.SafeString('<p><code>\'$example$\'</code> abcd</p>'));
422
446
  }, 1)
423
447
  });
424
- var render = hb.express3({});
448
+ var render = hb.express3({
449
+ restrictLayoutsTo: dirname
450
+ });
425
451
  var locals = H.createLocals('express3', dirname, {});
426
452
  render(dirname + '/index.hbs', locals, function(err, html) {
427
453
  assert.equal('<div><p><code>\'$example$\'</code> abcd</p></div>\n', html);
@@ -441,7 +467,9 @@ describe('issue-153', function() {
441
467
  done();
442
468
  }
443
469
  var hb = hbs.create()
444
- var render = hb.express3({});
470
+ var render = hb.express3({
471
+ restrictLayoutsTo: dirname
472
+ });
445
473
  var locals = H.createLocals('express3', dirname, { });
446
474
  render(dirname + '/index.hbs', locals, check);
447
475
  });
@@ -1,5 +1,6 @@
1
1
  var request = require('supertest');
2
2
  var assert = require('assert');
3
+ var path = require('path');
3
4
  var hbs = require('..');
4
5
 
5
6
 
@@ -65,6 +66,7 @@ describe('layouts', function() {
65
66
 
66
67
  it ('should process template-specified layout without option', function(done) {
67
68
  var render = hbs.create().express3({
69
+ restrictLayoutsTo: dirname
68
70
  });
69
71
  var locals = createLocals('express3', dirname);
70
72
 
@@ -76,6 +78,7 @@ describe('layouts', function() {
76
78
 
77
79
  it ('should allow options.layout to be specified', function(done) {
78
80
  var render = hbs.create().express3({
81
+ restrictLayoutsTo: dirname
79
82
  });
80
83
  var locals = createLocals('express3', dirname, { layout: 'layouts/default' });
81
84
 
@@ -85,8 +88,53 @@ describe('layouts', function() {
85
88
  });
86
89
  });
87
90
 
91
+ it('should error when using a layout outside of the restrictLayoutsTo', function(done) {
92
+ var render = hbs.create().express3({
93
+ restrictLayoutsTo: path.resolve(path.join(__dirname, '../'))
94
+ });
95
+ var locals = createLocals('express3', dirname, {layout: '/Users/egg/Code/Ghost/ghost/core/package.json'});
96
+
97
+ render(dirname + '/aside.hbs', locals, function (err, html) {
98
+ if (!err) {
99
+ return done(new Error('We expect an error when reading'));
100
+ }
101
+ return done();
102
+ });
103
+ });
104
+
105
+ it('should allow a layout inside a relative restrictLayoutsTo', function(done) {
106
+ var render = hbs.create().express3({
107
+ restrictLayoutsTo: path.relative(process.cwd(), dirname)
108
+ });
109
+ var locals = createLocals('express3', dirname, { layout: 'layouts/default' });
110
+
111
+ render(dirname + '/aside.hbs', locals, function(err, html) {
112
+ if (err) return done(err);
113
+ assert.equal('<dld>aside</dld>', stripWs(html));
114
+ done();
115
+ });
116
+ });
117
+
118
+ it('should error when a layout is in a sibling directory sharing the restrictLayoutsTo prefix', function(done) {
119
+ var restrictLayoutsTo = path.join(dirname, 'lay');
120
+ var render = hbs.create().express3({
121
+ restrictLayoutsTo: restrictLayoutsTo
122
+ });
123
+ var locals = createLocals('express3', dirname, { layout: 'layouts/default' });
124
+
125
+ render(dirname + '/aside.hbs', locals, function(err) {
126
+ assert.ok(err, 'expected an error');
127
+ assert.ok(
128
+ err.message.includes('does not reside in ' + restrictLayoutsTo),
129
+ 'unexpected error: ' + err.message
130
+ );
131
+ done();
132
+ });
133
+ });
134
+
88
135
  it ('should not process template-specified layout when options.layout is falsy', function(done) {
89
136
  var render = hbs.create().express3({
137
+ restrictLayoutsTo: dirname
90
138
  });
91
139
  var locals = createLocals('express3', dirname, { layout: false });
92
140
 
@@ -11,7 +11,9 @@ describe('local template options', function () {
11
11
 
12
12
  it('merges res.locals._templateOptions with the self._templateOptions', function (done) {
13
13
  var instance = hbs.create();
14
- var render = instance.express3({});
14
+ var render = instance.express3({
15
+ restrictLayoutsTo: dirname
16
+ });
15
17
  instance.updateTemplateOptions({
16
18
  data: {
17
19
  greeting: 'Hello,',
@@ -37,7 +39,9 @@ describe('local template options', function () {
37
39
 
38
40
  it('removes _templateOptions from the locals data', function (done) {
39
41
  var instance = hbs.create();
40
- var render = instance.express3({});
42
+ var render = instance.express3({
43
+ restrictLayoutsTo: dirname
44
+ });
41
45
  instance.updateTemplateOptions({
42
46
  data: {
43
47
  greeting: 'Hello,',
@@ -66,7 +70,9 @@ describe('local template options', function () {
66
70
 
67
71
  it('merges res.locals._templateOptions with the self._templateOptions', function (done) {
68
72
  var instance = hbs.create();
69
- var render = instance.express4({});
73
+ var render = instance.express4({
74
+ restrictLayoutsTo: dirname
75
+ });
70
76
  instance.updateTemplateOptions({
71
77
  data: {
72
78
  greeting: 'Hello,',
@@ -92,7 +98,9 @@ describe('local template options', function () {
92
98
 
93
99
  it('removes _templateOptions from the locals data', function (done) {
94
100
  var instance = hbs.create();
95
- var render = instance.express3({});
101
+ var render = instance.express3({
102
+ restrictLayoutsTo: dirname
103
+ });
96
104
  instance.updateTemplateOptions({
97
105
  data: {
98
106
  greeting: 'Hello,',
package/test/multiple.js CHANGED
@@ -10,7 +10,9 @@ describe('multiple directories', function() {
10
10
 
11
11
  beforeEach(function() {
12
12
  app = express();
13
- app.engine('hbs', hbs.express3());
13
+ app.engine('hbs', hbs.express3({
14
+ restrictLayoutsTo: './test/views/multiple'
15
+ }));
14
16
  app.set('view engine', 'hbs');
15
17
  app.get('/test1', function (req, res) {
16
18
  res.render('test1');
@@ -9,7 +9,8 @@ describe('non-express', function() {
9
9
 
10
10
  it ('should use viewsDir options', function(done) {
11
11
  var render = hbs.create().express3({
12
- viewsDir: dirname
12
+ viewsDir: dirname,
13
+ restrictLayoutsTo: dirname
13
14
  });
14
15
  var locals = H.createLocals('express3', dirname);
15
16
 
@@ -22,7 +23,8 @@ describe('non-express', function() {
22
23
  it ('should work with layoutsDir', function(done) {
23
24
  var render = hbs.create().express3({
24
25
  viewsDir: dirname,
25
- layoutsDir: dirname + '/layouts'
26
+ layoutsDir: dirname + '/layouts',
27
+ restrictLayoutsTo: dirname
26
28
  });
27
29
  var locals = H.createLocals('express3', dirname, {layout: 'default.hbs'});
28
30
 
@@ -10,7 +10,7 @@ describe('options', function() {
10
10
 
11
11
  it('should pretty print HTML', function(done) {
12
12
  var hb = hbs.create();
13
- var render = hb.express3({beautify: true});
13
+ var render = hb.express3({beautify: true, restrictLayoutsTo: dirname});
14
14
  var locals = H.createLocals('express3', dirname, {});
15
15
 
16
16
  render(dirname + '/index.hbs', locals, function(err, html) {
@@ -0,0 +1,70 @@
1
+ 'use strict';
2
+
3
+ var assert = require('assert');
4
+ var generateId = require('../lib/generate-id');
5
+ var resolver = require('../lib/resolver');
6
+
7
+ describe('resolver', function () {
8
+ it('detects an unresolved helper at the start of rendered output', function () {
9
+ assert.equal(resolver.hasResolvers('__aSyNcId__<_12345678__'), true);
10
+ });
11
+
12
+ it('does not report rendered output without a resolver marker', function () {
13
+ assert.equal(resolver.hasResolvers('rendered output'), false);
14
+ });
15
+
16
+ it('ignores prefix text that is not a cached helper id', function () {
17
+ var cache = { '__aSyNcId__<_abcdefgh__': Promise.resolve('') };
18
+ assert.equal(resolver.hasResolvers('x __aSyNcId__ y', cache), false);
19
+ assert.equal(resolver.hasResolvers('__aSyNcId__<_zzzzzzzz__', cache), false);
20
+ });
21
+
22
+ it('detects cached helper ids in raw and escaped form', function () {
23
+ var cache = { '__aSyNcId__<_abcdefgh__': Promise.resolve('') };
24
+ function escape(s) {
25
+ return s.replace('<', '&lt;');
26
+ }
27
+ assert.equal(resolver.hasResolvers('a __aSyNcId__<_abcdefgh__ b', cache, escape), true);
28
+ assert.equal(resolver.hasResolvers('a __aSyNcId__&lt;_abcdefgh__ b', cache, escape), true);
29
+ assert.equal(resolver.hasResolvers('a __aSyNcId__&lt;_abcdefgh__ b', cache), false);
30
+ });
31
+
32
+ it('resolves asynchronous helper output with its context', function (done) {
33
+ var cache = {};
34
+ var id = resolver.resolve(
35
+ cache,
36
+ function (context, callback) {
37
+ callback(context.value);
38
+ },
39
+ { value: 'resolved' },
40
+ );
41
+
42
+ resolver.done(cache, function (err, values) {
43
+ assert.ifError(err);
44
+ assert.equal(values[id], 'resolved');
45
+ done();
46
+ });
47
+ });
48
+
49
+ it('reports synchronous helper failures', function (done) {
50
+ var cache = {};
51
+ resolver.resolve(cache, function () {
52
+ throw new Error('helper failed');
53
+ });
54
+
55
+ resolver.done(cache, function (err) {
56
+ assert.equal(err.message, 'helper failed');
57
+ done();
58
+ });
59
+ });
60
+ });
61
+
62
+ describe('generateId', function () {
63
+ it('uses an eight-character default', function () {
64
+ assert.match(generateId(), /^[A-Za-z_]{8}$/);
65
+ });
66
+
67
+ it('uses the requested length', function () {
68
+ assert.match(generateId(16), /^[A-Za-z_]{16}$/);
69
+ });
70
+ });
@@ -0,0 +1 @@
1
+ hello {{body}}
@@ -0,0 +1 @@
1
+ hello {{value}}|{{{value}}}|{{async "a"}}