Merge remote-tracking branch 'origin/next' into next

This commit is contained in:
Leo 2017-03-14 18:32:42 -04:00
commit 78c139a201
62 changed files with 656 additions and 945 deletions

View file

@ -1,11 +1,6 @@
coverage
.vscode .vscode
examples /node_modules
docs /examples
node_modules /docs/lib
tests /mithril.js
test-utils /mithril.min.js
ospec
mithril.js
mithril.min.js
archive

View file

@ -60,7 +60,14 @@ module.exports = {
"id-blacklist": "error", "id-blacklist": "error",
"id-length": "off", "id-length": "off",
"id-match": "error", "id-match": "error",
"indent": "off", "indent": [
"warn",
"tab",
{
"outerIIFEBody": 0,
"SwitchCase": 1
}
],
"init-declarations": "off", "init-declarations": "off",
"jsx-quotes": "error", "jsx-quotes": "error",
"key-spacing": "off", "key-spacing": "off",
@ -188,7 +195,7 @@ module.exports = {
"quotes": [ "quotes": [
"error", "error",
"double", "double",
"avoid-escape" {"avoidEscape": true}
], ],
"radix": [ "radix": [
"error", "error",
@ -209,7 +216,7 @@ module.exports = {
"space-infix-ops": "off", "space-infix-ops": "off",
"space-unary-ops": "error", "space-unary-ops": "error",
"spaced-comment": "off", "spaced-comment": "off",
"strict": "off", "strict": ["error", "global"],
"template-curly-spacing": "error", "template-curly-spacing": "error",
"valid-jsdoc": "off", "valid-jsdoc": "off",
"vars-on-top": "off", "vars-on-top": "off",
@ -217,5 +224,6 @@ module.exports = {
"wrap-regex": "error", "wrap-regex": "error",
"yield-star-spacing": "error", "yield-star-spacing": "error",
"yoda": "off" "yoda": "off"
} },
}; "root": true
};

1
.gitignore vendored
View file

@ -4,3 +4,4 @@ jsconfig.json
npm-debug.log npm-debug.log
.vscode .vscode
.DS_Store .DS_Store
.eslintcache

View file

@ -10,10 +10,10 @@ cache:
directories: directories:
- node_modules - node_modules
# Custom install step so the travis scripts don't need to be in package.json # Custom install step so the travis-only stuff doesn't need to be in package.json
install: install:
- npm install - npm install
- npm install @alrra/travis-scripts@^3.0.1 - npm install @alrra/travis-scripts@^3.0.1 gh-pages@^0.12.0
# Bundle before running tests so the bundle is always up-to-date # Bundle before running tests so the bundle is always up-to-date
before_script: npm run build before_script: npm run build
@ -21,37 +21,43 @@ before_script: npm run build
# This is the default, but leaving so it is obvious # This is the default, but leaving so it is obvious
# script: npm test # script: npm test
# After a successful build create bundles & commit back to the repo # After a successful build commit changes back to repo
after_success: after_success:
- | - |
# Set up SSH environment
$(npm bin)/set-up-ssh \
--key "$encrypted_8b86e0359d64_key" \
--iv "$encrypted_8b86e0359d64_iv" \
--path-encrypted-key "./.deploy.enc"
# Commit bundle changes generated in before_script step
# --commands is a weird no-op but required for commit-changes to run
# --branch arg is to ensure this only runs against the `next` branch
$(npm bin)/commit-changes \
--commands "echo committing" \
--commit-message "Bundled output for commit $TRAVIS_COMMIT [skip ci]" \
--branch "next"
# Only want to commit when building a push on whatever $BRANCH is # Only want to commit docs when building pushes on master &
# this doesn't have the built-in branch protection likt commit-changes
if [ "$TRAVIS_EVENT_TYPE" == "push" ] && \ if [ "$TRAVIS_EVENT_TYPE" == "push" ] && \
[ "$TRAVIS_BRANCH" == "$BRANCH" ] && \ [ "$TRAVIS_BRANCH" == "master" ] && \
[ "$TRAVIS_REPO_SLUG" == "$REPO" ] [ "$TRAVIS_REPO_SLUG" == "lhorie/mithril.js" ]
then then
# Set up SSH environment # Generate docs
$(npm bin)/set-up-ssh \ $(npm-bin) run gendocs
--key "$encrypted_8b86e0359d64_key" \
--iv "$encrypted_8b86e0359d64_iv" \
--path-encrypted-key "./.deploy.enc"
# Commit changes (if there were any) from running build earlier # Commit docs to gh-pages branch
$(npm bin)/commit-changes \ # Using --add to ensure that archived versions aren't lost
--commands "echo committing" \ # Using --repo to force it to go over SSH so the saved keys are used (tschaub/gh-pages#160)
--commit-message "Bundled output for commit $TRAVIS_COMMIT [skip ci]" \ $(npm bin)/gh-pages --dist ./dist --add --repo "git@github.com:lhorie/mithril.js.git"
--branch "$BRANCH"
else else
echo "Not submitting build artifacts" echo "Not submitting documentation updates"
fi fi
# Environment configuration # Environment configuration
env: env:
global: global:
# Restrict the branch this will activate on
- BRANCH=next
- REPO=lhorie/mithril.js
# Set up GH_USER_EMAIL & GH_USER_NAME env variables used by travis-scripts package # Set up GH_USER_EMAIL & GH_USER_NAME env variables used by travis-scripts package
- secure: Xvqvm3+PvJu/rs3jl/NNn0RWLkkLkIoPHiL0GCfVRaywgjCYVN02g54NVvIDaOfybqPmu9E6PJFVs92vhF34NMFQHf4EWskynusIGV271R2BV0i+OJBfLMuLgiwm6zRn7/Zw4JvWIUGEwcnlz0qxbqdHsS0SOR3fIkFzePickW0= - secure: Xvqvm3+PvJu/rs3jl/NNn0RWLkkLkIoPHiL0GCfVRaywgjCYVN02g54NVvIDaOfybqPmu9E6PJFVs92vhF34NMFQHf4EWskynusIGV271R2BV0i+OJBfLMuLgiwm6zRn7/Zw4JvWIUGEwcnlz0qxbqdHsS0SOR3fIkFzePickW0=
- secure: Rf/ldEO9d4vItJhe6EmqWpFAyCARzoCb422nHnjr1hYJknnwIXpgyZ1C/7On/9o7rWPPf+8WcHC/rgjK2rthKCldzdG5I60LfWSNzap9lk3Aa4TpSCoDBuEp7JVvDr5tc3rKnBXVT71hOay7RSx1StWzXiJs9mjaeVMJzYzRT78= - secure: Rf/ldEO9d4vItJhe6EmqWpFAyCARzoCb422nHnjr1hYJknnwIXpgyZ1C/7On/9o7rWPPf+8WcHC/rgjK2rthKCldzdG5I60LfWSNzap9lk3Aa4TpSCoDBuEp7JVvDr5tc3rKnBXVT71hOay7RSx1StWzXiJs9mjaeVMJzYzRT78=

View file

@ -38,10 +38,10 @@ module.exports = function($window) {
var index = callbacks.indexOf(key) var index = callbacks.indexOf(key)
if (index > -1) callbacks.splice(index, 2) if (index > -1) callbacks.splice(index, 2)
} }
function redraw() { function redraw() {
for (var i = 1; i < callbacks.length; i += 2) { for (var i = 1; i < callbacks.length; i += 2) {
callbacks[i]() callbacks[i]()
} }
} }
return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render} return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render}
} }

View file

@ -71,8 +71,8 @@ o.spec("mount", function() {
o("redraws on events", function(done) { o("redraws on events", function(done) {
var onupdate = o.spy() var onupdate = o.spy()
var oninit = o.spy() var oninit = o.spy()
var onclick = o.spy() var onclick = o.spy()
var e = $window.document.createEvent("MouseEvents") var e = $window.document.createEvent("MouseEvents")
e.initEvent("click", true, true) e.initEvent("click", true, true)
@ -107,13 +107,13 @@ o.spec("mount", function() {
o("redraws several mount points on events", function(done, timeout) { o("redraws several mount points on events", function(done, timeout) {
timeout(60) timeout(60)
var onupdate0 = o.spy() var onupdate0 = o.spy()
var oninit0 = o.spy() var oninit0 = o.spy()
var onclick0 = o.spy() var onclick0 = o.spy()
var onupdate1 = o.spy() var onupdate1 = o.spy()
var oninit1 = o.spy() var oninit1 = o.spy()
var onclick1 = o.spy() var onclick1 = o.spy()
var e = $window.document.createEvent("MouseEvents") var e = $window.document.createEvent("MouseEvents")
@ -228,7 +228,7 @@ o.spec("mount", function() {
done() done()
}, FRAME_BUDGET) }, FRAME_BUDGET)
}) })
o("throttles", function(done, timeout) { o("throttles", function(done, timeout) {
timeout(200) timeout(200)
@ -252,4 +252,4 @@ o.spec("mount", function() {
}) })
}) })
}) })
}) })

View file

