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
examples
docs
node_modules
tests
test-utils
ospec
mithril.js
mithril.min.js
archive
/node_modules
/examples
/docs/lib
/mithril.js
/mithril.min.js

View file

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

1
.gitignore vendored
View file

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

View file

@ -10,10 +10,10 @@ cache:
directories:
- 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:
- 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
before_script: npm run build
@ -21,37 +21,43 @@ before_script: npm run build
# This is the default, but leaving so it is obvious
# 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:
- |
# 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" ] && \
[ "$TRAVIS_BRANCH" == "$BRANCH" ] && \
[ "$TRAVIS_REPO_SLUG" == "$REPO" ]
[ "$TRAVIS_BRANCH" == "master" ] && \
[ "$TRAVIS_REPO_SLUG" == "lhorie/mithril.js" ]
then
# Set up SSH environment
$(npm bin)/set-up-ssh \
--key "$encrypted_8b86e0359d64_key" \
--iv "$encrypted_8b86e0359d64_iv" \
--path-encrypted-key "./.deploy.enc"
# Generate docs
$(npm-bin) run gendocs
# Commit changes (if there were any) from running build earlier
$(npm bin)/commit-changes \
--commands "echo committing" \
--commit-message "Bundled output for commit $TRAVIS_COMMIT [skip ci]" \
--branch "$BRANCH"
# Commit docs to gh-pages branch
# Using --add to ensure that archived versions aren't lost
# Using --repo to force it to go over SSH so the saved keys are used (tschaub/gh-pages#160)
$(npm bin)/gh-pages --dist ./dist --add --repo "git@github.com:lhorie/mithril.js.git"
else
echo "Not submitting build artifacts"
echo "Not submitting documentation updates"
fi
# Environment configuration
env:
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
- secure: Xvqvm3+PvJu/rs3jl/NNn0RWLkkLkIoPHiL0GCfVRaywgjCYVN02g54NVvIDaOfybqPmu9E6PJFVs92vhF34NMFQHf4EWskynusIGV271R2BV0i+OJBfLMuLgiwm6zRn7/Zw4JvWIUGEwcnlz0qxbqdHsS0SOR3fIkFzePickW0=
- secure: Rf/ldEO9d4vItJhe6EmqWpFAyCARzoCb422nHnjr1hYJknnwIXpgyZ1C/7On/9o7rWPPf+8WcHC/rgjK2rthKCldzdG5I60LfWSNzap9lk3Aa4TpSCoDBuEp7JVvDr5tc3rKnBXVT71hOay7RSx1StWzXiJs9mjaeVMJzYzRT78=

View file

