haml-coffee
Advanced tools
| %h1 Include test | ||
| %p Demonstrating how includes work. | ||
| +include 'partials/test' | ||
| %p After text |
| <h1>Include test</h1> | ||
| <p>Demonstrating how includes work.</p> | ||
| <h2>Partial</h2> | ||
| <p>This is a partial that can be included</p> | ||
| <p>After text</p> |
| %h2 Partial | ||
| %p This is a partial that can be included |
| path = require('path') | ||
| Node = require('./node') | ||
| # Directive node for HAML statements that change the meaning or do interact | ||
| # uniquely with the HAML document. | ||
| # | ||
| # @example include a HAML document inside of another | ||
| # +include 'path/to/template'[, context] | ||
| # | ||
| module.exports = class Directive extends Node | ||
| # Map of available directives to methods. | ||
| # | ||
| directives: | ||
| # Includes a HAML document inside of the current one. Context included | ||
| # template is defaulted to the context of this template but may be changed | ||
| # by passing a second argument. | ||
| # | ||
| # @example Include with default context | ||
| # +include 'path/to/template' | ||
| # | ||
| # @example Include with custom context | ||
| # +include 'path/to/template', @context | ||
| # | ||
| include: (expression) -> | ||
| try [[], name, context] = expression.match(/\s*['"](.*)['"](?:,\s*(.*))?\s*/) | ||
| catch e | ||
| throw "Failed to parse the include directive from #{ expression }" | ||
| context = 'this' unless context | ||
| statement = switch @placement | ||
| when 'global' then "#{ @namespace }['#{ name }'].apply(#{ context })" | ||
| when 'amd' then "require('#{ name }').apply(#{ context })" | ||
| else | ||
| throw "Include directive not available when placement is #{ @placement }" | ||
| @opener = @markInsertingCode statement, false | ||
| # Evaluate the Haml directive. | ||
| # | ||
| evaluate: -> | ||
| directives = Object.keys(@directives).join('|') | ||
| try [[], name, rest] = @expression.match(///\+(#{ directives })(.*)///) | ||
| catch e | ||
| throw "Unable to recognize directive from #{ @expression }" | ||
| @directives[name].call this, rest |
+5
-2
| language: node_js | ||
| node_js: | ||
| - 0.8 | ||
| - 0.6 | ||
| - 0.7 | ||
| - 0.8 | ||
| - 0.9 | ||
| matrix: | ||
| allow_failures: | ||
| - node_js: 0.9 | ||
| branches: | ||
@@ -7,0 +10,0 @@ only: |
+7
-2
| # Haml Coffee Changelog | ||
| ## Master | ||
| ## Version 1.10.0, February 15, 2013 | ||
| * [#55](https://github.com/netzpirat/haml-coffee/issues/55): Add `+include` directive. ([@mehcode](https://github.com/mehcode)) | ||
| * [#54](https://github.com/netzpirat/haml-coffee/issues/54): Add `standalone` placement option. ([@Nami-Doc](https://github.com/Nami-Doc)) | ||
| ## Version 1.9.1, January 8, 2013 | ||
| * Fix setting a custom reference function. | ||
| ## Version 1.9.0, January 8, 2013 | ||
| ## Version 1.9.0, January 8, 2013 | ||
@@ -9,0 +14,0 @@ * HTML and Ruby style attributes can be mixed. |
+1
-1
@@ -1,2 +0,2 @@ | ||
| source :rubygems | ||
| source 'https://rubygems.org' | ||
@@ -3,0 +3,0 @@ gem 'ruby_gntp' |
+1
-1
@@ -11,3 +11,3 @@ { | ||
| ], | ||
| "version" : "1.9.1", | ||
| "version" : "1.10.0", | ||
| "licenses" : [ | ||
@@ -14,0 +14,0 @@ { |
+31
-1
@@ -30,2 +30,3 @@ # Haml Coffee Templates [](http://travis-ci.org/netzpirat/haml-coffee) | ||
| * [haml_coffee_assets](https://github.com/netzpirat/haml_coffee_assets) for projects using Rails. | ||
| * [stitch-haml-coffee](https://github.com/jnbt/stitch-haml-coffee) for projects using [Stitch](https://github.com/sstephenson/stitch). | ||
| * [guard-haml-coffee](https://github.com/ouvrages/guard-haml-coffee) for projects using [Guard](https://github.com/guard/guard). | ||
@@ -445,2 +446,28 @@ * [Haml Coffee compiler](https://raw.github.com/netzpirat/haml-coffee/master/dist/compiler/hamlcoffee.js) | ||
| ### Directives | ||
| Haml-Coffee supports currently a single directive that extends the HAML syntax. | ||
| ### Include | ||
| You can use the `+include` directive to include another template: | ||
| ```haml | ||
| %h1 Include | ||
| +include 'partials/test' | ||
| ``` | ||
| This will look up the specified template and include it. So if the partial `partials/test` contains | ||
| ```haml | ||
| %p Partial content | ||
| ``` | ||
| The final result will be | ||
| ```html | ||
| <h1>Include</h1> | ||
| <p>Partial content</p> | ||
| ``` | ||
| ## CoffeeScript support | ||
@@ -645,3 +672,3 @@ | ||
| * Name: `htmlEscape` | ||
| * Name: `escapeHtml` | ||
| * Type: `Boolean` | ||
@@ -710,2 +737,5 @@ * Default: `true` | ||
| * 'standalone' <br /> | ||
| Returns the template function without wrapping it | ||
| * `amd` <br /> | ||
@@ -712,0 +742,0 @@ Wraps the template function into a `define()` statement to allow async |
@@ -1,5 +0,6 @@ | ||
| fs = require 'fs' | ||
| fs = require 'fs' | ||
| CoffeeScript = require 'coffee-script' | ||
| HamlCoffee = require '../src/haml-coffee' | ||
| CoffeeScript = require 'coffee-script' | ||
| HamlCoffee = require '../src/haml-coffee' | ||
| HC = require '../src/hamlc' | ||
@@ -26,2 +27,5 @@ suites = [ | ||
| window = {} | ||
| window.HAML = {} | ||
| config = { | ||
@@ -31,2 +35,3 @@ escapeHtml : if spec.config?.escape_html is 'true' then true else false | ||
| extendScope : if spec.config?.extend_scope is 'true' then true else false | ||
| placement : spec.config?.placement || 'global' | ||
| format : spec.config?.format || 'xhtml' | ||
@@ -47,2 +52,13 @@ } | ||
| if spec.partials && config.placement is 'global' | ||
| report += "\n-------------------- Partial templates --------------------------\n" | ||
| for name, partial of spec.partials | ||
| try | ||
| source = fs.readFileSync("spec/suites/templates/#{ partial }.haml").toString() | ||
| window.HAML[name] = HC.compile(source) | ||
| report += "window.HAML['#{ name }'] compiled from source '#{ partial }'\n" | ||
| catch error | ||
| report += "Error compiling partial #{ name }: #{ error }" | ||
| if spec.locals | ||
@@ -65,3 +81,2 @@ report += "\n-------------------- Local variables --------------------------\n" | ||
| window = {} | ||
| eval template | ||
@@ -68,0 +83,0 @@ |
@@ -371,3 +371,3 @@ { | ||
| "evaluation in inserting functions" : { | ||
| "extending the scope" : { | ||
| "haml_template" : "coffee/extend_scope", | ||
@@ -535,3 +535,17 @@ "html_template" : "coffee/extend_scope", | ||
| }, | ||
| "directives" : { | ||
| "include" : { | ||
| "haml_template" : "directives/include", | ||
| "html_template" : "directives/include", | ||
| "config": { | ||
| "placement": "global" | ||
| }, | ||
| "partials" : { | ||
| "partials/test" : "directives/partials/test" | ||
| } | ||
| } | ||
| } | ||
| } |
@@ -21,2 +21,8 @@ CoffeeScript = require 'coffee-script' | ||
| # Extend the options with the name and namespace so that the | ||
| # compiler has these configuration properties from the beginning | ||
| # and that the API for this method can stay the same. | ||
| compilerOptions.namespace = namespace | ||
| compilerOptions.name = templateName | ||
| try | ||
@@ -35,4 +41,5 @@ source = fs.readFileSync(filename).toString() | ||
| compiler.parse source | ||
| haml = compiler.render templateName, namespace | ||
| haml = compiler.render | ||
| else | ||
@@ -68,2 +75,8 @@ console.error " #{ red }[haml coffee] no valid Haml extension.#{ reset }" | ||
| # Extend the options with the name and namespace so that the | ||
| # compiler has these configuration properties from the beginning | ||
| # and that the API for this method can stay the same. | ||
| compilerOptions.namespace = namespace | ||
| compilerOptions.name = templateName | ||
| try | ||
@@ -70,0 +83,0 @@ if templateName || compilerOptions.placement is 'amd' |
+52
-32
@@ -1,7 +0,8 @@ | ||
| Node = require('./nodes/node') | ||
| Text = require('./nodes/text') | ||
| Haml = require('./nodes/haml') | ||
| Code = require('./nodes/code') | ||
| Comment = require('./nodes/comment') | ||
| Filter = require('./nodes/filter') | ||
| Node = require('./nodes/node') | ||
| Text = require('./nodes/text') | ||
| Haml = require('./nodes/haml') | ||
| Code = require('./nodes/code') | ||
| Comment = require('./nodes/comment') | ||
| Filter = require('./nodes/filter') | ||
| Directive = require('./nodes/directive') | ||
@@ -18,3 +19,3 @@ {whitespace} = require('./util/text') | ||
| # The current version number. | ||
| @VERSION: '1.9.1' | ||
| @VERSION: '1.10.0' | ||
@@ -54,2 +55,21 @@ # Construct the HAML Coffee compiler. | ||
| if @options.placement is 'global' | ||
| @options.name ?= 'test' | ||
| @options.namespace ?= 'window.HAML' | ||
| # Create parameter name from the filename, e.g. a file `users/new.hamlc` | ||
| # will create `window.HAML.user.new` | ||
| segments = "#{ @options.namespace }.#{ @options.name }".replace(/(\s|-)+/g, '_').split(/\./) | ||
| @options.name = if @options.basename then segments.pop().split(/\/|\\/).pop() else segments.pop() | ||
| @options.namespace = segments.shift() | ||
| # Create code for file and namespace creation | ||
| @intro = '' | ||
| if segments.length isnt 0 | ||
| for segment in segments | ||
| @options.namespace += ".#{ segment }" | ||
| @intro += "#{ @options.namespace } ?= {}\n" | ||
| else | ||
| @intro += "#{ @options.namespace } ?= {}\n" | ||
| # Test if the indention level has changed, either | ||
@@ -144,2 +164,5 @@ # increased or decreased. | ||
| uglify : override.uglify || @options.uglify | ||
| placement : override.placement || @options.placement | ||
| namespace : override.namespace || @options.namespace | ||
| name : override.name || @options.name | ||
| } | ||
@@ -176,2 +199,6 @@ | ||
| # Detect directive node | ||
| else if expression.match(/^\+(.*)/) | ||
| node = new Directive(expression, options) | ||
| # Everything else is a text node | ||
@@ -295,12 +322,20 @@ else | ||
| # | ||
| # @param [String] templateName the name to register the template | ||
| # @param [String] namespace the namespace to register the template | ||
| # | ||
| render: (templateName, namespace = 'window.HAML') -> | ||
| render: -> | ||
| switch @options.placement | ||
| when 'amd' | ||
| @renderAmd() | ||
| when 'standalone' | ||
| @renderStandalone() | ||
| else | ||
| @renderGlobal templateName, namespace | ||
| @renderGlobal() | ||
| # Render a standalone version | ||
| renderStandalone: -> | ||
| template = """ | ||
| return (context) -> | ||
| (-> | ||
| #{indent(@precompile(), 2)} | ||
| ).call(context) | ||
| """ | ||
| # Render the parsed source code as CoffeeScript template wrapped in a | ||
@@ -359,26 +394,11 @@ # define() statement for AMD. If the global modules list contains a module | ||
| # @private | ||
| # @param [String] templateName the name to register the template | ||
| # @param [String] namespace the namespace to register the template | ||
| # @return [String] the CoffeeScript template source code | ||
| # | ||
| renderGlobal: (templateName, namespace = 'window.HAML') -> | ||
| template = '' | ||
| renderGlobal: -> | ||
| # Use the existing intro that is generated at the constructor | ||
| template = @intro | ||
| # Create parameter name from the filename, e.g. a file `users/new.hamlc` | ||
| # will create `window.HAML.user.new` | ||
| segments = "#{ namespace }.#{ templateName }".replace(/(\s|-)+/g, '_').split(/\./) | ||
| templateName = if @options.basename then segments.pop().split(/\/|\\/).pop() else segments.pop() | ||
| namespace = segments.shift() | ||
| # Create code for file and namespace creation | ||
| if segments.length isnt 0 | ||
| for segment in segments | ||
| namespace += ".#{ segment }" | ||
| template += "#{ namespace } ?= {}\n" | ||
| else | ||
| template += "#{ namespace } ?= {}\n" | ||
| # Render the template and extend the scope with the context | ||
| if @options.extendScope | ||
| template += "#{ namespace }['#{ templateName }'] = (context) -> ( ->\n" | ||
| template += "#{ @options.namespace }['#{ @options.name }'] = (context) -> ( ->\n" | ||
| template += " `with (context || {}) {`\n" | ||
@@ -391,3 +411,3 @@ template += "#{ indent(@precompile(), 1) }" | ||
| else | ||
| template += "#{ namespace }['#{ templateName }'] = (context) -> ( ->\n" | ||
| template += "#{ @options.namespace }['#{ @options.name }'] = (context) -> ( ->\n" | ||
| template += "#{ indent(@precompile(), 1) }" | ||
@@ -394,0 +414,0 @@ template += ").call(context)" |
+7
-1
@@ -48,6 +48,12 @@ fs = require 'fs' | ||
| template: (source, name, namespace, options = {}) -> | ||
| # Extend the options with the name and namespace so that the | ||
| # compiler has these configuration properties from the beginning | ||
| # and that the API for this method can stay the same. | ||
| options.namespace = namespace | ||
| options.name = name | ||
| compiler = new Compiler(options) | ||
| compiler.parse source | ||
| CoffeeScript.compile compiler.render(name, namespace) | ||
| CoffeeScript.compile compiler.render() | ||
@@ -54,0 +60,0 @@ # Express 3 templating interface with template function cache. |
@@ -63,2 +63,6 @@ {escapeHTML} = require('../util/text') | ||
| @placement = options.placement | ||
| @namespace = options.namespace | ||
| @name = options.name | ||
| # Add a child node. | ||
@@ -65,0 +69,0 @@ # |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
287420
1.89%111
3.74%2747
0.44%886
3.5%