@ -6,7 +6,6 @@ var browserMock = require("../../test-utils/browserMock")
var m = require("../../render/hyperscript") var m = require("../../render/hyperscript")
var callAsync = require("../../test-utils/callAsync") var callAsync = require("../../test-utils/callAsync")
var coreRenderer = require("../../render/render")
var apiRedraw = require("../../api/redraw") var apiRedraw = require("../../api/redraw")
var apiRouter = require("../../api/router") var apiRouter = require("../../api/router")
var Promise = require("../../promise/promise") var Promise = require("../../promise/promise")
@ -31,7 +30,7 @@ o.spec("route", function() {
o("throws on invalid `root` DOM node", function() { o("throws on invalid `root` DOM node", function() {
var threw = false var threw = false
try { try {
route(null, '/', {'/':{view: function() {}}}) route(null, "/", {"/":{view: function() {}}})
} catch (e) { } catch (e) {
threw = true threw = true
} }
@ -141,7 +140,7 @@ o.spec("route", function() {
done() done()
} }
}) })
o("redraws when render function is executed", function() { o("redraws when render function is executed", function() {
var onupdate = o.spy() var onupdate = o.spy()
var oninit = o.spy() var oninit = o.spy()
@ -206,7 +205,6 @@ o.spec("route", function() {
o("event handlers can skip redraw", function(done) { o("event handlers can skip redraw", function(done) {
var onupdate = o.spy() var onupdate = o.spy()
var oninit = o.spy() var oninit = o.spy()
var onclick = o.spy()
var e = $window.document.createEvent("MouseEvents") var e = $window.document.createEvent("MouseEvents")
e.initEvent("click", true, true) e.initEvent("click", true, true)
@ -354,11 +352,6 @@ o.spec("route", function() {
o("accepts RouteResolver with onmatch that returns Promise<undefined>", function(done) { o("accepts RouteResolver with onmatch that returns Promise<undefined>", function(done) {
var matchCount = 0 var matchCount = 0
var renderCount = 0 var renderCount = 0
var Component = {
view: function() {
return m("span")
}
}
var resolver = { var resolver = {
onmatch: function(args, requestedPath) { onmatch: function(args, requestedPath) {
@ -395,11 +388,6 @@ o.spec("route", function() {
o("accepts RouteResolver with onmatch that returns Promise<any>", function(done) { o("accepts RouteResolver with onmatch that returns Promise<any>", function(done) {
var matchCount = 0 var matchCount = 0
var renderCount = 0 var renderCount = 0
var Component = {
view: function() {
return m("span")
}
}
var resolver = { var resolver = {
onmatch: function(args, requestedPath) { onmatch: function(args, requestedPath) {
@ -437,14 +425,9 @@ o.spec("route", function() {
var matchCount = 0 var matchCount = 0
var renderCount = 0 var renderCount = 0
var spy = o.spy() var spy = o.spy()
var Component = {
view: function() {
return m("span")
}
}
var resolver = { var resolver = {
onmatch: function(args, requestedPath) { onmatch: function() {
matchCount++ matchCount++
return Promise.reject(new Error("error")) return Promise.reject(new Error("error"))
}, },
@ -499,7 +482,7 @@ o.spec("route", function() {
}) })
}) })
o("changing `vnode.key` in `render` resets the component", function(done, timeout){ o("changing `vnode.key` in `render` resets the component", function(done){
var oninit = o.spy() var oninit = o.spy()
var Component = { var Component = {
oninit: oninit, oninit: oninit,
@ -545,25 +528,19 @@ o.spec("route", function() {
}) })
o(root.firstChild.nodeName).equals("DIV") o(root.firstChild.nodeName).equals("DIV")
o(renderCount).equals(1)
}) })
o("RouteResolver `render` does not have component semantics", function(done) { o("RouteResolver `render` does not have component semantics", function(done) {
var renderCount = 0
var A = {
view: function() {
return m("div")
}
}
$window.location.href = prefix + "/a" $window.location.href = prefix + "/a"
route(root, "/a", { route(root, "/a", {
"/a" : { "/a" : {
render: function(vnode) { render: function() {
return m("div") return m("div")
}, },
}, },
"/b" : { "/b" : {
render: function(vnode) { render: function() {
return m("div") return m("div")
}, },
}, },
@ -632,7 +609,7 @@ o.spec("route", function() {
onmatch: function() { onmatch: function() {
matchCount++ matchCount++
}, },
render: function(vnode) { render: function() {
renderCount++ renderCount++
return {tag: Component} return {tag: Component}
}, },
@ -726,7 +703,7 @@ o.spec("route", function() {
render: render render: render
}, },
"/b" : { "/b" : {
render: function(vnode){ render: function(){
redirected = true redirected = true
} }
} }
@ -838,7 +815,7 @@ o.spec("route", function() {
}) })
callAsync(function() { callAsync(function() {
route.set('/b') route.set("/b")
callAsync(function() { callAsync(function() {
callAsync(function() { callAsync(function() {
callAsync(function() { callAsync(function() {
@ -865,7 +842,7 @@ o.spec("route", function() {
render: render render: render
}, },
"/b" : { "/b" : {
onmatch: function(vnode){ onmatch: function(){
redirected = true redirected = true
return {view: function() {}} return {view: function() {}}
} }
@ -895,7 +872,7 @@ o.spec("route", function() {
render: render render: render
}, },
"/b" : { "/b" : {
render: function(vnode){ render: function(){
redirected = true redirected = true
} }
} }
@ -924,7 +901,7 @@ o.spec("route", function() {
render: render render: render
}, },
"/b" : { "/b" : {
view: function(vnode){ view: function(){
redirected = true redirected = true
} }
} }
@ -1032,7 +1009,7 @@ o.spec("route", function() {
var render = o.spy(function() {return m("div")}) var render = o.spy(function() {return m("div")})
$window.location.href = prefix + "/" $window.location.href = prefix + "/"
route(root, '/', { route(root, "/", {
"/": { "/": {
onmatch: onmatch, onmatch: onmatch,
render: render render: render
@ -1081,23 +1058,23 @@ o.spec("route", function() {
o("routing with RouteResolver works more than once", function(done) { o("routing with RouteResolver works more than once", function(done) {
$window.location.href = prefix + "/a" $window.location.href = prefix + "/a"
route(root, '/a', { route(root, "/a", {
'/a': { "/a": {
render: function() { render: function() {
return m("a", "a") return m("a", "a")
} }
}, },
'/b': { "/b": {
render: function() { render: function() {
return m("b", "b") return m("b", "b")
} }
} }
}) })
route.set('/b') route.set("/b")
callAsync(function() { callAsync(function() {
route.set('/a') route.set("/a")
callAsync(function() { callAsync(function() {
o(root.firstChild.nodeName).equals("A") o(root.firstChild.nodeName).equals("A")
@ -1122,7 +1099,7 @@ o.spec("route", function() {
}) })
}) })
}, },
render: function(vnode) { render: function() {
rendered = true rendered = true
resolved = "a" resolved = "a"
} }
@ -1180,7 +1157,7 @@ o.spec("route", function() {
route.set("/b") route.set("/b")
}) })
}, },
render: function(vnode) { render: function() {
rendered = true rendered = true
resolved = "a" resolved = "a"
} }
@ -1210,7 +1187,7 @@ o.spec("route", function() {
var i = 0 var i = 0
$window.location.href = prefix + "/" $window.location.href = prefix + "/"
route(root, "/", { route(root, "/", {
"/": {view: function(v) {i++}} "/": {view: function() {i++}}
}) })
var before = i var before = i

View file

@ -1,3 +1,5 @@
"use strict"
var m = require("./index") var m = require("./index")
if (typeof module !== "undefined") module["exports"] = m if (typeof module !== "undefined") module["exports"] = m
else window.m = m else window.m = m

View file

@ -1,3 +1,4 @@
#!/usr/bin/env node #!/usr/bin/env node
"use strict"
require("../cli") require("../cli")

View file

@ -1,3 +1,5 @@
"use strict"
var o = require("../../ospec/ospec") var o = require("../../ospec/ospec")
var bundle = require("../bundle") var bundle = require("../bundle")
@ -5,10 +7,10 @@ var fs = require("fs")
var ns = "bundler/tests/" var ns = "bundler/tests/"
function read(filepath) { function read(filepath) {
try {return fs.readFileSync(ns + filepath, "utf8")} catch (e) {} try {return fs.readFileSync(ns + filepath, "utf8")} catch (e) {/* ignore */}
} }
function write(filepath, data) { function write(filepath, data) {
try {var exists = fs.statSync(ns + filepath).isFile()} catch (e) {} try {var exists = fs.statSync(ns + filepath).isFile()} catch (e) {/* ignore */}
if (exists) throw new Error("Don't call `write('" + filepath + "')`. Cannot overwrite file") if (exists) throw new Error("Don't call `write('" + filepath + "')`. Cannot overwrite file")
fs.writeFileSync(ns + filepath, data, "utf8") fs.writeFileSync(ns + filepath, data, "utf8")
} }
@ -18,254 +20,255 @@ function remove(filepath) {
o.spec("bundler", function() { o.spec("bundler", function() {
o("relative imports works", function() { o("relative imports works", function() {
write("a.js", `var b = require("./b")`) write("a.js", 'var b = require("./b")')
write("b.js", `module.exports = 1`) write("b.js", "module.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b = 1\n}());`)
o(read("out.js")).equals(";(function() {\nvar b = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports works with semicolons", function() { o("relative imports works with semicolons", function() {
write("a.js", `var b = require("./b");`) write("a.js", 'var b = require("./b");')
write("b.js", `module.exports = 1;`) write("b.js", "module.exports = 1;")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b = 1;\n}());`) o(read("out.js")).equals(";(function() {\nvar b = 1;\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports works with let", function() { o("relative imports works with let", function() {
write("a.js", `let b = require("./b")`) write("a.js", 'let b = require("./b")')
write("b.js", `module.exports = 1`) write("b.js", "module.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nlet b = 1\n}());`) o(read("out.js")).equals(";(function() {\nlet b = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports works with const", function() { o("relative imports works with const", function() {
write("a.js", 'const b = require("./b")') write("a.js", 'const b = require("./b")')
write("b.js", `module.exports = 1`) write("b.js", "module.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nconst b = 1\n}());`) o(read("out.js")).equals(";(function() {\nconst b = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports works with assignment", function() { o("relative imports works with assignment", function() {
write("a.js", `var a = {}\na.b = require("./b")`) write("a.js", 'var a = {}\na.b = require("./b")')
write("b.js", `module.exports = 1`) write("b.js", "module.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar a = {}\na.b = 1\n}());`) o(read("out.js")).equals(";(function() {\nvar a = {}\na.b = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports works with reassignment", function() { o("relative imports works with reassignment", function() {
write("a.js", `var b = {}\nb = require("./b")`) write("a.js", 'var b = {}\nb = require("./b")')
write("b.js", `module.exports = 1`) write("b.js", "module.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b = {}\nb = 1\n}());`) o(read("out.js")).equals(";(function() {\nvar b = {}\nb = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports removes extra use strict", function() { o("relative imports removes extra use strict", function() {
write("a.js", `"use strict"\nvar b = require("./b")`) write("a.js", '"use strict"\nvar b = require("./b")')
write("b.js", `"use strict"\nmodule.exports = 1`) write("b.js", '"use strict"\nmodule.exports = 1')
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\n"use strict"\nvar b = 1\n}());`) o(read("out.js")).equals(';(function() {\n"use strict"\nvar b = 1\n}());')
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports removes extra use strict using single quotes", function() { o("relative imports removes extra use strict using single quotes", function() {
write("a.js", `'use strict'\nvar b = require("./b")`) write("a.js", "'use strict'\nvar b = require(\"./b\")")
write("b.js", `'use strict'\nmodule.exports = 1`) write("b.js", "'use strict'\nmodule.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\n'use strict'\nvar b = 1\n}());`) o(read("out.js")).equals(";(function() {\n'use strict'\nvar b = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("relative imports removes extra use strict using mixed quotes", function() { o("relative imports removes extra use strict using mixed quotes", function() {
write("a.js", `"use strict"\nvar b = require("./b")`) write("a.js", '"use strict"\nvar b = require("./b")')
write("b.js", `'use strict'\nmodule.exports = 1`) write("b.js", "'use strict'\nmodule.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\n"use strict"\nvar b = 1\n}());`) o(read("out.js")).equals(';(function() {\n"use strict"\nvar b = 1\n}());')
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works w/ window", function() { o("works w/ window", function() {
write("a.js", `window.a = 1\nvar b = require("./b")`) write("a.js", 'window.a = 1\nvar b = require("./b")')
write("b.js", `module.exports = function() {return a}`) write("b.js", "module.exports = function() {return a}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nwindow.a = 1\nvar b = function() {return a}\n}());`) o(read("out.js")).equals(";(function() {\nwindow.a = 1\nvar b = function() {return a}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works without assignment", function() { o("works without assignment", function() {
write("a.js", `require("./b")`) write("a.js", 'require("./b")')
write("b.js", `1 + 1`) write("b.js", "1 + 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\n1 + 1\n}());`) o(read("out.js")).equals(";(function() {\n1 + 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works if used fluently", function() { o("works if used fluently", function() {
write("a.js", `var b = require("./b").toString()`) write("a.js", 'var b = require("./b").toString()')
write("b.js", `module.exports = []`) write("b.js", "module.exports = []")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = []\nvar b = _0.toString()\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = []\nvar b = _0.toString()\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works if used fluently w/ multiline", function() { o("works if used fluently w/ multiline", function() {
write("a.js", `var b = require("./b")\n\t.toString()`) write("a.js", 'var b = require("./b")\n\t.toString()')
write("b.js", `module.exports = []`) write("b.js", "module.exports = []")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = []\nvar b = _0\n\t.toString()\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = []\nvar b = _0\n\t.toString()\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works if used w/ curry", function() { o("works if used w/ curry", function() {
write("a.js", `var b = require("./b")()`) write("a.js", 'var b = require("./b")()')
write("b.js", `module.exports = function() {}`) write("b.js", "module.exports = function() {}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = function() {}\nvar b = _0()\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = function() {}\nvar b = _0()\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works if used w/ curry w/ multiline", function() { o("works if used w/ curry w/ multiline", function() {
write("a.js", `var b = require("./b")\n()`) write("a.js", 'var b = require("./b")\n()')
write("b.js", `module.exports = function() {}`) write("b.js", "module.exports = function() {}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = function() {}\nvar b = _0\n()\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = function() {}\nvar b = _0\n()\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works if used fluently in one place and not in another", function() { o("works if used fluently in one place and not in another", function() {
write("a.js", `var b = require("./b").toString()\nvar c = require("./c")`) write("a.js", 'var b = require("./b").toString()\nvar c = require("./c")')
write("b.js", `module.exports = []`) write("b.js", "module.exports = []")
write("c.js", `var b = require("./b")\nmodule.exports = function() {return b}`) write("c.js", 'var b = require("./b")\nmodule.exports = function() {return b}')
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = []\nvar b = _0.toString()\nvar b0 = _0\nvar c = function() {return b0}\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = []\nvar b = _0.toString()\nvar b0 = _0\nvar c = function() {return b0}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
remove("out.js") remove("out.js")
}) })
o("works if used in sequence", function() { o("works if used in sequence", function() {
write("a.js", `var b = require("./b"), c = require("./c")`) write("a.js", 'var b = require("./b"), c = require("./c")')
write("b.js", `module.exports = 1`) write("b.js", "module.exports = 1")
write("c.js", `var x\nmodule.exports = 2`) write("c.js", "var x\nmodule.exports = 2")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b = 1\nvar x\nvar c = 2\n}());`) o(read("out.js")).equals(";(function() {\nvar b = 1\nvar x\nvar c = 2\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
remove("out.js") remove("out.js")
}) })
o("works if assigned to property", function() { o("works if assigned to property", function() {
write("a.js", `var x = {}\nx.b = require("./b")\nx.c = require("./c")`) write("a.js", 'var x = {}\nx.b = require("./b")\nx.c = require("./c")')
write("b.js", `var bb = 1\nmodule.exports = bb`) write("b.js", "var bb = 1\nmodule.exports = bb")
write("c.js", `var cc = 2\nmodule.exports = cc`) write("c.js", "var cc = 2\nmodule.exports = cc")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar x = {}\nvar bb = 1\nx.b = bb\nvar cc = 2\nx.c = cc\n}());`) o(read("out.js")).equals(";(function() {\nvar x = {}\nvar bb = 1\nx.b = bb\nvar cc = 2\nx.c = cc\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
remove("out.js") remove("out.js")
}) })
o("works if assigned to property using bracket notation", function() { o("works if assigned to property using bracket notation", function() {
write("a.js", `var x = {}\nx["b"] = require("./b")\nx["c"] = require("./c")`) write("a.js", 'var x = {}\nx["b"] = require("./b")\nx["c"] = require("./c")')
write("b.js", `var bb = 1\nmodule.exports = bb`) write("b.js", "var bb = 1\nmodule.exports = bb")
write("c.js", `var cc = 2\nmodule.exports = cc`) write("c.js", "var cc = 2\nmodule.exports = cc")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar x = {}\nvar bb = 1\nx["b"] = bb\nvar cc = 2\nx["c"] = cc\n}());`) o(read("out.js")).equals(';(function() {\nvar x = {}\nvar bb = 1\nx["b"] = bb\nvar cc = 2\nx["c"] = cc\n}());')
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
remove("out.js") remove("out.js")
}) })
o("works if collision", function() { o("works if collision", function() {
write("a.js", `var b = require("./b")`) write("a.js", 'var b = require("./b")')
write("b.js", `var b = 1\nmodule.exports = 2`) write("b.js", "var b = 1\nmodule.exports = 2")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b0 = 1\nvar b = 2\n}());`) o(read("out.js")).equals(";(function() {\nvar b0 = 1\nvar b = 2\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("works if multiple aliases", function() { o("works if multiple aliases", function() {
write("a.js", `var b = require("./b")\n`) write("a.js", 'var b = require("./b")\n')
write("b.js", `var b = require("./c")\nb.x = 1\nmodule.exports = b`) write("b.js", 'var b = require("./c")\nb.x = 1\nmodule.exports = b')
write("c.js", `var b = {}\nmodule.exports = b`) write("c.js", "var b = {}\nmodule.exports = b")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b = {}\nb.x = 1\n}());`) o(read("out.js")).equals(";(function() {\nvar b = {}\nb.x = 1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
remove("out.js") remove("out.js")
}) })
o("works if multiple collision", function() { o("works if multiple collision", function() {
write("a.js", `var b = require("./b")\nvar c = require("./c")\nvar d = require("./d")`) write("a.js", 'var b = require("./b")\nvar c = require("./c")\nvar d = require("./d")')
write("b.js", `var a = 1\nmodule.exports = a`) write("b.js", "var a = 1\nmodule.exports = a")
write("c.js", `var a = 2\nmodule.exports = a`) write("c.js", "var a = 2\nmodule.exports = a")
write("d.js", `var a = 3\nmodule.exports = a`) write("d.js", "var a = 3\nmodule.exports = a")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar a = 1\nvar b = a\nvar a0 = 2\nvar c = a0\nvar a1 = 3\nvar d = a1\n}());`) o(read("out.js")).equals(";(function() {\nvar a = 1\nvar b = a\nvar a0 = 2\nvar c = a0\nvar a1 = 3\nvar d = a1\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
@ -273,38 +276,38 @@ o.spec("bundler", function() {
remove("out.js") remove("out.js")
}) })
o("works if included multiple times", function() { o("works if included multiple times", function() {
write("a.js", `module.exports = 123`) write("a.js", "module.exports = 123")
write("b.js", `var a = require("./a").toString()\nmodule.exports = a`) write("b.js", 'var a = require("./a").toString()\nmodule.exports = a')
write("c.js", `var a = require("./a").toString()\nvar b = require("./b")`) write("c.js", 'var a = require("./a").toString()\nvar b = require("./b")')
bundle(ns + "c.js", ns + "out.js") bundle(ns + "c.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = 123\nvar a = _0.toString()\nvar a0 = _0.toString()\nvar b = a0\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = 123\nvar a = _0.toString()\nvar a0 = _0.toString()\nvar b = a0\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
}) })
o("works if included multiple times reverse", function() { o("works if included multiple times reverse", function() {
write("a.js", `module.exports = 123`) write("a.js", "module.exports = 123")
write("b.js", `var a = require("./a").toString()\nmodule.exports = a`) write("b.js", 'var a = require("./a").toString()\nmodule.exports = a')
write("c.js", `var b = require("./b")\nvar a = require("./a").toString()`) write("c.js", 'var b = require("./b")\nvar a = require("./a").toString()')
bundle(ns + "c.js", ns + "out.js") bundle(ns + "c.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar _0 = 123\nvar a0 = _0.toString()\nvar b = a0\nvar a = _0.toString()\n}());`) o(read("out.js")).equals(";(function() {\nvar _0 = 123\nvar a0 = _0.toString()\nvar b = a0\nvar a = _0.toString()\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
}) })
o("reuses binding if possible", function() { o("reuses binding if possible", function() {
write("a.js", `var b = require("./b")\nvar c = require("./c")`) write("a.js", 'var b = require("./b")\nvar c = require("./c")')
write("b.js", `var d = require("./d")\nmodule.exports = function() {return d + 1}`) write("b.js", 'var d = require("./d")\nmodule.exports = function() {return d + 1}')
write("c.js", `var d = require("./d")\nmodule.exports = function() {return d + 2}`) write("c.js", 'var d = require("./d")\nmodule.exports = function() {return d + 2}')
write("d.js", `module.exports = 1`) write("d.js", "module.exports = 1")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar d = 1\nvar b = function() {return d + 1}\nvar c = function() {return d + 2}\n}());`) o(read("out.js")).equals(";(function() {\nvar d = 1\nvar b = function() {return d + 1}\nvar c = function() {return d + 2}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
@ -312,71 +315,71 @@ o.spec("bundler", function() {
remove("out.js") remove("out.js")
}) })
o("disambiguates conflicts if imported collides with itself", function() { o("disambiguates conflicts if imported collides with itself", function() {
write("a.js", `var b = require("./b")`) write("a.js", 'var b = require("./b")')
write("b.js", `var b = 1\nmodule.exports = function() {return b}`) write("b.js", "var b = 1\nmodule.exports = function() {return b}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b0 = 1\nvar b = function() {return b0}\n}());`) o(read("out.js")).equals(";(function() {\nvar b0 = 1\nvar b = function() {return b0}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("disambiguates conflicts if imported collides with something else", function() { o("disambiguates conflicts if imported collides with something else", function() {
write("a.js", `var a = 1\nvar b = require("./b")`) write("a.js", 'var a = 1\nvar b = require("./b")')
write("b.js", `var a = 2\nmodule.exports = function() {return a}`) write("b.js", "var a = 2\nmodule.exports = function() {return a}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar a = 1\nvar a0 = 2\nvar b = function() {return a0}\n}());`) o(read("out.js")).equals(";(function() {\nvar a = 1\nvar a0 = 2\nvar b = function() {return a0}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("disambiguates conflicts if imported collides with function declaration", function() { o("disambiguates conflicts if imported collides with function declaration", function() {
write("a.js", `function a() {}\nvar b = require("./b")`) write("a.js", 'function a() {}\nvar b = require("./b")')
write("b.js", `var a = 2\nmodule.exports = function() {return a}`) write("b.js", "var a = 2\nmodule.exports = function() {return a}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nfunction a() {}\nvar a0 = 2\nvar b = function() {return a0}\n}());`) o(read("out.js")).equals(";(function() {\nfunction a() {}\nvar a0 = 2\nvar b = function() {return a0}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("disambiguates conflicts if imported collides with another module's private", function() { o("disambiguates conflicts if imported collides with another module's private", function() {
write("a.js", `var b = require("./b")\nvar c = require("./c")`) write("a.js", 'var b = require("./b")\nvar c = require("./c")')
write("b.js", `var a = 1\nmodule.exports = function() {return a}`) write("b.js", "var a = 1\nmodule.exports = function() {return a}")
write("c.js", `var a = 2\nmodule.exports = function() {return a}`) write("c.js", "var a = 2\nmodule.exports = function() {return a}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar a = 1\nvar b = function() {return a}\nvar a0 = 2\nvar c = function() {return a0}\n}());`) o(read("out.js")).equals(";(function() {\nvar a = 1\nvar b = function() {return a}\nvar a0 = 2\nvar c = function() {return a0}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("c.js") remove("c.js")
remove("out.js") remove("out.js")
}) })
o("does not mess up strings", function() { o("does not mess up strings", function() {
write("a.js", `var b = require("./b")`) write("a.js", 'var b = require("./b")')
write("b.js", `var b = "b b b \\\" b"\nmodule.exports = function() {return b}`) write("b.js", 'var b = "b b b \\" b"\nmodule.exports = function() {return b}')
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b0 = "b b b \\\" b"\nvar b = function() {return b0}\n}());`) o(read("out.js")).equals(';(function() {\nvar b0 = "b b b \\\" b"\nvar b = function() {return b0}\n}());')
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
o("does not mess up properties", function() { o("does not mess up properties", function() {
write("a.js", `var b = require("./b")`) write("a.js", 'var b = require("./b")')
write("b.js", `var b = {b: 1}\nmodule.exports = function() {return b.b}`) write("b.js", "var b = {b: 1}\nmodule.exports = function() {return b.b}")
bundle(ns + "a.js", ns + "out.js") bundle(ns + "a.js", ns + "out.js")
o(read("out.js")).equals(`;(function() {\nvar b0 = {b: 1}\nvar b = function() {return b0.b}\n}());`) o(read("out.js")).equals(";(function() {\nvar b0 = {b: 1}\nvar b = function() {return b0.b}\n}());")
remove("a.js") remove("a.js")
remove("b.js") remove("b.js")
remove("out.js") remove("out.js")
}) })
}) })

1
docs/CNAME Normal file
View file

@ -0,0 +1 @@
mithril.js.org

View file

@ -1,15 +1,17 @@
"use strict"
var fs = require("fs") var fs = require("fs")
var path = require("path") var path = require("path")
var marked = require("marked") var marked = require("marked")
var layout = fs.readFileSync("./docs/layout.html", "utf-8") var layout = fs.readFileSync("./docs/layout.html", "utf-8")
var version = JSON.parse(fs.readFileSync("./package.json", "utf-8")).version var version = JSON.parse(fs.readFileSync("./package.json", "utf-8")).version
try {fs.mkdirSync("../mithril")} catch (e) {} try {fs.mkdirSync("./dist")} catch (e) {/* ignore */}
try {fs.mkdirSync("../mithril/archive")} catch (e) {} try {fs.mkdirSync("./dist/archive")} catch (e) {/* ignore */}
try {fs.mkdirSync("../mithril/archive/v" + version)} catch (e) {} try {fs.mkdirSync("./dist/archive/v" + version)} catch (e) {/* ignore */}
try {fs.mkdirSync("../mithril/archive/v" + version + "/lib")} catch (e) {} try {fs.mkdirSync("./dist/archive/v" + version + "/lib")} catch (e) {/* ignore */}
try {fs.mkdirSync("../mithril/archive/v" + version + "/lib/prism")} catch (e) {} try {fs.mkdirSync("./dist/archive/v" + version + "/lib/prism")} catch (e) {/* ignore */}
try {fs.mkdirSync("../mithril/lib")} catch (e) {} try {fs.mkdirSync("./dist/lib")} catch (e) {/* ignore */}
try {fs.mkdirSync("../mithril/lib/prism")} catch (e) {} try {fs.mkdirSync("./dist/lib/prism")} catch (e) {/* ignore */}
var guides = fs.readFileSync("docs/guides.md", "utf-8") var guides = fs.readFileSync("docs/guides.md", "utf-8")
var methods = fs.readFileSync("docs/methods.md", "utf-8") var methods = fs.readFileSync("docs/methods.md", "utf-8")
@ -33,7 +35,7 @@ function generate(pathname) {
.replace(/`((?:\S| -> |, )+)(\|)(\S+)`/gim, function(match, a, b, c) { // fix pipes in code tags .replace(/`((?:\S| -> |, )+)(\|)(\S+)`/gim, function(match, a, b, c) { // fix pipes in code tags
return "<code>" + (a + b + c).replace(/\|/g, "&#124;") + "</code>" return "<code>" + (a + b + c).replace(/\|/g, "&#124;") + "</code>"
}) })
.replace(/(^# .+?(?:\r?\n){2,}?)(?:(-(?:.|\r|\n)+?)((?:\r?\n){2,})|)/m, function(match, title, nav, space) { // inject menu .replace(/(^# .+?(?:\r?\n){2,}?)(?:(-(?:.|\r|\n)+?)((?:\r?\n){2,})|)/m, function(match, title, nav) { // inject menu
var file = path.basename(pathname) var file = path.basename(pathname)
var link = new RegExp("([ \t]*)(- )(\\[.+?\\]\\(" + file + "\\))") var link = new RegExp("([ \t]*)(- )(\\[.+?\\]\\(" + file + "\\))")
var replace = function(match, space, li, link) { var replace = function(match, space, li, link) {
@ -53,14 +55,14 @@ function generate(pathname) {
.replace(/\[version\]/, version) // update version .replace(/\[version\]/, version) // update version
.replace(/\[body\]/, markedHtml) .replace(/\[body\]/, markedHtml)
.replace(/<h(.) id="([^"]+?)">(.+?)<\/h.>/gim, function(match, n, id, text) { // fix anchors .replace(/<h(.) id="([^"]+?)">(.+?)<\/h.>/gim, function(match, n, id, text) { // fix anchors
return "<h" + n + " id=\"" + text.toLowerCase().replace(/<(\/?)code>/g, "").replace(/<a.*?>.+?<\/a>/g, "").replace(/\.|\[|\]|&quot;|\/|\(|\)/g, "").replace(/\s/g, "-") + "\">" + text + "</h" + n + ">" return "<h" + n + ' id="' + text.toLowerCase().replace(/<(\/?)code>/g, "").replace(/<a.*?>.+?<\/a>/g, "").replace(/\.|\[|\]|&quot;|\/|\(|\)/g, "").replace(/\s/g, "-") + '">' + text + "</h" + n + ">"
}) })
fs.writeFileSync("../mithril/archive/v" + version + "/" + outputFilename.replace(/^docs\//, ""), html, "utf-8") fs.writeFileSync("./dist/archive/v" + version + "/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
fs.writeFileSync("../mithril/" + outputFilename.replace(/^docs\//, ""), html, "utf-8") fs.writeFileSync("./dist/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
} }
else if (!pathname.match(/lint|generate/)) { else if (!pathname.match(/lint|generate/)) {
fs.writeFileSync("../mithril/archive/v" + version + "/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8") fs.writeFileSync("./dist/archive/v" + version + "/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8")
fs.writeFileSync("../mithril/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8") fs.writeFileSync("./dist/" + pathname.replace(/^docs\//, ""), fs.readFileSync(pathname, "utf-8"), "utf-8")
} }
} }
} }

View file

@ -45,8 +45,8 @@ var link = <a href={url}>{greeting + "!"}</a>
Components can be used by using a convention of uppercasing the first letter of the component name: Components can be used by using a convention of uppercasing the first letter of the component name:
```jsx ```jsx
m.mount(document.body, <MyComponent />) m.render(document.body, <MyComponent />)
// equivalent to m.mount(document.body, m(MyComponent)) // equivalent to m.render(document.body, m(MyComponent))
``` ```
--- ---

View file

@ -1,4 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
"use strict"
var fs = require("fs") var fs = require("fs")
var path = require("path") var path = require("path")
@ -100,11 +101,11 @@ function ensureLinkIsValid(file, data) {
} }
function initMocks() { function initMocks() {
global.window = require("../test-utils/browserMock")() global.window = require("../test-utils/browserMock")() // eslint-disable-line global-require
global.document = window.document global.document = window.document
global.m = require("../index") global.m = require("../index") // eslint-disable-line global-require
global.o = require("../ospec/ospec") global.o = require("../ospec/ospec") // eslint-disable-line global-require
global.stream = require("../stream") global.stream = require("../stream") // eslint-disable-line global-require
global.alert = function() {} global.alert = function() {}
//routes consumed by request.md //routes consumed by request.md
@ -121,7 +122,7 @@ function initMocks() {
"GET /api/v1/todos": function() { "GET /api/v1/todos": function() {
return {status: 200, responseText: JSON.stringify([])} return {status: 200, responseText: JSON.stringify([])}
}, },
"PUT /api/v1/users/1": function() { "PUT /api/v1/users/1": function(request) {
return {status: 200, responseText: request.query.callback ? request.query.callback + "([])" : "[]"} return {status: 200, responseText: request.query.callback ? request.query.callback + "([])" : "[]"}
}, },
"POST /api/v1/upload": function() { "POST /api/v1/upload": function() {

View file

@ -73,9 +73,11 @@ Property | Type | Description
`text` | `(String|Number|Boolean)?` | This is used instead of `children` if a vnode contains a text node as its only child. This is done for performance reasons. Component vnodes never use the `text` property even if they have a text node as their only child. `text` | `(String|Number|Boolean)?` | This is used instead of `children` if a vnode contains a text node as its only child. This is done for performance reasons. Component vnodes never use the `text` property even if they have a text node as their only child.
`dom` | `Element?` | Points to the element that corresponds to the vnode. This property is `undefined` in the `oninit` lifecycle method. In fragments and trusted HTML vnodes, `dom` points to the first element in the range. `dom` | `Element?` | Points to the element that corresponds to the vnode. This property is `undefined` in the `oninit` lifecycle method. In fragments and trusted HTML vnodes, `dom` points to the first element in the range.
`domSize` | `Number?` | This is only set in fragment and trusted HTML vnodes, and it's `undefined` in all other vnode types. It defines the number of DOM elements that the vnode represents (starting from the element referenced by the `dom` property). `domSize` | `Number?` | This is only set in fragment and trusted HTML vnodes, and it's `undefined` in all other vnode types. It defines the number of DOM elements that the vnode represents (starting from the element referenced by the `dom` property).
`state` | `Object` | An object that is persisted between redraws. In component vnodes, `state` is a shallow clone of the component object. `state` | `Object`? | An object that is persisted between redraws. It is provided by the core engine when needed. In component vnodes, the `state` inherits prototypically from the component object/class.
`events` | `Object?` | An object that is persisted between redraws and that stores event handlers so that they can be removed using the DOM API. The `events` property is `undefined` if there are no event handlers defined. This property is only used internally by Mithril, do not use it. `events` | `Object?` | An object that is persisted between redraws and that stores event handlers so that they can be removed using the DOM API. The `events` property is `undefined` if there are no event handlers defined. This property is only used internally by Mithril, do not use it.
--- ---
### Vnode types ### Vnode types

View file

@ -38,7 +38,7 @@ var state = {
update: function(title) { update: function(title) {
if (state.editing != null) { if (state.editing != null) {
state.editing.title = title.trim() state.editing.title = title.trim()
if (state.editing.title === "") destroy(state.editing) if (state.editing.title === "") state.destroy(state.editing)
state.editing = null state.editing = null
} }
}, },
@ -104,7 +104,7 @@ var Todos = {
m("label", {ondblclick: function() {state.dispatch("edit", [todo])}}, todo.title), m("label", {ondblclick: function() {state.dispatch("edit", [todo])}}, todo.title),
m("button.destroy", {onclick: function() {state.dispatch("destroy", [todo])}}), m("button.destroy", {onclick: function() {state.dispatch("destroy", [todo])}}),
]), ]),
m("input.edit", {onupdate: function(vnode) {ui.focus(vnode, todo)}, onkeypress: ui.save, onblur: ui.save}) m("input.edit", {onupdate: function(vnode) {ui.focus(vnode, todo)}, onkeyup: ui.save, onblur: ui.save})
]) ])
}), }),
]), ]),

View file

@ -1,3 +1,5 @@
"use strict"
var hyperscript = require("./render/hyperscript") var hyperscript = require("./render/hyperscript")
hyperscript.trust = require("./render/trust") hyperscript.trust = require("./render/trust")

308
mithril.d.ts vendored
View file

@ -1,308 +0,0 @@
// Type definitions for mithril.js 1.0
// Project: https://github.com/lhorie/mithril.js
// Definitions by: Mike Linkovich <https://github.com/spacejack>
declare namespace Mithril {
interface Lifecycle<A,S> {
/** The oninit hook is called before a vnode is touched by the virtual DOM engine. */
oninit?: (this: S, vnode: Vnode<A,S>) => void;
/** The oncreate hook is called after a DOM element is created and attached to the document. */
oncreate?: (this: S, vnode: VnodeDOM<A,S>) => void;
/** The onbeforeupdate hook is called before a vnode is diffed in a update. */
onbeforeupdate?: (this: S, vnode: Vnode<A,S>, old: Vnode<A,S>) => boolean;
/** The onupdate hook is called after a DOM element is updated, while attached to the document. */
onupdate?: (this: S, vnode: VnodeDOM<A,S>) => void;
/** The onbeforeremove hook is called before a DOM element is detached from the document. If a Promise is returned, Mithril only detaches the DOM element after the promise completes. */
onbeforeremove?: (this: S, vnode: VnodeDOM<A,S>) => Promise<any> | void;
/** The onremove hook is called before a DOM element is removed from the document. */
onremove?: (this: S, vnode: VnodeDOM<A,S>) => void;
}
interface Hyperscript {
/** Creates a virtual element (Vnode). */
(selector: string, ...children: any[]): Vnode<any,any>;
/** Creates a virtual element (Vnode). */
<A,S>(component: Component<A,S> | {new(vnode: CVnode<A>): ClassComponent<A>} | FactoryComponent<A,S>, a?: (A & Lifecycle<A,S>) | Children, ...children: Children[]): Vnode<A,S>;
/** Creates a fragment virtual element (Vnode). */
fragment(attrs: any, children: Children[]): Vnode<any,any>;
/** Turns an HTML string into a virtual element (Vnode). Do not use trust on unsanitized user input. */
trust(html: string): Vnode<any,any>;
}
interface RouteResolver {
/** The onmatch hook is called when the router needs to find a component to render. */
onmatch?: (args: any, requestedPath: string) => Mithril.Component<any,any> | {new(vnode: CVnode<any>): ClassComponent<any>} | FactoryComponent<any,any> | Promise<Mithril.Component<any,any> | {new(): Component<any,any>} | FactoryComponent<any,any>> | void;
/** The render method is called on every redraw for a matching route. */
render?: (vnode: Mithril.Vnode<any,any>) => Children;
}
interface RouteDefs {
[url: string]: Component<any,any> | {new(vnode: CVnode<any>): ClassComponent<any>} | FactoryComponent<any,any> | RouteResolver;
}
interface RouteOptions {
replace?: boolean;
state?: any;
title?: string;
}
interface Route {
/** Creates application routes and mounts Components and/or RouteResolvers to a DOM element. */
(element: HTMLElement, defaultRoute: string, routes: RouteDefs): void;
/** Returns the last fully resolved routing path, without the prefix. */
get(): string;
/** Redirects to a matching route or to the default route if no matching routes can be found. */
set(route: string, data?: any, options?: RouteOptions): void;
/** Defines a router prefix which is a fragment of the URL that dictates the underlying strategy used by the router. */
prefix(urlFragment: string): void;
/** This method is meant to be used in conjunction with an <a> Vnode's oncreate hook. */
link(vnode: Vnode<any,any>): (e: Event) => void;
/** Returns the named parameter value from the current route. */
param(name?: string): any;
}
interface Mount {
/** Mounts a component to a DOM element, enabling it to autoredraw on user events. */
(element: Element, component: Component<any,any> | {new(vnode: CVnode<any>): ClassComponent<any>} | FactoryComponent<any,any> | null): void;
}
interface WithAttr {
/** Creates an event handler which takes the value of the specified DOM element property and calls a function with it as the argument. */
(name: string, callback: (value: any) => void, thisArg?: any): (e: {currentTarget: any, [p: string]: any}) => boolean;
}
interface ParseQueryString {
/** Returns an object with key/value pairs parsed from a string of the form: ?a=1&b=2 */
(queryString: string): any;
}
interface BuildQueryString {
/** Turns the key/value pairs of an object into a string of the form: a=1&b=2 */
(values: {[p: string]: any}): string;
}
interface RequestOptions<T> {
method?: string;
data?: any;
async?: boolean;
user?: string;
password?: string;
withCredentials?: boolean;
config?: (xhr: XMLHttpRequest) => void;
headers?: any;
type?: any;
serialize?: (data: any) => string;
deserialize?: (str: string) => T;
extract?: (xhr: XMLHttpRequest, options: RequestOptions<T>) => string;
useBody?: boolean;
background?: boolean;
}
interface RequestOptionsAll<T> extends RequestOptions<T> {
url: string;
}
interface Request {
/** Makes an XHR request and returns a promise. */
<T>(options: RequestOptionsAll<T>): Promise<T>;
/** Makes an XHR request and returns a promise. */
<T>(url: string, options?: RequestOptions<T>): Promise<T>;
}
interface JsonpOptions {
data?: any;
type?: any;
callbackName?: string;
callbackKey?: string;
background?: boolean;
}
interface JsonpOptionsAll extends JsonpOptions {
url: string;
}
interface Jsonp {
/** Makes a JSON-P request and returns a promise. */
<T>(options: JsonpOptionsAll): Promise<T>;
/** Makes a JSON-P request and returns a promise. */
<T>(url: string, options?: JsonpOptions): Promise<T>;
}
interface RequestService {
request: Request;
jsonp: Jsonp;
}
interface Render {
/** Renders a vnode structure into a DOM element. */
(el: Element, vnodes: Children): void;
}
interface RenderService {
render: Render
}
interface Redraw {
/** Manually triggers a redraw of mounted components. */
(): void;
}
interface RedrawService {
redraw: Redraw
render: Render
}
interface Static extends Hyperscript {
route: Route;
mount: Mount;
withAttr: WithAttr;
render: Render;
redraw: Redraw;
request: Request;
jsonp: Jsonp;
parseQueryString: ParseQueryString;
buildQueryString: BuildQueryString;
version: string;
}
// Vnode children types
type Child = Vnode<any,any> | string | number | boolean | null | undefined;
interface ChildArray extends Array<Children> {}
type Children = Child | ChildArray;
interface Vnode<A, S extends Lifecycle<A,S>> {
tag: string | Component<A,S>;
attrs: A;
state: S;
key?: string;
children?: Vnode<any,any>[];
events?: any;
}
// In some lifecycle methods, Vnode will have a dom property
// and possibly a domSize property.
interface VnodeDOM<A,S> extends Vnode<A,S> {
dom: Element;
domSize?: number;
}
interface CVnode<A> extends Vnode<A, ClassComponent<A>> {}
interface CVnodeDOM<A> extends VnodeDOM<A, ClassComponent<A>> {}
interface Component<A, S extends Lifecycle<A,S>> extends Lifecycle<A,S> {
view (this: S, vnode: Vnode<A,S>): Vnode<any,any> | null | void | (Vnode<any,any> | null | void)[];
}
interface ClassComponent<A> extends Lifecycle<A,ClassComponent<A>> {
view (this: ClassComponent<A>, vnode: CVnode<A>): Vnode<any,any> | null | void | (Vnode<any,any> | null | void)[];
}
// Factory component
type FactoryComponent<A,S> = (vnode: Vnode<A,S>) => Component<A,S>
type Unary<T,U> = (input: T) => U;
interface Functor<T> {
map<U>(f: Unary<T,U>): Functor<U>;
ap?(f: Functor<T>): Functor<T>;
}
interface Stream<T> {
/** Returns the value of the stream. */
(): T;
/** Sets the value of the stream. */
(value: T): this;
/** Creates a dependent stream whose value is set to the result of the callback function. */
map(f: (current: T) => Stream<T> | T | void): Stream<T>;
/** Creates a dependent stream whose value is set to the result of the callback function. */
map<U>(f: (current: T) => Stream<U> | U): Stream<U>;
/** This method is functionally identical to stream. It exists to conform to Fantasy Land's Applicative specification. */
of(val?: T): Stream<T>;
/** Apply. */
ap<U>(f: Stream<(value: T) => U>): Stream<U>;
/** A co-dependent stream that unregisters dependent streams when set to true. */
end: Stream<boolean>;
}
type StreamCombiner<T> = (...streams: any[]) => T
interface StreamFactory {
/** Creates a stream. */
<T>(val?: T): Stream<T>;
/** Creates a computed stream that reactively updates if any of its upstreams are updated. */
combine<T>(combiner: StreamCombiner<T>, streams: Stream<any>[]): Stream<T>;
/** Creates a stream whose value is the array of values from an array of streams. */
merge(streams: Stream<any>[]): Stream<any[]>;
/** A special value that can be returned to stream callbacks to halt execution of downstreams. */
HALT: any;
}
interface StreamScan {
/** Creates a new stream with the results of calling the function on every incoming stream with and accumulator and the incoming value. */
<T,U>(fn: (acc: U, value: T) => U, acc: U, stream: Stream<T>): Stream<U>;
}
interface StreamScanMerge {
/** Takes an array of pairs of streams and scan functions and merges all those streams using the given functions into a single stream. */
<T,U>(pairs: [Stream<T>, (acc: U, value: T) => U][], acc: U): Stream<U>;
/** Takes an array of pairs of streams and scan functions and merges all those streams using the given functions into a single stream. */
<U>(pairs: [Stream<any>, (acc: U, value: any) => U][], acc: U): Stream<U>;
}
}
declare module 'mithril' {
const m: Mithril.Static;
export = m;
}
declare module 'mithril/hyperscript' {
const h: Mithril.Hyperscript;
export = h;
}
declare module 'mithril/mount' {
const m: Mithril.Mount;
export = m;
}
declare module 'mithril/route' {
const r: Mithril.Route;
export = r;
}
declare module 'mithril/request' {
const r: Mithril.RequestService;
export = r;
}
declare module 'mithril/render' {
const r: Mithril.RenderService;
export = r;
}
declare module 'mithril/redraw' {
const r: Mithril.RedrawService;
export = r;
}
declare module 'mithril/util/withAttr' {
const withAttr: Mithril.WithAttr;
export = withAttr;
}
declare module 'mithril/stream' {
const s: Mithril.StreamFactory;
export = s;
}
declare module 'mithril/stream/scan' {
const s: Mithril.StreamScan;
export = s;
}
declare module 'mithril/stream/scanMerge' {
const sm: Mithril.StreamScanMerge;
export = sm;
}

View file

@ -1,7 +1,7 @@
;(function() { ;(function() {
"use strict"
function Vnode(tag, key, attrs0, children, text, dom) { function Vnode(tag, key, attrs0, children, text, dom) {
return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: {}, events: undefined, instance: undefined, skip: false} return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined, skip: false}
} }
Vnode.normalize = function(node) { Vnode.normalize = function(node) {
if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)
@ -389,6 +389,7 @@ var coreRenderer = function($window) {
function createNode(parent, vnode, hooks, ns, nextSibling) { function createNode(parent, vnode, hooks, ns, nextSibling) {
var tag = vnode.tag var tag = vnode.tag
if (typeof tag === "string") { if (typeof tag === "string") {
vnode.state = {}
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
switch (tag) { switch (tag) {
case "#": return createText(parent, vnode, nextSibling) case "#": return createText(parent, vnode, nextSibling)
@ -597,7 +598,10 @@ var coreRenderer = function($window) {
if (!recycling && shouldNotUpdate(vnode, old)) return if (!recycling && shouldNotUpdate(vnode, old)) return
if (typeof oldTag === "string") { if (typeof oldTag === "string") {
if (vnode.attrs != null) { if (vnode.attrs != null) {
if (recycling) initLifecycle(vnode.attrs, vnode, hooks) if (recycling) {
vnode.state = {}
initLifecycle(vnode.attrs, vnode, hooks)
}
else updateLifecycle(vnode.attrs, vnode, hooks) else updateLifecycle(vnode.attrs, vnode, hooks)
} }
switch (oldTag) { switch (oldTag) {
@ -990,11 +994,11 @@ var _11 = function($window) {
var index = callbacks.indexOf(key1) var index = callbacks.indexOf(key1)
if (index > -1) callbacks.splice(index, 2) if (index > -1) callbacks.splice(index, 2)
} }
function redraw() { function redraw() {
for (var i = 1; i < callbacks.length; i += 2) { for (var i = 1; i < callbacks.length; i += 2) {
callbacks[i]() callbacks[i]()
} }
} }
return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render} return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render}
} }
var redrawService = _11(window) var redrawService = _11(window)

86
mithril.min.js vendored
View file

@ -1,43 +1,43 @@
(function(){function B(b,d,f,g,e,p){return{tag:b,key:d,attrs:f,children:g,text:e,dom:p,domSize:void 0,state:{},events:void 0,instance:void 0,skip:!1}}function C(b){var d=arguments[1],f=2,g;if(null==b||"string"!==typeof b&&"function"!==typeof b&&"function"!==typeof b.view)throw Error("The selector must be either a string or a component.");if("string"===typeof b){var e;if(!(e=M[b])){g="div";for(var p=[],k={};e=P.exec(b);){var q=e[1],m=e[2];""===q&&""!==m?g=m:"#"===q?k.id=m:"."===q?p.push(m):"["===e[3][0]&& (function(){function B(a,d,f,g,e,p){return{tag:a,key:d,attrs:f,children:g,text:e,dom:p,domSize:void 0,state:void 0,events:void 0,instance:void 0,skip:!1}}function C(a){var d=arguments[1],f=2,g;if(null==a||"string"!==typeof a&&"function"!==typeof a&&"function"!==typeof a.view)throw Error("The selector must be either a string or a component.");if("string"===typeof a){var e;if(!(e=M[a])){g="div";for(var p=[],k={};e=P.exec(a);){var q=e[1],n=e[2];""===q&&""!==n?g=n:"#"===q?k.id=n:"."===q?p.push(n):"["===
((q=e[6])&&(q=q.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")),"class"===e[4]?p.push(q):k[e[4]]=q||!0)}0<p.length&&(k.className=p.join(" "));e=M[b]={tag:g,attrs:k}}}if(!d)d={};else if("object"!==typeof d||null!=d.tag||Array.isArray(d))d={},f=1;if(arguments.length===f+1)g=arguments[f],Array.isArray(g)||(g=[g]);else for(g=[];f<arguments.length;)g.push(arguments[f++]);f=B.normalizeChildren(g);if("string"===typeof b){g=!1;var l,u,p=d.className||d["class"],a;for(a in e.attrs)N.call(e.attrs,a)&&(d[a]= e[3][0]&&((q=e[6])&&(q=q.replace(/\\(["'])/g,"$1").replace(/\\\\/g,"\\")),"class"===e[4]?p.push(q):k[e[4]]=q||!0)}0<p.length&&(k.className=p.join(" "));e=M[a]={tag:g,attrs:k}}}if(!d)d={};else if("object"!==typeof d||null!=d.tag||Array.isArray(d))d={},f=1;if(arguments.length===f+1)g=arguments[f],Array.isArray(g)||(g=[g]);else for(g=[];f<arguments.length;)g.push(arguments[f++]);f=B.normalizeChildren(g);if("string"===typeof a){g=!1;var l,u,p=d.className||d["class"],b;for(b in e.attrs)N.call(e.attrs,
e.attrs[a]);null!=p&&(null!=d["class"]&&(d["class"]=void 0,d.className=p),null!=e.attrs.className&&(d.className=e.attrs.className+" "+p));for(a in d)if(N.call(d,a)&&"key"!==a){g=!0;break}Array.isArray(f)&&1===f.length&&null!=f[0]&&"#"===f[0].tag?u=f[0].children:l=f;return B(e.tag,d.key,g?d:void 0,l,u)}return B(b,d.key,d,f)}function Q(b){var d=0,f=null,g="function"===typeof requestAnimationFrame?requestAnimationFrame:setTimeout;return function(){var e=Date.now();0===d||16<=e-d?(d=e,b()):null===f&& b)&&(d[b]=e.attrs[b]);null!=p&&(null!=d["class"]&&(d["class"]=void 0,d.className=p),null!=e.attrs.className&&(d.className=e.attrs.className+" "+p));for(b in d)if(N.call(d,b)&&"key"!==b){g=!0;break}Array.isArray(f)&&1===f.length&&null!=f[0]&&"#"===f[0].tag?u=f[0].children:l=f;return B(e.tag,d.key,g?d:void 0,l,u)}return B(a,d.key,d,f)}function Q(a){var d=0,f=null,g="function"===typeof requestAnimationFrame?requestAnimationFrame:setTimeout;return function(){var e=Date.now();0===d||16<=e-d?(d=e,a()):
(f=g(function(){f=null;b();d=Date.now()},16-(e-d)))}}B.normalize=function(b){return Array.isArray(b)?B("[",void 0,void 0,B.normalizeChildren(b),void 0,void 0):null!=b&&"object"!==typeof b?B("#",void 0,void 0,!1===b?"":b,void 0,void 0):b};B.normalizeChildren=function(b){for(var d=0;d<b.length;d++)b[d]=B.normalize(b[d]);return b};var P=/(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g,M={},N={}.hasOwnProperty;C.trust=function(b){null==b&&(b="");return B("<",void 0,void 0, null===f&&(f=g(function(){f=null;a();d=Date.now()},16-(e-d)))}}B.normalize=function(a){return Array.isArray(a)?B("[",void 0,void 0,B.normalizeChildren(a),void 0,void 0):null!=a&&"object"!==typeof a?B("#",void 0,void 0,!1===a?"":a,void 0,void 0):a};B.normalizeChildren=function(a){for(var d=0;d<a.length;d++)a[d]=B.normalize(a[d]);return a};var P=/(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g,M={},N={}.hasOwnProperty;C.trust=function(a){null==a&&(a="");return B("<",void 0,
b,void 0,void 0)};C.fragment=function(b,d){return B("[",b.key,b,B.normalizeChildren(d),void 0,void 0)};var x=function(b){function d(b,a){return function r(d){var k;try{if(!a||null==d||"object"!==typeof d&&"function"!==typeof d||"function"!==typeof(k=d.then))l(function(){a||0!==b.length||console.error("Possible unhandled promise rejection:",d);for(var f=0;f<b.length;f++)b[f](d);e.length=0;p.length=0;m.state=a;m.retry=function(){r(d)}});else{if(d===g)throw new TypeError("Promise can't be resolved w/ itself"); void 0,a,void 0,void 0)};C.fragment=function(a,d){return B("[",a.key,a,B.normalizeChildren(d),void 0,void 0)};var x=function(a){function d(a,b){return function r(d){var k;try{if(!b||null==d||"object"!==typeof d&&"function"!==typeof d||"function"!==typeof(k=d.then))l(function(){b||0!==a.length||console.error("Possible unhandled promise rejection:",d);for(var f=0;f<a.length;f++)a[f](d);e.length=0;p.length=0;n.state=b;n.retry=function(){r(d)}});else{if(d===g)throw new TypeError("Promise can't be resolved w/ itself");
f(k.bind(d))}}catch(R){q(R)}}}function f(b){function a(a){return function(b){0<d++||a(b)}}var d=0,e=a(q);try{b(a(k),e)}catch(A){e(A)}}if(!(this instanceof x))throw Error("Promise must be called with `new`");if("function"!==typeof b)throw new TypeError("executor must be a function");var g=this,e=[],p=[],k=d(e,!0),q=d(p,!1),m=g._instance={resolvers:e,rejectors:p},l="function"===typeof setImmediate?setImmediate:setTimeout;f(b)};x.prototype.then=function(b,d){function f(b,d,f,k){d.push(function(a){if("function"!== f(k.bind(d))}}catch(R){q(R)}}}function f(a){function b(b){return function(a){0<d++||b(a)}}var d=0,e=b(q);try{a(b(k),e)}catch(A){e(A)}}if(!(this instanceof x))throw Error("Promise must be called with `new`");if("function"!==typeof a)throw new TypeError("executor must be a function");var g=this,e=[],p=[],k=d(e,!0),q=d(p,!1),n=g._instance={resolvers:e,rejectors:p},l="function"===typeof setImmediate?setImmediate:setTimeout;f(a)};x.prototype.then=function(a,d){function f(a,d,f,k){d.push(function(b){if("function"!==
typeof b)f(a);else try{e(b(a))}catch(w){p&&p(w)}});"function"===typeof g.retry&&k===g.state&&g.retry()}var g=this._instance,e,p,k=new x(function(b,d){e=b;p=d});f(b,g.resolvers,e,!0);f(d,g.rejectors,p,!1);return k};x.prototype["catch"]=function(b){return this.then(null,b)};x.resolve=function(b){return b instanceof x?b:new x(function(d){d(b)})};x.reject=function(b){return new x(function(d,f){f(b)})};x.all=function(b){return new x(function(d,f){var g=b.length,e=0,p=[];if(0===b.length)d([]);else for(var k= typeof a)f(b);else try{e(a(b))}catch(w){p&&p(w)}});"function"===typeof g.retry&&k===g.state&&g.retry()}var g=this._instance,e,p,k=new x(function(a,d){e=a;p=d});f(a,g.resolvers,e,!0);f(d,g.rejectors,p,!1);return k};x.prototype["catch"]=function(a){return this.then(null,a)};x.resolve=function(a){return a instanceof x?a:new x(function(d){d(a)})};x.reject=function(a){return new x(function(d,f){f(a)})};x.all=function(a){return new x(function(d,f){var g=a.length,e=0,p=[];if(0===a.length)d([]);else for(var k=
0;k<b.length;k++)(function(k){function m(b){e++;p[k]=b;e===g&&d(p)}null==b[k]||"object"!==typeof b[k]&&"function"!==typeof b[k]||"function"!==typeof b[k].then?m(b[k]):b[k].then(m,f)})(k)})};x.race=function(b){return new x(function(d,f){for(var g=0;g<b.length;g++)b[g].then(d,f)})};"undefined"!==typeof window?("undefined"===typeof window.Promise&&(window.Promise=x),x=window.Promise):"undefined"!==typeof global&&("undefined"===typeof global.Promise&&(global.Promise=x),x=global.Promise);var F=function(b){function d(b, 0;k<a.length;k++)(function(k){function n(a){e++;p[k]=a;e===g&&d(p)}null==a[k]||"object"!==typeof a[k]&&"function"!==typeof a[k]||"function"!==typeof a[k].then?n(a[k]):a[k].then(n,f)})(k)})};x.race=function(a){return new x(function(d,f){for(var g=0;g<a.length;g++)a[g].then(d,f)})};"undefined"!==typeof window?("undefined"===typeof window.Promise&&(window.Promise=x),x=window.Promise):"undefined"!==typeof global&&("undefined"===typeof global.Promise&&(global.Promise=x),x=global.Promise);var F=function(a){function d(a,
g){if(Array.isArray(g))for(var e=0;e<g.length;e++)d(b+"["+e+"]",g[e]);else if("[object Object]"===Object.prototype.toString.call(g))for(e in g)d(b+"["+e+"]",g[e]);else f.push(encodeURIComponent(b)+(null!=g&&""!==g?"="+encodeURIComponent(g):""))}if("[object Object]"!==Object.prototype.toString.call(b))return"";var f=[],g;for(g in b)d(g,b[g]);return f.join("&")},S=/^file:\/\//i,K=function(b,d){function f(){function a(){0===--b&&"function"===typeof u&&u()}var b=0;return function A(d){var e=d.then;d.then= g){if(Array.isArray(g))for(var e=0;e<g.length;e++)d(a+"["+e+"]",g[e]);else if("[object Object]"===Object.prototype.toString.call(g))for(e in g)d(a+"["+e+"]",g[e]);else f.push(encodeURIComponent(a)+(null!=g&&""!==g?"="+encodeURIComponent(g):""))}if("[object Object]"!==Object.prototype.toString.call(a))return"";var f=[],g;for(g in a)d(g,a[g]);return f.join("&")},S=/^file:\/\//i,K=function(a,d){function f(){function b(){0===--a&&"function"===typeof u&&u()}var a=0;return function A(d){var e=d.then;d.then=
function(){b++;var f=e.apply(d,arguments);f.then(a,function(d){a();if(0===b)throw d;});return A(f)};return d}}function g(a,b){if("string"===typeof a){var d=a;a=b||{};null==a.url&&(a.url=d)}return a}function e(a,b){if(null==b)return a;for(var d=a.match(/:[^\/]+/gi)||[],e=0;e<d.length;e++){var f=d[e].slice(1);null!=b[f]&&(a=a.replace(d[e],b[f]))}return a}function p(a,b){var d=F(b);if(""!==d){var e=0>a.indexOf("?")?"?":"&";a+=e+d}return a}function k(a){try{return""!==a?JSON.parse(a):null}catch(w){throw Error(a); function(){a++;var f=e.apply(d,arguments);f.then(b,function(d){b();if(0===a)throw d;});return A(f)};return d}}function g(b,a){if("string"===typeof b){var d=b;b=a||{};null==b.url&&(b.url=d)}return b}function e(b,a){if(null==a)return b;for(var d=b.match(/:[^\/]+/gi)||[],e=0;e<d.length;e++){var f=d[e].slice(1);null!=a[f]&&(b=b.replace(d[e],a[f]))}return b}function p(b,a){var d=F(a);if(""!==d){var e=0>b.indexOf("?")?"?":"&";b+=e+d}return b}function k(b){try{return""!==b?JSON.parse(b):null}catch(w){throw Error(b);
}}function q(a){return a.responseText}function m(a,b){if("function"===typeof a)if(Array.isArray(b))for(var d=0;d<b.length;d++)b[d]=new a(b[d]);else return new a(b);return b}var l=0,u;return{request:function(a,l){var u=f();a=g(a,l);var w=new d(function(d,f){null==a.method&&(a.method="GET");a.method=a.method.toUpperCase();var g="GET"===a.method||"TRACE"===a.method?!1:"boolean"===typeof a.useBody?a.useBody:!0;"function"!==typeof a.serialize&&(a.serialize="undefined"!==typeof FormData&&a.data instanceof }}function q(b){return b.responseText}function n(b,a){if("function"===typeof b)if(Array.isArray(a))for(var d=0;d<a.length;d++)a[d]=new b(a[d]);else return new b(a);return a}var l=0,u;return{request:function(b,l){var u=f();b=g(b,l);var w=new d(function(d,f){null==b.method&&(b.method="GET");b.method=b.method.toUpperCase();var g="GET"===b.method||"TRACE"===b.method?!1:"boolean"===typeof b.useBody?b.useBody:!0;"function"!==typeof b.serialize&&(b.serialize="undefined"!==typeof FormData&&b.data instanceof
FormData?function(h){return h}:JSON.stringify);"function"!==typeof a.deserialize&&(a.deserialize=k);"function"!==typeof a.extract&&(a.extract=q);a.url=e(a.url,a.data);g?a.data=a.serialize(a.data):a.url=p(a.url,a.data);var l=new b.XMLHttpRequest,u=!1,w=l.abort;l.abort=function(){u=!0;w.call(l)};l.open(a.method,a.url,"boolean"===typeof a.async?a.async:!0,"string"===typeof a.user?a.user:void 0,"string"===typeof a.password?a.password:void 0);a.serialize===JSON.stringify&&g&&l.setRequestHeader("Content-Type", FormData?function(h){return h}:JSON.stringify);"function"!==typeof b.deserialize&&(b.deserialize=k);"function"!==typeof b.extract&&(b.extract=q);b.url=e(b.url,b.data);g?b.data=b.serialize(b.data):b.url=p(b.url,b.data);var l=new a.XMLHttpRequest,u=!1,w=l.abort;l.abort=function(){u=!0;w.call(l)};l.open(b.method,b.url,"boolean"===typeof b.async?b.async:!0,"string"===typeof b.user?b.user:void 0,"string"===typeof b.password?b.password:void 0);b.serialize===JSON.stringify&&g&&l.setRequestHeader("Content-Type",
"application/json; charset=utf-8");a.deserialize===k&&l.setRequestHeader("Accept","application/json, text/*");a.withCredentials&&(l.withCredentials=a.withCredentials);for(var r in a.headers)({}).hasOwnProperty.call(a.headers,r)&&l.setRequestHeader(r,a.headers[r]);"function"===typeof a.config&&(l=a.config(l,a)||l);l.onreadystatechange=function(){if(!u&&4===l.readyState)try{var h=a.extract!==q?a.extract(l,a):a.deserialize(a.extract(l,a));if(200<=l.status&&300>l.status||304===l.status||S.test(a.url))d(m(a.type, "application/json; charset=utf-8");b.deserialize===k&&l.setRequestHeader("Accept","application/json, text/*");b.withCredentials&&(l.withCredentials=b.withCredentials);for(var r in b.headers)({}).hasOwnProperty.call(b.headers,r)&&l.setRequestHeader(r,b.headers[r]);"function"===typeof b.config&&(l=b.config(l,b)||l);l.onreadystatechange=function(){if(!u&&4===l.readyState)try{var h=b.extract!==q?b.extract(l,b):b.deserialize(b.extract(l,b));if(200<=l.status&&300>l.status||304===l.status||S.test(b.url))d(n(b.type,
h));else{var c=Error(l.responseText),n;for(n in h)c[n]=h[n];f(c)}}catch(v){f(v)}};g&&null!=a.data?l.send(a.data):l.send()});return!0===a.background?w:u(w)},jsonp:function(a,k){var u=f();a=g(a,k);var q=new d(function(d,f){var g=a.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+l++,k=b.document.createElement("script");b[g]=function(e){k.parentNode.removeChild(k);d(m(a.type,e));delete b[g]};k.onerror=function(){k.parentNode.removeChild(k);f(Error("JSONP request failed"));delete b[g]};null== h));else{var c=Error(l.responseText),m;for(m in h)c[m]=h[m];f(c)}}catch(v){f(v)}};g&&null!=b.data?l.send(b.data):l.send()});return!0===b.background?w:u(w)},jsonp:function(b,k){var u=f();b=g(b,k);var q=new d(function(d,f){var g=b.callbackName||"_mithril_"+Math.round(1E16*Math.random())+"_"+l++,k=a.document.createElement("script");a[g]=function(e){k.parentNode.removeChild(k);d(n(b.type,e));delete a[g]};k.onerror=function(){k.parentNode.removeChild(k);f(Error("JSONP request failed"));delete a[g]};null==
a.data&&(a.data={});a.url=e(a.url,a.data);a.data[a.callbackKey||"callback"]=g;k.src=p(a.url,a.data);b.document.documentElement.appendChild(k)});return!0===a.background?q:u(q)},setCompletionCallback:function(a){u=a}}}(window,x),O=function(b){function d(h,c,n,a,b,d,e){for(;n<a;n++){var v=c[n];null!=v&&f(h,v,b,e,d)}}function f(h,c,n,a,b){var v=c.tag;if("string"===typeof v)switch(null!=c.attrs&&C(c.attrs,c,n),v){case "#":return c.dom=D.createTextNode(c.children),l(h,c.dom,b),c.dom;case "<":return g(h, b.data&&(b.data={});b.url=e(b.url,b.data);b.data[b.callbackKey||"callback"]=g;k.src=p(b.url,b.data);a.document.documentElement.appendChild(k)});return!0===b.background?q:u(q)},setCompletionCallback:function(b){u=b}}}(window,x),O=function(a){function d(h,c,m,b,a,d,e){for(;m<b;m++){var v=c[m];null!=v&&f(h,v,a,e,d)}}function f(h,c,m,b,a){var v=c.tag;if("string"===typeof v)switch(c.state={},null!=c.attrs&&C(c.attrs,c,m),v){case "#":return c.dom=D.createTextNode(c.children),l(h,c.dom,a),c.dom;case "<":return g(h,
c,b);case "[":var k=D.createDocumentFragment();null!=c.children&&(v=c.children,d(k,v,0,v.length,n,null,a));c.dom=k.firstChild;c.domSize=k.childNodes.length;l(h,k,b);return k;default:var m=c.tag;switch(c.tag){case "svg":a="http://www.w3.org/2000/svg";break;case "math":a="http://www.w3.org/1998/Math/MathML"}var t=(v=c.attrs)&&v.is,m=a?t?D.createElementNS(a,m,{is:t}):D.createElementNS(a,m):t?D.createElement(m,{is:t}):D.createElement(m);c.dom=m;if(null!=v)for(k in t=a,v)A(c,k,null,v[k],t);l(h,m,b);null!= c,a);case "[":var k=D.createDocumentFragment();null!=c.children&&(v=c.children,d(k,v,0,v.length,m,null,b));c.dom=k.firstChild;c.domSize=k.childNodes.length;l(h,k,a);return k;default:var n=c.tag;switch(c.tag){case "svg":b="http://www.w3.org/2000/svg";break;case "math":b="http://www.w3.org/1998/Math/MathML"}var t=(v=c.attrs)&&v.is,n=b?t?D.createElementNS(b,n,{is:t}):D.createElementNS(b,n):t?D.createElement(n,{is:t}):D.createElement(n);c.dom=n;if(null!=v)for(k in t=b,v)A(c,k,null,v[k],t);l(h,n,a);null!=
c.attrs&&null!=c.attrs.contenteditable?u(c):(null!=c.text&&(""!==c.text?m.textContent=c.text:c.children=[B("#",void 0,void 0,c.text,void 0,void 0)]),null!=c.children&&(h=c.children,d(m,h,0,h.length,n,null,a),h=c.attrs,"select"===c.tag&&null!=h&&("value"in h&&A(c,"value",null,h.value,void 0),"selectedIndex"in h&&A(c,"selectedIndex",null,h.selectedIndex,void 0))));return m}else{e(c,n);if(null!=c.instance){if(c.instance===c)throw Error("A view cannot return the vnode it received as arguments");n=f(h, c.attrs&&null!=c.attrs.contenteditable?u(c):(null!=c.text&&(""!==c.text?n.textContent=c.text:c.children=[B("#",void 0,void 0,c.text,void 0,void 0)]),null!=c.children&&(h=c.children,d(n,h,0,h.length,m,null,b),h=c.attrs,"select"===c.tag&&null!=h&&("value"in h&&A(c,"value",null,h.value,void 0),"selectedIndex"in h&&A(c,"selectedIndex",null,h.selectedIndex,void 0))));return n}else{e(c,m);if(null!=c.instance){if(c.instance===c)throw Error("A view cannot return the vnode it received as arguments");m=f(h,
c.instance,n,a,b);c.dom=c.instance.dom;c.domSize=null!=c.dom?c.instance.domSize:0;l(h,n,b);c=n}else c.domSize=0,c=J;return c}}function g(h,c,a){var n={caption:"table",thead:"table",tbody:"table",tfoot:"table",tr:"tbody",th:"tr",td:"tr",colgroup:"table",col:"colgroup"}[(c.children.match(/^\s*?<(\w+)/im)||[])[1]]||"div",n=D.createElement(n);n.innerHTML=c.children;c.dom=n.firstChild;c.domSize=n.childNodes.length;c=D.createDocumentFragment();for(var b;b=n.firstChild;)c.appendChild(b);l(h,c,a);return c} c.instance,m,b,a);c.dom=c.instance.dom;c.domSize=null!=c.dom?c.instance.domSize:0;l(h,m,a);c=m}else c.domSize=0,c=J;return c}}function g(h,c,b){var m={caption:"table",thead:"table",tbody:"table",tfoot:"table",tr:"tbody",th:"tr",td:"tr",colgroup:"table",col:"colgroup"}[(c.children.match(/^\s*?<(\w+)/im)||[])[1]]||"div",m=D.createElement(m);m.innerHTML=c.children;c.dom=m.firstChild;c.domSize=m.childNodes.length;c=D.createDocumentFragment();for(var a;a=m.firstChild;)c.appendChild(a);l(h,c,b);return c}
function e(h,c){var a;if("function"===typeof h.tag){h.state=null;a=h.tag;if(null!=a.$$reentrantLock$$)return J;a.$$reentrantLock$$=!0;h.state=null!=h.tag.prototype&&"function"===typeof h.tag.prototype.view?new h.tag(h):h.tag(h)}else{h.state=Object.create(h.tag);a=h.state.view;if(null!=a.$$reentrantLock$$)return J;a.$$reentrantLock$$=!0}null!=h.attrs&&C(h.attrs,h,c);C(h.state,h,c);h.instance=B.normalize(h.state.view(h));a.$$reentrantLock$$=null}function p(h,c,n,b,e,g,p){if(c!==n&&(null!=c||null!=n))if(null== function e(h,c){var m;if("function"===typeof h.tag){h.state=null;m=h.tag;if(null!=m.$$reentrantLock$$)return J;m.$$reentrantLock$$=!0;h.state=null!=h.tag.prototype&&"function"===typeof h.tag.prototype.view?new h.tag(h):h.tag(h)}else{h.state=Object.create(h.tag);m=h.state.view;if(null!=m.$$reentrantLock$$)return J;m.$$reentrantLock$$=!0}null!=h.attrs&&C(h.attrs,h,c);C(h.state,h,c);h.instance=B.normalize(h.state.view(h));m.$$reentrantLock$$=null}function p(h,c,m,a,e,g,p){if(c!==m&&(null!=c||null!=m))if(null==
c)d(h,n,0,n.length,e,g,void 0);else if(null==n)a(c,0,c.length,n);else{if(c.length===n.length){for(var v=!1,t=0;t<n.length;t++)if(null!=n[t]&&null!=c[t]){v=null==n[t].key&&null==c[t].key;break}if(v){for(t=0;t<c.length;t++)c[t]!==n[t]&&(null==c[t]&&null!=n[t]?f(h,n[t],e,p,m(c,t+1,g)):null==n[t]?a(c,t,t+1,n):k(h,c[t],n[t],e,m(c,t+1,g),b,p));return}}if(!b)a:{if(null!=c.pool&&Math.abs(c.pool.length-n.length)<=Math.abs(c.length-n.length)&&(b=n[0]&&n[0].children&&n[0].children.length||0,Math.abs((c.pool[0]&& c)d(h,m,0,m.length,e,g,void 0);else if(null==m)b(c,0,c.length,m);else{if(c.length===m.length){for(var v=!1,t=0;t<m.length;t++)if(null!=m[t]&&null!=c[t]){v=null==m[t].key&&null==c[t].key;break}if(v){for(t=0;t<c.length;t++)c[t]!==m[t]&&(null==c[t]&&null!=m[t]?f(h,m[t],e,p,n(c,t+1,g)):null==m[t]?b(c,t,t+1,m):k(h,c[t],m[t],e,n(c,t+1,g),a,p));return}}if(!a)a:{if(null!=c.pool&&Math.abs(c.pool.length-m.length)<=Math.abs(c.length-m.length)&&(a=m[0]&&m[0].children&&m[0].children.length||0,Math.abs((c.pool[0]&&
c.pool[0].children&&c.pool[0].children.length||0)-b)<=Math.abs((c[0]&&c[0].children&&c[0].children.length||0)-b))){b=!0;break a}b=!1}if(b){var u=c.pool;c=c.concat(c.pool)}for(var t=v=0,w=c.length-1,y=n.length-1,G;w>=v&&y>=t;){var r=c[v],z=n[t];if(r!==z||b)if(null==r)v++;else if(null==z)t++;else if(r.key===z.key){var A=null!=u&&v>=c.length-u.length||null==u&&b;v++;t++;k(h,r,z,e,m(c,v,g),A,p);b&&r.tag===z.tag&&l(h,q(r),g)}else if(r=c[w],r!==z||b)if(null==r)w--;else if(null==z)t++;else if(r.key===z.key)A= c.pool[0].children&&c.pool[0].children.length||0)-a)<=Math.abs((c[0]&&c[0].children&&c[0].children.length||0)-a))){a=!0;break a}a=!1}if(a){var u=c.pool;c=c.concat(c.pool)}for(var t=v=0,w=c.length-1,y=m.length-1,G;w>=v&&y>=t;){var r=c[v],z=m[t];if(r!==z||a)if(null==r)v++;else if(null==z)t++;else if(r.key===z.key){var A=null!=u&&v>=c.length-u.length||null==u&&a;v++;t++;k(h,r,z,e,n(c,v,g),A,p);a&&r.tag===z.tag&&l(h,q(r),g)}else if(r=c[w],r!==z||a)if(null==r)w--;else if(null==z)t++;else if(r.key===z.key)A=
null!=u&&w>=c.length-u.length||null==u&&b,k(h,r,z,e,m(c,w+1,g),A,p),(b||t<y)&&l(h,q(r),m(c,v,g)),w--,t++;else break;else w--,t++;else v++,t++}for(;w>=v&&y>=t;){r=c[w];z=n[y];if(r!==z||b)if(null==r)w--;else{if(null!=z)if(r.key===z.key)A=null!=u&&w>=c.length-u.length||null==u&&b,k(h,r,z,e,m(c,w+1,g),A,p),b&&r.tag===z.tag&&l(h,q(r),g),null!=r.dom&&(g=r.dom),w--;else{if(!G){G=c;var r=w,A={},E;for(E=0;E<r;E++){var x=G[E];null!=x&&(x=x.key,null!=x&&(A[x]=E))}G=A}null!=z&&(r=G[z.key],null!=r?(A=c[r],k(h, null!=u&&w>=c.length-u.length||null==u&&a,k(h,r,z,e,n(c,w+1,g),A,p),(a||t<y)&&l(h,q(r),n(c,v,g)),w--,t++;else break;else w--,t++;else v++,t++}for(;w>=v&&y>=t;){r=c[w];z=m[y];if(r!==z||a)if(null==r)w--;else{if(null!=z)if(r.key===z.key)A=null!=u&&w>=c.length-u.length||null==u&&a,k(h,r,z,e,n(c,w+1,g),A,p),a&&r.tag===z.tag&&l(h,q(r),g),null!=r.dom&&(g=r.dom),w--;else{if(!G){G=c;var r=w,A={},E;for(E=0;E<r;E++){var x=G[E];null!=x&&(x=x.key,null!=x&&(A[x]=E))}G=A}null!=z&&(r=G[z.key],null!=r?(A=c[r],k(h,
A,z,e,m(c,w+1,g),b,p),l(h,q(A),g),c[r].skip=!0,null!=A.dom&&(g=A.dom)):g=f(h,z,e,void 0,g))}y--}else w--,y--;if(y<t)break}d(h,n,t,y+1,e,g,p);a(c,v,w+1,n)}}function k(h,c,a,b,d,m,l){var n=c.tag;if(n===a.tag){a.state=c.state;a.events=c.events;var v;if(v=!m){var r,z;null!=a.attrs&&"function"===typeof a.attrs.onbeforeupdate&&(r=a.attrs.onbeforeupdate.call(a.state,a,c));"string"!==typeof a.tag&&"function"===typeof a.state.onbeforeupdate&&(z=a.state.onbeforeupdate(a,c));void 0===r&&void 0===z||r||z?v=!1: A,z,e,n(c,w+1,g),a,p),l(h,q(A),g),c[r].skip=!0,null!=A.dom&&(g=A.dom)):g=f(h,z,e,void 0,g))}y--}else w--,y--;if(y<t)break}d(h,m,t,y+1,e,g,p);b(c,v,w+1,m)}}function k(h,c,a,b,d,n,l){var m=c.tag;if(m===a.tag){a.state=c.state;a.events=c.events;var v;if(v=!n){var r,z;null!=a.attrs&&"function"===typeof a.attrs.onbeforeupdate&&(r=a.attrs.onbeforeupdate.call(a.state,a,c));"string"!==typeof a.tag&&"function"===typeof a.state.onbeforeupdate&&(z=a.state.onbeforeupdate(a,c));void 0===r&&void 0===z||r||z?v=!1:
(a.dom=c.dom,a.domSize=c.domSize,a.instance=c.instance,v=!0)}if(!v)if("string"===typeof n)switch(null!=a.attrs&&(m?C(a.attrs,a,b):I(a.attrs,a,b)),n){case "#":c.children.toString()!==a.children.toString()&&(c.dom.nodeValue=a.children);a.dom=c.dom;break;case "<":c.children!==a.children?(q(c),g(h,a,d)):(a.dom=c.dom,a.domSize=c.domSize);break;case "[":p(h,c.children,a.children,m,b,d,l);c=0;b=a.children;a.dom=null;if(null!=b){for(m=0;m<b.length;m++){var y=b[m];null!=y&&null!=y.dom&&(null==a.dom&&(a.dom= (a.dom=c.dom,a.domSize=c.domSize,a.instance=c.instance,v=!0)}if(!v)if("string"===typeof m)switch(null!=a.attrs&&(n?(a.state={},C(a.attrs,a,b)):I(a.attrs,a,b)),m){case "#":c.children.toString()!==a.children.toString()&&(c.dom.nodeValue=a.children);a.dom=c.dom;break;case "<":c.children!==a.children?(q(c),g(h,a,d)):(a.dom=c.dom,a.domSize=c.domSize);break;case "[":p(h,c.children,a.children,n,b,d,l);c=0;b=a.children;a.dom=null;if(null!=b){for(n=0;n<b.length;n++){var y=b[n];null!=y&&null!=y.dom&&(null==
y.dom),c+=y.domSize||1)}1!==c&&(a.domSize=c)}break;default:h=l;d=a.dom=c.dom;switch(a.tag){case "svg":h="http://www.w3.org/2000/svg";break;case "math":h="http://www.w3.org/1998/Math/MathML"}"textarea"===a.tag&&(null==a.attrs&&(a.attrs={}),null!=a.text&&(a.attrs.value=a.text,a.text=void 0));l=c.attrs;n=a.attrs;v=h;if(null!=n)for(y in n)A(a,y,l&&l[y],n[y],v);if(null!=l)for(y in l)null!=n&&y in n||("className"===y&&(y="class"),"o"!==y[0]||"n"!==y[1]||E(y)?"key"!==y&&a.dom.removeAttribute(y):x(a,y,void 0)); a.dom&&(a.dom=y.dom),c+=y.domSize||1)}1!==c&&(a.domSize=c)}break;default:h=l;d=a.dom=c.dom;switch(a.tag){case "svg":h="http://www.w3.org/2000/svg";break;case "math":h="http://www.w3.org/1998/Math/MathML"}"textarea"===a.tag&&(null==a.attrs&&(a.attrs={}),null!=a.text&&(a.attrs.value=a.text,a.text=void 0));l=c.attrs;m=a.attrs;v=h;if(null!=m)for(y in m)A(a,y,l&&l[y],m[y],v);if(null!=l)for(y in l)null!=m&&y in m||("className"===y&&(y="class"),"o"!==y[0]||"n"!==y[1]||E(y)?"key"!==y&&a.dom.removeAttribute(y):
null!=a.attrs&&null!=a.attrs.contenteditable?u(a):null!=c.text&&null!=a.text&&""!==a.text?c.text.toString()!==a.text.toString()&&(c.dom.firstChild.nodeValue=a.text):(null!=c.text&&(c.children=[B("#",void 0,void 0,c.text,void 0,c.dom.firstChild)]),null!=a.text&&(a.children=[B("#",void 0,void 0,a.text,void 0,void 0)]),p(d,c.children,a.children,m,b,null,h))}else m?e(a,b):(a.instance=B.normalize(a.state.view(a)),null!=a.attrs&&I(a.attrs,a,b),I(a.state,a,b)),null!=a.instance?(null==c.instance?f(h,a.instance, x(a,y,void 0));null!=a.attrs&&null!=a.attrs.contenteditable?u(a):null!=c.text&&null!=a.text&&""!==a.text?c.text.toString()!==a.text.toString()&&(c.dom.firstChild.nodeValue=a.text):(null!=c.text&&(c.children=[B("#",void 0,void 0,c.text,void 0,c.dom.firstChild)]),null!=a.text&&(a.children=[B("#",void 0,void 0,a.text,void 0,void 0)]),p(d,c.children,a.children,n,b,null,h))}else n?e(a,b):(a.instance=B.normalize(a.state.view(a)),null!=a.attrs&&I(a.attrs,a,b),I(a.state,a,b)),null!=a.instance?(null==c.instance?
b,l,d):k(h,c.instance,a.instance,b,d,m,l),a.dom=a.instance.dom,a.domSize=a.instance.domSize):null!=c.instance?(w(c.instance,null),a.dom=void 0,a.domSize=0):(a.dom=c.dom,a.domSize=c.domSize)}else w(c,null),f(h,a,b,l,d)}function q(a){var c=a.domSize;if(null!=c||null==a.dom){var b=D.createDocumentFragment();if(0<c){for(a=a.dom;--c;)b.appendChild(a.nextSibling);b.insertBefore(a,b.firstChild)}return b}return a.dom}function m(a,c,b){for(;c<a.length;c++)if(null!=a[c]&&null!=a[c].dom)return a[c].dom;return b} f(h,a.instance,b,l,d):k(h,c.instance,a.instance,b,d,n,l),a.dom=a.instance.dom,a.domSize=a.instance.domSize):null!=c.instance?(w(c.instance,null),a.dom=void 0,a.domSize=0):(a.dom=c.dom,a.domSize=c.domSize)}else w(c,null),f(h,a,b,l,d)}function q(a){var c=a.domSize;if(null!=c||null==a.dom){var b=D.createDocumentFragment();if(0<c){for(a=a.dom;--c;)b.appendChild(a.nextSibling);b.insertBefore(a,b.firstChild)}return b}return a.dom}function n(a,c,b){for(;c<a.length;c++)if(null!=a[c]&&null!=a[c].dom)return a[c].dom;
function l(a,c,b){b&&b.parentNode?a.insertBefore(c,b):a.appendChild(c)}function u(a){var c=a.children;if(null!=c&&1===c.length&&"<"===c[0].tag)c=c[0].children,a.dom.innerHTML!==c&&(a.dom.innerHTML=c);else if(null!=a.text||null!=c&&0!==c.length)throw Error("Child node of a contenteditable must be trusted");}function a(a,c,b,d){for(;c<b;c++){var h=a[c];null!=h&&(h.skip?h.skip=!1:w(h,d))}}function w(a,c){function b(){if(++d===h&&(r(a),a.dom)){var b=a.domSize||1;if(1<b)for(var e=a.dom;--b;){var g=e.nextSibling, return b}function l(a,c,b){b&&b.parentNode?a.insertBefore(c,b):a.appendChild(c)}function u(a){var c=a.children;if(null!=c&&1===c.length&&"<"===c[0].tag)c=c[0].children,a.dom.innerHTML!==c&&(a.dom.innerHTML=c);else if(null!=a.text||null!=c&&0!==c.length)throw Error("Child node of a contenteditable must be trusted");}function b(a,c,b,d){for(;c<b;c++){var h=a[c];null!=h&&(h.skip?h.skip=!1:w(h,d))}}function w(a,c){function b(){if(++d===h&&(r(a),a.dom)){var b=a.domSize||1;if(1<b)for(var e=a.dom;--b;){var g=
f=g.parentNode;null!=f&&f.removeChild(g)}b=a.dom;e=b.parentNode;null!=e&&e.removeChild(b);if(b=null!=c&&null==a.domSize)b=a.attrs,b=!(null!=b&&(b.oncreate||b.onupdate||b.onbeforeremove||b.onremove));b&&"string"===typeof a.tag&&(c.pool?c.pool.push(a):c.pool=[a])}}var h=1,d=0;if(a.attrs&&a.attrs.onbeforeremove){var e=a.attrs.onbeforeremove.call(a.state,a);null!=e&&"function"===typeof e.then&&(h++,e.then(b,b))}"string"!==typeof a.tag&&a.state.onbeforeremove&&(e=a.state.onbeforeremove(a),null!=e&&"function"=== e.nextSibling,m=g.parentNode;null!=m&&m.removeChild(g)}b=a.dom;e=b.parentNode;null!=e&&e.removeChild(b);if(b=null!=c&&null==a.domSize)b=a.attrs,b=!(null!=b&&(b.oncreate||b.onupdate||b.onbeforeremove||b.onremove));b&&"string"===typeof a.tag&&(c.pool?c.pool.push(a):c.pool=[a])}}var h=1,d=0;if(a.attrs&&a.attrs.onbeforeremove){var e=a.attrs.onbeforeremove.call(a.state,a);null!=e&&"function"===typeof e.then&&(h++,e.then(b,b))}"string"!==typeof a.tag&&a.state.onbeforeremove&&(e=a.state.onbeforeremove(a),
typeof e.then&&(h++,e.then(b,b)));b()}function r(a){a.attrs&&a.attrs.onremove&&a.attrs.onremove.call(a.state,a);if("string"!==typeof a.tag&&a.state.onremove)a.state.onremove(a);if(null!=a.instance)r(a.instance);else if(a=a.children,Array.isArray(a))for(var c=0;c<a.length;c++){var b=a[c];null!=b&&r(b)}}function A(a,c,b,d,e){var h=a.dom;if("key"!==c&&"is"!==c&&(b!==d||"value"===c||"checked"===c||"selectedIndex"===c||"selected"===c&&a.dom===D.activeElement||"object"===typeof d)&&"undefined"!==typeof d&& null!=e&&"function"===typeof e.then&&(h++,e.then(b,b)));b()}function r(a){a.attrs&&a.attrs.onremove&&a.attrs.onremove.call(a.state,a);if("string"!==typeof a.tag&&a.state.onremove)a.state.onremove(a);if(null!=a.instance)r(a.instance);else if(a=a.children,Array.isArray(a))for(var c=0;c<a.length;c++){var b=a[c];null!=b&&r(b)}}function A(a,c,b,d,e){var h=a.dom;if("key"!==c&&"is"!==c&&(b!==d||"value"===c||"checked"===c||"selectedIndex"===c||"selected"===c&&a.dom===D.activeElement||"object"===typeof d)&&
!E(c)){var g=c.indexOf(":");if(-1<g&&"xlink"===c.substr(0,g))h.setAttributeNS("http://www.w3.org/1999/xlink",c.slice(g+1),d);else if("o"===c[0]&&"n"===c[1]&&"function"===typeof d)x(a,c,d);else if("style"===c)if(a=b,a===d&&(h.style.cssText="",a=null),null==d)h.style.cssText="";else if("string"===typeof d)h.style.cssText=d;else{"string"===typeof a&&(h.style.cssText="");for(var f in d)h.style[f]=d[f];if(null!=a&&"string"!==typeof a)for(f in a)f in d||(h.style[f]="")}else c in h&&"href"!==c&&"list"!== "undefined"!==typeof d&&!E(c)){var g=c.indexOf(":");if(-1<g&&"xlink"===c.substr(0,g))h.setAttributeNS("http://www.w3.org/1999/xlink",c.slice(g+1),d);else if("o"===c[0]&&"n"===c[1]&&"function"===typeof d)x(a,c,d);else if("style"===c)if(a=b,a===d&&(h.style.cssText="",a=null),null==d)h.style.cssText="";else if("string"===typeof d)h.style.cssText=d;else{"string"===typeof a&&(h.style.cssText="");for(var f in d)h.style[f]=d[f];if(null!=a&&"string"!==typeof a)for(f in a)f in d||(h.style[f]="")}else c in
c&&"form"!==c&&"width"!==c&&"height"!==c&&void 0===e&&!(a.attrs.is||-1<a.tag.indexOf("-"))?"input"===a.tag&&"value"===c&&a.dom.value==d&&a.dom===D.activeElement||"select"===a.tag&&"value"===c&&a.dom.value==d&&a.dom===D.activeElement||"option"===a.tag&&"value"===c&&a.dom.value==d||("input"===a.tag&&"type"===c?h.setAttribute(c,d):h[c]=d):"boolean"===typeof d?d?h.setAttribute(c,""):h.removeAttribute(c):h.setAttribute("className"===c?"class":c,d)}}function E(a){return"oninit"===a||"oncreate"===a||"onupdate"=== h&&"href"!==c&&"list"!==c&&"form"!==c&&"width"!==c&&"height"!==c&&void 0===e&&!(a.attrs.is||-1<a.tag.indexOf("-"))?"input"===a.tag&&"value"===c&&a.dom.value==d&&a.dom===D.activeElement||"select"===a.tag&&"value"===c&&a.dom.value==d&&a.dom===D.activeElement||"option"===a.tag&&"value"===c&&a.dom.value==d||("input"===a.tag&&"type"===c?h.setAttribute(c,d):h[c]=d):"boolean"===typeof d?d?h.setAttribute(c,""):h.removeAttribute(c):h.setAttribute("className"===c?"class":c,d)}}function E(a){return"oninit"===
a||"onremove"===a||"onbeforeremove"===a||"onbeforeupdate"===a}function x(a,c,b){var d=a.dom,e="function"!==typeof F?b:function(a){var c=b.call(d,a);F.call(d,a);return c};if(c in d)d[c]="function"===typeof b?e:null;else{var h=c.slice(2);void 0===a.events&&(a.events={});a.events[c]!==e&&(null!=a.events[c]&&d.removeEventListener(h,a.events[c],!1),"function"===typeof b&&(a.events[c]=e,d.addEventListener(h,a.events[c],!1)))}}function C(a,b,d){"function"===typeof a.oninit&&a.oninit.call(b.state,b);"function"=== a||"oncreate"===a||"onupdate"===a||"onremove"===a||"onbeforeremove"===a||"onbeforeupdate"===a}function x(a,c,b){var d=a.dom,e="function"!==typeof F?b:function(a){var c=b.call(d,a);F.call(d,a);return c};if(c in d)d[c]="function"===typeof b?e:null;else{var h=c.slice(2);void 0===a.events&&(a.events={});a.events[c]!==e&&(null!=a.events[c]&&d.removeEventListener(h,a.events[c],!1),"function"===typeof b&&(a.events[c]=e,d.addEventListener(h,a.events[c],!1)))}}function C(a,c,b){"function"===typeof a.oninit&&
typeof a.oncreate&&d.push(a.oncreate.bind(b.state,b))}function I(a,b,d){"function"===typeof a.onupdate&&d.push(a.onupdate.bind(b.state,b))}var D=b.document,J=D.createDocumentFragment(),F;return{render:function(a,b){if(!a)throw Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var c=[],d=D.activeElement;null==a.vnodes&&(a.textContent="");Array.isArray(b)||(b=[b]);p(a,a.vnodes,B.normalizeChildren(b),!1,c,null,void 0);a.vnodes=b;for(var e=0;e<c.length;e++)c[e](); a.oninit.call(c.state,c);"function"===typeof a.oncreate&&b.push(a.oncreate.bind(c.state,c))}function I(a,c,b){"function"===typeof a.onupdate&&b.push(a.onupdate.bind(c.state,c))}var D=a.document,J=D.createDocumentFragment(),F;return{render:function(a,b){if(!a)throw Error("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.");var c=[],d=D.activeElement;null==a.vnodes&&(a.textContent="");Array.isArray(b)||(b=[b]);p(a,a.vnodes,B.normalizeChildren(b),!1,c,null,void 0);a.vnodes=
D.activeElement!==d&&d.focus()},setEventCallback:function(a){return F=a}}},H=function(b){function d(b){b=g.indexOf(b);-1<b&&g.splice(b,2)}function f(){for(var b=1;b<g.length;b+=2)g[b]()}b=O(b);b.setEventCallback(function(b){!1!==b.redraw&&f()});var g=[];return{subscribe:function(b,f){d(b);g.push(b,Q(f))},unsubscribe:d,redraw:f,render:b.render}}(window);K.setCompletionCallback(H.redraw);C.mount=function(b){return function(d,f){if(null===f)b.render(d,[]),b.unsubscribe(d);else{if(null==f.view&&"function"!== b;for(var e=0;e<c.length;e++)c[e]();D.activeElement!==d&&d.focus()},setEventCallback:function(a){return F=a}}},H=function(a){function d(a){a=g.indexOf(a);-1<a&&g.splice(a,2)}function f(){for(var a=1;a<g.length;a+=2)g[a]()}a=O(a);a.setEventCallback(function(a){!1!==a.redraw&&f()});var g=[];return{subscribe:function(a,f){d(a);g.push(a,Q(f))},unsubscribe:d,redraw:f,render:a.render}}(window);K.setCompletionCallback(H.redraw);C.mount=function(a){return function(d,f){if(null===f)a.render(d,[]),a.unsubscribe(d);
typeof f)throw Error("m.mount(element, component) expects a component, not a vnode");b.subscribe(d,function(){b.render(d,B(f))});b.redraw()}}}(H);var T=x,L=function(b){if(""===b||null==b)return{};"?"===b.charAt(0)&&(b=b.slice(1));b=b.split("&");for(var d={},f={},g=0;g<b.length;g++){var e=b[g].split("="),p=decodeURIComponent(e[0]),e=2===e.length?decodeURIComponent(e[1]):"";"true"===e?e=!0:"false"===e&&(e=!1);var k=p.split(/\]\[?|\[/),q=d;-1<p.indexOf("[")&&k.pop();for(var m=0;m<k.length;m++){var p= else{if(null==f.view&&"function"!==typeof f)throw Error("m.mount(element, component) expects a component, not a vnode");a.subscribe(d,function(){a.render(d,B(f))});a.redraw()}}}(H);var T=x,L=function(a){if(""===a||null==a)return{};"?"===a.charAt(0)&&(a=a.slice(1));a=a.split("&");for(var d={},f={},g=0;g<a.length;g++){var e=a[g].split("="),p=decodeURIComponent(e[0]),e=2===e.length?decodeURIComponent(e[1]):"";"true"===e?e=!0:"false"===e&&(e=!1);var k=p.split(/\]\[?|\[/),q=d;-1<p.indexOf("[")&&k.pop();
k[m],l=k[m+1],l=""==l||!isNaN(parseInt(l,10)),u=m===k.length-1;""===p&&(p=k.slice(0,m).join(),null==f[p]&&(f[p]=0),p=f[p]++);null==q[p]&&(q[p]=u?e:l?[]:{});q=q[p]}}return d},U=function(b){function d(d){var e=b.location[d].replace(/(?:%[a-f89][a-f0-9])+/gim,decodeURIComponent);"pathname"===d&&"/"!==e[0]&&(e="/"+e);return e}function f(b){return function(){null==k&&(k=p(function(){k=null;b()}))}}function g(b,d,e){var a=b.indexOf("?"),g=b.indexOf("#"),f=-1<a?a:-1<g?g:b.length;if(-1<a){var a=L(b.slice(a+ for(var n=0;n<k.length;n++){var p=k[n],l=k[n+1],l=""==l||!isNaN(parseInt(l,10)),u=n===k.length-1;""===p&&(p=k.slice(0,n).join(),null==f[p]&&(f[p]=0),p=f[p]++);null==q[p]&&(q[p]=u?e:l?[]:{});q=q[p]}}return d},U=function(a){function d(d){var e=a.location[d].replace(/(?:%[a-f89][a-f0-9])+/gim,decodeURIComponent);"pathname"===d&&"/"!==e[0]&&(e="/"+e);return e}function f(a){return function(){null==k&&(k=p(function(){k=null;a()}))}}function g(a,d,e){var b=a.indexOf("?"),g=a.indexOf("#"),f=-1<b?b:-1<g?g:
1,-1<g?g:b.length)),k;for(k in a)d[k]=a[k]}if(-1<g)for(k in d=L(b.slice(g+1)),d)e[k]=d[k];return b.slice(0,f)}var e="function"===typeof b.history.pushState,p="function"===typeof setImmediate?setImmediate:setTimeout,k,q={prefix:"#!",getPath:function(){switch(q.prefix.charAt(0)){case "#":return d("hash").slice(q.prefix.length);case "?":return d("search").slice(q.prefix.length)+d("hash");default:return d("pathname").slice(q.prefix.length)+d("search")+d("hash")}},setPath:function(d,f,k){var a={},l={}; a.length;if(-1<b){var b=L(a.slice(b+1,-1<g?g:a.length)),k;for(k in b)d[k]=b[k]}if(-1<g)for(k in d=L(a.slice(g+1)),d)e[k]=d[k];return a.slice(0,f)}var e="function"===typeof a.history.pushState,p="function"===typeof setImmediate?setImmediate:setTimeout,k,q={prefix:"#!",getPath:function(){switch(q.prefix.charAt(0)){case "#":return d("hash").slice(q.prefix.length);case "?":return d("search").slice(q.prefix.length)+d("hash");default:return d("pathname").slice(q.prefix.length)+d("search")+d("hash")}},setPath:function(d,
d=g(d,a,l);if(null!=f){for(var m in f)a[m]=f[m];d=d.replace(/:([^\/]+)/g,function(b,d){delete a[d];return f[d]})}(m=F(a))&&(d+="?"+m);(l=F(l))&&(d+="#"+l);e?(l=k?k.state:null,m=k?k.title:null,b.onpopstate(),k&&k.replace?b.history.replaceState(l,m,q.prefix+d):b.history.pushState(l,m,q.prefix+d)):b.location.href=q.prefix+d},defineRoutes:function(d,k,p){function a(){var a=q.getPath(),e={},f=g(a,e,e),l=b.history.state;if(null!=l)for(var m in l)e[m]=l[m];for(var u in d)if(l=new RegExp("^"+u.replace(/:[^\/]+?\.{3}/g, f,k){var b={},l={};d=g(d,b,l);if(null!=f){for(var n in f)b[n]=f[n];d=d.replace(/:([^\/]+)/g,function(a,d){delete b[d];return f[d]})}(n=F(b))&&(d+="?"+n);(l=F(l))&&(d+="#"+l);e?(l=k?k.state:null,n=k?k.title:null,a.onpopstate(),k&&k.replace?a.history.replaceState(l,n,q.prefix+d):a.history.pushState(l,n,q.prefix+d)):a.location.href=q.prefix+d},defineRoutes:function(d,k,p){function b(){var b=q.getPath(),e={},f=g(b,e,e),l=a.history.state;if(null!=l)for(var n in l)e[n]=l[n];for(var u in d)if(l=new RegExp("^"+
"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$"),l.test(f)){f.replace(l,function(){for(var b=u.match(/:[^\/]+/g)||[],g=[].slice.call(arguments,1,-2),f=0;f<b.length;f++)e[b[f].replace(/:|\./g,"")]=decodeURIComponent(g[f]);k(d[u],e,a,u)});return}p(a,e)}e?b.onpopstate=f(a):"#"===q.prefix.charAt(0)&&(b.onhashchange=a);a()}};return q};C.route=function(b,d){var f=U(b),g=function(b){return b},e,p,k,q,m,l=function(b,a,l){if(null==b)throw Error("Ensure the DOM element that was passed to `m.route` is not undefined"); u.replace(/:[^\/]+?\.{3}/g,"(.*?)").replace(/:[^\/]+/g,"([^\\/]+)")+"/?$"),l.test(f)){f.replace(l,function(){for(var a=u.match(/:[^\/]+/g)||[],g=[].slice.call(arguments,1,-2),f=0;f<a.length;f++)e[a[f].replace(/:|\./g,"")]=decodeURIComponent(g[f]);k(d[u],e,b,u)});return}p(b,e)}e?a.onpopstate=f(b):"#"===q.prefix.charAt(0)&&(a.onhashchange=b);b()}};return q};C.route=function(a,d){var f=U(a),g=function(a){return a},e,p,k,q,n,l=function(a,b,l){if(null==a)throw Error("Ensure the DOM element that was passed to `m.route` is not undefined");
var u=function(){null!=e&&d.render(b,e(B(p,k.key,k)))},w=function(b){if(b!==a)f.setPath(a,null,{replace:!0});else throw Error("Could not resolve default route "+a);};f.defineRoutes(l,function(a,b,d){var f=m=function(a,l){f===m&&(p=null==l||"function"!==typeof l.view&&"function"!==typeof l?"div":l,k=b,q=d,m=null,e=(a.render||g).bind(a),u())};a.view||"function"===typeof a?f({},a):a.onmatch?T.resolve(a.onmatch(b,d)).then(function(b){f(a,b)},w):f(a,"div")},w);d.subscribe(b,u)};l.set=function(b,a,d){null!= var u=function(){null!=e&&d.render(a,e(B(p,k.key,k)))},w=function(a){if(a!==b)f.setPath(b,null,{replace:!0});else throw Error("Could not resolve default route "+b);};f.defineRoutes(l,function(a,b,d){var f=n=function(a,l){f===n&&(p=null==l||"function"!==typeof l.view&&"function"!==typeof l?"div":l,k=b,q=d,n=null,e=(a.render||g).bind(a),u())};a.view||"function"===typeof a?f({},a):a.onmatch?T.resolve(a.onmatch(b,d)).then(function(b){f(a,b)},w):f(a,"div")},w);d.subscribe(a,u)};l.set=function(a,b,d){null!=
m&&(d={replace:!0});m=null;f.setPath(b,a,d)};l.get=function(){return q};l.prefix=function(b){f.prefix=b};l.link=function(b){b.dom.setAttribute("href",f.prefix+b.attrs.href);b.dom.onclick=function(a){a.ctrlKey||a.metaKey||a.shiftKey||2===a.which||(a.preventDefault(),a.redraw=!1,a=this.getAttribute("href"),0===a.indexOf(f.prefix)&&(a=a.slice(f.prefix.length)),l.set(a,void 0,void 0))}};l.param=function(b){return"undefined"!==typeof k&&"undefined"!==typeof b?k[b]:k};return l}(window,H);C.withAttr=function(b, n&&(d={replace:!0});n=null;f.setPath(a,b,d)};l.get=function(){return q};l.prefix=function(a){f.prefix=a};l.link=function(a){a.dom.setAttribute("href",f.prefix+a.attrs.href);a.dom.onclick=function(a){a.ctrlKey||a.metaKey||a.shiftKey||2===a.which||(a.preventDefault(),a.redraw=!1,a=this.getAttribute("href"),0===a.indexOf(f.prefix)&&(a=a.slice(f.prefix.length)),l.set(a,void 0,void 0))}};l.param=function(a){return"undefined"!==typeof k&&"undefined"!==typeof a?k[a]:k};return l}(window,H);C.withAttr=function(a,
d,f){return function(g){d.call(f||this,b in g.currentTarget?g.currentTarget[b]:g.currentTarget.getAttribute(b))}};var V=O(window);C.render=V.render;C.redraw=H.redraw;C.request=K.request;C.jsonp=K.jsonp;C.parseQueryString=L;C.buildQueryString=F;C.version="1.0.1";C.vnode=B;"undefined"!==typeof module?module.exports=C:window.m=C})(); d,f){return function(g){d.call(f||this,a in g.currentTarget?g.currentTarget[a]:g.currentTarget.getAttribute(a))}};var V=O(window);C.render=V.render;C.redraw=H.redraw;C.request=K.request;C.jsonp=K.jsonp;C.parseQueryString=L;C.buildQueryString=F;C.version="1.0.1";C.vnode=B;"undefined"!==typeof module?module.exports=C:window.m=C})();

View file

@ -1,3 +1,5 @@
"use strict"
var redrawService = require("./redraw") var redrawService = require("./redraw")
module.exports = require("./api/mount")(redrawService) module.exports = require("./api/mount")(redrawService)

View file

@ -278,12 +278,20 @@ ospec will automatically evaluate all `*.js` files in any folder named `/tests`.
$ npm test $ npm test
``` ```
#### Installing ospec globally #### Direct use from the command line
While it's recommended to install ospec locally to maintain reproducible environments, sometimes it may be deemed appropriate to install it globally. To do so, run this command: Ospec doesn't work when installed globally. Using global scripts is generally a bad idea since you can end up with different, incompatible versions of the same package installed locally and globally.
To work around this limitation, you can use [`npm-run`](https://www.npmjs.com/package/npm-run) which enables one to run the binaries of locally installed packages.
``` ```
npm install ospec -g npm install npm-run -g
```
Then, from a project that has ospec installed as a (dev) dependency:
```
npm-run ospec
``` ```
--- ---

View file

@ -1,4 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
"use strict"
var fs = require("fs") var fs = require("fs")
var path = require("path") var path = require("path")
@ -31,9 +32,9 @@ function traverseDirectory(pathname, callback) {
}) })
} }
traverseDirectory(".", function(pathname, stat, children) { traverseDirectory(".", function(pathname) {
if (pathname.match(/(?:^|\/)tests\/.*\.js$/)) { if (pathname.match(/(?:^|\/)tests\/.*\.js$/)) {
require(path.normalize(process.cwd()) + "/" + pathname) require(path.normalize(process.cwd()) + "/" + pathname) // eslint-disable-line global-require
} }
}) })
.then(o.run) .then(o.run)

View file

@ -1,3 +1,4 @@
/* eslint-disable no-bitwise, no-process-exit */
"use strict" "use strict"
module.exports = new function init() { module.exports = new function init() {
@ -121,8 +122,8 @@ module.exports = new function init() {
} }
function unique(subject) { function unique(subject) {
if (hasOwn.call(ctx, subject)) { if (hasOwn.call(ctx, subject)) {
console.warn("A test or a spec named `" + subject + "` was already defined") console.warn("A test or a spec named `" + subject + "` was already defined")
while (hasOwn.call(ctx, subject)) subject += '*' while (hasOwn.call(ctx, subject)) subject += "*"
} }
return subject return subject
} }

View file

@ -28,11 +28,11 @@ o.spec("ospec", function() {
o.beforeEach(function() {b = 1}) o.beforeEach(function() {b = 1})
o.afterEach(function() {b = 0}) o.afterEach(function() {b = 0})
try {o('illegal assertion')} catch (e) {illegalAssertionThrows = true} try {o("illegal assertion")} catch (e) {illegalAssertionThrows = true}
o("assertions", function() { o("assertions", function() {
var nestedTestDeclarationThrows = false var nestedTestDeclarationThrows = false
try {o('illegal nested test', function(){})} catch (e) {nestedTestDeclarationThrows = true} try {o("illegal nested test", function(){})} catch (e) {nestedTestDeclarationThrows = true}
o(illegalAssertionThrows).equals(true) o(illegalAssertionThrows).equals(true)
o(nestedTestDeclarationThrows).equals(true) o(nestedTestDeclarationThrows).equals(true)
@ -51,7 +51,7 @@ o.spec("ospec", function() {
o(undef1).notDeepEquals(undef2) o(undef1).notDeepEquals(undef2)
o(undef1).notDeepEquals({}) o(undef1).notDeepEquals({})
o({}).notDeepEquals(undef1) o({}).notDeepEquals(undef1)
var sparse1 = [void 1, void 2, void 3] var sparse1 = [void 1, void 2, void 3]
delete sparse1[0] delete sparse1[0]
var sparse2 = [void 1, void 2, void 3] var sparse2 = [void 1, void 2, void 3]
@ -63,7 +63,7 @@ o.spec("ospec", function() {
monkeypatch1.field = 3 monkeypatch1.field = 3
var monkeypatch2 = [1, 2] var monkeypatch2 = [1, 2]
monkeypatch2.field = 4 monkeypatch2.field = 4
o(monkeypatch1).notDeepEquals([1, 2]) o(monkeypatch1).notDeepEquals([1, 2])
o(monkeypatch1).notDeepEquals(monkeypatch2) o(monkeypatch1).notDeepEquals(monkeypatch2)

View file

@ -5,7 +5,6 @@
"author": "Leo Horie", "author": "Leo Horie",
"license": "MIT", "license": "MIT",
"main": "mithril.js", "main": "mithril.js",
"types": "mithril.d.ts",
"repository": "lhorie/mithril.js", "repository": "lhorie/mithril.js",
"scripts": { "scripts": {
"dev": "node bundler/cli browser.js -o mithril.js -w", "dev": "node bundler/cli browser.js -o mithril.js -w",
@ -15,6 +14,7 @@
"lintdocs": "node docs/lint", "lintdocs": "node docs/lint",
"gendocs": "node docs/generate", "gendocs": "node docs/generate",
"lint": "eslint .", "lint": "eslint .",
"lint:fix": "eslint . --fix",
"test": "node ospec/bin/ospec", "test": "node ospec/bin/ospec",
"posttest": "npm run lint || true", "posttest": "npm run lint || true",
"cover": "istanbul cover --print both ospec/bin/ospec", "cover": "istanbul cover --print both ospec/bin/ospec",

View file

@ -57,7 +57,7 @@ o.spec("promise", function() {
o.spec("resolve", function() { o.spec("resolve", function() {
o("resolves once", function(done) { o("resolves once", function(done) {
var callCount = 0 var callCount = 0
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function(resolve) {
resolve(1) resolve(1)
resolve(2) resolve(2)
callAsync(function() {resolve(3)}) callAsync(function() {resolve(3)})
@ -89,7 +89,7 @@ o.spec("promise", function() {
var promise = Promise.resolve() var promise = Promise.resolve()
state = 1 state = 1
promise.then(function(value) { promise.then(function() {
o(state).equals(2) o(state).equals(2)
done() done()
}) })
@ -104,7 +104,7 @@ o.spec("promise", function() {
}) })
}) })
o("resolves asynchronously via executor", function(done) { o("resolves asynchronously via executor", function(done) {
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function(resolve) {
callAsync(function() {resolve(1)}) callAsync(function() {resolve(1)})
}) })
@ -185,7 +185,7 @@ o.spec("promise", function() {
var promise = Promise.reject() var promise = Promise.reject()
state = 1 state = 1
promise.then(null, function(value) { promise.then(null, function() {
o(state).equals(2) o(state).equals(2)
done() done()
}) })
@ -232,7 +232,7 @@ o.spec("promise", function() {
}) })
}) })
o("rejects via executor on error", function(done) { o("rejects via executor on error", function(done) {
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function() {
throw 1 throw 1
}) })
@ -281,7 +281,7 @@ o.spec("promise", function() {
}).then(done) }).then(done)
}) })
o("absorbs resolved promise in executor resolve", function(done) { o("absorbs resolved promise in executor resolve", function(done) {
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function(resolve) {
var p = Promise.resolve(1) var p = Promise.resolve(1)
resolve(p) resolve(p)
}) })
@ -310,7 +310,7 @@ o.spec("promise", function() {
}) })
}) })
o("absorbs rejected promise in executor resolve", function(done) { o("absorbs rejected promise in executor resolve", function(done) {
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function(resolve) {
resolve(Promise.reject(1)) resolve(Promise.reject(1))
}) })
@ -330,7 +330,7 @@ o.spec("promise", function() {
}) })
}) })
o("absorbs pending promise that resolves via static resolver", function(done) { o("absorbs pending promise that resolves via static resolver", function(done) {
var pending = new Promise(function(resolve, reject) { var pending = new Promise(function(resolve) {
setTimeout(function() {resolve(1)}, 10) setTimeout(function() {resolve(1)}, 10)
}) })
var promise = Promise.resolve(pending) var promise = Promise.resolve(pending)
@ -341,10 +341,10 @@ o.spec("promise", function() {
}) })
}) })
o("absorbs pending promise that resolves in executor resolve", function(done) { o("absorbs pending promise that resolves in executor resolve", function(done) {
var pending = new Promise(function(resolve, reject) { var pending = new Promise(function(resolve) {
setTimeout(function() {resolve(1)}, 10) setTimeout(function() {resolve(1)}, 10)
}) })
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function(resolve) {
resolve(pending) resolve(pending)
}) })
@ -354,7 +354,7 @@ o.spec("promise", function() {
}) })
}) })
o("absorbs pending promise that resolves on fulfillment", function(done) { o("absorbs pending promise that resolves on fulfillment", function(done) {
var pending = new Promise(function(resolve, reject) { var pending = new Promise(function(resolve) {
setTimeout(function() {resolve(1)}, 10) setTimeout(function() {resolve(1)}, 10)
}) })
var promise = Promise.resolve() var promise = Promise.resolve()
@ -381,7 +381,7 @@ o.spec("promise", function() {
var pending = new Promise(function(resolve, reject) { var pending = new Promise(function(resolve, reject) {
setTimeout(function() {reject(1)}, 10) setTimeout(function() {reject(1)}, 10)
}) })
var promise = new Promise(function(resolve, reject) { var promise = new Promise(function(resolve) {
resolve(pending) resolve(pending)
}) })
@ -521,7 +521,7 @@ o.spec("promise", function() {
o.spec("race", function() { o.spec("race", function() {
o("resolves to first resolved", function(done) { o("resolves to first resolved", function(done) {
var a = Promise.resolve(1) var a = Promise.resolve(1)
var b = new Promise(function(resolve, reject) { var b = new Promise(function(resolve) {
callAsync(function() {resolve(2)}) callAsync(function() {resolve(2)})
}) })
Promise.race([a, b]).then(function(value) { Promise.race([a, b]).then(function(value) {
@ -542,7 +542,7 @@ o.spec("promise", function() {
}) })
o.spec("all", function() { o.spec("all", function() {
o("resolves to array", function(done) { o("resolves to array", function(done) {
var a = new Promise(function(resolve, reject) { var a = new Promise(function(resolve) {
callAsync(function() {resolve(1)}) callAsync(function() {resolve(1)})
}) })
var b = Promise.resolve(2) var b = Promise.resolve(2)
@ -558,7 +558,7 @@ o.spec("promise", function() {
}) })
}) })
o("resolves non-promise to itself", function(done) { o("resolves non-promise to itself", function(done) {
var a = new Promise(function(resolve, reject) { var a = new Promise(function(resolve) {
callAsync(function() {resolve(1)}) callAsync(function() {resolve(1)})
}) })
var b = Promise.resolve(2) var b = Promise.resolve(2)
@ -584,18 +584,18 @@ o.spec("promise", function() {
var readCount = 0 var readCount = 0
var promise = Promise.resolve(1).then(function() { var promise = Promise.resolve(1).then(function() {
return Object.create(null, { return Object.create(null, {
then: { then: {
get: function () { get: function () {
++readCount ++readCount
return function(onFulfilled) { return function(onFulfilled) {
onFulfilled() onFulfilled()
} }
} }
} }
}) })
}) })
promise.then(function(value) { promise.then(function() {
o(readCount).equals(1) o(readCount).equals(1)
done() done()
}) })

View file

@ -1 +1,3 @@
module.exports = require("./api/redraw")(window) "use strict"
module.exports = require("./api/redraw")(window)

View file

@ -1 +1,3 @@
module.exports = require("./render/render")(window) "use strict"
module.exports = require("./render/render")(window)

View file

@ -21,6 +21,7 @@ module.exports = function($window) {
function createNode(parent, vnode, hooks, ns, nextSibling) { function createNode(parent, vnode, hooks, ns, nextSibling) {
var tag = vnode.tag var tag = vnode.tag
if (typeof tag === "string") { if (typeof tag === "string") {
vnode.state = {}
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks) if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
switch (tag) { switch (tag) {
case "#": return createText(parent, vnode, nextSibling) case "#": return createText(parent, vnode, nextSibling)
@ -238,7 +239,10 @@ module.exports = function($window) {
if (!recycling && shouldNotUpdate(vnode, old)) return if (!recycling && shouldNotUpdate(vnode, old)) return
if (typeof oldTag === "string") { if (typeof oldTag === "string") {
if (vnode.attrs != null) { if (vnode.attrs != null) {
if (recycling) initLifecycle(vnode.attrs, vnode, hooks) if (recycling) {
vnode.state = {}
initLifecycle(vnode.attrs, vnode, hooks)
}
else updateLifecycle(vnode.attrs, vnode, hooks) else updateLifecycle(vnode.attrs, vnode, hooks)
} }
switch (oldTag) { switch (oldTag) {

View file

@ -12,19 +12,19 @@ o.spec("attributes", function() {
render = vdom($window).render render = vdom($window).render
}) })
o.spec("customElements", function(){ o.spec("customElements", function(){
o("when vnode is customElement, custom setAttribute called", function(){ o("when vnode is customElement, custom setAttribute called", function(){
var normal = [ var normal = [
{ tag: "input", attrs: { value: 'hello' } }, {tag: "input", attrs: {value: "hello"}},
{ tag: "input", attrs: { value: 'hello' } }, {tag: "input", attrs: {value: "hello"}},
{ tag: "input", attrs: { value: 'hello' } } {tag: "input", attrs: {value: "hello"}}
] ]
var custom = [ var custom = [
{ tag: "custom-element", attrs: { custom: 'x' } }, {tag: "custom-element", attrs: {custom: "x"}},
{ tag: "input", attrs: { is: 'something-special', custom: 'x' } }, {tag: "input", attrs: {is: "something-special", custom: "x"}},
{ tag: "custom-element", attrs: { is: 'something-special', custom: 'x' } } {tag: "custom-element", attrs: {is: "something-special", custom: "x"}}
] ]
var view = normal.concat(custom) var view = normal.concat(custom)
@ -43,8 +43,8 @@ o.spec("attributes", function() {
} }
render(root, view) render(root, view)
o(spy.callCount).equals( custom.length ) o(spy.callCount).equals(custom.length)
}) })
}) })
@ -133,7 +133,7 @@ o.spec("attributes", function() {
}) })
o.spec("contenteditable throws on untrusted children", function() { o.spec("contenteditable throws on untrusted children", function() {
o("including text nodes", function() { o("including text nodes", function() {
var div = {tag: "div", attrs: {contenteditable: true}, text: ''} var div = {tag: "div", attrs: {contenteditable: true}, text: ""}
var succeeded = false var succeeded = false
try { try {
@ -141,7 +141,7 @@ o.spec("attributes", function() {
succeeded = true succeeded = true
} }
catch(e){} catch(e){/* ignore */}
o(succeeded).equals(false) o(succeeded).equals(false)
}) })
@ -154,7 +154,7 @@ o.spec("attributes", function() {
succeeded = true succeeded = true
} }
catch(e){} catch(e){/* ignore */}
o(succeeded).equals(false) o(succeeded).equals(false)
}) })
@ -167,7 +167,7 @@ o.spec("attributes", function() {
succeeded = true succeeded = true
} }
catch(e){} catch(e){/* ignore */}
o(succeeded).equals(true) o(succeeded).equals(true)
}) })
@ -180,7 +180,7 @@ o.spec("attributes", function() {
succeeded = true succeeded = true
} }
catch(e){} catch(e){/* ignore */}
o(succeeded).equals(true) o(succeeded).equals(true)
}) })

View file

@ -63,7 +63,7 @@ o.spec("component", function() {
o("updates root from null", function() { o("updates root from null", function() {
var visible = false var visible = false
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return visible ? {tag: "div"} : null return visible ? {tag: "div"} : null
} }
}) })
@ -76,7 +76,7 @@ o.spec("component", function() {
o("updates root from primitive", function() { o("updates root from primitive", function() {
var visible = false var visible = false
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return visible ? {tag: "div"} : false return visible ? {tag: "div"} : false
} }
}) })
@ -89,7 +89,7 @@ o.spec("component", function() {
o("updates root to null", function() { o("updates root to null", function() {
var visible = true var visible = true
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return visible ? {tag: "div"} : null return visible ? {tag: "div"} : null
} }
}) })
@ -102,7 +102,7 @@ o.spec("component", function() {
o("updates root to primitive", function() { o("updates root to primitive", function() {
var visible = true var visible = true
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return visible ? {tag: "div"} : false return visible ? {tag: "div"} : false
} }
}) })
@ -114,7 +114,7 @@ o.spec("component", function() {
}) })
o("updates root from null to null", function() { o("updates root from null to null", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return null return null
} }
}) })
@ -125,7 +125,7 @@ o.spec("component", function() {
}) })
o("removes", function() { o("removes", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return {tag: "div"} return {tag: "div"}
} }
}) })
@ -138,7 +138,7 @@ o.spec("component", function() {
}) })
o("svg works when creating across component boundary", function() { o("svg works when creating across component boundary", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return {tag: "g"} return {tag: "g"}
} }
}) })
@ -148,7 +148,7 @@ o.spec("component", function() {
}) })
o("svg works when updating across component boundary", function() { o("svg works when updating across component boundary", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return {tag: "g"} return {tag: "g"}
} }
}) })
@ -161,7 +161,7 @@ o.spec("component", function() {
o.spec("return value", function() { o.spec("return value", function() {
o("can return fragments", function() { o("can return fragments", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return [ return [
{tag: "label"}, {tag: "label"},
{tag: "input"}, {tag: "input"},
@ -176,7 +176,7 @@ o.spec("component", function() {
}) })
o("can return string", function() { o("can return string", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return "a" return "a"
} }
}) })
@ -187,7 +187,7 @@ o.spec("component", function() {
}) })
o("can return falsy string", function() { o("can return falsy string", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return "" return ""
} }
}) })
@ -198,7 +198,7 @@ o.spec("component", function() {
}) })
o("can return number", function() { o("can return number", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return 1 return 1
} }
}) })
@ -209,7 +209,7 @@ o.spec("component", function() {
}) })
o("can return falsy number", function() { o("can return falsy number", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return 0 return 0
} }
}) })
@ -220,7 +220,7 @@ o.spec("component", function() {
}) })
o("can return boolean", function() { o("can return boolean", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return true return true
} }
}) })
@ -231,7 +231,7 @@ o.spec("component", function() {
}) })
o("can return falsy boolean", function() { o("can return falsy boolean", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return false return false
} }
}) })
@ -242,7 +242,7 @@ o.spec("component", function() {
}) })
o("can return null", function() { o("can return null", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return null return null
} }
}) })
@ -252,7 +252,7 @@ o.spec("component", function() {
}) })
o("can return undefined", function() { o("can return undefined", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return undefined return undefined
} }
}) })
@ -278,7 +278,7 @@ o.spec("component", function() {
}) })
o("can update when returning fragments", function() { o("can update when returning fragments", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return [ return [
{tag: "label"}, {tag: "label"},
{tag: "input"}, {tag: "input"},
@ -294,7 +294,7 @@ o.spec("component", function() {
}) })
o("can update when returning primitive", function() { o("can update when returning primitive", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return "a" return "a"
} }
}) })
@ -306,7 +306,7 @@ o.spec("component", function() {
}) })
o("can update when returning null", function() { o("can update when returning null", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return null return null
} }
}) })
@ -317,7 +317,7 @@ o.spec("component", function() {
}) })
o("can remove when returning fragments", function() { o("can remove when returning fragments", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return [ return [
{tag: "label"}, {tag: "label"},
{tag: "input"}, {tag: "input"},
@ -334,7 +334,7 @@ o.spec("component", function() {
}) })
o("can remove when returning primitive", function() { o("can remove when returning primitive", function() {
var component = createComponent({ var component = createComponent({
view: function(vnode) { view: function() {
return "a" return "a"
} }
}) })
@ -403,7 +403,7 @@ o.spec("component", function() {
viewCalled = true viewCalled = true
return [{tag: "div", attrs: {id: "a"}, text: "b"}] return [{tag: "div", attrs: {id: "a"}, text: "b"}]
}, },
oninit: function(vnode) { oninit: function() {
o(viewCalled).equals(false) o(viewCalled).equals(false)
}, },
} }
@ -646,7 +646,6 @@ o.spec("component", function() {
return {tag: "div"} return {tag: "div"}
} }
}) })
var update = o.spy()
var vnode = {tag: component, key: 1} var vnode = {tag: component, key: 1}
var updated = {tag: component, key: 1} var updated = {tag: component, key: 1}
@ -786,15 +785,15 @@ o.spec("component", function() {
} else { } else {
o(vnode.state).notEquals(firstState) o(vnode.state).notEquals(firstState)
} }
return {tag: 'div'} return {tag: "div"}
}) })
var component = createComponent({view: view}) var component = createComponent({view: view})
render(root, [{tag: 'div', children: [{tag: component, key: 1}]}]) render(root, [{tag: "div", children: [{tag: component, key: 1}]}])
var child = root.firstChild.firstChild var child = root.firstChild.firstChild
render(root, []) render(root, [])
step = 1 step = 1
render(root, [{tag: 'div', children: [{tag: component, key: 1}]}]) render(root, [{tag: "div", children: [{tag: component, key: 1}]}])
o(child).equals(root.firstChild.firstChild) o(child).equals(root.firstChild.firstChild)
o(view.callCount).equals(2) o(view.callCount).equals(2)
@ -802,7 +801,6 @@ o.spec("component", function() {
}) })
o.spec("state", function() { o.spec("state", function() {
o("initializes state", function() { o("initializes state", function() {
var called = 0
var data = {a: 1} var data = {a: 1}
var component = createComponent(createComponent({ var component = createComponent(createComponent({
data: data, data: data,
@ -818,8 +816,7 @@ o.spec("component", function() {
o(vnode.state.data).equals(data) o(vnode.state.data).equals(data)
} }
}) })
o('state proxies to the component object/prototype', function() { o("state proxies to the component object/prototype", function() {
var called = 0
var body = {a: 1} var body = {a: 1}
var data = [body] var data = [body]
var component = createComponent(createComponent({ var component = createComponent(createComponent({
@ -843,7 +840,6 @@ o.spec("component", function() {
o.spec("Tests specific to certain component kinds", function() { o.spec("Tests specific to certain component kinds", function() {
o.spec("state", function() { o.spec("state", function() {
o("POJO", function() { o("POJO", function() {
var called = 0
var data = {} var data = {}
var component = { var component = {
data: data, data: data,
@ -876,8 +872,6 @@ o.spec("component", function() {
component.prototype.view = view component.prototype.view = view
component.prototype.oninit = oninit component.prototype.oninit = oninit
var context
render(root, [{tag: component, attrs: {oninit: oninit}}]) render(root, [{tag: component, attrs: {oninit: oninit}}])
render(root, [{tag: component, attrs: {oninit: oninit}}]) render(root, [{tag: component, attrs: {oninit: oninit}}])
render(root, []) render(root, [])

View file

@ -1,3 +1,4 @@
/* eslint-disable no-script-url */
"use strict" "use strict"
var o = require("../../ospec/ospec") var o = require("../../ospec/ospec")

View file

@ -1,3 +1,5 @@
"use strict"
var o = require("../../ospec/ospec") var o = require("../../ospec/ospec")
var m = require("../../render/hyperscript") var m = require("../../render/hyperscript")

View file

@ -17,7 +17,6 @@ o.spec("onbeforeremove", function() {
o("does not call onbeforeremove when creating", function() { o("does not call onbeforeremove when creating", function() {
var create = o.spy() var create = o.spy()
var update = o.spy()
var vnode = {tag: "div", attrs: {onbeforeremove: create}} var vnode = {tag: "div", attrs: {onbeforeremove: create}}
render(root, [vnode]) render(root, [vnode])
@ -142,7 +141,7 @@ o.spec("onbeforeremove", function() {
o(vnode.dom.attributes["onbeforeremove"]).equals(undefined) o(vnode.dom.attributes["onbeforeremove"]).equals(undefined)
}) })
o("does not recycle when there's an onbeforeremove", function() { o("does not recycle when there's an onbeforeremove", function() {
var remove = function(vnode) {} var remove = function() {}
var vnode = {tag: "div", key: 1, attrs: {onbeforeremove: remove}} var vnode = {tag: "div", key: 1, attrs: {onbeforeremove: remove}}
var updated = {tag: "div", key: 1, attrs: {onbeforeremove: remove}} var updated = {tag: "div", key: 1, attrs: {onbeforeremove: remove}}
@ -153,7 +152,7 @@ o.spec("onbeforeremove", function() {
o(vnode.dom).notEquals(updated.dom) o(vnode.dom).notEquals(updated.dom)
}) })
o("does not leave elements out of order during removal", function(done) { o("does not leave elements out of order during removal", function(done) {
var remove = function(vnode) {return Promise.resolve()} var remove = function() {return Promise.resolve()}
var vnodes = [{tag: "div", key: 1, attrs: {onbeforeremove: remove}, text: "1"}, {tag: "div", key: 2, attrs: {onbeforeremove: remove}, text: "2"}] var vnodes = [{tag: "div", key: 1, attrs: {onbeforeremove: remove}, text: "1"}, {tag: "div", key: 2, attrs: {onbeforeremove: remove}, text: "2"}]
var updated = {tag: "div", key: 2, attrs: {onbeforeremove: remove}, text: "2"} var updated = {tag: "div", key: 2, attrs: {onbeforeremove: remove}, text: "2"}

View file

@ -92,11 +92,10 @@ o.spec("onbeforeupdate", function() {
o("is not called on creation", function() { o("is not called on creation", function() {
var count = 0 var count = 0
var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}} var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}}
var updated = {tag: "div", attrs: {id: "b", onbeforeupdate: onbeforeupdate}}
render(root, [vnode]) render(root, [vnode])
function onbeforeupdate(vnode, old) { function onbeforeupdate() {
count++ count++
return true return true
} }
@ -112,7 +111,7 @@ o.spec("onbeforeupdate", function() {
render(root, [vnode]) render(root, [vnode])
render(root, [updated]) render(root, [updated])
function onbeforeupdate(vnode, old) { function onbeforeupdate() {
count++ count++
return true return true
} }
@ -263,7 +262,7 @@ o.spec("onbeforeupdate", function() {
}) })
o("is not called on component creation", function() { o("is not called on component creation", function() {
var component = createComponent({ createComponent({
onbeforeupdate: onbeforeupdate, onbeforeupdate: onbeforeupdate,
view: function(vnode) { view: function(vnode) {
return {tag: "div", attrs: vnode.attrs} return {tag: "div", attrs: vnode.attrs}
@ -272,11 +271,10 @@ o.spec("onbeforeupdate", function() {
var count = 0 var count = 0
var vnode = {tag: "div", attrs: {id: "a"}} var vnode = {tag: "div", attrs: {id: "a"}}
var updated = {tag: "div", attrs: {id: "b"}}
render(root, [vnode]) render(root, [vnode])
function onbeforeupdate(vnode, old) { function onbeforeupdate() {
count++ count++
return true return true
} }
@ -299,7 +297,7 @@ o.spec("onbeforeupdate", function() {
render(root, [vnode]) render(root, [vnode])
render(root, [updated]) render(root, [updated])
function onbeforeupdate(vnode, old) { function onbeforeupdate() {
count++ count++
return true return true
} }
@ -308,4 +306,4 @@ o.spec("onbeforeupdate", function() {
}) })
}) })
}) })
}) })

View file

@ -128,7 +128,6 @@ o.spec("oncreate", function() {
}) })
o("does not call oncreate when removing", function() { o("does not call oncreate when removing", function() {
var create = o.spy() var create = o.spy()
var update = o.spy()
var vnode = {tag: "div", attrs: {oncreate: create}, state: {}} var vnode = {tag: "div", attrs: {oncreate: create}, state: {}}
render(root, [vnode]) render(root, [vnode])

View file

@ -128,7 +128,6 @@ o.spec("oninit", function() {
}) })
o("does not call oninit when removing", function() { o("does not call oninit when removing", function() {
var create = o.spy() var create = o.spy()
var update = o.spy()
var vnode = {tag: "div", attrs: {oninit: create}, state: {}} var vnode = {tag: "div", attrs: {oninit: create}, state: {}}
render(root, [vnode]) render(root, [vnode])

View file

@ -59,7 +59,6 @@ o.spec("onupdate", function() {
}) })
o("does not call old onupdate when removing the onupdate property in new vnode", function() { o("does not call old onupdate when removing the onupdate property in new vnode", function() {
var create = o.spy() var create = o.spy()
var update = o.spy()
var vnode = {tag: "a", attrs: {onupdate: create}} var vnode = {tag: "a", attrs: {onupdate: create}}
var updated = {tag: "a"} var updated = {tag: "a"}

View file

@ -1,7 +1,6 @@
"use strict" "use strict"
var o = require("../../ospec/ospec") var o = require("../../ospec/ospec")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock") var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render") var vdom = require("../../render/render")
@ -124,7 +123,7 @@ o.spec("render", function() {
var onbeforeupdate = o.spy() var onbeforeupdate = o.spy()
function A() { function A() {
return { return {
view: function(vnode) {throw new Error("error")}, view: function() {throw new Error("error")},
oninit: oninit, oninit: oninit,
onbeforeupdate: onbeforeupdate onbeforeupdate: onbeforeupdate
} }
@ -143,11 +142,11 @@ o.spec("render", function() {
o(onbeforeupdate.callCount).equals(0) o(onbeforeupdate.callCount).equals(0)
}) })
o("does not try to re-initialize a closure component whose oninit has thrown", function() { o("does not try to re-initialize a closure component whose oninit has thrown", function() {
var oninit = o.spy(function(vnode) {throw new Error("error")}) var oninit = o.spy(function() {throw new Error("error")})
var onbeforeupdate = o.spy() var onbeforeupdate = o.spy()
function A() { function A() {
return { return {
view: function(vnode) {}, view: function() {},
oninit: oninit, oninit: oninit,
onbeforeupdate: onbeforeupdate onbeforeupdate: onbeforeupdate
} }

View file

@ -213,10 +213,10 @@ o.spec("updateElement", function() {
}) })
o("updates svg child", function() { o("updates svg child", function() {
var vnode = {tag: "svg", children: [{ var vnode = {tag: "svg", children: [{
tag: 'circle' tag: "circle"
}]} }]}
var updated = {tag: "svg", children: [{ var updated = {tag: "svg", children: [{
tag: 'line' tag: "line"
}]} }]}
render(root, [vnode]) render(root, [vnode])
@ -235,7 +235,7 @@ o.spec("updateElement", function() {
render(root, [vnode]) render(root, [vnode])
var c = vnode.dom var c = vnode.dom
o(root.childNodes.length).equals(1) o(root.childNodes.length).equals(1)
o(a).equals(c) o(a).equals(c)
}) })
@ -254,7 +254,7 @@ o.spec("updateElement", function() {
render(root, [e, b, f]) render(root, [e, b, f])
var y = root.childNodes[1] var y = root.childNodes[1]
o(root.childNodes.length).equals(3) o(root.childNodes.length).equals(3)
o(x).equals(y) o(x).equals(y)
}) })

View file

@ -727,7 +727,7 @@ o.spec("updateNodes", function() {
}) })
o("change type, position and length", function() { o("change type, position and length", function() {
var vnodes = {tag: "div", children: [ var vnodes = {tag: "div", children: [
undefined, undefined,
{tag: "#", children: "a"} {tag: "#", children: "a"}
]} ]}
var updated = {tag: "div", children: [ var updated = {tag: "div", children: [
@ -738,7 +738,7 @@ o.spec("updateNodes", function() {
render(root, vnodes) render(root, vnodes)
render(root, updated) render(root, updated)
o(root.firstChild.childNodes.length).equals(1) o(root.firstChild.childNodes.length).equals(1)
}) })
o("removes then recreates then reverses children", function() { o("removes then recreates then reverses children", function() {
@ -864,13 +864,13 @@ o.spec("updateNodes", function() {
var vnodes = [{tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] var vnodes = [{tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}]
var temp = [null, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] var temp = [null, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}]
var updated = [{tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] var updated = [{tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}]
render(root, vnodes) render(root, vnodes)
var before = vnodes[1].dom var before = vnodes[1].dom
render(root, temp) render(root, temp)
render(root, updated) render(root, updated)
var after = updated[1].dom var after = updated[1].dom
o(before).equals(after) o(before).equals(after)
o(create.callCount).equals(1) o(create.callCount).equals(1)
o(update.callCount).equals(2) o(update.callCount).equals(2)
@ -883,13 +883,13 @@ o.spec("updateNodes", function() {
var vnodes = [{tag: "b"}, {tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] var vnodes = [{tag: "b"}, {tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}]
var temp = [{tag: "b"}, null, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] var temp = [{tag: "b"}, null, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}]
var updated = [{tag: "b"}, {tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}] var updated = [{tag: "b"}, {tag: "div"}, {tag: "a", attrs: {oncreate: create, onupdate: update, onremove: remove}}]
render(root, vnodes) render(root, vnodes)
var before = vnodes[2].dom var before = vnodes[2].dom
render(root, temp) render(root, temp)
render(root, updated) render(root, updated)
var after = updated[2].dom var after = updated[2].dom
o(before).equals(after) o(before).equals(after)
o(create.callCount).equals(1) o(create.callCount).equals(1)
o(update.callCount).equals(2) o(update.callCount).equals(2)
@ -898,11 +898,10 @@ o.spec("updateNodes", function() {
o("node is recreated if key changes to undefined", function () { o("node is recreated if key changes to undefined", function () {
var vnode = {tag: "b", key: 1} var vnode = {tag: "b", key: 1}
var updated = {tag: "b"} var updated = {tag: "b"}
render(root, vnode) render(root, vnode)
var dom = vnode.dom
render(root, updated) render(root, updated)
o(vnode.dom).notEquals(updated.dom) o(vnode.dom).notEquals(updated.dom)
}) })
components.forEach(function(cmp){ components.forEach(function(cmp){
@ -943,4 +942,4 @@ o.spec("updateNodes", function() {
}) })
}) })
}) })
}) })

View file

@ -1,5 +1,7 @@
"use strict"
function Vnode(tag, key, attrs, children, text, dom) { function Vnode(tag, key, attrs, children, text, dom) {
return {tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: undefined, state: {}, events: undefined, instance: undefined, skip: false} return {tag: tag, key: key, attrs: attrs, children: children, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined, skip: false}
} }
Vnode.normalize = function(node) { Vnode.normalize = function(node) {
if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)

View file

@ -1,2 +1,4 @@
"use strict"
var PromisePolyfill = require("./promise/promise") var PromisePolyfill = require("./promise/promise")
module.exports = require("./request/request")(window, PromisePolyfill) module.exports = require("./request/request")(window, PromisePolyfill)

View file

@ -7,7 +7,7 @@ var Promise = require("../../promise/promise")
var parseQueryString = require("../../querystring/parse") var parseQueryString = require("../../querystring/parse")
o.spec("jsonp", function() { o.spec("jsonp", function() {
var mock, jsonp, spy, complete var mock, jsonp, complete
o.beforeEach(function() { o.beforeEach(function() {
mock = xhrMock() mock = xhrMock()
var requestService = Request(mock, Promise) var requestService = Request(mock, Promise)
@ -28,7 +28,6 @@ o.spec("jsonp", function() {
}).then(done) }).then(done)
}) })
o("first argument can be a string aliasing url property", function(done){ o("first argument can be a string aliasing url property", function(done){
var s = new Date
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function(request) {
var queryData = parseQueryString(request.query) var queryData = parseQueryString(request.query)
@ -104,8 +103,8 @@ o.spec("jsonp", function() {
return {status: 200, responseText: queryData["callback"] + "([])"} return {status: 200, responseText: queryData["callback"] + "([])"}
} }
}) })
var promise = jsonp("/item", {background: true}).then(function() {}) jsonp("/item", {background: true}).then(function() {})
setTimeout(function() { setTimeout(function() {
o(complete.callCount).equals(0) o(complete.callCount).equals(0)
done() done()

View file

@ -18,7 +18,6 @@ o.spec("xhr", function() {
o.spec("success", function() { o.spec("success", function() {
o("works via GET", function(done) { o("works via GET", function(done) {
var s = new Date
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function() { "GET /item": function() {
return {status: 200, responseText: JSON.stringify({a: 1})} return {status: 200, responseText: JSON.stringify({a: 1})}
@ -31,7 +30,6 @@ o.spec("xhr", function() {
}) })
}) })
o("implicit GET method", function(done){ o("implicit GET method", function(done){
var s = new Date
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function() { "GET /item": function() {
return {status: 200, responseText: JSON.stringify({a: 1})} return {status: 200, responseText: JSON.stringify({a: 1})}
@ -44,7 +42,6 @@ o.spec("xhr", function() {
}) })
}) })
o("first argument can be a string aliasing url property", function(done){ o("first argument can be a string aliasing url property", function(done){
var s = new Date
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function() { "GET /item": function() {
return {status: 200, responseText: JSON.stringify({a: 1})} return {status: 200, responseText: JSON.stringify({a: 1})}
@ -172,7 +169,7 @@ o.spec("xhr", function() {
} }
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: JSON.stringify([{id: 1}, {id: 2}, {id: 3}])} return {status: 200, responseText: JSON.stringify([{id: 1}, {id: 2}, {id: 3}])}
} }
}) })
@ -186,7 +183,7 @@ o.spec("xhr", function() {
} }
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: JSON.stringify({id: 1})} return {status: 200, responseText: JSON.stringify({id: 1})}
} }
}) })
@ -228,12 +225,12 @@ o.spec("xhr", function() {
} }
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: JSON.stringify({test: 123})} return {status: 200, responseText: JSON.stringify({test: 123})}
} }
}) })
xhr({method: "GET", url: "/item", deserialize: deserialize}).then(function(data) { xhr({method: "GET", url: "/item", deserialize: deserialize}).then(function(data) {
o(data).equals("{\"test\":123}") o(data).equals('{"test":123}')
}).then(done) }).then(done)
}) })
o("deserialize parameter works in POST", function(done) { o("deserialize parameter works in POST", function(done) {
@ -242,40 +239,40 @@ o.spec("xhr", function() {
} }
mock.$defineRoutes({ mock.$defineRoutes({
"POST /item": function(request) { "POST /item": function() {
return {status: 200, responseText: JSON.stringify({test: 123})} return {status: 200, responseText: JSON.stringify({test: 123})}
} }
}) })
xhr({method: "POST", url: "/item", deserialize: deserialize}).then(function(data) { xhr({method: "POST", url: "/item", deserialize: deserialize}).then(function(data) {
o(data).equals("{\"test\":123}") o(data).equals('{"test":123}')
}).then(done) }).then(done)
}) })
o("extract parameter works in GET", function(done) { o("extract parameter works in GET", function(done) {
var extract = function(data) { var extract = function() {
return JSON.stringify({test: 123}) return JSON.stringify({test: 123})
} }
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
xhr({method: "GET", url: "/item", extract: extract}).then(function(data) { xhr({method: "GET", url: "/item", extract: extract}).then(function(data) {
o(data).equals("{\"test\":123}") o(data).equals('{"test":123}')
}).then(done) }).then(done)
}) })
o("extract parameter works in POST", function(done) { o("extract parameter works in POST", function(done) {
var extract = function(data) { var extract = function() {
return JSON.stringify({test: 123}) return JSON.stringify({test: 123})
} }
mock.$defineRoutes({ mock.$defineRoutes({
"POST /item": function(request) { "POST /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
xhr({method: "POST", url: "/item", extract: extract}).then(function(data) { xhr({method: "POST", url: "/item", extract: extract}).then(function(data) {
o(data).equals("{\"test\":123}") o(data).equals('{"test":123}')
}).then(done) }).then(done)
}) })
o("ignores deserialize if extract is defined", function(done) { o("ignores deserialize if extract is defined", function(done) {
@ -285,7 +282,7 @@ o.spec("xhr", function() {
var deserialize = o.spy() var deserialize = o.spy()
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
@ -297,7 +294,7 @@ o.spec("xhr", function() {
}) })
o("config parameter works", function(done) { o("config parameter works", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"POST /item": function(request) { "POST /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
@ -311,7 +308,7 @@ o.spec("xhr", function() {
}) })
o("requests don't block each other", function(done) { o("requests don't block each other", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: "[]"} return {status: 200, responseText: "[]"}
} }
}) })
@ -328,7 +325,7 @@ o.spec("xhr", function() {
}) })
o("requests trigger finally once with a chained then", function(done) { o("requests trigger finally once with a chained then", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: "[]"} return {status: 200, responseText: "[]"}
} }
}) })
@ -342,11 +339,11 @@ o.spec("xhr", function() {
}) })
o("requests does not trigger finally when background: true", function(done) { o("requests does not trigger finally when background: true", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 200, responseText: "[]"} return {status: 200, responseText: "[]"}
} }
}) })
var promise = xhr("/item", {background: true}).then(function() {}) xhr("/item", {background: true}).then(function() {})
setTimeout(function() { setTimeout(function() {
o(complete.callCount).equals(0) o(complete.callCount).equals(0)
@ -355,7 +352,7 @@ o.spec("xhr", function() {
}) })
o("headers are set when header arg passed", function(done) { o("headers are set when header arg passed", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"POST /item": function(request) { "POST /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
@ -367,7 +364,7 @@ o.spec("xhr", function() {
}) })
o("headers are with higher precedence than default headers", function(done) { o("headers are with higher precedence than default headers", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"POST /item": function(request) { "POST /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
@ -379,7 +376,7 @@ o.spec("xhr", function() {
}) })
o("json headers are set to the correct default value", function(done) { o("json headers are set to the correct default value", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"POST /item": function(request) { "POST /item": function() {
return {status: 200, responseText: ""} return {status: 200, responseText: ""}
} }
}) })
@ -391,7 +388,6 @@ o.spec("xhr", function() {
} }
}) })
o("doesn't fail on abort", function(done) { o("doesn't fail on abort", function(done) {
var s = new Date
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function() { "GET /item": function() {
return {status: 200, responseText: JSON.stringify({a: 1})} return {status: 200, responseText: JSON.stringify({a: 1})}
@ -410,9 +406,9 @@ o.spec("xhr", function() {
done() done()
}, 0) }, 0)
} }
Object.defineProperty(xhr, 'onreadystatechange', { Object.defineProperty(xhr, "onreadystatechange", {
set: function(val) { onreadystatechange = val } set: function(val) { onreadystatechange = val },
, get: function() { return testonreadystatechange } get: function() { return testonreadystatechange }
}) })
xhr.abort() xhr.abort()
} }
@ -424,7 +420,6 @@ o.spec("xhr", function() {
}) })
}) })
o("doesn't fail on file:// status 0", function(done) { o("doesn't fail on file:// status 0", function(done) {
var s = new Date
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function() { "GET /item": function() {
return {status: 0, responseText: JSON.stringify({a: 1})} return {status: 0, responseText: JSON.stringify({a: 1})}
@ -456,7 +451,7 @@ o.spec("xhr", function() {
o.spec("failure", function() { o.spec("failure", function() {
o("rejects on server error", function(done) { o("rejects on server error", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 500, responseText: JSON.stringify({error: "error"})} return {status: 500, responseText: JSON.stringify({error: "error"})}
} }
}) })
@ -467,7 +462,7 @@ o.spec("xhr", function() {
}) })
o("extends Error with JSON response", function(done) { o("extends Error with JSON response", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 500, responseText: JSON.stringify({message: "error", stack: "error on line 1"})} return {status: 500, responseText: JSON.stringify({message: "error", stack: "error on line 1"})}
} }
}) })
@ -479,7 +474,7 @@ o.spec("xhr", function() {
}) })
o("rejects on non-JSON server error", function(done) { o("rejects on non-JSON server error", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 500, responseText: "error"} return {status: 500, responseText: "error"}
} }
}) })
@ -489,7 +484,7 @@ o.spec("xhr", function() {
}) })
o("triggers all branched catches upon rejection", function(done) { o("triggers all branched catches upon rejection", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 500, responseText: "error"} return {status: 500, responseText: "error"}
} }
}) })
@ -515,7 +510,7 @@ o.spec("xhr", function() {
}) })
o("rejects on cors-like error", function(done) { o("rejects on cors-like error", function(done) {
mock.$defineRoutes({ mock.$defineRoutes({
"GET /item": function(request) { "GET /item": function() {
return {status: 0} return {status: 0}
} }
}) })

View file

@ -1,3 +1,5 @@
"use strict"
var redrawService = require("./redraw") var redrawService = require("./redraw")
module.exports = require("./api/router")(window, redrawService) module.exports = require("./api/router")(window, redrawService)

View file

@ -6,7 +6,7 @@ var Router = require("../../router/router")
o.spec("Router.getPath", function() { o.spec("Router.getPath", function() {
void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) { void [{protocol: "http:", hostname: "localhost"}, {protocol: "file:", hostname: "/"}].forEach(function(env) {
void ["#", "?", "", "#!", "?!", '/foo'].forEach(function(prefix) { void ["#", "?", "", "#!", "?!", "/foo"].forEach(function(prefix) {
o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() { o.spec("using prefix `" + prefix + "` starting on " + env.protocol + "//" + env.hostname, function() {
var $window, router, onRouteChange, onFail var $window, router, onRouteChange, onFail

View file

@ -1 +1,3 @@
module.exports = require("./stream/stream") "use strict"
module.exports = require("./stream/stream")

View file

@ -22,7 +22,7 @@ o.spec("scan", function() {
parent(7) parent(7)
parent("11") parent("11")
parent(undefined) parent(undefined)
parent({ a: 1 }) parent({a: 1})
var result = child() var result = child()
// deepEquals fails on arrays? // deepEquals fails on arrays?
@ -32,4 +32,3 @@ o.spec("scan", function() {
o(result[3]).deepEquals({a: 1}) o(result[3]).deepEquals({a: 1})
}) })
}) })

View file

@ -1,7 +1,6 @@
"use strict" "use strict"
var o = require("../../ospec/ospec") var o = require("../../ospec/ospec")
var callAsync = require("../../test-utils/callAsync")
var Stream = require("../stream") var Stream = require("../stream")
o.spec("stream", function() { o.spec("stream", function() {
@ -105,7 +104,7 @@ o.spec("stream", function() {
var streams = [] var streams = []
var a = Stream() var a = Stream()
var b = Stream() var b = Stream()
var c = Stream.combine(function(a, b, changed) { Stream.combine(function(a, b, changed) {
streams = changed streams = changed
}, [a, b]) }, [a, b])
@ -119,7 +118,7 @@ o.spec("stream", function() {
var streams = [] var streams = []
var a = Stream(3) var a = Stream(3)
var b = Stream(5) var b = Stream(5)
var c = Stream.combine(function(a, b, changed) { Stream.combine(function(a, b, changed) {
streams = changed streams = changed
}, [a, b]) }, [a, b])
@ -130,7 +129,7 @@ o.spec("stream", function() {
}) })
o("combine can return undefined", function() { o("combine can return undefined", function() {
var a = Stream(1) var a = Stream(1)
var b = Stream.combine(function(a) { var b = Stream.combine(function() {
return undefined return undefined
}, [a]) }, [a])
@ -138,7 +137,7 @@ o.spec("stream", function() {
}) })
o("combine can return stream", function() { o("combine can return stream", function() {
var a = Stream(1) var a = Stream(1)
var b = Stream.combine(function(a) { var b = Stream.combine(function() {
return Stream(2) return Stream(2)
}, [a]) }, [a])
@ -146,7 +145,7 @@ o.spec("stream", function() {
}) })
o("combine can return pending stream", function() { o("combine can return pending stream", function() {
var a = Stream(1) var a = Stream(1)
var b = Stream.combine(function(a) { var b = Stream.combine(function() {
return Stream() return Stream()
}, [a]) }, [a])
@ -155,22 +154,22 @@ o.spec("stream", function() {
o("combine can halt", function() { o("combine can halt", function() {
var count = 0 var count = 0
var a = Stream(1) var a = Stream(1)
var b = Stream.combine(function(a) { var b = Stream.combine(function() {
return Stream.HALT return Stream.HALT
}, [a]) }, [a])["fantasy-land/map"](function() {
["fantasy-land/map"](function() {
count++ count++
return 1 return 1
}) })
o(b()).equals(undefined) o(b()).equals(undefined)
o(count).equals(0)
}) })
o("combine will throw with a helpful error if given non-stream values", function () { o("combine will throw with a helpful error if given non-stream values", function () {
var spy = o.spy() var spy = o.spy()
var a = Stream(1) var a = Stream(1)
var thrown = null; var thrown = null;
try { try {
var b = Stream.combine(spy, [a, '']) Stream.combine(spy, [a, ""])
} catch (e) { } catch (e) {
thrown = e thrown = e
} }
@ -210,8 +209,9 @@ o.spec("stream", function() {
var a = Stream() var a = Stream()
var b = Stream() var b = Stream()
var all = Stream.merge([a.map(id), b.map(id)]).map(function(data) { Stream.merge([a.map(id), b.map(id)]).map(function(data) {
value = data[0] + data[1] value = data[0] + data[1]
return undefined
}) })
a(1) a(1)
@ -344,7 +344,7 @@ o.spec("stream", function() {
}) })
o("works with pending stream", function() { o("works with pending stream", function() {
var stream = Stream(undefined) var stream = Stream(undefined)
var mapped = stream["fantasy-land/map"](function(value) {return Stream()}) var mapped = stream["fantasy-land/map"](function() {return Stream()})
o(mapped()()).equals(undefined) o(mapped()()).equals(undefined)
}) })

View file

@ -1,27 +1,29 @@
"use strict"
module.exports = [ module.exports = [
{ {
kind: 'POJO', kind: "POJO",
create: function(methods) { create: function(methods) {
var res = {view: function() {return {tag:'div'}}} var res = {view: function() {return {tag:"div"}}}
Object.keys(methods || {}).forEach(function(m){res[m] = methods[m]}) Object.keys(methods || {}).forEach(function(m){res[m] = methods[m]})
return res return res
} }
}, { }, {
kind: 'constructible', kind: "constructible",
create: function(methods) { create: function(methods) {
function res(){} function res(){}
res.prototype.view = function() {return {tag:'div'}} res.prototype.view = function() {return {tag:"div"}}
Object.keys(methods || {}).forEach(function(m){res.prototype[m] = methods[m]}) Object.keys(methods || {}).forEach(function(m){res.prototype[m] = methods[m]})
return res return res
} }
}, { }, {
kind: 'closure', kind: "closure",
create: function(methods) { create: function(methods) {
return function() { return function() {
var res = {view: function() {return {tag:'div'}}} var res = {view: function() {return {tag:"div"}}}
Object.keys(methods || {}).forEach(function(m){res[m] = methods[m]}) Object.keys(methods || {}).forEach(function(m){res[m] = methods[m]})
return res return res
} }
} }
} }
] ]

View file

@ -96,7 +96,7 @@ module.exports = function() {
declList = declList.replace( declList = declList.replace(
/("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*')|\/\*[\s\S]*?\*\//g, /("(?:\\.|[^"\n])*"|'(?:\\.|[^'\n])*')|\/\*[\s\S]*?\*\//g,
function(m, str){ function(m, str){
return str || '' return str || ""
} }
) )
/*eslint-disable no-cond-assign*/ /*eslint-disable no-cond-assign*/
@ -115,7 +115,7 @@ module.exports = function() {
var activeElement var activeElement
var $window = { var $window = {
document: { document: {
createElement: function(tag, is) { createElement: function(tag) {
var cssText = "" var cssText = ""
var style = {} var style = {}
Object.defineProperty(style, "cssText", { Object.defineProperty(style, "cssText", {
@ -211,11 +211,11 @@ module.exports = function() {
else this.setAttribute("class", value) else this.setAttribute("class", value)
}, },
focus: function() {activeElement = this}, focus: function() {activeElement = this},
addEventListener: function(type, callback, useCapture) { addEventListener: function(type, callback) {
if (events[type] == null) events[type] = [callback] if (events[type] == null) events[type] = [callback]
else events[type].push(callback) else events[type].push(callback)
}, },
removeEventListener: function(type, callback, useCapture) { removeEventListener: function(type, callback) {
if (events[type] != null) { if (events[type] != null) {
var index = events[type].indexOf(callback) var index = events[type].indexOf(callback)
if (index > -1) events[type].splice(index, 1) if (index > -1) events[type].splice(index, 1)
@ -241,7 +241,6 @@ module.exports = function() {
} }
if (element.nodeName === "A") { if (element.nodeName === "A") {
var href
Object.defineProperty(element, "href", { Object.defineProperty(element, "href", {
get: function() {return this.attributes["href"] === undefined ? "" : "[FIXME implement]"}, get: function() {return this.attributes["href"] === undefined ? "" : "[FIXME implement]"},
set: function(value) {this.setAttribute("href", value)}, set: function(value) {this.setAttribute("href", value)},
@ -271,7 +270,9 @@ module.exports = function() {
enumerable: true, enumerable: true,
}) })
} }
/* eslint-disable radix */
if (element.nodeName === "CANVAS") { if (element.nodeName === "CANVAS") {
Object.defineProperty(element, "width", { Object.defineProperty(element, "width", {
get: function() {return this.attributes["width"] ? Math.floor(parseInt(this.attributes["width"].nodeValue) || 0) : 300}, get: function() {return this.attributes["width"] ? Math.floor(parseInt(this.attributes["width"].nodeValue) || 0) : 300},
@ -283,6 +284,8 @@ module.exports = function() {
}) })
} }
/* eslint-enable radix */
function getOptions(element) { function getOptions(element) {
var options = [] var options = []
for (var i = 0; i < element.childNodes.length; i++) { for (var i = 0; i < element.childNodes.length; i++) {
@ -297,17 +300,18 @@ module.exports = function() {
element.firstChild != null ? element.firstChild.nodeValue : "" element.firstChild != null ? element.firstChild.nodeValue : ""
} }
if (element.nodeName === "SELECT") { if (element.nodeName === "SELECT") {
var selectedValue, selectedIndex = 0 // var selectedValue
var selectedIndex = 0
Object.defineProperty(element, "selectedIndex", { Object.defineProperty(element, "selectedIndex", {
get: function() {return getOptions(this).length > 0 ? selectedIndex : -1}, get: function() {return getOptions(this).length > 0 ? selectedIndex : -1},
set: function(value) { set: function(value) {
var options = getOptions(this) var options = getOptions(this)
if (value >= 0 && value < options.length) { if (value >= 0 && value < options.length) {
selectedValue = getOptionValue(options[selectedIndex]) // selectedValue = getOptionValue(options[selectedIndex])
selectedIndex = value selectedIndex = value
} }
else { else {
selectedValue = "" // selectedValue = ""
selectedIndex = -1 selectedIndex = -1
} }
}, },
@ -323,12 +327,12 @@ module.exports = function() {
var stringValue = String(value) var stringValue = String(value)
for (var i = 0; i < options.length; i++) { for (var i = 0; i < options.length; i++) {
if (getOptionValue(options[i]) === stringValue) { if (getOptionValue(options[i]) === stringValue) {
selectedValue = stringValue // selectedValue = stringValue
selectedIndex = i selectedIndex = i
return return
} }
} }
selectedValue = stringValue // selectedValue = stringValue
selectedIndex = -1 selectedIndex = -1
}, },
enumerable: true, enumerable: true,

View file

@ -3,7 +3,7 @@
module.exports = function parseURL(url, root) { module.exports = function parseURL(url, root) {
var data = {} var data = {}
var protocolIndex = url.indexOf("://") var protocolIndex = url.indexOf("://")
var pathnameIndex = protocolIndex > - 1 ? url.indexOf("/", protocolIndex + 3) : url.indexOf("/") var pathnameIndex = protocolIndex > -1 ? url.indexOf("/", protocolIndex + 3) : url.indexOf("/")
var searchIndex = url.indexOf("?") var searchIndex = url.indexOf("?")
var hashIndex = url.indexOf("#") var hashIndex = url.indexOf("#")
if ((pathnameIndex > searchIndex && searchIndex > -1) || (pathnameIndex > hashIndex && hashIndex > -1)) pathnameIndex = -1 if ((pathnameIndex > searchIndex && searchIndex > -1) || (pathnameIndex > hashIndex && hashIndex > -1)) pathnameIndex = -1

View file

@ -4,7 +4,7 @@ var parseURL = require("../test-utils/parseURL")
module.exports = function(options) { module.exports = function(options) {
if (options == null) options = {} if (options == null) options = {}
var $window = options.window || {} var $window = options.window || {}
var protocol = options.protocol || "http:" var protocol = options.protocol || "http:"
var hostname = options.hostname || "localhost" var hostname = options.hostname || "localhost"
@ -33,7 +33,7 @@ module.exports = function(options) {
} }
return isNew return isNew
} }
function prefix(prefix, value) { function prefix(prefix, value) {
if (value === "") return "" if (value === "") return ""
return (value.charAt(0) !== prefix ? prefix : "") + value return (value.charAt(0) !== prefix ? prefix : "") + value

View file

@ -17,7 +17,7 @@ o.spec("browserMock", function() {
}) })
o("$window.onhashchange can be reached from the pushStateMock functions", function(done) { o("$window.onhashchange can be reached from the pushStateMock functions", function(done) {
$window.onhashchange = o.spy() $window.onhashchange = o.spy()
$window.location.hash = '#a' $window.location.hash = "#a"
callAsync(function(){ callAsync(function(){
o($window.onhashchange.callCount).equals(1) o($window.onhashchange.callCount).equals(1)
@ -33,7 +33,7 @@ o.spec("browserMock", function() {
}) })
o("$window.onunload can be reached from the pushStateMock functions", function() { o("$window.onunload can be reached from the pushStateMock functions", function() {
$window.onunload = o.spy() $window.onunload = o.spy()
$window.location.href = '/a' $window.location.href = "/a"
o($window.onunload.callCount).equals(1) o($window.onunload.callCount).equals(1)
}) })

View file

@ -4,51 +4,51 @@ var o = require("../../ospec/ospec")
var components = require("../../test-utils/components") var components = require("../../test-utils/components")
o.spec("test-utils/components", function() { o.spec("test-utils/components", function() {
var test = o.spy(function(component) { var test = o.spy(function(component) {
return function() { return function() {
o('works', function() { o("works", function() {
o(typeof component.kind).equals('string') o(typeof component.kind).equals("string")
var methods = {oninit: function(){}, view: function(){}} var methods = {oninit: function(){}, view: function(){}}
var cmp1, cmp2 var cmp1, cmp2
if (component.kind === "POJO") { if (component.kind === "POJO") {
cmp1 = component.create() cmp1 = component.create()
cmp2 = component.create(methods) cmp2 = component.create(methods)
} else if (component.kind === "constructible") { } else if (component.kind === "constructible") {
cmp1 = new (component.create()) cmp1 = new (component.create())
cmp2 = new (component.create(methods)) cmp2 = new (component.create(methods))
} else if (component.kind === "closure") { } else if (component.kind === "closure") {
cmp1 = component.create()() cmp1 = component.create()()
cmp2 = component.create(methods)() cmp2 = component.create(methods)()
} else { } else {
throw new Error("unexpected component kind") throw new Error("unexpected component kind")
} }
o(cmp1 != null).equals(true) o(cmp1 != null).equals(true)
o(typeof cmp1.view).equals("function") o(typeof cmp1.view).equals("function")
var vnode = cmp1.view() var vnode = cmp1.view()
o(vnode != null).equals(true) o(vnode != null).equals(true)
o(vnode).deepEquals({tag: "div"}) o(vnode).deepEquals({tag: "div"})
if (component.kind !== 'constructible') { if (component.kind !== "constructible") {
o(cmp2).deepEquals(methods) o(cmp2).deepEquals(methods)
} else { } else {
// deepEquals doesn't search the prototype, do it manually // deepEquals doesn't search the prototype, do it manually
o(cmp2 != null).equals(true) o(cmp2 != null).equals(true)
o(cmp2.view).equals(methods.view) o(cmp2.view).equals(methods.view)
o(cmp2.oninit).equals(methods.oninit) o(cmp2.oninit).equals(methods.oninit)
} }
}) })
} }
}) })
o.after(function(){ o.after(function(){
o(test.callCount).equals(3) o(test.callCount).equals(3)
}) })
components.forEach(function(component) { components.forEach(function(component) {
o.spec(component.kind, test(component)) o.spec(component.kind, test(component))
}) })
}) })

View file

@ -321,7 +321,7 @@ o.spec("domMock", function() {
o(div.getAttribute("id")).equals("aaa") o(div.getAttribute("id")).equals("aaa")
}) })
}) })
o.spec("setAttribute", function() { o.spec("setAttribute", function() {
o("works", function() { o("works", function() {
var div = $document.createElement("div") var div = $document.createElement("div")
@ -393,7 +393,6 @@ o.spec("domMock", function() {
o.spec("textContent", function() { o.spec("textContent", function() {
o("works", function() { o("works", function() {
var div = $document.createElement("div") var div = $document.createElement("div")
var a = $document.createElement("a")
div.textContent = "aaa" div.textContent = "aaa"
o(div.childNodes.length).equals(1) o(div.childNodes.length).equals(1)
@ -402,7 +401,6 @@ o.spec("domMock", function() {
}) })
o("works with empty string", function() { o("works with empty string", function() {
var div = $document.createElement("div") var div = $document.createElement("div")
var a = $document.createElement("a")
div.textContent = "" div.textContent = ""
o(div.childNodes.length).equals(0) o(div.childNodes.length).equals(0)
@ -514,8 +512,8 @@ o.spec("domMock", function() {
var div = $document.createElement("div") var div = $document.createElement("div")
div.style.cssText = "background: url(';'); font-family: \";\"" div.style.cssText = "background: url(';'); font-family: \";\""
o(div.style.background).equals("url(';')") o(div.style.background).equals("url(';')")
o(div.style.fontFamily).equals("\";\"") o(div.style.fontFamily).equals('";"')
o(div.style.cssText).equals("background: url(';'); font-family: \";\";") o(div.style.cssText).equals("background: url(';'); font-family: \";\";")
}) })
o("comments in style.cssText are stripped", function(){ o("comments in style.cssText are stripped", function(){
@ -534,9 +532,10 @@ o.spec("domMock", function() {
}) })
o("setting style throws", function () { o("setting style throws", function () {
var div = $document.createElement("div")
var err = false var err = false
try { try {
div.style = '' div.style = ""
} catch (e) { } catch (e) {
err = e err = e
} }
@ -919,55 +918,55 @@ o.spec("domMock", function() {
o.spec("canvas width and height", function() { o.spec("canvas width and height", function() {
o("setting property works", function() { o("setting property works", function() {
var canvas = $document.createElement("canvas") var canvas = $document.createElement("canvas")
canvas.width = 100 canvas.width = 100
o(canvas.attributes["width"].nodeValue).equals("100") o(canvas.attributes["width"].nodeValue).equals("100")
o(canvas.width).equals(100) o(canvas.width).equals(100)
canvas.height = 100 canvas.height = 100
o(canvas.attributes["height"].nodeValue).equals("100") o(canvas.attributes["height"].nodeValue).equals("100")
o(canvas.height).equals(100) o(canvas.height).equals(100)
}) })
o("setting string casts to number", function() { o("setting string casts to number", function() {
var canvas = $document.createElement("canvas") var canvas = $document.createElement("canvas")
canvas.width = "100" canvas.width = "100"
o(canvas.attributes["width"].nodeValue).equals("100") o(canvas.attributes["width"].nodeValue).equals("100")
o(canvas.width).equals(100) o(canvas.width).equals(100)
canvas.height = "100" canvas.height = "100"
o(canvas.attributes["height"].nodeValue).equals("100") o(canvas.attributes["height"].nodeValue).equals("100")
o(canvas.height).equals(100) o(canvas.height).equals(100)
}) })
o("setting float casts to int", function() { o("setting float casts to int", function() {
var canvas = $document.createElement("canvas") var canvas = $document.createElement("canvas")
canvas.width = 1.2 canvas.width = 1.2
o(canvas.attributes["width"].nodeValue).equals("1") o(canvas.attributes["width"].nodeValue).equals("1")
o(canvas.width).equals(1) o(canvas.width).equals(1)
canvas.height = 1.2 canvas.height = 1.2
o(canvas.attributes["height"].nodeValue).equals("1") o(canvas.attributes["height"].nodeValue).equals("1")
o(canvas.height).equals(1) o(canvas.height).equals(1)
}) })
o("setting percentage fails", function() { o("setting percentage fails", function() {
var canvas = $document.createElement("canvas") var canvas = $document.createElement("canvas")
canvas.width = "100%" canvas.width = "100%"
o(canvas.attributes["width"].nodeValue).equals("0") o(canvas.attributes["width"].nodeValue).equals("0")
o(canvas.width).equals(0) o(canvas.width).equals(0)
canvas.height = "100%" canvas.height = "100%"
o(canvas.attributes["height"].nodeValue).equals("0") o(canvas.attributes["height"].nodeValue).equals("0")
o(canvas.height).equals(0) o(canvas.height).equals(0)
}) })
o("setting attribute works", function() { o("setting attribute works", function() {
var canvas = $document.createElement("canvas") var canvas = $document.createElement("canvas")
canvas.setAttribute("width", "100%") canvas.setAttribute("width", "100%")
o(canvas.attributes["width"].nodeValue).equals("100%") o(canvas.attributes["width"].nodeValue).equals("100%")
o(canvas.width).equals(100) o(canvas.width).equals(100)
canvas.setAttribute("height", "100%") canvas.setAttribute("height", "100%")
o(canvas.attributes["height"].nodeValue).equals("100%") o(canvas.attributes["height"].nodeValue).equals("100%")
o(canvas.height).equals(100) o(canvas.height).equals(100)

View file

@ -168,13 +168,13 @@ o.spec("pushStateMock", function() {
}) })
o.spec("set protocol", function() { o.spec("set protocol", function() {
o("setting protocol throws", function(done) { o("setting protocol throws", function(done) {
var old = $window.location.href
try { try {
$window.location.protocol = "https://" $window.location.protocol = "https://"
} }
catch (e) { catch (e) {
done() return done()
} }
throw new Error("Expected an error")
}) })
}) })
o.spec("set port", function() { o.spec("set port", function() {
@ -413,17 +413,17 @@ o.spec("pushStateMock", function() {
}) })
o("replaceState does not break forward history", function() { o("replaceState does not break forward history", function() {
$window.onpopstate = o.spy() $window.onpopstate = o.spy()
$window.history.pushState(null, null, "b") $window.history.pushState(null, null, "b")
$window.history.back() $window.history.back()
o($window.onpopstate.callCount).equals(1) o($window.onpopstate.callCount).equals(1)
o($window.location.href).equals("http://localhost/") o($window.location.href).equals("http://localhost/")
$window.history.replaceState(null, null, "a") $window.history.replaceState(null, null, "a")
o($window.location.href).equals("http://localhost/a") o($window.location.href).equals("http://localhost/a")
$window.history.forward() $window.history.forward()
o($window.onpopstate.callCount).equals(2) o($window.onpopstate.callCount).equals(2)
@ -431,46 +431,46 @@ o.spec("pushStateMock", function() {
}) })
o("pushstate retains state", function() { o("pushstate retains state", function() {
$window.onpopstate = o.spy() $window.onpopstate = o.spy()
$window.history.pushState({a: 1}, null, "#a") $window.history.pushState({a: 1}, null, "#a")
$window.history.pushState({b: 2}, null, "#b") $window.history.pushState({b: 2}, null, "#b")
o($window.onpopstate.callCount).equals(0) o($window.onpopstate.callCount).equals(0)
$window.history.back() $window.history.back()
o($window.onpopstate.callCount).equals(1) o($window.onpopstate.callCount).equals(1)
o($window.onpopstate.args[0].type).equals("popstate") o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({a: 1}) o($window.onpopstate.args[0].state).deepEquals({a: 1})
$window.history.back() $window.history.back()
o($window.onpopstate.callCount).equals(2) o($window.onpopstate.callCount).equals(2)
o($window.onpopstate.args[0].type).equals("popstate") o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).equals(null) o($window.onpopstate.args[0].state).equals(null)
$window.history.forward() $window.history.forward()
o($window.onpopstate.callCount).equals(3) o($window.onpopstate.callCount).equals(3)
o($window.onpopstate.args[0].type).equals("popstate") o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({a: 1}) o($window.onpopstate.args[0].state).deepEquals({a: 1})
$window.history.forward() $window.history.forward()
o($window.onpopstate.callCount).equals(4) o($window.onpopstate.callCount).equals(4)
o($window.onpopstate.args[0].type).equals("popstate") o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({b: 2}) o($window.onpopstate.args[0].state).deepEquals({b: 2})
}) })
o("replacestate replaces state", function() { o("replacestate replaces state", function() {
$window.onpopstate = o.spy(pop) $window.onpopstate = o.spy(pop)
$window.history.replaceState({a: 1}, null, "a") $window.history.replaceState({a: 1}, null, "a")
o($window.history.state).deepEquals({a: 1}) o($window.history.state).deepEquals({a: 1})
$window.history.pushState(null, null, "a") $window.history.pushState(null, null, "a")
$window.history.back() $window.history.back()
function pop(e) { function pop(e) {
o(e.state).deepEquals({a: 1}) o(e.state).deepEquals({a: 1})
o($window.history.state).deepEquals({a: 1}) o($window.history.state).deepEquals({a: 1})

View file

@ -5,13 +5,13 @@ var xhrMock = require("../../test-utils/xhrMock")
var parseQueryString = require("../../querystring/parse") var parseQueryString = require("../../querystring/parse")
o.spec("xhrMock", function() { o.spec("xhrMock", function() {
var $window, ajax var $window
o.beforeEach(function() { o.beforeEach(function() {
$window = xhrMock() $window = xhrMock()
}) })
o.spec("xhr", function() { o.spec("xhr", function() {
o("works", function(done, timeout) { o("works", function(done) {
$window.$defineRoutes({ $window.$defineRoutes({
"GET /item": function(request) { "GET /item": function(request) {
o(request.url).equals("/item") o(request.url).equals("/item")
@ -29,7 +29,7 @@ o.spec("xhrMock", function() {
} }
xhr.send() xhr.send()
}) })
o("works w/ search", function(done, timeout) { o("works w/ search", function(done) {
$window.$defineRoutes({ $window.$defineRoutes({
"GET /item": function(request) { "GET /item": function(request) {
o(request.query).equals("?a=b") o(request.query).equals("?a=b")
@ -45,7 +45,7 @@ o.spec("xhrMock", function() {
} }
xhr.send() xhr.send()
}) })
o("works w/ body", function(done, timeout) { o("works w/ body", function(done) {
$window.$defineRoutes({ $window.$defineRoutes({
"POST /item": function(request) { "POST /item": function(request) {
o(request.body).equals("a=b") o(request.body).equals("a=b")
@ -61,7 +61,7 @@ o.spec("xhrMock", function() {
} }
xhr.send("a=b") xhr.send("a=b")
}) })
o("handles routing error", function(done, timeout) { o("handles routing error", function(done) {
var xhr = new $window.XMLHttpRequest() var xhr = new $window.XMLHttpRequest()
xhr.open("GET", "/nonexistent") xhr.open("GET", "/nonexistent")
xhr.onreadystatechange = function() { xhr.onreadystatechange = function() {
@ -113,7 +113,7 @@ o.spec("xhrMock", function() {
done() done()
} }
}) })
o("works with other querystring params", function(done, timeout) { o("works with other querystring params", function(done) {
$window.$defineRoutes({ $window.$defineRoutes({
"GET /test": function(request) { "GET /test": function(request) {
var queryData = parseQueryString(request.query) var queryData = parseQueryString(request.query)

View file

@ -6,7 +6,7 @@ var parseQueryString = require("../querystring/parse")
module.exports = function() { module.exports = function() {
var routes = {} var routes = {}
var callback = "callback" // var callback = "callback"
var serverErrorHandler = function(url) { var serverErrorHandler = function(url) {
return {status: 500, responseText: "server error, most likely the URL was not defined " + url} return {status: 500, responseText: "server error, most likely the URL was not defined " + url}
} }
@ -43,7 +43,6 @@ module.exports = function() {
} }
self.readyState = 4 self.readyState = 4
if (args.async === true) { if (args.async === true) {
var s = new Date
callAsync(function() { callAsync(function() {
if (typeof self.onreadystatechange === "function") self.onreadystatechange() if (typeof self.onreadystatechange === "function") self.onreadystatechange()
}) })
@ -64,7 +63,7 @@ module.exports = function() {
var urlData = parseURL(element.src, {protocol: "http:", hostname: "localhost", port: "", pathname: "/"}) var urlData = parseURL(element.src, {protocol: "http:", hostname: "localhost", port: "", pathname: "/"})
var handler = routes["GET " + urlData.pathname] || serverErrorHandler.bind(null, element.src) var handler = routes["GET " + urlData.pathname] || serverErrorHandler.bind(null, element.src)
var data = handler({url: urlData.pathname, query: urlData.search, body: null}) var data = handler({url: urlData.pathname, query: urlData.search, body: null})
var query = parseQueryString(urlData.search) parseQueryString(urlData.search)
callAsync(function() { callAsync(function() {
if (data.status === 200) { if (data.status === 200) {
new Function("$window", "with ($window) return " + data.responseText).call($window, $window) new Function("$window", "with ($window) return " + data.responseText).call($window, $window)
@ -83,8 +82,8 @@ module.exports = function() {
$defineRoutes: function(rules) { $defineRoutes: function(rules) {
routes = rules routes = rules
}, },
$defineJSONPCallbackKey: function(key) { $defineJSONPCallbackKey: function(/* key */) {
callback = key // callback = key
}, },
} }
return $window return $window

View file

@ -10,7 +10,7 @@ o.spec("api", function() {
o.beforeEach(function() { o.beforeEach(function() {
var mock = browserMock() var mock = browserMock()
if (typeof global !== "undefined") global.window = mock if (typeof global !== "undefined") global.window = mock
m = require("../mithril") m = require("../mithril") // eslint-disable-line global-require
}) })
o.spec("m", function() { o.spec("m", function() {
@ -174,4 +174,4 @@ o.spec("api", function() {
}) })
}) })
}) })
}) })