-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Include commented source for riot.compiler
- Loading branch information
Showing
1 changed file
with
136 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
|
||
/* | ||
Compilation for the browser | ||
*/ | ||
riot.compile = (function () { | ||
|
||
var | ||
doc = window.document, | ||
promise, | ||
ready | ||
|
||
// Gets a .tag file via asynchronous http. Once received, runs the callback on it. | ||
function GET(url, fn, opts) { | ||
var req = new XMLHttpRequest() | ||
|
||
req.onreadystatechange = function() { | ||
if (req.readyState === 4 && | ||
(req.status === 200 || !req.status && req.responseText.length)) | ||
fn(req.responseText, opts, url) | ||
} | ||
req.open('GET', url, true) | ||
req.send('') | ||
} | ||
|
||
// Removes additional indentation of the source | ||
function unindent(src, dbg) { | ||
var indent = src.match(/^([ \t]*)</m) // only before first tag | ||
if (indent && indent[1]) src = src.replace(new RegExp('^' + indent[1], 'gm'), '') | ||
return src | ||
} | ||
|
||
// Runs the call to `riot.tag2` generated by the compiler | ||
function globalEval(js, opts, comp) { | ||
var | ||
node = doc.createElement('script'), | ||
root = doc.documentElement | ||
|
||
node.text = js // writes the code into our new `script` element | ||
root.appendChild(node) // injects it to page, execution is immediate | ||
root.removeChild(node) // tmpl created, the script is no longer required | ||
} | ||
|
||
// Compile all tags defined with `<script type="riot/tag">`` to JavaScript. | ||
// These can be inlined script definitions or external resources that load scripts | ||
// defined with src attribute. | ||
// After all scripts are compiled the given callback method is called. | ||
function compileScripts(fn) { | ||
var | ||
scripts = doc.querySelectorAll('script[type="riot/tag"]'), | ||
scriptsAmount = scripts.length | ||
|
||
function done() { | ||
promise.trigger('ready') // signal we are done | ||
ready = true | ||
if (fn) fn() | ||
} | ||
|
||
function compileTag(src, opts, url) { | ||
globalEval(compile(src, opts, url)) | ||
if (!--scriptsAmount) done() | ||
} | ||
|
||
if (!scriptsAmount) done() | ||
else { | ||
for (var i = 0; i < scripts.length; ++i) { // Array.prototype.map is heavy | ||
var | ||
script = scripts[i], | ||
opts = {template: script.getAttribute('template')}, | ||
url = script.getAttribute('src') | ||
|
||
url ? GET(url, compileTag, opts) : compileTag(unindent(script.innerHTML), opts) | ||
} | ||
} | ||
} | ||
|
||
//// Entry point ----- | ||
|
||
return function (arg, fn) { | ||
|
||
if (typeof arg === 'string') { | ||
// fix in both, compile was called here and in globalEval | ||
|
||
if (/^\s*</.test(arg)) { // this is a bit faster than trim() | ||
// `riot.compile(tag [, true])` | ||
// returns the tag as a string, if `true` is given, do not execute. | ||
var js = compile(unindent(arg)) // fix: pass unindented src to compile, don't fake test | ||
if (!fn) globalEval(js) | ||
return js | ||
} | ||
|
||
// `riot.compile(url [, callback])` | ||
// Loads the url and compiles all tags after which the callback is called. | ||
GET(arg, function (str) { | ||
var js = compile(str, {}, arg) // .tag do not need unindent | ||
globalEval(js) | ||
if (fn) fn(js, str) | ||
}) | ||
|
||
} | ||
else { | ||
|
||
// `riot.compile([callback])` | ||
// Compile all tags defined with `<script type="riot/tag">`` to JavaScript. | ||
|
||
// must be a function | ||
fn = typeof arg !== 'function' ? undefined : arg | ||
|
||
// all compiled | ||
if (ready) | ||
return fn && fn() | ||
|
||
// add to queue | ||
if (promise) { | ||
if (fn) promise.on('ready', fn) | ||
|
||
// grab riot/tag elements + load & execute them | ||
} else { | ||
promise = riot.observable() | ||
compileScripts(fn) | ||
} | ||
} | ||
} | ||
|
||
})() | ||
|
||
// reassign mount methods | ||
var mount = riot.mount | ||
|
||
riot.mount = function(a, b, c) { | ||
var ret | ||
riot.compile(function() { ret = mount(a, b, c) }) | ||
return ret | ||
} | ||
|
||
// @deprecated | ||
riot.mountTo = riot.mount |