@ -38,10 +38,10 @@ module.exports = function($window) {
var index = callbacks.indexOf(key)
if (index > -1) callbacks.splice(index, 2)
}
function redraw() {
for (var i = 1; i < callbacks.length; i += 2) {
callbacks[i]()
}
}
function redraw() {
for (var i = 1; i < callbacks.length; i += 2) {
callbacks[i]()
}
}
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) {
var onupdate = o.spy()
var oninit = o.spy()
var onclick = o.spy()
var oninit = o.spy()
var onclick = o.spy()
var e = $window.document.createEvent("MouseEvents")
e.initEvent("click", true, true)
@ -107,13 +107,13 @@ o.spec("mount", function() {
o("redraws several mount points on events", function(done, timeout) {
timeout(60)
var onupdate0 = o.spy()
var oninit0 = o.spy()
var onclick0 = o.spy()
var oninit0 = o.spy()
var onclick0 = o.spy()
var onupdate1 = o.spy()
var oninit1 = o.spy()
var onclick1 = o.spy()
var oninit1 = o.spy()
var onclick1 = o.spy()
var e = $window.document.createEvent("MouseEvents")
@ -228,7 +228,7 @@ o.spec("mount", function() {
done()
}, FRAME_BUDGET)
})
o("throttles", function(done, timeout) {
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 callAsync = require("../../test-utils/callAsync")
var coreRenderer = require("../../render/render")
var apiRedraw = require("../../api/redraw")
var apiRouter = require("../../api/router")
var Promise = require("../../promise/promise")
@ -31,7 +30,7 @@ o.spec("route", function() {
o("throws on invalid `root` DOM node", function() {
var threw = false
try {
route(null, '/', {'/':{view: function() {}}})
route(null, "/", {"/":{view: function() {}}})
} catch (e) {
threw = true
}
@ -141,7 +140,7 @@ o.spec("route", function() {
done()
}
})
o("redraws when render function is executed", function() {
var onupdate = o.spy()
var oninit = o.spy()
@ -206,7 +205,6 @@ o.spec("route", function() {
o("event handlers can skip redraw", function(done) {
var onupdate = o.spy()
var oninit = o.spy()
var onclick = o.spy()
var e = $window.document.createEvent("MouseEvents")
e.initEvent("click", true, true)
@ -354,11 +352,6 @@ o.spec("route", function() {
o("accepts RouteResolver with onmatch that returns Promise<undefined>", function(done) {
var matchCount = 0
var renderCount = 0
var Component = {
view: function() {
return m("span")
}
}
var resolver = {
onmatch: function(args, requestedPath) {
@ -395,11 +388,6 @@ o.spec("route", function() {
o("accepts RouteResolver with onmatch that returns Promise<any>", function(done) {
var matchCount = 0
var renderCount = 0
var Component = {
view: function() {
return m("span")
}
}
var resolver = {
onmatch: function(args, requestedPath) {
@ -437,14 +425,9 @@ o.spec("route", function() {
var matchCount = 0
var renderCount = 0
var spy = o.spy()
var Component = {
view: function() {
return m("span")
}
}
var resolver = {
onmatch: function(args, requestedPath) {
onmatch: function() {
matchCount++
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 Component = {
oninit: oninit,
@ -545,25 +528,19 @@ o.spec("route", function() {
})
o(root.firstChild.nodeName).equals("DIV")
o(renderCount).equals(1)
})
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"
route(root, "/a", {
"/a" : {
render: function(vnode) {
render: function() {
return m("div")
},
},
"/b" : {
render: function(vnode) {
render: function() {
return m("div")
},
},
@ -632,7 +609,7 @@ o.spec("route", function() {
onmatch: function() {
matchCount++
},
render: function(vnode) {
render: function() {
renderCount++
return {tag: Component}
},
@ -726,7 +703,7 @@ o.spec("route", function() {
render: render
},
"/b" : {
render: function(vnode){
render: function(){
redirected = true
}
}
@ -838,7 +815,7 @@ o.spec("route", function() {
})
callAsync(function() {
route.set('/b')
route.set("/b")
callAsync(function() {
callAsync(function() {
callAsync(function() {
@ -865,7 +842,7 @@ o.spec("route", function() {
render: render
},
"/b" : {
onmatch: function(vnode){
onmatch: function(){
redirected = true
return {view: function() {}}
}
@ -895,7 +872,7 @@ o.spec("route", function() {
render: render
},
"/b" : {
render: function(vnode){
render: function(){
redirected = true
}
}
@ -924,7 +901,7 @@ o.spec("route", function() {
render: render
},
"/b" : {
view: function(vnode){
view: function(){
redirected = true
}
}
@ -1032,7 +1009,7 @@ o.spec("route", function() {
var render = o.spy(function() {return m("div")})
$window.location.href = prefix + "/"
route(root, '/', {
route(root, "/", {
"/": {
onmatch: onmatch,
render: render
@ -1081,23 +1058,23 @@ o.spec("route", function() {
o("routing with RouteResolver works more than once", function(done) {
$window.location.href = prefix + "/a"
route(root, '/a', {
'/a': {
route(root, "/a", {
"/a": {
render: function() {
return m("a", "a")
}
},
'/b': {
"/b": {
render: function() {
return m("b", "b")
}
}
})
route.set('/b')
route.set("/b")
callAsync(function() {
route.set('/a')
route.set("/a")
callAsync(function() {
o(root.firstChild.nodeName).equals("A")
@ -1122,7 +1099,7 @@ o.spec("route", function() {
})
})
},
render: function(vnode) {
render: function() {
rendered = true
resolved = "a"
}
@ -1180,7 +1157,7 @@ o.spec("route", function() {
route.set("/b")
})
},
render: function(vnode) {
render: function() {
rendered = true
resolved = "a"
}
@ -1210,7 +1187,7 @@ o.spec("route", function() {
var i = 0
$window.location.href = prefix + "/"
route(root, "/", {
"/": {view: function(v) {i++}}
"/": {view: function() {i++}}
})
var before = i

View file

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

View file

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

View file

@ -1,3 +1,5 @@
"use strict"
var o = require("../../ospec/ospec")
var bundle = require("../bundle")
@ -5,10 +7,10 @@ var fs = require("fs")
var ns = "bundler/tests/"
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) {
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")
fs.writeFileSync(ns + filepath, data, "utf8")
}
@ -18,254 +20,255 @@ function remove(filepath) {
o.spec("bundler", function() {
o("relative imports works", function() {
write("a.js", `var b = require("./b")`)
write("b.js", `module.exports = 1`)
write("a.js", 'var b = require("./b")')
write("b.js", "module.exports = 1")
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("b.js")
remove("out.js")
})
o("relative imports works with semicolons", function() {
write("a.js", `var b = require("./b");`)
write("b.js", `module.exports = 1;`)
write("a.js", 'var b = require("./b");')
write("b.js", "module.exports = 1;")
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("b.js")
remove("out.js")
})
o("relative imports works with let", function() {
write("a.js", `let b = require("./b")`)
write("b.js", `module.exports = 1`)
write("a.js", 'let b = require("./b")')
write("b.js", "module.exports = 1")
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("b.js")
remove("out.js")
})
o("relative imports works with const", function() {
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")
o(read("out.js")).equals(`;(function() {\nconst b = 1\n}());`)
o(read("out.js")).equals(";(function() {\nconst b = 1\n}());")
remove("a.js")
remove("b.js")
remove("out.js")
})
o("relative imports works with assignment", function() {
write("a.js", `var a = {}\na.b = require("./b")`)
write("b.js", `module.exports = 1`)
write("a.js", 'var a = {}\na.b = require("./b")')
write("b.js", "module.exports = 1")
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("b.js")
remove("out.js")
})
o("relative imports works with reassignment", function() {
write("a.js", `var b = {}\nb = require("./b")`)
write("b.js", `module.exports = 1`)
write("a.js", 'var b = {}\nb = require("./b")')
write("b.js", "module.exports = 1")
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("b.js")
remove("out.js")
})
o("relative imports removes extra use strict", function() {
write("a.js", `"use strict"\nvar b = require("./b")`)
write("b.js", `"use strict"\nmodule.exports = 1`)
write("a.js", '"use strict"\nvar b = require("./b")')
write("b.js", '"use strict"\nmodule.exports = 1')
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("b.js")
remove("out.js")
})
o("relative imports removes extra use strict using single quotes", function() {
write("a.js", `'use strict'\nvar b = require("./b")`)
write("b.js", `'use strict'\nmodule.exports = 1`)
write("a.js", "'use strict'\nvar b = require(\"./b\")")
write("b.js", "'use strict'\nmodule.exports = 1")
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("b.js")
remove("out.js")
})
o("relative imports removes extra use strict using mixed quotes", function() {
write("a.js", `"use strict"\nvar b = require("./b")`)
write("b.js", `'use strict'\nmodule.exports = 1`)
write("a.js", '"use strict"\nvar b = require("./b")')
write("b.js", "'use strict'\nmodule.exports = 1")
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("b.js")
remove("out.js")
})
o("works w/ window", function() {
write("a.js", `window.a = 1\nvar b = require("./b")`)
write("b.js", `module.exports = function() {return a}`)
write("a.js", 'window.a = 1\nvar b = require("./b")')
write("b.js", "module.exports = function() {return a}")
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("b.js")
remove("out.js")
})
o("works without assignment", function() {
write("a.js", `require("./b")`)
write("b.js", `1 + 1`)
write("a.js", 'require("./b")')
write("b.js", "1 + 1")
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("b.js")
remove("out.js")
})
o("works if used fluently", function() {
write("a.js", `var b = require("./b").toString()`)
write("b.js", `module.exports = []`)
write("a.js", 'var b = require("./b").toString()')
write("b.js", "module.exports = []")
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("b.js")
remove("out.js")
})
o("works if used fluently w/ multiline", function() {
write("a.js", `var b = require("./b")\n\t.toString()`)
write("b.js", `module.exports = []`)
write("a.js", 'var b = require("./b")\n\t.toString()')
write("b.js", "module.exports = []")
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("b.js")
remove("out.js")
})
o("works if used w/ curry", function() {
write("a.js", `var b = require("./b")()`)
write("b.js", `module.exports = function() {}`)
write("a.js", 'var b = require("./b")()')
write("b.js", "module.exports = function() {}")
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("b.js")
remove("out.js")
})
o("works if used w/ curry w/ multiline", function() {
write("a.js", `var b = require("./b")\n()`)
write("b.js", `module.exports = function() {}`)
write("a.js", 'var b = require("./b")\n()')
write("b.js", "module.exports = function() {}")
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("b.js")
remove("out.js")
})
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("b.js", `module.exports = []`)
write("c.js", `var b = require("./b")\nmodule.exports = function() {return b}`)
write("a.js", 'var b = require("./b").toString()\nvar c = require("./c")')
write("b.js", "module.exports = []")
write("c.js", 'var b = require("./b")\nmodule.exports = function() {return b}')
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("b.js")
remove("c.js")
remove("out.js")
})
o("works if used in sequence", function() {
write("a.js", `var b = require("./b"), c = require("./c")`)
write("b.js", `module.exports = 1`)
write("c.js", `var x\nmodule.exports = 2`)
write("a.js", 'var b = require("./b"), c = require("./c")')
write("b.js", "module.exports = 1")
write("c.js", "var x\nmodule.exports = 2")
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("b.js")
remove("c.js")
remove("out.js")
})
o("works if assigned to property", function() {
write("a.js", `var x = {}\nx.b = require("./b")\nx.c = require("./c")`)
write("b.js", `var bb = 1\nmodule.exports = bb`)
write("c.js", `var cc = 2\nmodule.exports = cc`)
write("a.js", 'var x = {}\nx.b = require("./b")\nx.c = require("./c")')
write("b.js", "var bb = 1\nmodule.exports = bb")
write("c.js", "var cc = 2\nmodule.exports = cc")
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("b.js")
remove("c.js")
remove("out.js")
})
o("works if assigned to property using bracket notation", function() {
write("a.js", `var x = {}\nx["b"] = require("./b")\nx["c"] = require("./c")`)
write("b.js", `var bb = 1\nmodule.exports = bb`)
write("c.js", `var cc = 2\nmodule.exports = cc`)
write("a.js", 'var x = {}\nx["b"] = require("./b")\nx["c"] = require("./c")')
write("b.js", "var bb = 1\nmodule.exports = bb")
write("c.js", "var cc = 2\nmodule.exports = cc")
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("b.js")
remove("c.js")
remove("out.js")
})
o("works if collision", function() {
write("a.js", `var b = require("./b")`)
write("b.js", `var b = 1\nmodule.exports = 2`)
write("a.js", 'var b = require("./b")')
write("b.js", "var b = 1\nmodule.exports = 2")
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("b.js")
remove("out.js")
})
o("works if multiple aliases", function() {
write("a.js", `var b = require("./b")\n`)
write("b.js", `var b = require("./c")\nb.x = 1\nmodule.exports = b`)
write("c.js", `var b = {}\nmodule.exports = b`)
write("a.js", 'var b = require("./b")\n')
write("b.js", 'var b = require("./c")\nb.x = 1\nmodule.exports = b')
write("c.js", "var b = {}\nmodule.exports = b")
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("b.js")
remove("c.js")
remove("out.js")
})
o("works if multiple collision", function() {
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("c.js", `var a = 2\nmodule.exports = a`)
write("d.js", `var a = 3\nmodule.exports = a`)
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("c.js", "var a = 2\nmodule.exports = a")
write("d.js", "var a = 3\nmodule.exports = a")
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("b.js")
remove("c.js")
@ -273,38 +276,38 @@ o.spec("bundler", function() {
remove("out.js")
})
o("works if included multiple times", function() {
write("a.js", `module.exports = 123`)
write("b.js", `var a = require("./a").toString()\nmodule.exports = a`)
write("c.js", `var a = require("./a").toString()\nvar b = require("./b")`)
write("a.js", "module.exports = 123")
write("b.js", 'var a = require("./a").toString()\nmodule.exports = a')
write("c.js", 'var a = require("./a").toString()\nvar b = require("./b")')
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("b.js")
remove("c.js")
})
o("works if included multiple times reverse", function() {
write("a.js", `module.exports = 123`)
write("b.js", `var a = require("./a").toString()\nmodule.exports = a`)
write("c.js", `var b = require("./b")\nvar a = require("./a").toString()`)
write("a.js", "module.exports = 123")
write("b.js", 'var a = require("./a").toString()\nmodule.exports = a')
write("c.js", 'var b = require("./b")\nvar a = require("./a").toString()')
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("b.js")
remove("c.js")
})
o("reuses binding if possible", function() {
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("c.js", `var d = require("./d")\nmodule.exports = function() {return d + 2}`)
write("d.js", `module.exports = 1`)
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("c.js", 'var d = require("./d")\nmodule.exports = function() {return d + 2}')
write("d.js", "module.exports = 1")
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("b.js")
remove("c.js")
@ -312,71 +315,71 @@ o.spec("bundler", function() {
remove("out.js")
})
o("disambiguates conflicts if imported collides with itself", function() {
write("a.js", `var b = require("./b")`)
write("b.js", `var b = 1\nmodule.exports = function() {return b}`)
write("a.js", 'var b = require("./b")')
write("b.js", "var b = 1\nmodule.exports = function() {return b}")
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("b.js")
remove("out.js")
})
o("disambiguates conflicts if imported collides with something else", function() {
write("a.js", `var a = 1\nvar b = require("./b")`)
write("b.js", `var a = 2\nmodule.exports = function() {return a}`)
write("a.js", 'var a = 1\nvar b = require("./b")')
write("b.js", "var a = 2\nmodule.exports = function() {return a}")
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("b.js")
remove("out.js")
})
o("disambiguates conflicts if imported collides with function declaration", function() {
write("a.js", `function a() {}\nvar b = require("./b")`)
write("b.js", `var a = 2\nmodule.exports = function() {return a}`)
write("a.js", 'function a() {}\nvar b = require("./b")')
write("b.js", "var a = 2\nmodule.exports = function() {return a}")
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("b.js")
remove("out.js")
})
o("disambiguates conflicts if imported collides with another module's private", function() {
write("a.js", `var b = require("./b")\nvar c = require("./c")`)
write("b.js", `var a = 1\nmodule.exports = function() {return a}`)
write("c.js", `var a = 2\nmodule.exports = function() {return a}`)
write("a.js", 'var b = require("./b")\nvar c = require("./c")')
write("b.js", "var a = 1\nmodule.exports = function() {return a}")
write("c.js", "var a = 2\nmodule.exports = function() {return a}")
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("b.js")
remove("c.js")
remove("out.js")
})
o("does not mess up strings", function() {
write("a.js", `var b = require("./b")`)
write("b.js", `var b = "b b b \\\" b"\nmodule.exports = function() {return b}`)
write("a.js", 'var b = require("./b")')
write("b.js", 'var b = "b b b \\" b"\nmodule.exports = function() {return b}')
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("b.js")
remove("out.js")
})
o("does not mess up properties", function() {
write("a.js", `var b = require("./b")`)
write("b.js", `var b = {b: 1}\nmodule.exports = function() {return b.b}`)
write("a.js", 'var b = require("./b")')
write("b.js", "var b = {b: 1}\nmodule.exports = function() {return b.b}")
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("b.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 path = require("path")
var marked = require("marked")
var layout = fs.readFileSync("./docs/layout.html", "utf-8")
var version = JSON.parse(fs.readFileSync("./package.json", "utf-8")).version
try {fs.mkdirSync("../mithril")} catch (e) {}
try {fs.mkdirSync("../mithril/archive")} catch (e) {}
try {fs.mkdirSync("../mithril/archive/v" + version)} catch (e) {}
try {fs.mkdirSync("../mithril/archive/v" + version + "/lib")} catch (e) {}
try {fs.mkdirSync("../mithril/archive/v" + version + "/lib/prism")} catch (e) {}
try {fs.mkdirSync("../mithril/lib")} catch (e) {}
try {fs.mkdirSync("../mithril/lib/prism")} catch (e) {}
try {fs.mkdirSync("./dist")} catch (e) {/* ignore */}
try {fs.mkdirSync("./dist/archive")} catch (e) {/* ignore */}
try {fs.mkdirSync("./dist/archive/v" + version)} catch (e) {/* ignore */}
try {fs.mkdirSync("./dist/archive/v" + version + "/lib")} catch (e) {/* ignore */}
try {fs.mkdirSync("./dist/archive/v" + version + "/lib/prism")} catch (e) {/* ignore */}
try {fs.mkdirSync("./dist/lib")} catch (e) {/* ignore */}
try {fs.mkdirSync("./dist/lib/prism")} catch (e) {/* ignore */}
var guides = fs.readFileSync("docs/guides.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
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 link = new RegExp("([ \t]*)(- )(\\[.+?\\]\\(" + file + "\\))")
var replace = function(match, space, li, link) {
@ -53,14 +55,14 @@ function generate(pathname) {
.replace(/\[version\]/, version) // update version
.replace(/\[body\]/, markedHtml)
.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("../mithril/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
fs.writeFileSync("./dist/archive/v" + version + "/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
fs.writeFileSync("./dist/" + outputFilename.replace(/^docs\//, ""), html, "utf-8")
}
else if (!pathname.match(/lint|generate/)) {
fs.writeFileSync("../mithril/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/archive/v" + version + "/" + 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:
```jsx
m.mount(document.body, <MyComponent />)
// equivalent to m.mount(document.body, m(MyComponent))
m.render(document.body, <MyComponent />)
// equivalent to m.render(document.body, m(MyComponent))
```
---

View file

@ -1,4 +1,5 @@
#!/usr/bin/env node
"use strict"
var fs = require("fs")
var path = require("path")
@ -100,11 +101,11 @@ function ensureLinkIsValid(file, data) {
}
function initMocks() {
global.window = require("../test-utils/browserMock")()
global.window = require("../test-utils/browserMock")() // eslint-disable-line global-require
global.document = window.document
global.m = require("../index")
global.o = require("../ospec/ospec")
global.stream = require("../stream")
global.m = require("../index") // eslint-disable-line global-require
global.o = require("../ospec/ospec") // eslint-disable-line global-require
global.stream = require("../stream") // eslint-disable-line global-require
global.alert = function() {}
//routes consumed by request.md
@ -121,7 +122,7 @@ function initMocks() {
"GET /api/v1/todos": function() {
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 + "([])" : "[]"}
},
"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.
`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).
`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.
---
### Vnode types

View file

@ -38,7 +38,7 @@ var state = {
update: function(title) {
if (state.editing != null) {
state.editing.title = title.trim()
if (state.editing.title === "") destroy(state.editing)
if (state.editing.title === "") state.destroy(state.editing)
state.editing = null
}
},
@ -104,7 +104,7 @@ var Todos = {
m("label", {ondblclick: function() {state.dispatch("edit", [todo])}}, todo.title),
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")
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() {
"use strict"
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) {
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) {
var tag = vnode.tag
if (typeof tag === "string") {
vnode.state = {}
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
switch (tag) {
case "#": return createText(parent, vnode, nextSibling)
@ -597,7 +598,10 @@ var coreRenderer = function($window) {
if (!recycling && shouldNotUpdate(vnode, old)) return
if (typeof oldTag === "string") {
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)
}
switch (oldTag) {
@ -990,11 +994,11 @@ var _11 = function($window) {
var index = callbacks.indexOf(key1)
if (index > -1) callbacks.splice(index, 2)
}
function redraw() {
for (var i = 1; i < callbacks.length; i += 2) {
callbacks[i]()
}
}
function redraw() {
for (var i = 1; i < callbacks.length; i += 2) {
callbacks[i]()
}
}
return {subscribe: subscribe, unsubscribe: unsubscribe, redraw: redraw, render: renderService.render}
}
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]&&
((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.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&&
(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,
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");
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"!==
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=
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,
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=
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 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
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",
"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,
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==
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,
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.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.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}
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==
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.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=
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,
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.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=
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));
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,
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}
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,
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"===
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&&
!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"!==
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"===
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"===
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]();
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"!==
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=
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+
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={};
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,
"(.*?)").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");
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!=
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,
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})();
(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):"["===
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,
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()):
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,
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(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 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<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(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(){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(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 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");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),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==
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,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?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,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 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,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)-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&&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,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 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==
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):
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?
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;
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=
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),
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)&&
"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
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||"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&&
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=
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);
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();
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:
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,
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("^"+
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(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!=
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,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")
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
```
#### 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
"use strict"
var fs = require("fs")
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$/)) {
require(path.normalize(process.cwd()) + "/" + pathname)
require(path.normalize(process.cwd()) + "/" + pathname) // eslint-disable-line global-require
}
})
.then(o.run)

View file

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

View file

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

View file

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

View file

@ -57,7 +57,7 @@ o.spec("promise", function() {
o.spec("resolve", function() {
o("resolves once", function(done) {
var callCount = 0
var promise = new Promise(function(resolve, reject) {
var promise = new Promise(function(resolve) {
resolve(1)
resolve(2)
callAsync(function() {resolve(3)})
@ -89,7 +89,7 @@ o.spec("promise", function() {
var promise = Promise.resolve()
state = 1
promise.then(function(value) {
promise.then(function() {
o(state).equals(2)
done()
})
@ -104,7 +104,7 @@ o.spec("promise", function() {
})
})
o("resolves asynchronously via executor", function(done) {
var promise = new Promise(function(resolve, reject) {
var promise = new Promise(function(resolve) {
callAsync(function() {resolve(1)})
})
@ -185,7 +185,7 @@ o.spec("promise", function() {
var promise = Promise.reject()
state = 1
promise.then(null, function(value) {
promise.then(null, function() {
o(state).equals(2)
done()
})
@ -232,7 +232,7 @@ o.spec("promise", function() {
})
})
o("rejects via executor on error", function(done) {
var promise = new Promise(function(resolve, reject) {
var promise = new Promise(function() {
throw 1
})
@ -281,7 +281,7 @@ o.spec("promise", function() {
}).then(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)
resolve(p)
})
@ -310,7 +310,7 @@ o.spec("promise", function() {
})
})
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))
})
@ -330,7 +330,7 @@ o.spec("promise", function() {
})
})
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)
})
var promise = Promise.resolve(pending)
@ -341,10 +341,10 @@ o.spec("promise", function() {
})
})
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)
})
var promise = new Promise(function(resolve, reject) {
var promise = new Promise(function(resolve) {
resolve(pending)
})
@ -354,7 +354,7 @@ o.spec("promise", function() {
})
})
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)
})
var promise = Promise.resolve()
@ -381,7 +381,7 @@ o.spec("promise", function() {
var pending = new Promise(function(resolve, reject) {
setTimeout(function() {reject(1)}, 10)
})
var promise = new Promise(function(resolve, reject) {
var promise = new Promise(function(resolve) {
resolve(pending)
})
@ -521,7 +521,7 @@ o.spec("promise", function() {
o.spec("race", function() {
o("resolves to first resolved", function(done) {
var a = Promise.resolve(1)
var b = new Promise(function(resolve, reject) {
var b = new Promise(function(resolve) {
callAsync(function() {resolve(2)})
})
Promise.race([a, b]).then(function(value) {
@ -542,7 +542,7 @@ o.spec("promise", function() {
})
o.spec("all", function() {
o("resolves to array", function(done) {
var a = new Promise(function(resolve, reject) {
var a = new Promise(function(resolve) {
callAsync(function() {resolve(1)})
})
var b = Promise.resolve(2)
@ -558,7 +558,7 @@ o.spec("promise", function() {
})
})
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)})
})
var b = Promise.resolve(2)
@ -584,18 +584,18 @@ o.spec("promise", function() {
var readCount = 0
var promise = Promise.resolve(1).then(function() {
return Object.create(null, {
then: {
get: function () {
++readCount
return function(onFulfilled) {
onFulfilled()
}
}
}
})
then: {
get: function () {
++readCount
return function(onFulfilled) {
onFulfilled()
}
}
}
})
})
promise.then(function(value) {
promise.then(function() {
o(readCount).equals(1)
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) {
var tag = vnode.tag
if (typeof tag === "string") {
vnode.state = {}
if (vnode.attrs != null) initLifecycle(vnode.attrs, vnode, hooks)
switch (tag) {
case "#": return createText(parent, vnode, nextSibling)
@ -238,7 +239,10 @@ module.exports = function($window) {
if (!recycling && shouldNotUpdate(vnode, old)) return
if (typeof oldTag === "string") {
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)
}
switch (oldTag) {

View file

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

View file

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

View file

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

View file

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

View file

@ -17,7 +17,6 @@ o.spec("onbeforeremove", function() {
o("does not call onbeforeremove when creating", function() {
var create = o.spy()
var update = o.spy()
var vnode = {tag: "div", attrs: {onbeforeremove: create}}
render(root, [vnode])
@ -142,7 +141,7 @@ o.spec("onbeforeremove", function() {
o(vnode.dom.attributes["onbeforeremove"]).equals(undefined)
})
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 updated = {tag: "div", key: 1, attrs: {onbeforeremove: remove}}
@ -153,7 +152,7 @@ o.spec("onbeforeremove", function() {
o(vnode.dom).notEquals(updated.dom)
})
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 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() {
var count = 0
var vnode = {tag: "div", attrs: {id: "a", onbeforeupdate: onbeforeupdate}}
var updated = {tag: "div", attrs: {id: "b", onbeforeupdate: onbeforeupdate}}
render(root, [vnode])
function onbeforeupdate(vnode, old) {
function onbeforeupdate() {
count++
return true
}
@ -112,7 +111,7 @@ o.spec("onbeforeupdate", function() {
render(root, [vnode])
render(root, [updated])
function onbeforeupdate(vnode, old) {
function onbeforeupdate() {
count++
return true
}
@ -263,7 +262,7 @@ o.spec("onbeforeupdate", function() {
})
o("is not called on component creation", function() {
var component = createComponent({
createComponent({
onbeforeupdate: onbeforeupdate,
view: function(vnode) {
return {tag: "div", attrs: vnode.attrs}
@ -272,11 +271,10 @@ o.spec("onbeforeupdate", function() {
var count = 0
var vnode = {tag: "div", attrs: {id: "a"}}
var updated = {tag: "div", attrs: {id: "b"}}
render(root, [vnode])
function onbeforeupdate(vnode, old) {
function onbeforeupdate() {
count++
return true
}
@ -299,7 +297,7 @@ o.spec("onbeforeupdate", function() {
render(root, [vnode])
render(root, [updated])
function onbeforeupdate(vnode, old) {
function onbeforeupdate() {
count++
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() {
var create = o.spy()
var update = o.spy()
var vnode = {tag: "div", attrs: {oncreate: create}, state: {}}
render(root, [vnode])

View file

@ -128,7 +128,6 @@ o.spec("oninit", function() {
})
o("does not call oninit when removing", function() {
var create = o.spy()
var update = o.spy()
var vnode = {tag: "div", attrs: {oninit: create}, state: {}}
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() {
var create = o.spy()
var update = o.spy()
var vnode = {tag: "a", attrs: {onupdate: create}}
var updated = {tag: "a"}

View file

@ -1,7 +1,6 @@
"use strict"
var o = require("../../ospec/ospec")
var components = require("../../test-utils/components")
var domMock = require("../../test-utils/domMock")
var vdom = require("../../render/render")
@ -124,7 +123,7 @@ o.spec("render", function() {
var onbeforeupdate = o.spy()
function A() {
return {
view: function(vnode) {throw new Error("error")},
view: function() {throw new Error("error")},
oninit: oninit,
onbeforeupdate: onbeforeupdate
}
@ -143,11 +142,11 @@ o.spec("render", function() {
o(onbeforeupdate.callCount).equals(0)
})
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()
function A() {
return {
view: function(vnode) {},
view: function() {},
oninit: oninit,
onbeforeupdate: onbeforeupdate
}

View file

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

View file

@ -727,7 +727,7 @@ o.spec("updateNodes", function() {
})
o("change type, position and length", function() {
var vnodes = {tag: "div", children: [
undefined,
undefined,
{tag: "#", children: "a"}
]}
var updated = {tag: "div", children: [
@ -738,7 +738,7 @@ o.spec("updateNodes", function() {
render(root, vnodes)
render(root, updated)
o(root.firstChild.childNodes.length).equals(1)
})
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 temp = [null, {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)
var before = vnodes[1].dom
render(root, temp)
render(root, updated)
var after = updated[1].dom
o(before).equals(after)
o(create.callCount).equals(1)
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 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}}]
render(root, vnodes)
var before = vnodes[2].dom
render(root, temp)
render(root, updated)
var after = updated[2].dom
o(before).equals(after)
o(create.callCount).equals(1)
o(update.callCount).equals(2)
@ -898,11 +898,10 @@ o.spec("updateNodes", function() {
o("node is recreated if key changes to undefined", function () {
var vnode = {tag: "b", key: 1}
var updated = {tag: "b"}
render(root, vnode)
var dom = vnode.dom
render(root, updated)
o(vnode.dom).notEquals(updated.dom)
})
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) {
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) {
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")
module.exports = require("./request/request")(window, PromisePolyfill)

View file

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

View file

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

View file

@ -1,3 +1,5 @@
"use strict"
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() {
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() {
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("11")
parent(undefined)
parent({ a: 1 })
parent({a: 1})
var result = child()
// deepEquals fails on arrays?
@ -32,4 +32,3 @@ o.spec("scan", function() {
o(result[3]).deepEquals({a: 1})
})
})

View file

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

View file

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

View file

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

View file

@ -3,7 +3,7 @@
module.exports = function parseURL(url, root) {
var data = {}
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 hashIndex = url.indexOf("#")
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) {
if (options == null) options = {}
var $window = options.window || {}
var protocol = options.protocol || "http:"
var hostname = options.hostname || "localhost"
@ -33,7 +33,7 @@ module.exports = function(options) {
}
return isNew
}
function prefix(prefix, value) {
if (value === "") return ""
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) {
$window.onhashchange = o.spy()
$window.location.hash = '#a'
$window.location.hash = "#a"
callAsync(function(){
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() {
$window.onunload = o.spy()
$window.location.href = '/a'
$window.location.href = "/a"
o($window.onunload.callCount).equals(1)
})

View file

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

View file

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

View file

@ -168,13 +168,13 @@ o.spec("pushStateMock", function() {
})
o.spec("set protocol", function() {
o("setting protocol throws", function(done) {
var old = $window.location.href
try {
$window.location.protocol = "https://"
}
catch (e) {
done()
return done()
}
throw new Error("Expected an error")
})
})
o.spec("set port", function() {
@ -413,17 +413,17 @@ o.spec("pushStateMock", function() {
})
o("replaceState does not break forward history", function() {
$window.onpopstate = o.spy()
$window.history.pushState(null, null, "b")
$window.history.back()
o($window.onpopstate.callCount).equals(1)
o($window.location.href).equals("http://localhost/")
$window.history.replaceState(null, null, "a")
o($window.location.href).equals("http://localhost/a")
$window.history.forward()
o($window.onpopstate.callCount).equals(2)
@ -431,46 +431,46 @@ o.spec("pushStateMock", function() {
})
o("pushstate retains state", function() {
$window.onpopstate = o.spy()
$window.history.pushState({a: 1}, null, "#a")
$window.history.pushState({b: 2}, null, "#b")
o($window.onpopstate.callCount).equals(0)
$window.history.back()
o($window.onpopstate.callCount).equals(1)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({a: 1})
$window.history.back()
o($window.onpopstate.callCount).equals(2)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).equals(null)
$window.history.forward()
o($window.onpopstate.callCount).equals(3)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({a: 1})
$window.history.forward()
o($window.onpopstate.callCount).equals(4)
o($window.onpopstate.args[0].type).equals("popstate")
o($window.onpopstate.args[0].state).deepEquals({b: 2})
})
o("replacestate replaces state", function() {
$window.onpopstate = o.spy(pop)
$window.history.replaceState({a: 1}, null, "a")
o($window.history.state).deepEquals({a: 1})
$window.history.pushState(null, null, "a")
$window.history.back()
function pop(e) {
o(e.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")
o.spec("xhrMock", function() {
var $window, ajax
var $window
o.beforeEach(function() {
$window = xhrMock()
})
o.spec("xhr", function() {
o("works", function(done, timeout) {
o("works", function(done) {
$window.$defineRoutes({
"GET /item": function(request) {
o(request.url).equals("/item")
@ -29,7 +29,7 @@ o.spec("xhrMock", function() {
}
xhr.send()
})
o("works w/ search", function(done, timeout) {
o("works w/ search", function(done) {
$window.$defineRoutes({
"GET /item": function(request) {
o(request.query).equals("?a=b")
@ -45,7 +45,7 @@ o.spec("xhrMock", function() {
}
xhr.send()
})
o("works w/ body", function(done, timeout) {
o("works w/ body", function(done) {
$window.$defineRoutes({
"POST /item": function(request) {
o(request.body).equals("a=b")
@ -61,7 +61,7 @@ o.spec("xhrMock", function() {
}
xhr.send("a=b")
})
o("handles routing error", function(done, timeout) {
o("handles routing error", function(done) {
var xhr = new $window.XMLHttpRequest()
xhr.open("GET", "/nonexistent")
xhr.onreadystatechange = function() {
@ -113,7 +113,7 @@ o.spec("xhrMock", function() {
done()
}
})
o("works with other querystring params", function(done, timeout) {
o("works with other querystring params", function(done) {
$window.$defineRoutes({
"GET /test": function(request) {
var queryData = parseQueryString(request.query)

View file

@ -6,7 +6,7 @@ var parseQueryString = require("../querystring/parse")
module.exports = function() {
var routes = {}
var callback = "callback"
// var callback = "callback"
var serverErrorHandler = function(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
if (args.async === true) {
var s = new Date
callAsync(function() {
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 handler = routes["GET " + urlData.pathname] || serverErrorHandler.bind(null, element.src)
var data = handler({url: urlData.pathname, query: urlData.search, body: null})
var query = parseQueryString(urlData.search)
parseQueryString(urlData.search)
callAsync(function() {
if (data.status === 200) {
new Function("$window", "with ($window) return " + data.responseText).call($window, $window)
@ -83,8 +82,8 @@ module.exports = function() {
$defineRoutes: function(rules) {
routes = rules
},
$defineJSONPCallbackKey: function(key) {
callback = key
$defineJSONPCallbackKey: function(/* key */) {
// callback = key
},
}
return $window

View file

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