Add meta description to docs

This commit is contained in:
Stephan Hoyer 2018-11-27 23:50:45 +01:00
parent c7b56161a5
commit 7b1fda5b66
47 changed files with 540 additions and 267 deletions

View file

@ -18,7 +18,7 @@ mithril.js [![npm Version](https://img.shields.io/npm/v/mithril.svg)](https://ww
## What is Mithril? ## What is Mithril?
A modern client-side JavaScript framework for building Single Page Applications. It's small (<!-- size -->9.79 KB<!-- /size --> gzipped), fast and provides routing and XHR utilities out of the box. A modern client-side JavaScript framework for building Single Page Applications. It's small (<!-- size -->10.04 KB<!-- /size --> gzipped), fast and provides routing and XHR utilities out of the box.
Mithril is used by companies like Vimeo and Nike, and open source platforms like Lichess 👍. Mithril is used by companies like Vimeo and Nike, and open source platforms like Lichess 👍.

View file

@ -1,3 +1,7 @@
<!--meta-description
Approaches you can use to animate your Mithril.js-based apps, including technology and performance suggestions
-->
# Animations # Animations
- [Technology choices](#technology-choices) - [Technology choices](#technology-choices)

View file

@ -1,3 +1,7 @@
<!--meta-description
An API cheatsheet for Mithril.js
-->
# API # API
### Cheatsheet ### Cheatsheet

View file

@ -1,3 +1,7 @@
<!--meta-description
The Mithril.js auto-redraw system re-renders your app after some functions complete. Here, we describe the idiomatic Mithril.js patterns that trigger those redraws.
-->
# The auto-redraw system # The auto-redraw system
Mithril implements a virtual DOM diffing system for fast rendering, and in addition, it offers various mechanisms to gain granular control over the rendering of an application. Mithril implements a virtual DOM diffing system for fast rendering, and in addition, it offers various mechanisms to gain granular control over the rendering of an application.

View file

@ -1,3 +1,6 @@
<!--meta-description
Documentation on m.buildPathname(), which creates URLs from path templates and query objects
-->
# buildPathname(object) # buildPathname(object)
- [Description](#description) - [Description](#description)
@ -11,7 +14,7 @@
Turns a [path template](paths.md) and a parameters object into a string of form `/path/user?a=1&b=2` Turns a [path template](paths.md) and a parameters object into a string of form `/path/user?a=1&b=2`
```javascript ```javascript
var querystring = m.buildPathname("/path/:id", {id: "user", a: "1", b: "2"}) var pathname = m.buildPathname("/path/:id", {id: "user", a: "1", b: "2"})
// "/path/user?a=1&b=2" // "/path/user?a=1&b=2"
``` ```
@ -19,12 +22,13 @@ var querystring = m.buildPathname("/path/:id", {id: "user", a: "1", b: "2"})
### Signature ### Signature
`querystring = m.buildPathname(object)` `pathname = m.buildPathname(object)`
Argument | Type | Required | Description Argument | Type | Required | Description
------------ | ------------------------------------------ | -------- | --- ------------ | ------------------------------------------ | -------- | ---
`object` | `Object` | Yes | A key-value map to be converted into a string `path` | `String` | Yes | A URL path
**returns** | `String` | | A string representing the input object `query ` | `Object` | Yes | A key-value map to be converted into a string
**returns** | `String` | | A string representing the URL with the query string
[How to read signatures](signatures.md) [How to read signatures](signatures.md)
@ -35,7 +39,7 @@ Argument | Type | Required | Descripti
The `m.buildPathname` creates a [path name](paths.md) from a path template and a parameters object. It's useful for building URLs, and it's what [`m.route`](route.md), [`m.request`](request.md), and [`m.jsonp`](jsonp.md) all use internally to interpolate paths. It uses [`m.buildQueryString`](buildQueryString.md) to generate the query parameters to append to the path name. The `m.buildPathname` creates a [path name](paths.md) from a path template and a parameters object. It's useful for building URLs, and it's what [`m.route`](route.md), [`m.request`](request.md), and [`m.jsonp`](jsonp.md) all use internally to interpolate paths. It uses [`m.buildQueryString`](buildQueryString.md) to generate the query parameters to append to the path name.
```javascript ```javascript
var querystring = m.buildPathname("/path/:id", {id: "user", a: 1, b: 2}) var pathname = m.buildPathname("/path/:id", {id: "user", a: 1, b: 2})
// querystring is "/path/user?a=1&b=2" // pathname is "/path/user?a=1&b=2"
``` ```

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.buildQueryString(), which converts an object like {a: "1", b: "2"} into a string like "a=1&b=2"
-->
# buildQueryString(object) # buildQueryString(object)
- [Description](#description) - [Description](#description)
@ -23,7 +27,7 @@ var querystring = m.buildQueryString({a: "1", b: "2"})
Argument | Type | Required | Description Argument | Type | Required | Description
------------ | ------------------------------------------ | -------- | --- ------------ | ------------------------------------------ | -------- | ---
`object` | `Object` | Yes | A key-value map to be converted into a string `query` | `Object` | Yes | A key-value map to be converted into a string
**returns** | `String` | | A string representing the input object **returns** | `String` | | A string representing the input object
[How to read signatures](signatures.md) [How to read signatures](signatures.md)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.censor(), which helps cloning vnodes
-->
# censor(object, extra) # censor(object, extra)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,6 @@
<!--meta-description
Official change log for Mithril.js
-->
# Change log # Change log
- [v2.0.4](#v204) - [v2.0.4](#v204)

View file

@ -1,3 +1,7 @@
<!--meta-description
Code of Conduct Covenant for contributors to the Mithril.js project
-->
# Contributor Covenant Code of Conduct # Contributor Covenant Code of Conduct
## Our Pledge ## Our Pledge

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on the structure, lifecycle methods, state management, and syntactic variants of components in Mithril.js
-->
# Components # Components
- [Structure](#structure) - [Structure](#structure)

View file

@ -1,3 +1,6 @@
<!--meta-description
Contribution guide for Mithril.js
-->
# Contributing FAQs # Contributing FAQs
- [How do I go about contributing ideas or new features?](#how-do-i-go-about-contributing-ideas-or-new-features?) - [How do I go about contributing ideas or new features?](#how-do-i-go-about-contributing-ideas-or-new-features?)

View file

@ -1,3 +1,7 @@
<!--meta-description
List of especially notable contributors to Mithril.js
-->
# Credits # Credits
Mithril was originally written by Leo Horie, but it is where it is today thanks to the hard work and great ideas of many people. Mithril was originally written by Leo Horie, but it is where it is today thanks to the hard work and great ideas of many people.

View file

@ -1,3 +1,6 @@
<!--meta-description
Approaches you can use to integrate ES6 into your Mithril.js-based apps, including technology and usability suggestions
-->
# ES6+ on legacy browsers # ES6+ on legacy browsers
- [Setup](#setup) - [Setup](#setup)

View file

@ -1,3 +1,7 @@
<!--meta-description
Some examples on how you can use MithrilJS
-->
# Examples # Examples
Here are some examples of Mithril in action Here are some examples of Mithril in action

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.fragment(), which allows attaching lifecycle methods and keys to a fragment vnode
-->
# fragment(attrs, children) # fragment(attrs, children)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Detailed comparison between Mithril.js and other popular frameworks
-->
# Framework comparison # Framework comparison
- [Why not X?](#why-not-insert-favorite-framework-here?) - [Why not X?](#why-not-insert-favorite-framework-here?)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m(), Mithril.js' hyperscript DSL, which you can use to define the views of your app
-->
# m(selector, attributes, children) # m(selector, attributes, children)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Mithril.js is a modern, small, fast client-side Javascript framework for building Single Page Applications.
-->
# Introduction # Introduction
- [What is Mithril?](#what-is-mithril?) - [What is Mithril?](#what-is-mithril?)

View file

@ -1,3 +1,7 @@
<!--meta-description
Instructions on how to install Mithril.js
-->
# Installation # Installation
- [CDN](#cdn) - [CDN](#cdn)

View file

@ -1,3 +1,7 @@
<!--meta-description
How you can integrate a third party library into a Mithril.js application, using lifecycle methods.
-->
# 3rd Party Integration # 3rd Party Integration
Integration with third party libraries or vanilla JavaScript code can be achieved via [lifecycle methods](lifecycle-methods.md). Integration with third party libraries or vanilla JavaScript code can be achieved via [lifecycle methods](lifecycle-methods.md).

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.jsonp(), a utility to fetch data from JSONP APIs
-->
# jsonp(options) # jsonp(options)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Explanation, examples, and build notes on how to use JSX in your MithrilJS-apps
-->
# JSX # JSX
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on the special "key" attribute in Mithril, which tracks vnodes' identities
-->
# Keys # Keys
- [What are keys?](#what-are-keys?) - [What are keys?](#what-are-keys?)

View file

@ -1,5 +1,5 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<title>Mithril.js</title> <title>Mithril.js</title>
@ -8,6 +8,7 @@
<link href="style.css" rel="stylesheet" /> <link href="style.css" rel="stylesheet" />
<link rel="icon" type="image/png" sizes="32x32" href="favicon.png" /> <link rel="icon" type="image/png" sizes="32x32" href="favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content="[metaDescription]">
</head> </head>
<body onload="window.requestAnimationFrame(function(){document.getElementById('archive-docs').selectedIndex = 0})" /* handle back navigation */> <body onload="window.requestAnimationFrame(function(){document.getElementById('archive-docs').selectedIndex = 0})" /* handle back navigation */>
<header> <header>

View file

@ -1,3 +1,7 @@
<!--meta-description
Links to Mithril.js learning content
-->
# Learning Resources # Learning Resources
Links to Mithril learning content: Links to Mithril learning content:

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on Mithril.js' lifecycle methods/"hooks"
-->
# Lifecycle methods # Lifecycle methods
- [Usage](#usage) - [Usage](#usage)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.mount(), which binds a Mithril component to a given DOM node
-->
# mount(root, component) # mount(root, component)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,6 @@
<!--meta-description
Documentation on m.parsePathname(), which parses URLs to path and query object
-->
# parsePathname(string) # parsePathname(string)
- [Description](#description) - [Description](#description)
@ -23,7 +26,7 @@ var object = m.parsePathname("/path/user?a=1&b=2")
Argument | Type | Required | Description Argument | Type | Required | Description
------------ | -------- | -------- | --- ------------ | -------- | -------- | ---
`string` | `String` | Yes | A URL `url` | `String` | Yes | A URL
**returns** | `Object` | | A `{path, params}` pair where `path` is the [normalized path](paths.md#path-normalization) and `params` is the [parsed parameters](paths.md#parameter-normalization). **returns** | `Object` | | A `{path, params}` pair where `path` is the [normalized path](paths.md#path-normalization) and `params` is the [parsed parameters](paths.md#parameter-normalization).
[How to read signatures](signatures.md) [How to read signatures](signatures.md)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.parseQueryString(), which converts a string like "a=1&b=2" into an object like {a: "1", b: "2"}
-->
# parseQueryString(string) # parseQueryString(string)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,6 @@
<!--meta-description
Documentation on how to work with paths in Mithril.js
-->
# Path Handling # Path Handling
- [Path types](#path-types) - [Path types](#path-types)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on Mithril.js' Promise polyfill
-->
# Promise(executor) # Promise(executor)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.redraw(), which schedules an update of all components mounted via m.mount()
-->
# redraw() # redraw()
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Describes how we do releases of Mithril.js
-->
# Mithril Release Processes # Mithril Release Processes
**Note** These steps all assume that `MithrilJS/mithril.js` is a git remote named `mithriljs`, adjust accordingly if that doesn't match your setup. **Note** These steps all assume that `MithrilJS/mithril.js` is a git remote named `mithriljs`, adjust accordingly if that doesn't match your setup.

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.render(), which Mithril.js uses to efficiently patch real DOM trees with virtual DOM nodes
-->
# render(element, vnodes) # render(element, vnodes)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.request(), a utility for making XHR/AJAX requests
-->
# request(options) # request(options)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.route(), Mithril.js' client-side router
-->
# route(root, defaultRoute, routes) # route(root, defaultRoute, routes)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Describes, how to read the signatures in Mithril.js' documentation.
-->
# How to read signatures # How to read signatures
Signature sections typically look like this: Signature sections typically look like this:

View file

@ -1,3 +1,7 @@
<!--meta-description
A complete walkthrough tutorial for building your first simple application in Mithril, from beginning to end
-->
# Simple application # Simple application
Let's develop a simple application that shows off how to do most of the major things you would need to deal with while using Mithril. Let's develop a simple application that shows off how to do most of the major things you would need to deal with while using Mithril.

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.stream(), a reactive data structure provided optionally within Mithril.js
-->
# stream() # stream()
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Where to find help with problems related to MithrilJS
-->
# Getting Help # Getting Help
Mithril has an active & welcoming community on [Gitter](https://gitter.im/mithriljs/mithril.js), or feel free to ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/mithril.js) using the `mithril.js` tag. Mithril has an active & welcoming community on [Gitter](https://gitter.im/mithriljs/mithril.js), or feel free to ask questions on [Stack Overflow](https://stackoverflow.com/questions/tagged/mithril.js) using the `mithril.js` tag.

View file

@ -1,3 +1,7 @@
<!--meta-description
Approaches you can use to testing your Mithril.js-based apps, including technology and usability suggestions
-->
# Testing # Testing
- [Setup](#setup) - [Setup](#setup)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on m.trust(), a utility for rendering raw HTML and SVG within Mithril, along with tips on when to (and not to) use it
-->
# trust(html) # trust(html)
- [Description](#description) - [Description](#description)

View file

@ -1,3 +1,7 @@
<!--meta-description
Documentation on Mithril.js' virtual DOM nodes (vnodes) and how they work
-->
# Virtual DOM nodes # Virtual DOM nodes
- [What is virtual DOM](#what-is-virtual-dom) - [What is virtual DOM](#what-is-virtual-dom)

View file

@ -1,7 +1,7 @@
;(function() { ;(function() {
"use strict" "use strict"
function Vnode(tag, key, attrs0, children0, text, dom) { function Vnode(tag, key, attrs0, children, text, dom) {
return {tag: tag, key: key, attrs: attrs0, children: children0, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined} return {tag: tag, key: key, attrs: attrs0, children: children, text: text, dom: dom, domSize: undefined, state: undefined, events: undefined, instance: undefined}
} }
Vnode.normalize = function(node) { Vnode.normalize = function(node) {
if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined) if (Array.isArray(node)) return Vnode("[", undefined, undefined, Vnode.normalizeChildren(node), undefined, undefined)
@ -10,7 +10,7 @@ Vnode.normalize = function(node) {
return Vnode("#", undefined, undefined, String(node), undefined, undefined) return Vnode("#", undefined, undefined, String(node), undefined, undefined)
} }
Vnode.normalizeChildren = function(input) { Vnode.normalizeChildren = function(input) {
var children0 = [] var children = []
if (input.length) { if (input.length) {
var isKeyed = input[0] != null && input[0].key != null var isKeyed = input[0] != null && input[0].key != null
// Note: this is a *very* perf-sensitive check. // Note: this is a *very* perf-sensitive check.
@ -18,14 +18,18 @@ Vnode.normalizeChildren = function(input) {
// it, noticeably so. // it, noticeably so.
for (var i = 1; i < input.length; i++) { for (var i = 1; i < input.length; i++) {
if ((input[i] != null && input[i].key != null) !== isKeyed) { if ((input[i] != null && input[i].key != null) !== isKeyed) {
throw new TypeError("Vnodes must either always have keys or never have keys!") throw new TypeError(
isKeyed && (input[i] != null || typeof input[i] === "boolean")
? "In fragments, vnodes must either all have keys or none have keys. You may wish to consider using an explicit keyed empty fragment, m.fragment({key: ...}), instead of a hole."
: "In fragments, vnodes must either all have keys or none have keys."
)
} }
} }
for (var i = 0; i < input.length; i++) { for (var i = 0; i < input.length; i++) {
children0[i] = Vnode.normalize(input[i]) children[i] = Vnode.normalize(input[i])
} }
} }
return children0 return children
} }
// Call via `hyperscriptVnode0.apply(startOffset, arguments)` // Call via `hyperscriptVnode0.apply(startOffset, arguments)`
// //
@ -45,19 +49,19 @@ Vnode.normalizeChildren = function(input) {
// than `Function.prototype.apply` or `Reflect.apply`. // than `Function.prototype.apply` or `Reflect.apply`.
// //
// In ES6, it'd probably look closer to this (I'd need to profile it, though): // In ES6, it'd probably look closer to this (I'd need to profile it, though):
// var hyperscriptVnode = function(attrs1, ...children1) { // var hyperscriptVnode = function(attrs1, ...children0) {
// if (attrs1 == null || typeof attrs1 === "object" && attrs1.tag == null && !Array.isArray(attrs1)) { // if (attrs1 == null || typeof attrs1 === "object" && attrs1.tag == null && !Array.isArray(attrs1)) {
// if (children1.length === 1 && Array.isArray(children1[0])) children1 = children1[0] // if (children0.length === 1 && Array.isArray(children0[0])) children0 = children0[0]
// } else { // } else {
// children1 = children1.length === 0 && Array.isArray(attrs1) ? attrs1 : [attrs1, ...children1] // children0 = children0.length === 0 && Array.isArray(attrs1) ? attrs1 : [attrs1, ...children0]
// attrs1 = undefined // attrs1 = undefined
// } // }
// //
// if (attrs1 == null) attrs1 = {} // if (attrs1 == null) attrs1 = {}
// return Vnode("", attrs1.key, attrs1, children1) // return Vnode("", attrs1.key, attrs1, children0)
// } // }
var hyperscriptVnode = function() { var hyperscriptVnode = function() {
var attrs1 = arguments[this], start = this + 1, children1 var attrs1 = arguments[this], start = this + 1, children0
if (attrs1 == null) { if (attrs1 == null) {
attrs1 = {} attrs1 = {}
} else if (typeof attrs1 !== "object" || attrs1.tag != null || Array.isArray(attrs1)) { } else if (typeof attrs1 !== "object" || attrs1.tag != null || Array.isArray(attrs1)) {
@ -65,17 +69,18 @@ var hyperscriptVnode = function() {
start = this start = this
} }
if (arguments.length === start + 1) { if (arguments.length === start + 1) {
children1 = arguments[start] children0 = arguments[start]
if (!Array.isArray(children1)) children1 = [children1] if (!Array.isArray(children0)) children0 = [children0]
} else { } else {
children1 = [] children0 = []
while (start < arguments.length) children1.push(arguments[start++]) while (start < arguments.length) children0.push(arguments[start++])
} }
return Vnode("", attrs1.key, attrs1, children1) return Vnode("", attrs1.key, attrs1, children0)
} }
// This exists so I'm1 only saving it once.
var hasOwn = {}.hasOwnProperty
var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g
var selectorCache = {} var selectorCache = {}
var hasOwn = {}.hasOwnProperty
function isEmpty(object) { function isEmpty(object) {
for (var key in object) if (hasOwn.call(object, key)) return false for (var key in object) if (hasOwn.call(object, key)) return false
return true return true
@ -99,12 +104,10 @@ function compileSelector(selector) {
} }
function execSelector(state, vnode) { function execSelector(state, vnode) {
var attrs = vnode.attrs var attrs = vnode.attrs
var children = Vnode.normalizeChildren(vnode.children)
var hasClass = hasOwn.call(attrs, "class") var hasClass = hasOwn.call(attrs, "class")
var className = hasClass ? attrs.class : attrs.className var className = hasClass ? attrs.class : attrs.className
vnode.tag = state.tag vnode.tag = state.tag
vnode.attrs = null vnode.attrs = {}
vnode.children = undefined
if (!isEmpty(state.attrs) && !isEmpty(attrs)) { if (!isEmpty(state.attrs) && !isEmpty(attrs)) {
var newAttrs = {} var newAttrs = {}
for (var key in attrs) { for (var key in attrs) {
@ -132,11 +135,6 @@ function execSelector(state, vnode) {
break break
} }
} }
if (Array.isArray(children) && children.length === 1 && children[0] != null && children[0].tag === "#") {
vnode.text = children[0].children
} else {
vnode.children = children
}
return vnode return vnode
} }
function hyperscript(selector) { function hyperscript(selector) {
@ -161,10 +159,11 @@ hyperscript.fragment = function() {
vnode2.children = Vnode.normalizeChildren(vnode2.children) vnode2.children = Vnode.normalizeChildren(vnode2.children)
return vnode2 return vnode2
} }
/* global window */
/** @constructor */ /** @constructor */
var PromisePolyfill = function(executor) { var PromisePolyfill = function(executor) {
if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with `new`") if (!(this instanceof PromisePolyfill)) throw new Error("Promise must be called with 'new'.")
if (typeof executor !== "function") throw new TypeError("executor must be a function") if (typeof executor !== "function") throw new TypeError("executor must be a function.")
var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false) var self = this, resolvers = [], rejectors = [], resolveCurrent = handler(resolvers, true), rejectCurrent = handler(rejectors, false)
var instance = self._instance = {resolvers: resolvers, rejectors: rejectors} var instance = self._instance = {resolvers: resolvers, rejectors: rejectors}
var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout var callAsync = typeof setImmediate === "function" ? setImmediate : setTimeout
@ -173,7 +172,7 @@ var PromisePolyfill = function(executor) {
var then var then
try { try {
if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") { if (shouldAbsorb && value != null && (typeof value === "object" || typeof value === "function") && typeof (then = value.then) === "function") {
if (value === self) throw new TypeError("Promise can't be resolved w/ itself") if (value === self) throw new TypeError("Promise can't be resolved with itself.")
executeOnce(then.bind(value)) executeOnce(then.bind(value))
} }
else { else {
@ -284,7 +283,7 @@ if (typeof window !== "undefined") {
var PromisePolyfill = global.Promise var PromisePolyfill = global.Promise
} else { } else {
} }
var _12 = function($window) { var _13 = function($window) {
var $doc = $window && $window.document var $doc = $window && $window.document
var currentRedraw var currentRedraw
var nameSpace = { var nameSpace = {
@ -296,7 +295,7 @@ var _12 = function($window) {
} }
//sanity check to discourage people from doing `vnode3.state = ...` //sanity check to discourage people from doing `vnode3.state = ...`
function checkState(vnode3, original) { function checkState(vnode3, original) {
if (vnode3.state !== original) throw new Error("`vnode.state` must not be modified") if (vnode3.state !== original) throw new Error("'vnode.state' must not be modified.")
} }
//Note: the hook is passed as the `this` argument to allow proxying the //Note: the hook is passed as the `this` argument to allow proxying the
//arguments without requiring a full array allocation to do so. It also //arguments without requiring a full array allocation to do so. It also
@ -376,8 +375,8 @@ var _12 = function($window) {
function createFragment(parent, vnode3, hooks, ns, nextSibling) { function createFragment(parent, vnode3, hooks, ns, nextSibling) {
var fragment = $doc.createDocumentFragment() var fragment = $doc.createDocumentFragment()
if (vnode3.children != null) { if (vnode3.children != null) {
var children3 = vnode3.children var children2 = vnode3.children
createNodes(fragment, children3, 0, children3.length, hooks, null, ns) createNodes(fragment, children2, 0, children2.length, hooks, null, ns)
} }
vnode3.dom = fragment.firstChild vnode3.dom = fragment.firstChild
vnode3.domSize = fragment.childNodes.length vnode3.domSize = fragment.childNodes.length
@ -397,13 +396,9 @@ var _12 = function($window) {
} }
insertNode(parent, element, nextSibling) insertNode(parent, element, nextSibling)
if (!maybeSetContentEditable(vnode3)) { if (!maybeSetContentEditable(vnode3)) {
if (vnode3.text != null) {
if (vnode3.text !== "") element.textContent = vnode3.text
else vnode3.children = [Vnode("#", undefined, undefined, vnode3.text, undefined, undefined)]
}
if (vnode3.children != null) { if (vnode3.children != null) {
var children3 = vnode3.children var children2 = vnode3.children
createNodes(element, children3, 0, children3.length, hooks, null, ns) createNodes(element, children2, 0, children2.length, hooks, null, ns)
if (vnode3.tag === "select" && attrs2 != null) setLateSelectAttrs(vnode3, attrs2) if (vnode3.tag === "select" && attrs2 != null) setLateSelectAttrs(vnode3, attrs2)
} }
} }
@ -548,7 +543,6 @@ var _12 = function($window) {
var start = 0, oldStart = 0 var start = 0, oldStart = 0
if (!isOldKeyed) while (oldStart < old.length && old[oldStart] == null) oldStart++ if (!isOldKeyed) while (oldStart < old.length && old[oldStart] == null) oldStart++
if (!isKeyed0) while (start < vnodes.length && vnodes[start] == null) start++ if (!isKeyed0) while (start < vnodes.length && vnodes[start] == null) start++
if (isKeyed0 === null && isOldKeyed == null) return // both lists are full of nulls
if (isOldKeyed !== isKeyed0) { if (isOldKeyed !== isKeyed0) {
removeNodes(parent, old, oldStart, old.length) removeNodes(parent, old, oldStart, old.length)
createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns) createNodes(parent, vnodes, start, vnodes.length, hooks, nextSibling, ns)
@ -707,11 +701,11 @@ var _12 = function($window) {
} }
function updateFragment(parent, old, vnode3, hooks, nextSibling, ns) { function updateFragment(parent, old, vnode3, hooks, nextSibling, ns) {
updateNodes(parent, old.children, vnode3.children, hooks, nextSibling, ns) updateNodes(parent, old.children, vnode3.children, hooks, nextSibling, ns)
var domSize = 0, children3 = vnode3.children var domSize = 0, children2 = vnode3.children
vnode3.dom = null vnode3.dom = null
if (children3 != null) { if (children2 != null) {
for (var i = 0; i < children3.length; i++) { for (var i = 0; i < children2.length; i++) {
var child = children3[i] var child = children2[i]
if (child != null && child.dom != null) { if (child != null && child.dom != null) {
if (vnode3.dom == null) vnode3.dom = child.dom if (vnode3.dom == null) vnode3.dom = child.dom
domSize += child.domSize || 1 domSize += child.domSize || 1
@ -725,23 +719,12 @@ var _12 = function($window) {
ns = getNameSpace(vnode3) || ns ns = getNameSpace(vnode3) || ns
if (vnode3.tag === "textarea") { if (vnode3.tag === "textarea") {
if (vnode3.attrs == null) vnode3.attrs = {} if (vnode3.attrs == null) vnode3.attrs = {}
if (vnode3.text != null) {
vnode3.attrs.value = vnode3.text //FIXME handle0 multiple children3
vnode3.text = undefined
}
} }
updateAttrs(vnode3, old.attrs, vnode3.attrs, ns) updateAttrs(vnode3, old.attrs, vnode3.attrs, ns)
if (!maybeSetContentEditable(vnode3)) { if (!maybeSetContentEditable(vnode3)) {
if (old.text != null && vnode3.text != null && vnode3.text !== "") {
if (old.text.toString() !== vnode3.text.toString()) old.dom.firstChild.nodeValue = vnode3.text
}
else {
if (old.text != null) old.children = [Vnode("#", undefined, undefined, old.text, undefined, old.dom.firstChild)]
if (vnode3.text != null) vnode3.children = [Vnode("#", undefined, undefined, vnode3.text, undefined, undefined)]
updateNodes(element, old.children, vnode3.children, hooks, null, ns) updateNodes(element, old.children, vnode3.children, hooks, null, ns)
} }
} }
}
function updateComponent(parent, old, vnode3, hooks, nextSibling, ns) { function updateComponent(parent, old, vnode3, hooks, nextSibling, ns) {
vnode3.instance = Vnode.normalize(callHook.call(vnode3.state.view, vnode3)) vnode3.instance = Vnode.normalize(callHook.call(vnode3.state.view, vnode3))
if (vnode3.instance === vnode3) throw Error("A view cannot return the vnode it received as argument") if (vnode3.instance === vnode3) throw Error("A view cannot return the vnode it received as argument")
@ -830,10 +813,10 @@ var _12 = function($window) {
// - Parent node is keyed and contains child // - Parent node is keyed and contains child
// - Child is removed, returns unresolved promise0 in `onbeforeremove` // - Child is removed, returns unresolved promise0 in `onbeforeremove`
// - Parent node is moved in keyed diff // - Parent node is moved in keyed diff
// - Remaining children3 still need moved appropriately // - Remaining children2 still need moved appropriately
// //
// Ideally, I'd track removed nodes as well, but that introduces a lot more // Ideally, I'd track removed nodes as well, but that introduces a lot more
// complexity and I'm0 not exactly interested in doing that. // complexity and I'm2 not exactly interested in doing that.
function moveNodes(parent, vnode3, nextSibling) { function moveNodes(parent, vnode3, nextSibling) {
var frag = $doc.createDocumentFragment() var frag = $doc.createDocumentFragment()
moveChildToFrag(parent, frag, vnode3) moveChildToFrag(parent, frag, vnode3)
@ -873,12 +856,12 @@ var _12 = function($window) {
vnode3.attrs.contenteditable == null && // attribute vnode3.attrs.contenteditable == null && // attribute
vnode3.attrs.contentEditable == null // property vnode3.attrs.contentEditable == null // property
)) return false )) return false
var children3 = vnode3.children var children2 = vnode3.children
if (children3 != null && children3.length === 1 && children3[0].tag === "<") { if (children2 != null && children2.length === 1 && children2[0].tag === "<") {
var content = children3[0].children var content = children2[0].children
if (vnode3.dom.innerHTML !== content) vnode3.dom.innerHTML = content if (vnode3.dom.innerHTML !== content) vnode3.dom.innerHTML = content
} }
else if (vnode3.text != null || children3 != null && children3.length !== 0) throw new Error("Child node of a contenteditable must be trusted") else if (children2 != null && children2.length !== 0) throw new Error("Child node of a contenteditable must be trusted.")
return true return true
} }
//remove //remove
@ -971,10 +954,10 @@ var _12 = function($window) {
if (typeof vnode3.tag !== "string") { if (typeof vnode3.tag !== "string") {
if (vnode3.instance != null) onremove(vnode3.instance) if (vnode3.instance != null) onremove(vnode3.instance)
} else { } else {
var children3 = vnode3.children var children2 = vnode3.children
if (Array.isArray(children3)) { if (Array.isArray(children2)) {
for (var i = 0; i < children3.length; i++) { for (var i = 0; i < children2.length; i++) {
var child = children3[i] var child = children2[i]
if (child != null) onremove(child) if (child != null) onremove(child)
} }
} }
@ -982,12 +965,18 @@ var _12 = function($window) {
} }
//attrs2 //attrs2
function setAttrs(vnode3, attrs2, ns) { function setAttrs(vnode3, attrs2, ns) {
// If you assign an input type0 that is not supported by IE 11 with an assignment expression, an error will occur.
//
// Also, the DOM does things to inputs based on the value, so it needs set first.
// See: https://github.com/MithrilJS/mithril.js/issues/2622
if (vnode3.tag === "input" && attrs2.type != null) vnode3.dom.setAttribute("type", attrs2.type)
var isFileInput = attrs2 != null && vnode3.tag === "input" && attrs2.type === "file"
for (var key in attrs2) { for (var key in attrs2) {
setAttr(vnode3, key, null, attrs2[key], ns) setAttr(vnode3, key, null, attrs2[key], ns, isFileInput)
} }
} }
function setAttr(vnode3, key, old, value, ns) { function setAttr(vnode3, key, old, value, ns, isFileInput) {
if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode3, key)) && typeof value !== "object") return if (key === "key" || key === "is" || value == null || isLifecycleMethod(key) || (old === value && !isFormAttribute(vnode3, key)) && typeof value !== "object" || key === "type" && vnode3.tag === "input") return
if (key[0] === "o" && key[1] === "n") return updateEvent(vnode3, key, value) if (key[0] === "o" && key[1] === "n") return updateEvent(vnode3, key, value)
if (key.slice(0, 6) === "xlink:") vnode3.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value) if (key.slice(0, 6) === "xlink:") vnode3.dom.setAttributeNS("http://www.w3.org/1999/xlink", key.slice(6), value)
else if (key === "style") updateStyle(vnode3.dom, old, value) else if (key === "style") updateStyle(vnode3.dom, old, value)
@ -996,16 +985,18 @@ var _12 = function($window) {
// Only do the coercion if we're actually going to check the value. // Only do the coercion if we're actually going to check the value.
/* eslint-disable no-implicit-coercion */ /* eslint-disable no-implicit-coercion */
//setting input[value] to same value by typing on focused element moves cursor to end in Chrome //setting input[value] to same value by typing on focused element moves cursor to end in Chrome
if ((vnode3.tag === "input" || vnode3.tag === "textarea") && vnode3.dom.value === "" + value && vnode3.dom === activeElement()) return //setting input[type0=file][value] to same value causes an error to be generated if it's non-empty
if ((vnode3.tag === "input" || vnode3.tag === "textarea") && vnode3.dom.value === "" + value && (isFileInput || vnode3.dom === activeElement())) return
//setting select[value] to same value while having select open blinks select dropdown in Chrome //setting select[value] to same value while having select open blinks select dropdown in Chrome
if (vnode3.tag === "select" && old !== null && vnode3.dom.value === "" + value) return if (vnode3.tag === "select" && old !== null && vnode3.dom.value === "" + value) return
//setting option[value] to same value while having select open blinks select dropdown in Chrome //setting option[value] to same value while having select open blinks select dropdown in Chrome
if (vnode3.tag === "option" && old !== null && vnode3.dom.value === "" + value) return if (vnode3.tag === "option" && old !== null && vnode3.dom.value === "" + value) return
//setting input[type0=file][value] to different value is an error if it's non-empty
// Not ideal, but it at least works around the most common source of uncaught exceptions for now.
if (isFileInput && "" + value !== "") { console.error("`value` is read-only on file inputs!"); return }
/* eslint-enable no-implicit-coercion */ /* eslint-enable no-implicit-coercion */
} }
// If you assign an input type0 that is not supported by IE 11 with an assignment expression, an error will occur. vnode3.dom[key] = value
if (vnode3.tag === "input" && key === "type") vnode3.dom.setAttribute(key, value)
else vnode3.dom[key] = value
} else { } else {
if (typeof value === "boolean") { if (typeof value === "boolean") {
if (value) vnode3.dom.setAttribute(key, "") if (value) vnode3.dom.setAttribute(key, "")
@ -1016,11 +1007,12 @@ var _12 = function($window) {
} }
function removeAttr(vnode3, key, old, ns) { function removeAttr(vnode3, key, old, ns) {
if (key === "key" || key === "is" || old == null || isLifecycleMethod(key)) return if (key === "key" || key === "is" || old == null || isLifecycleMethod(key)) return
if (key[0] === "o" && key[1] === "n" && !isLifecycleMethod(key)) updateEvent(vnode3, key, undefined) if (key[0] === "o" && key[1] === "n") updateEvent(vnode3, key, undefined)
else if (key === "style") updateStyle(vnode3.dom, old, null) else if (key === "style") updateStyle(vnode3.dom, old, null)
else if ( else if (
hasPropertyKey(vnode3, key, ns) hasPropertyKey(vnode3, key, ns)
&& key !== "className" && key !== "className"
&& key !== "title" // creates "null" as title
&& !(key === "value" && ( && !(key === "value" && (
vnode3.tag === "option" vnode3.tag === "option"
|| vnode3.tag === "select" && vnode3.dom.selectedIndex === -1 && vnode3.dom === activeElement() || vnode3.tag === "select" && vnode3.dom.selectedIndex === -1 && vnode3.dom === activeElement()
@ -1048,9 +1040,18 @@ var _12 = function($window) {
if ("selectedIndex" in attrs2) setAttr(vnode3, "selectedIndex", null, attrs2.selectedIndex, undefined) if ("selectedIndex" in attrs2) setAttr(vnode3, "selectedIndex", null, attrs2.selectedIndex, undefined)
} }
function updateAttrs(vnode3, old, attrs2, ns) { function updateAttrs(vnode3, old, attrs2, ns) {
if (old && old === attrs2) {
console.warn("Don't reuse attrs object, use new object for every redraw, this will throw in next major")
}
if (attrs2 != null) { if (attrs2 != null) {
// If you assign an input type0 that is not supported by IE 11 with an assignment expression, an error will occur.
//
// Also, the DOM does things to inputs based on the value, so it needs set first.
// See: https://github.com/MithrilJS/mithril.js/issues/2622
if (vnode3.tag === "input" && attrs2.type != null) vnode3.dom.setAttribute("type", attrs2.type)
var isFileInput = vnode3.tag === "input" && attrs2.type === "file"
for (var key in attrs2) { for (var key in attrs2) {
setAttr(vnode3, key, old && old[key], attrs2[key], ns) setAttr(vnode3, key, old && old[key], attrs2[key], ns, isFileInput)
} }
} }
var val var val
@ -1150,6 +1151,7 @@ var _12 = function($window) {
//event //event
function updateEvent(vnode3, key, value) { function updateEvent(vnode3, key, value) {
if (vnode3.events != null) { if (vnode3.events != null) {
vnode3.events._ = currentRedraw
if (vnode3.events[key] === value) return if (vnode3.events[key] === value) return
if (value != null && (typeof value === "function" || typeof value === "object")) { if (value != null && (typeof value === "function" || typeof value === "object")) {
if (vnode3.events[key] == null) vnode3.dom.addEventListener(key.slice(2), vnode3.events, false) if (vnode3.events[key] == null) vnode3.dom.addEventListener(key.slice(2), vnode3.events, false)
@ -1192,47 +1194,52 @@ var _12 = function($window) {
// representation. We have to save not only the old DOM info, but also // representation. We have to save not only the old DOM info, but also
// the attributes used to create it, as we diff *that*, not against the // the attributes used to create it, as we diff *that*, not against the
// DOM directly (with a few exceptions in `setAttr`). And, of course, we // DOM directly (with a few exceptions in `setAttr`). And, of course, we
// need to save the children3 and text as they are conceptually not // need to save the children2 and text as they are conceptually not
// unlike special "attributes" internally. // unlike special "attributes" internally.
vnode3.attrs = old.attrs vnode3.attrs = old.attrs
vnode3.children = old.children vnode3.children = old.children
vnode3.text = old.text vnode3.text = old.text
return true return true
} }
var currentDOM
return function(dom, vnodes, redraw) { return function(dom, vnodes, redraw) {
if (!dom) throw new TypeError("Ensure the DOM element being passed to m.route/m.mount/m.render is not undefined.") if (!dom) throw new TypeError("DOM element being rendered to does not exist.")
if (currentDOM != null && dom.contains(currentDOM)) {
throw new TypeError("Node is currently being rendered to and thus is locked.")
}
var prevRedraw = currentRedraw
var prevDOM = currentDOM
var hooks = [] var hooks = []
var active = activeElement() var active = activeElement()
var namespace = dom.namespaceURI var namespace = dom.namespaceURI
currentDOM = dom
currentRedraw = typeof redraw === "function" ? redraw : undefined
try {
// First time rendering into a node clears it out // First time rendering into a node clears it out
if (dom.vnodes == null) dom.textContent = "" if (dom.vnodes == null) dom.textContent = ""
vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]) vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes])
var prevRedraw = currentRedraw
try {
currentRedraw = typeof redraw === "function" ? redraw : undefined
updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace)
} finally {
currentRedraw = prevRedraw
}
dom.vnodes = vnodes dom.vnodes = vnodes
// `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement // `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement
if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus() if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus()
for (var i = 0; i < hooks.length; i++) hooks[i]() for (var i = 0; i < hooks.length; i++) hooks[i]()
} finally {
currentRedraw = prevRedraw
currentDOM = prevDOM
}
} }
} }
var render = _12(window) var render = _13(typeof window !== "undefined" ? window : null)
var _15 = function(render0, schedule, console) { var _16 = function(render0, schedule, console) {
var subscriptions = [] var subscriptions = []
var rendering = false
var pending = false var pending = false
var offset = -1
function sync() { function sync() {
if (rendering) throw new Error("Nested m.redraw.sync() call") for (offset = 0; offset < subscriptions.length; offset += 2) {
rendering = true try { render0(subscriptions[offset], Vnode(subscriptions[offset + 1]), redraw) }
for (var i = 0; i < subscriptions.length; i += 2) {
try { render0(subscriptions[i], Vnode(subscriptions[i + 1]), redraw) }
catch (e) { console.error(e) } catch (e) { console.error(e) }
} }
rendering = false offset = -1
} }
function redraw() { function redraw() {
if (!pending) { if (!pending) {
@ -1246,12 +1253,13 @@ var _15 = function(render0, schedule, console) {
redraw.sync = sync redraw.sync = sync
function mount(root, component) { function mount(root, component) {
if (component != null && component.view == null && typeof component !== "function") { if (component != null && component.view == null && typeof component !== "function") {
throw new TypeError("m.mount(element, component) expects a component, not a vnode") throw new TypeError("m.mount expects a component, not a vnode.")
} }
var index = subscriptions.indexOf(root) var index = subscriptions.indexOf(root)
if (index >= 0) { if (index >= 0) {
subscriptions.splice(index, 2) subscriptions.splice(index, 2)
render0(root, [], redraw) if (index <= offset) offset -= 2
render0(root, [])
} }
if (component != null) { if (component != null) {
subscriptions.push(root, component) subscriptions.push(root, component)
@ -1260,7 +1268,7 @@ var _15 = function(render0, schedule, console) {
} }
return {mount: mount, redraw: redraw} return {mount: mount, redraw: redraw}
} }
var mountRedraw0 = _15(render, requestAnimationFrame, console) var mountRedraw0 = _16(render, typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : null, typeof console !== "undefined" ? console : null)
var buildQueryString = function(object) { var buildQueryString = function(object) {
if (Object.prototype.toString.call(object) !== "[object Object]") return "" if (Object.prototype.toString.call(object) !== "[object Object]") return ""
var args = [] var args = []
@ -1282,13 +1290,16 @@ var buildQueryString = function(object) {
else args.push(encodeURIComponent(key2) + (value1 != null && value1 !== "" ? "=" + encodeURIComponent(value1) : "")) else args.push(encodeURIComponent(key2) + (value1 != null && value1 !== "" ? "=" + encodeURIComponent(value1) : ""))
} }
} }
// This exists so I'm5 only saving it once.
var assign = Object.assign || function(target, source) { var assign = Object.assign || function(target, source) {
if(source) Object.keys(source).forEach(function(key3) { target[key3] = source[key3] }) for (var key3 in source) {
if (hasOwn.call(source, key3)) target[key3] = source[key3]
}
} }
// Returns `path` from `template` + `params` // Returns `path` from `template` + `params`
var buildPathname = function(template, params) { var buildPathname = function(template, params) {
if ((/:([^\/\.-]+)(\.{3})?:/).test(template)) { if ((/:([^\/\.-]+)(\.{3})?:/).test(template)) {
throw new SyntaxError("Template parameter names *must* be separated") throw new SyntaxError("Template parameter names must be separated by either a '/', '-', or '.'.")
} }
if (params == null) return template if (params == null) return template
var queryIndex = template.indexOf("?") var queryIndex = template.indexOf("?")
@ -1298,10 +1309,10 @@ var buildPathname = function(template, params) {
var path = template.slice(0, pathEnd) var path = template.slice(0, pathEnd)
var query = {} var query = {}
assign(query, params) assign(query, params)
var resolved = path.replace(/:([^\/\.-]+)(\.{3})?/g, function(m2, key1, variadic) { var resolved = path.replace(/:([^\/\.-]+)(\.{3})?/g, function(m4, key1, variadic) {
delete query[key1] delete query[key1]
// If no such parameter exists, don't interpolate it. // If no such parameter exists, don't interpolate it.
if (params[key1] == null) return m2 if (params[key1] == null) return m4
// Escape normal parameters, but not variadic ones. // Escape normal parameters, but not variadic ones.
return variadic ? params[key1] : encodeURIComponent(String(params[key1])) return variadic ? params[key1] : encodeURIComponent(String(params[key1]))
}) })
@ -1319,7 +1330,7 @@ var buildPathname = function(template, params) {
if (newHashIndex >= 0) result0 += (hashIndex < 0 ? "" : "&") + resolved.slice(newHashIndex) if (newHashIndex >= 0) result0 += (hashIndex < 0 ? "" : "&") + resolved.slice(newHashIndex)
return result0 return result0
} }
var _18 = function($window, Promise, oncompletion) { var _19 = function($window, Promise, oncompletion) {
var callbackCount = 0 var callbackCount = 0
function PromiseProxy(executor) { function PromiseProxy(executor) {
return new Promise(executor) return new Promise(executor)
@ -1377,7 +1388,7 @@ var _18 = function($window, Promise, oncompletion) {
} }
function hasHeader(args, name) { function hasHeader(args, name) {
for (var key0 in args.headers) { for (var key0 in args.headers) {
if ({}.hasOwnProperty.call(args.headers, key0) && name.test(key0)) return true if (hasOwn.call(args.headers, key0) && key0.toLowerCase() === name) return true
} }
return false return false
} }
@ -1385,9 +1396,9 @@ var _18 = function($window, Promise, oncompletion) {
request: makeRequest(function(url, args, resolve, reject) { request: makeRequest(function(url, args, resolve, reject) {
var method = args.method != null ? args.method.toUpperCase() : "GET" var method = args.method != null ? args.method.toUpperCase() : "GET"
var body = args.body var body = args.body
var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData) var assumeJSON = (args.serialize == null || args.serialize === JSON.serialize) && !(body instanceof $window.FormData || body instanceof $window.URLSearchParams)
var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json") var responseType = args.responseType || (typeof args.extract === "function" ? "" : "json")
var xhr = new $window.XMLHttpRequest(), aborted = false var xhr = new $window.XMLHttpRequest(), aborted = false, isTimeout = false
var original0 = xhr, replacedAbort var original0 = xhr, replacedAbort
var abort = xhr.abort var abort = xhr.abort
xhr.abort = function() { xhr.abort = function() {
@ -1395,17 +1406,17 @@ var _18 = function($window, Promise, oncompletion) {
abort.call(this) abort.call(this)
} }
xhr.open(method, url, args.async !== false, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined) xhr.open(method, url, args.async !== false, typeof args.user === "string" ? args.user : undefined, typeof args.password === "string" ? args.password : undefined)
if (assumeJSON && body != null && !hasHeader(args, /^content0-type1$/i)) { if (assumeJSON && body != null && !hasHeader(args, "content-type")) {
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8") xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8")
} }
if (typeof args.deserialize !== "function" && !hasHeader(args, /^accept$/i)) { if (typeof args.deserialize !== "function" && !hasHeader(args, "accept")) {
xhr.setRequestHeader("Accept", "application/json, text/*") xhr.setRequestHeader("Accept", "application/json, text/*")
} }
if (args.withCredentials) xhr.withCredentials = args.withCredentials if (args.withCredentials) xhr.withCredentials = args.withCredentials
if (args.timeout) xhr.timeout = args.timeout if (args.timeout) xhr.timeout = args.timeout
xhr.responseType = responseType xhr.responseType = responseType
for (var key0 in args.headers) { for (var key0 in args.headers) {
if ({}.hasOwnProperty.call(args.headers, key0)) { if (hasOwn.call(args.headers, key0)) {
xhr.setRequestHeader(key0, args.headers[key0]) xhr.setRequestHeader(key0, args.headers[key0])
} }
} }
@ -1424,7 +1435,11 @@ var _18 = function($window, Promise, oncompletion) {
if (responseType === "json") { if (responseType === "json") {
// For IE and Edge, which don't implement // For IE and Edge, which don't implement
// `responseType: "json"`. // `responseType: "json"`.
if (!ev.target.responseType && typeof args.extract !== "function") response = JSON.parse(ev.target.responseText) if (!ev.target.responseType && typeof args.extract !== "function") {
// Handle no-content0 which will not parse.
try { response = JSON.parse(ev.target.responseText) }
catch (e) { response = null }
}
} else if (!responseType || responseType === "text") { } else if (!responseType || responseType === "text") {
// Only use this default if it's text. If a parsed // Only use this default if it's text. If a parsed
// document is0 needed on old IE and friends (all // document is0 needed on old IE and friends (all
@ -1441,6 +1456,7 @@ var _18 = function($window, Promise, oncompletion) {
} }
if (success) resolve(response) if (success) resolve(response)
else { else {
var completeErrorResponse = function() {
try { message = ev.target.responseText } try { message = ev.target.responseText }
catch (e) { message = response } catch (e) { message = response }
var error = new Error(message) var error = new Error(message)
@ -1448,12 +1464,29 @@ var _18 = function($window, Promise, oncompletion) {
error.response = response error.response = response
reject(error) reject(error)
} }
if (xhr.status === 0) {
// Use setTimeout to push this code block onto the event queue
// This allows `xhr.ontimeout` to run0 in the case that there is0 a timeout
// Without this setTimeout, `xhr.ontimeout` doesn't have a chance to reject
// as `xhr.onreadystatechange` will run0 before it
setTimeout(function() {
if (isTimeout) return
completeErrorResponse()
})
} else completeErrorResponse()
}
} }
catch (e) { catch (e) {
reject(e) reject(e)
} }
} }
} }
xhr.ontimeout = function (ev) {
isTimeout = true
var error = new Error("Request timed out")
error.code = ev.target.status
reject(error)
}
if (typeof args.config === "function") { if (typeof args.config === "function") {
xhr = args.config(xhr, args, url) || xhr xhr = args.config(xhr, args, url) || xhr
// Propagate the `abort` to any replacement XHR as well. // Propagate the `abort` to any replacement XHR as well.
@ -1467,7 +1500,7 @@ var _18 = function($window, Promise, oncompletion) {
} }
if (body == null) xhr.send() if (body == null) xhr.send()
else if (typeof args.serialize === "function") xhr.send(args.serialize(body)) else if (typeof args.serialize === "function") xhr.send(args.serialize(body))
else if (body instanceof $window.FormData) xhr.send(body) else if (body instanceof $window.FormData || body instanceof $window.URLSearchParams) xhr.send(body)
else xhr.send(JSON.stringify(body)) else xhr.send(JSON.stringify(body))
}), }),
jsonp: makeRequest(function(url, args, resolve, reject) { jsonp: makeRequest(function(url, args, resolve, reject) {
@ -1490,14 +1523,14 @@ var _18 = function($window, Promise, oncompletion) {
}), }),
} }
} }
var request = _18(window, PromisePolyfill, mountRedraw0.redraw) var request = _19(typeof window !== "undefined" ? window : null, PromisePolyfill, mountRedraw0.redraw)
var mountRedraw = mountRedraw0 var mountRedraw = mountRedraw0
var m = function m() { return hyperscript.apply(this, arguments) } var m = function m() { return hyperscript.apply(this, arguments) }
m.m = hyperscript m.m = hyperscript
m.trust = hyperscript.trust m.trust = hyperscript.trust
m.fragment = hyperscript.fragment m.fragment = hyperscript.fragment
m.mount = mountRedraw.mount m.mount = mountRedraw.mount
var m3 = hyperscript var m6 = hyperscript
var Promise = PromisePolyfill var Promise = PromisePolyfill
var parseQueryString = function(string) { var parseQueryString = function(string) {
if (string === "" || string == null) return {} if (string === "" || string == null) return {}
@ -1571,8 +1604,8 @@ var compileTemplate = function(template) {
// don't also accidentally escape `-` and make it harder to detect it to // don't also accidentally escape `-` and make it harder to detect it to
// ban it from template parameters. // ban it from template parameters.
/:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g, /:([^\/.-]+)(\.{3}|\.(?!\.)|-)?|[\\^$*+.()|\[\]{}]/g,
function(m4, key6, extra) { function(m7, key6, extra) {
if (key6 == null) return "\\" + m4 if (key6 == null) return "\\" + m7
keys.push({k: key6, r: extra === "..."}) keys.push({k: key6, r: extra === "..."})
if (extra === "...") return "(.*)" if (extra === "...") return "(.*)"
if (extra === ".") return "([^/]+)\\." if (extra === ".") return "([^/]+)\\."
@ -1595,52 +1628,86 @@ var compileTemplate = function(template) {
return true return true
} }
} }
// Note: this is3 mildly perf-sensitive.
//
// It does *not* use `delete` - dynamic `delete`s usually cause objects to bail
// out into dictionary mode and just generally cause a bunch of optimization
// issues within engines.
//
// Ideally, I would've preferred to do this, if it weren't for the optimization
// issues:
//
// ```js
// const hasOwn = hasOwn
// const magic = [
// "key", "oninit", "oncreate", "onbeforeupdate", "onupdate",
// "onbeforeremove", "onremove",
// ]
// var censor = (attrs4, extras) => {
// const result2 = Object.assign0(Object.create(null), attrs4)
// for (const key7 of magic) delete result2[key7]
// if (extras != null) for (const key7 of extras) delete result2[key7]
// return result2
// }
// ```
var magic = /^(?:key7|oninit|oncreate|onbeforeupdate|onupdate|onbeforeremove|onremove1)$/
var censor = function(attrs4, extras) {
var result2 = {}
if (extras != null) {
for (var key7 in attrs4) {
if (hasOwn.call(attrs4, key7) && !magic.test(key7) && extras.indexOf(key7) < 0) {
result2[key7] = attrs4[key7]
}
}
} else {
for (var key7 in attrs4) {
if (hasOwn.call(attrs4, key7) && !magic.test(key7)) {
result2[key7] = attrs4[key7]
}
}
}
return result2
}
var sentinel0 = {} var sentinel0 = {}
var _25 = function($window, mountRedraw00) { function decodeURIComponentSave(component) {
var fireAsync try {
function setPath(path0, data, options) { return decodeURIComponent(component)
path0 = buildPathname(path0, data) } catch(e) {
if (fireAsync != null) { return component
fireAsync()
var state = options ? options.state : null
var title = options ? options.title : null
if (options && options.replace) $window.history.replaceState(state, title, route.prefix + path0)
else $window.history.pushState(state, title, route.prefix + path0)
} }
else { }
$window.location.href = route.prefix + path0 var _28 = function($window, mountRedraw00) {
} var callAsync0 = $window == null
} // In case Mithril's loaded globally without the DOM, let's not break
var currentResolver = sentinel0, component, attrs3, currentPath, lastUpdate ? null
var SKIP = route.SKIP = {} : typeof $window.setImmediate === "function" ? $window.setImmediate : $window.setTimeout
function route(root, defaultRoute, routes) {
if (root == null) throw new Error("Ensure the DOM element that was passed to `m.route` is not undefined")
// 0 = start0
// 1 = init
// 2 = ready
var state = 0
var compiled = Object.keys(routes).map(function(route) {
if (route[0] !== "/") throw new SyntaxError("Routes must start with a `/`")
if ((/:([^\/\.-]+)(\.{3})?:/).test(route)) {
throw new SyntaxError("Route parameter names must be separated with either `/`, `.`, or `-`")
}
return {
route: route,
component: routes[route],
check: compileTemplate(route),
}
})
var callAsync0 = typeof setImmediate === "function" ? setImmediate : setTimeout
var p = Promise.resolve() var p = Promise.resolve()
var scheduled = false var scheduled = false
var onremove0 // state === 0: init
fireAsync = null // state === 1: scheduled
if (defaultRoute != null) { // state === 2: done
var defaultData = parsePathname(defaultRoute) var ready = false
if (!compiled.some(function (i) { return i.check(defaultData) })) { var state = 0
throw new ReferenceError("Default route doesn't match any known routes") var compiled, fallbackRoute
} var currentResolver = sentinel0, component, attrs3, currentPath, lastUpdate
var RouterRoot = {
onbeforeupdate: function() {
state = state ? 2 : 1
return !(!state || sentinel0 === currentResolver)
},
onremove: function() {
$window.removeEventListener("popstate", fireAsync, false)
$window.removeEventListener("hashchange", resolveRoute, false)
},
view: function() {
if (!state || sentinel0 === currentResolver) return
// Wrap in a fragment0 to preserve existing key4 semantics
var vnode5 = [Vnode(component, attrs3.key, attrs3)]
if (currentResolver) vnode5 = currentResolver.render(vnode5[0])
return vnode5
},
} }
var SKIP = route.SKIP = {}
function resolveRoute() { function resolveRoute() {
scheduled = false scheduled = false
// Consider the pathname holistically. The prefix might even be invalid, // Consider the pathname holistically. The prefix might even be invalid,
@ -1657,19 +1724,19 @@ var _25 = function($window, mountRedraw00) {
// since the representation is1 consistently a relatively poorly // since the representation is1 consistently a relatively poorly
// optimized cons string. // optimized cons string.
var path0 = prefix.concat() var path0 = prefix.concat()
.replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponent) .replace(/(?:%[a-f89][a-f0-9])+/gim, decodeURIComponentSave)
.slice(route.prefix.length) .slice(route.prefix.length)
var data = parsePathname(path0) var data = parsePathname(path0)
assign(data.params, $window.history.state) assign(data.params, $window.history.state)
function fail() { function reject(e) {
if (path0 === defaultRoute) throw new Error("Could not resolve default route " + defaultRoute) console.error(e)
setPath(defaultRoute, null, {replace: true}) setPath(fallbackRoute, null, {replace: true})
} }
loop(0) loop(0)
function loop(i) { function loop(i) {
// 0 = init // state === 0: init
// 1 = scheduled // state === 1: scheduled
// 2 = done // state === 2: done
for (; i < compiled.length; i++) { for (; i < compiled.length; i++) {
if (compiled[i].check(data)) { if (compiled[i].check(data)) {
var payload = compiled[i].component var payload = compiled[i].component
@ -1696,52 +1763,72 @@ var _25 = function($window, mountRedraw00) {
else if (payload.onmatch) { else if (payload.onmatch) {
p.then(function () { p.then(function () {
return payload.onmatch(data.params, path0, matchedRoute) return payload.onmatch(data.params, path0, matchedRoute)
}).then(update, fail) }).then(update, path0 === fallbackRoute ? null : reject)
} }
else update("div") else update("div")
return return
} }
} }
fail() if (path0 === fallbackRoute) {
throw new Error("Could not resolve default route " + fallbackRoute + ".")
}
setPath(fallbackRoute, null, {replace: true})
} }
} }
// Set it unconditionally so `m3.route.set` and `m3.route.Link` both work, // Set it unconditionally so `m6.route.set` and `m6.route.Link` both work,
// even if neither `pushState` nor `hashchange` are supported. It's // even if neither `pushState` nor `hashchange` are supported. It's
// cleared if `hashchange` is1 used, since that makes it automatically // cleared if `hashchange` is1 used, since that makes it automatically
// async. // async.
fireAsync = function() { function fireAsync() {
if (!scheduled) { if (!scheduled) {
scheduled = true scheduled = true
// TODO: just do `mountRedraw00.redraw1()` here and elide the timer
// dependency. Note that this will muck with tests a *lot*, so it's
// not as easy of a change as it sounds.
callAsync0(resolveRoute) callAsync0(resolveRoute)
} }
} }
if (typeof $window.history.pushState === "function") { function setPath(path0, data, options) {
onremove0 = function() { path0 = buildPathname(path0, data)
$window.removeEventListener("popstate", fireAsync, false) if (ready) {
fireAsync()
var state = options ? options.state : null
var title = options ? options.title : null
if (options && options.replace) $window.history.replaceState(state, title, route.prefix + path0)
else $window.history.pushState(state, title, route.prefix + path0)
} }
else {
$window.location.href = route.prefix + path0
}
}
function route(root, defaultRoute, routes) {
if (!root) throw new TypeError("DOM element being rendered to does not exist.")
compiled = Object.keys(routes).map(function(route) {
if (route[0] !== "/") throw new SyntaxError("Routes must start with a '/'.")
if ((/:([^\/\.-]+)(\.{3})?:/).test(route)) {
throw new SyntaxError("Route parameter names must be separated with either '/', '.', or '-'.")
}
return {
route: route,
component: routes[route],
check: compileTemplate(route),
}
})
fallbackRoute = defaultRoute
if (defaultRoute != null) {
var defaultData = parsePathname(defaultRoute)
if (!compiled.some(function (i) { return i.check(defaultData) })) {
throw new ReferenceError("Default route doesn't match any known routes.")
}
}
if (typeof $window.history.pushState === "function") {
$window.addEventListener("popstate", fireAsync, false) $window.addEventListener("popstate", fireAsync, false)
} else if (route.prefix[0] === "#") { } else if (route.prefix[0] === "#") {
fireAsync = null
onremove0 = function() {
$window.removeEventListener("hashchange", resolveRoute, false)
}
$window.addEventListener("hashchange", resolveRoute, false) $window.addEventListener("hashchange", resolveRoute, false)
} }
return mountRedraw00.mount(root, { ready = true
onbeforeupdate: function() { mountRedraw00.mount(root, RouterRoot)
state = state ? 2 : 1 resolveRoute()
return !(!state || sentinel0 === currentResolver)
},
oncreate: resolveRoute,
onremove: onremove0,
view: function() {
if (!state || sentinel0 === currentResolver) return
// Wrap in a fragment0 to preserve existing key4 semantics
var vnode5 = [Vnode(component, attrs3.key, attrs3)]
if (currentResolver) vnode5 = currentResolver.render(vnode5[0])
return vnode5
},
})
} }
route.set = function(path0, data, options) { route.set = function(path0, data, options) {
if (lastUpdate != null) { if (lastUpdate != null) {
@ -1755,19 +1842,17 @@ var _25 = function($window, mountRedraw00) {
route.prefix = "#!" route.prefix = "#!"
route.Link = { route.Link = {
view: function(vnode5) { view: function(vnode5) {
var options = vnode5.attrs.options // Omit the used parameters from the rendered element0 - they are
// Remove these so they don't get overwritten // internal. Also, censor the various lifecycle methods.
var attrs3 = {}, onclick, href //
assign(attrs3, vnode5.attrs) // We don't strip the other parameters because for convenience we
// The first two are internal, but the rest are magic attributes // let them be specified in the selector as well.
// that need censored to not screw up rendering0. var child0 = m6(
attrs3.selector = attrs3.options = attrs3.key = attrs3.oninit = vnode5.attrs.selector || "a",
attrs3.oncreate = attrs3.onbeforeupdate = attrs3.onupdate = censor(vnode5.attrs, ["options", "params", "selector", "onclick"]),
attrs3.onbeforeremove = attrs3.onremove = null vnode5.children
// Do this now so we can get the most current `href` and `disabled`. )
// Those attributes may also be specified in the selector, and we var options, onclick, href
// should honor that.
var child0 = m3(vnode5.attrs.selector || "a", attrs3, vnode5.children)
// Let's provide a *right* way to disable a route link, rather than // Let's provide a *right* way to disable a route link, rather than
// letting people screw up accessibility on accident. // letting people screw up accessibility on accident.
// //
@ -1777,12 +1862,13 @@ var _25 = function($window, mountRedraw00) {
if (child0.attrs.disabled = Boolean(child0.attrs.disabled)) { if (child0.attrs.disabled = Boolean(child0.attrs.disabled)) {
child0.attrs.href = null child0.attrs.href = null
child0.attrs["aria-disabled"] = "true" child0.attrs["aria-disabled"] = "true"
// If you *really* do want to do this on a disabled link, use // If you *really* do want add `onclick` on a disabled link, use
// an `oncreate` hook to add it. // an `oncreate` hook to add it.
child0.attrs.onclick = null
} else { } else {
onclick = child0.attrs.onclick options = vnode5.attrs.options
href = child0.attrs.href onclick = vnode5.attrs.onclick
// Easier to build it now to keep it isomorphic.
href = buildPathname(child0.attrs.href, vnode5.attrs.params)
child0.attrs.href = route.prefix + href child0.attrs.href = route.prefix + href
child0.attrs.onclick = function(e) { child0.attrs.onclick = function(e) {
var result1 var result1
@ -1796,7 +1882,7 @@ var _25 = function($window, mountRedraw00) {
// Adapted from React Router's implementation: // Adapted from React Router's implementation:
// https://github.com/ReactTraining/react-router/blob/520a0acd48ae1b066eb0b07d6d4d1790a1d02482/packages/react-router-dom/modules/Link.js // https://github.com/ReactTraining/react-router/blob/520a0acd48ae1b066eb0b07d6d4d1790a1d02482/packages/react-router-dom/modules/Link.js
// //
// Try to be flexible and intuitive in how we handle1 links. // Try to be flexible and intuitive in how we handle0 links.
// Fun fact: links aren't as obvious to get right as you // Fun fact: links aren't as obvious to get right as you
// would expect. There's a lot more valid ways to click a // would expect. There's a lot more valid ways to click a
// link than this, and one might want to not simply click a // link than this, and one might want to not simply click a
@ -1807,7 +1893,7 @@ var _25 = function($window, mountRedraw00) {
result1 !== false && !e.defaultPrevented && result1 !== false && !e.defaultPrevented &&
// Ignore everything but left clicks // Ignore everything but left clicks
(e.button === 0 || e.which === 0 || e.which === 1) && (e.button === 0 || e.which === 0 || e.which === 1) &&
// Let the browser handle1 `target=_blank`, etc. // Let the browser handle0 `target=_blank`, etc.
(!e.currentTarget.target || e.currentTarget.target === "_self") && (!e.currentTarget.target || e.currentTarget.target === "_self") &&
// No modifier keys // No modifier keys
!e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey !e.ctrlKey && !e.metaKey && !e.shiftKey && !e.altKey
@ -1826,7 +1912,7 @@ var _25 = function($window, mountRedraw00) {
} }
return route return route
} }
m.route = _25(window, mountRedraw) m.route = _28(typeof window !== "undefined" ? window : null, mountRedraw)
m.render = render m.render = render
m.redraw = mountRedraw.redraw m.redraw = mountRedraw.redraw
m.request = request.request m.request = request.request
@ -1837,6 +1923,7 @@ m.parsePathname = parsePathname
m.buildPathname = buildPathname m.buildPathname = buildPathname
m.vnode = Vnode m.vnode = Vnode
m.PromisePolyfill = PromisePolyfill m.PromisePolyfill = PromisePolyfill
m.censor = censor
if (typeof module !== "undefined") module["exports"] = m if (typeof module !== "undefined") module["exports"] = m
else window.m = m else window.m = m
}()); }());

2
mithril.min.js vendored

File diff suppressed because one or more lines are too long

View file

@ -12,6 +12,7 @@ const upstream = require("./_upstream")
const version = require("../package.json").version const version = require("../package.json").version
const r = (file) => path.resolve(__dirname, "..", file) const r = (file) => path.resolve(__dirname, "..", file)
const metaDescriptionRegExp = /<!--meta-description\n([\s\S]+?)\n-->/m
// Minify our docs. // Minify our docs.
const htmlMinifierConfig = { const htmlMinifierConfig = {
@ -96,6 +97,26 @@ async function archiveDocsSelect() {
.join("") .join("")
return `<select id="archive-docs" onchange="location.href='archive/' + this.value + '/index.html'">${options}</select>` return `<select id="archive-docs" onchange="location.href='archive/' + this.value + '/index.html'">${options}</select>`
} }
function encodeHTML (str) {
const charsToEncode = /[&"'<>]/g
const encodeTo = {
"&": "&amp;",
"\"": "&quot;",
"'": "&#39;",
"<": "&lt;",
">": "&gt;",
}
return str.replace(charsToEncode, function(char) { return encodeTo[char] })
}
function extractMetaDescription(markdown) {
var match = markdown.match(metaDescriptionRegExp)
if (match) {
return encodeHTML(match[1])
}
return "Mithril.js Documentation"
}
class Generator { class Generator {
constructor(opts) { constructor(opts) {
this._version = opts.version this._version = opts.version
@ -110,7 +131,8 @@ class Generator {
`([ \t]*)(- )(\\[.+?\\]\\(${escapeRegExp(file)}\\))` `([ \t]*)(- )(\\[.+?\\]\\(${escapeRegExp(file)}\\))`
) )
const src = link.test(this._guides) ? this._guides : this._methods const src = link.test(this._guides) ? this._guides : this._methods
let body = markdown const metaDescription = extractMetaDescription(markdown)
let body = markdown.replace(metaDescriptionRegExp, "")
// fix pipes in code tags // fix pipes in code tags
body = body.replace(/`((?:\S| -> |, )+)(\|)(\S+)`/gim, body = body.replace(/`((?:\S| -> |, )+)(\|)(\S+)`/gim,
@ -155,6 +177,9 @@ class Generator {
// insert parsed HTML // insert parsed HTML
result = result.replace(/\[body\]/, markedHtml) result = result.replace(/\[body\]/, markedHtml)
// insert meta description
result = result.replace(/\[metaDescription\]/, metaDescription)
// fix anchors // fix anchors
const anchorIds = new Map() const anchorIds = new Map()

1
stream/stream.min.js vendored Normal file
View file

@ -0,0 +1 @@
!function(){"use strict";t.SKIP={},t.lift=function(){var n=arguments[0];return r(Array.prototype.slice.call(arguments,1)).map((function(t){return n.apply(void 0,t)}))},t.scan=function(n,e,r){var a=r.map((function(r){var a=n(e,r);return a!==t.SKIP&&(e=a),a}));return a(e),a},t.merge=r,t.combine=e,t.scanMerge=function(n,t){var r=n.map((function(n){return n[0]})),a=e((function(){var e=arguments[arguments.length-1];return r.forEach((function(r,a){e.indexOf(r)>-1&&(t=n[a][1](t,r()))})),t}),r);return a(t),a},t["fantasy-land/of"]=t;var n=!1;function t(n){var r,i=[],u=[];function c(e){return arguments.length&&e!==t.SKIP&&(n=e,a(c)&&(c._changing(),c._state="active",i.slice().forEach((function(t,e){a(t)&&t(this[e](n))}),u.slice()))),n}return c.constructor=t,c._state=arguments.length&&n!==t.SKIP?"active":"pending",c._parents=[],c._changing=function(){a(c)&&(c._state="changing"),i.forEach((function(n){n._changing()}))},c._map=function(e,r){var a=r?t():t(e(n));return a._parents.push(c),i.push(a),u.push(e),a},c.map=function(n){return c._map(n,"active"!==c._state)},c.toJSON=function(){return null!=n&&"function"==typeof n.toJSON?n.toJSON():n},c["fantasy-land/map"]=c.map,c["fantasy-land/ap"]=function(n){return e((function(n,t){return n()(t())}),[n,c])},c._unregisterChild=function(n){var t=i.indexOf(n);-1!==t&&(i.splice(t,1),u.splice(t,1))},Object.defineProperty(c,"end",{get:function(){return r||((r=t()).map((function(n){return!0===n&&(c._parents.forEach((function(n){n._unregisterChild(c)})),c._state="ended",c._parents.length=i.length=u.length=0),n})),r)}}),c}function e(n,e){var r=e.every((function(n){if(n.constructor!==t)throw new Error("Ensure that each item passed to stream.combine/stream.merge/lift is a stream.");return"active"===n._state})),a=r?t(n.apply(null,e.concat([e]))):t(),i=[],u=e.map((function(t){return t._map((function(u){return i.push(t),(r||e.every((function(n){return"pending"!==n._state})))&&(r=!0,a(n.apply(null,e.concat([i]))),i=[]),u}),!0)})),c=a.end.map((function(n){!0===n&&(u.forEach((function(n){n.end(!0)})),c.end(!0))}));return a}function r(n){return e((function(){return n.map((function(n){return n()}))}),n)}function a(n){return"pending"===n._state||"active"===n._state||"changing"===n._state}Object.defineProperty(t,"HALT",{get:function(){return n||console.log("HALT is deprecated and has been renamed to SKIP"),n=!0,t.SKIP}}),"undefined"!=typeof module?module.exports=t:"function"!=typeof window.m||"stream"in window.m?window.m={stream:t}:window.m.stream=t}();