Skip to content

Instantly share code, notes, and snippets.

@Rendez
Last active August 29, 2015 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Rendez/05c5c9403e7ef6e4f41e to your computer and use it in GitHub Desktop.
Save Rendez/05c5c9403e7ef6e4f41e to your computer and use it in GitHub Desktop.
Mustache extension(s) in Sprockets for Can.JS via JST

Can.js: how to register mustache templates via sprockets.

Conditions

  • Must use Sprockets for requiring mustache templates.
  • Mustache templates have to be compiled with can.mustache for compatibility with 2.0 and 3.0
  • Must expose compiled templates under a namespace, defaults to the commonly used JST variable exposed in the main object (window)

Example

#= require ./panel_component
#= require ./tabs_view_model
#= require templates/tabs_component
#= require templates/tabs_view

# Tabs Widget Component

can.Component.extend
  tag: 'tabs'
  scope: this.TabsViewModel
  template: JST['tabs_component']

Author

Luis Merino is CTO at Proudsugar.com, please refer to the contact email.

# Based on Sinatra app; self.registered used by `register` method.
module CanjsAssets
module Config
extend self
attr_writer :path_prefix, :template_namespace, :extensions
def template_namespace
@template_namespace || 'JST'
end
def path_prefix
@path_prefix ||= 'templates'
end
def extensions
@extensions ||= ['.mustache', '.ms']
end
def self.registered(app)
extensions.each do |ext|
app.sprockets.register_engine(ext, Template)
end
end
end
end
require 'tilt'
require 'json'
module CanjsAssets
module Unindent
# http://bit.ly/aze9FV
# Strip leading whitespace from each line that is the same as the
# amount of whitespace on the first line of the string.
# Leaves _additional_ indentation on later lines intact.
def unindent(heredoc)
heredoc.gsub(/^#{heredoc[/\A\s*/]}/, '')
end
end
class Template < Tilt::Template
include Unindent
def self.default_mime_type
'application/javascript'
end
def prepare
@template_path = TemplatePath.new(@file)
end
def evaluate(scope, locals, &block)
source = data
# remove trailing \n on file, for some reason the directives pipeline adds this
source.chomp!($/)
compile(source)
end
def compile(source)
template = "can.mustache(#{JSON.dump(source)})"
template_namespace = CanjsAssets::Config.template_namespace
unindent <<-TEMPLATE
(function() {
this.#{template_namespace} || (this.#{template_namespace} = {});
this.#{template_namespace}[#{@template_path.name}] = #{template};
return this.#{template_namespace}[#{@template_path.name}];
}).call(this);
TEMPLATE
end
protected
class TemplatePath
def initialize(path)
@full_path = path
end
def name
template_name
end
private
def relative_path
@full_path.match(/.*#{CanjsAssets::Config.path_prefix}\/((.*\/)*([^.]*)).*$/)[1]
end
def template_name
relative_path.dump
end
end
end
end
@cherifGsoul
Copy link

that's great, it's a good practice to prefix your custom tag http://canjs.com/docs/can.Component.prototype.tag.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment