Skip to content

Instantly share code, notes, and snippets.

@kozy4324
Created September 12, 2014 10:29
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 kozy4324/a8ddc38fd12eb0d60a64 to your computer and use it in GitHub Desktop.
Save kozy4324/a8ddc38fd12eb0d60a64 to your computer and use it in GitHub Desktop.
CoffeeScriptコンパイルと依存関係解決をしながらQUnit実行HTMLを出力するサーバーのGruntタスク
module.exports = (grunt) ->
grunt.registerTask 'connect_qunit', 'QUnit実行HTML配信サーバーを起動(CoffeeScriptコンパイル含む)', ->
options = @options
port: 0xBEEF
hostname: 'localhost'
base: '.'
urlNameSpace: 'qunit'
testDir: 'js_test'
srcDir: 'js'
includeLibs: []
options.includeLibs.unshift(
'https://code.jquery.com/jquery-2.1.1.min.js'
'/___resources/sinon-1.7.3.js'
'/___resources/sinon-qunit-1.0.0.js'
)
coffee = require "#{process.cwd()}/node_modules/coffee-script"
# (R)eg(E)
re = (pattern) -> new RegExp(pattern)
# (R)eg(E)xp(T)est
ret = (pattern, value) -> new RegExp(pattern).test value
readScriptFile = (path) ->
path = path.replace /js$/, 'coffee'
try
coffee.compile grunt.file.read(path).toString("utf8")
catch err
try
grunt.file.read(path.replace(/coffee$/, 'js')).toString("utf8")
catch err
null
proc = (req, res, next) ->
{srcDir, testDir, urlNameSpace} = options
{pathname} = req._parsedUrl
switch
when ret "^(/|/#{urlNameSpace}/)$", pathname
res.setHeader 'Content-Type', 'text/html'
res.end grunt.file.expand("#{testDir}/**/*.{js,coffee}").sort().map((name) ->
url = name.replace re("^#{testDir}"), "/#{urlNameSpace}"
"""<a href="#{url}">#{url}</a><br/>"""
).join('')
when ret "^/#{urlNameSpace}/", pathname
path = pathname.replace re("^/#{urlNameSpace}/"), ""
res.setHeader 'Content-Type', 'text/html'
res.end tmpl
libs: options.includeLibs.map (url) -> if ret "^(https?://|/)", url then url else "/#{url}"
title: path
target_test: "/#{testDir}/#{path}".replace re("/./"), "/"
target_js: "/#{srcDir}/#{path}".replace re("/./"), "/"
when ret "^/___resources/", pathname
switch
when ret 'css$', pathname
res.setHeader 'Content-Type', 'text/css'
when ret 'js$', pathname
res.setHeader 'Content-Type', 'text/javascript'
res.end grunt.file.read "#{__dirname}/qunit_resources/#{pathname.replace(re("^/___resources/"), '')}"
when ret "\\.(js|coffee)$", pathname
res.setHeader 'Content-Type', 'text/javascript'
content = readScriptFile ".#{pathname}"
content = """alert("Can\'t load #{pathname}");""" unless content?
buf = []
(content.match(/@requires.*/g) || []).forEach (matched) ->
dep_path = matched.replace(/@requires\s+/, '').replace(/(\.js|\.coffee)?\s*$/, '.js')
dep_content = readScriptFile "./#{srcDir}/#{dep_path}"
dep_content = """alert("Can\'t load @requires #{dep_path}");""" unless dep_content?
buf.push dep_content
res.end buf.concat(content).join("\n")
else
next()
options.middleware = (connect, options) -> [proc, connect.static(options.base)]
grunt.config.merge connect:
connect_qunit:
options: options
grunt.loadNpmTasks 'grunt-contrib-connect'
if this.flags.keepalive
grunt.task.run 'connect:connect_qunit:keepalive'
else
grunt.task.run 'connect:connect_qunit'
tmpl = (data) -> """
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>#{data.title}</title>
<link rel="stylesheet" href="/___resources/qunit.css" media="screen">
<script src="/___resources/qunit.js"></script>
#{("<script src=\"#{path}\"></script>" for path in data.libs or []).join("\n")}
<script src="#{data.target_js}"></script>
<script src="#{data.target_test}"></script>
</head>
<body>
<h1 id="qunit-header">#{data.title}</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">this had better work.</div>
</body>
</html>
"""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment