1
0
mirror of https://github.com/squidfunk/mkdocs-material.git synced 2024-11-28 01:10:58 +01:00

Fixed flow in build process

This commit is contained in:
squidfunk 2017-02-20 23:26:51 +01:00
parent 07e2eb4f85
commit 7908140dc5
13 changed files with 209 additions and 74 deletions

View File

@ -23,6 +23,9 @@
/material /material
/site /site
# Files generated by flow typechecker
/tmp
# Files generated by visual tests # Files generated by visual tests
/gemini-report /gemini-report
/tests/visual/data /tests/visual/data

View File

@ -1,2 +1,5 @@
[ignore] [ignore]
<PROJECT_ROOT>/node_modules .*/node_modules/.*
[options]
strip_root=true

3
.gitignore vendored
View File

@ -31,6 +31,9 @@
/MANIFEST /MANIFEST
/site /site
# Files generated by flow typechecker
/tmp
# Files generated by visual tests # Files generated by visual tests
/gemini-report /gemini-report
/tests/visual/baseline/local /tests/visual/baseline/local

View File

@ -145,12 +145,6 @@ gulp.task("assets:images:clean",
* JavaScript * JavaScript
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
/*
* Annotate javascript
*/
gulp.task("assets:javascripts:flow:annotate",
load("assets/javascripts/flow/annotate"))
/* /*
* Build application logic * Build application logic
*/ */
@ -165,7 +159,7 @@ gulp.task("assets:javascripts:build:modernizr", [
], load("assets/javascripts/build/modernizr")) ], load("assets/javascripts/build/modernizr"))
/* /*
* Build application logic and modernizr * Build application logic and Modernizr
*/ */
gulp.task("assets:javascripts:build", (args.clean ? [ gulp.task("assets:javascripts:build", (args.clean ? [
"assets:javascripts:clean" "assets:javascripts:clean"
@ -184,6 +178,12 @@ gulp.task("assets:javascripts:build", (args.clean ? [
gulp.task("assets:javascripts:clean", gulp.task("assets:javascripts:clean",
load("assets/javascripts/clean")) load("assets/javascripts/clean"))
/*
* Annotate JavaScript
*/
gulp.task("assets:javascripts:annotate",
load("assets/javascripts/annotate"))
/* /*
* Lint JavaScript * Lint JavaScript
*/ */

View File

@ -24,7 +24,7 @@ import jsdoc2flow from "flow-jsdoc"
import through from "through2" import through from "through2"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Task: lint JavaScript * Task: annotate JavaScript
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
export default (gulp, config) => { export default (gulp, config) => {
@ -48,6 +48,6 @@ export default (gulp, config) => {
})) }))
/* Print errors */ /* Print errors */
.pipe(gulp.dest("tmp/javascripts")) .pipe(gulp.dest("tmp/assets/javascripts"))
} }
} }

View File

@ -880,11 +880,13 @@ var Listener = function () {
* Generic event listener * Generic event listener
* *
* @constructor * @constructor
* @property {(HTMLCollection<HTMLElement>)} els_ - Event targets *
* @property {(Array<EventTarget>)} els_ - Event targets
* @property {Object} handler_- Event handlers * @property {Object} handler_- Event handlers
* @property {Array<string>} events_ - Event names * @property {Array<string>} events_ - Event names
* @property {Function} update_ - Update handler * @property {Function} update_ - Update handler
* @param {?(string|EventTarget|HTMLCollection<HTMLElement>)} els - *
* @param {?(string|EventTarget|NodeList<EventTarget>)} els -
* Selector or Event targets * Selector or Event targets
* @param {(string|Array<string>)} events - Event names * @param {(string|Array<string>)} events - Event names
* @param {(Object|Function)} handler - Handler to be invoked * @param {(Object|Function)} handler - Handler to be invoked
@ -894,8 +896,7 @@ var Listener = function () {
_classCallCheck(this, Listener); _classCallCheck(this, Listener);
this.els_ = Array.prototype.slice.call(typeof els === "string" ? document.querySelectorAll(els) : [els]); this.els_ = Array.prototype.slice.call(typeof els === "string" ? document.querySelectorAll(els) : [].concat(els));
console.log(this.els_);
/* Set handler as function or directly as object */ /* Set handler as function or directly as object */
this.handler_ = typeof handler === "function" ? { update: handler } : handler; this.handler_ = typeof handler === "function" ? { update: handler } : handler;
@ -5825,7 +5826,9 @@ var MatchMedia =
* switches the given listeners on or off. * switches the given listeners on or off.
* *
* @constructor * @constructor
*
* @property {Function} handler_ - Media query event handler * @property {Function} handler_ - Media query event handler
*
* @param {string} query - Media query to test for * @param {string} query - Media query to test for
* @param {Listener} listener - Event listener * @param {Listener} listener - Event listener
*/ */
@ -5931,11 +5934,13 @@ var Blur = function () {
* Blur links within the table of contents above current page y-offset * Blur links within the table of contents above current page y-offset
* *
* @constructor * @constructor
*
* @property {NodeList<HTMLElement>} els_ - Table of contents links * @property {NodeList<HTMLElement>} els_ - Table of contents links
* @property {Array<HTMLElement>} anchors_ - Referenced anchor nodes * @property {Array<HTMLElement>} anchors_ - Referenced anchor nodes
* @property {number} index_ - Current link index * @property {number} index_ - Current link index
* @property {number} offset_ - Current page y-offset * @property {number} offset_ - Current page y-offset
* @property {boolean} dir_ - Scroll direction change * @property {boolean} dir_ - Scroll direction change
*
* @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements * @param {(string|NodeList<HTMLElement>)} els - Selector or HTML elements
*/ */
function Blur(els) { function Blur(els) {
@ -6078,13 +6083,17 @@ var Collapse = function () {
* Expand or collapse navigation on toggle * Expand or collapse navigation on toggle
* *
* @constructor * @constructor
*
* @property {HTMLElement} el_ - Navigation list * @property {HTMLElement} el_ - Navigation list
*
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
*/ */
function Collapse(el) { function Collapse(el) {
_classCallCheck(this, Collapse); _classCallCheck(this, Collapse);
this.el_ = typeof el === "string" ? document.querySelector(el) || new HTMLElement() : el; var ref = typeof el === "string" ? document.querySelector(el) : el;
if (!(ref instanceof HTMLElement)) throw new ReferenceError();
this.el_ = ref;
} }
/** /**
@ -6203,13 +6212,17 @@ var Scrolling = function () {
* Set overflow scrolling on the current active pane (for iOS) * Set overflow scrolling on the current active pane (for iOS)
* *
* @constructor * @constructor
*
* @property {HTMLElement} el_ - Navigation * @property {HTMLElement} el_ - Navigation
*
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
*/ */
function Scrolling(el) { function Scrolling(el) {
_classCallCheck(this, Scrolling); _classCallCheck(this, Scrolling);
this.el_ = typeof el === "string" ? document.querySelector(el) : el; var ref = typeof el === "string" ? document.querySelector(el) : el;
if (!(ref instanceof HTMLElement)) throw new ReferenceError();
this.el_ = ref;
} }
/** /**
@ -6227,13 +6240,17 @@ var Scrolling = function () {
/* Find all toggles and check which one is active */ /* Find all toggles and check which one is active */
var toggles = this.el_.querySelectorAll("[data-md-toggle]"); var toggles = this.el_.querySelectorAll("[data-md-toggle]");
Array.prototype.forEach.call(toggles, function (toggle) { Array.prototype.forEach.call(toggles, function (toggle) {
if (toggle.checked) { if (toggle instanceof HTMLInputElement && toggle.checked) {
/* Find corresponding navigational pane */ /* Find corresponding navigational pane */
var pane = toggle.nextElementSibling; var pane = toggle.nextElementSibling;
while (pane.tagName !== "NAV") { if (!(pane instanceof HTMLElement)) throw new ReferenceError();
while (pane.tagName !== "NAV" && pane.nextElementSibling) {
pane = pane.nextElementSibling; pane = pane.nextElementSibling;
} /* Find current and parent list elements */ } /* Check references */
if (!(toggle.parentNode instanceof HTMLElement) || !(toggle.parentNode.parentNode instanceof HTMLElement)) throw new ReferenceError();
/* Find current and parent list elements */
var parent = toggle.parentNode.parentNode; var parent = toggle.parentNode.parentNode;
var target = pane.children[pane.children.length - 1]; var target = pane.children[pane.children.length - 1];
@ -6253,36 +6270,46 @@ var Scrolling = function () {
}, { }, {
key: "update", key: "update",
value: function update(ev) { value: function update(ev) {
var target = ev.target;
if (!(target instanceof HTMLElement)) throw new ReferenceError();
/* Find corresponding navigational pane */ /* Find corresponding navigational pane */
var pane = ev.target.nextElementSibling; var pane = target.nextElementSibling;
while (pane.tagName !== "NAV") { if (!(pane instanceof HTMLElement)) throw new ReferenceError();
while (pane.tagName !== "NAV" && pane.nextElementSibling) {
pane = pane.nextElementSibling; pane = pane.nextElementSibling;
} /* Find current and parent list elements */ } /* Check references */
var parent = ev.target.parentNode.parentNode; if (!(target.parentNode instanceof HTMLElement) || !(target.parentNode.parentNode instanceof HTMLElement)) throw new ReferenceError();
var target = pane.children[pane.children.length - 1];
/* Find parent and active panes */
var parent = target.parentNode.parentNode;
var active = pane.children[pane.children.length - 1];
/* Always reset all lists when transitioning */ /* Always reset all lists when transitioning */
parent.style.webkitOverflowScrolling = ""; parent.style.webkitOverflowScrolling = "";
target.style.webkitOverflowScrolling = ""; active.style.webkitOverflowScrolling = "";
/* Set overflow scrolling on parent */ /* Set overflow scrolling on parent pane */
if (!ev.target.checked) { if (!target.checked) {
(function () { (function () {
var end = function end() { var end = function end() {
if (pane instanceof HTMLElement) {
parent.style.webkitOverflowScrolling = "touch"; parent.style.webkitOverflowScrolling = "touch";
pane.removeEventListener("transitionend", end); pane.removeEventListener("transitionend", end);
}
}; };
pane.addEventListener("transitionend", end, false); pane.addEventListener("transitionend", end, false);
})(); })();
} }
/* Set overflow scrolling on target */ /* Set overflow scrolling on active pane */
if (ev.target.checked) { if (target.checked) {
(function () { (function () {
var end = function end() { var end = function end() {
target.style.webkitOverflowScrolling = "touch"; if (pane instanceof HTMLElement) {
pane.removeEventListener("transitionend", end, false); active.style.webkitOverflowScrolling = "touch";
pane.removeEventListener("transitionend", end);
}
}; };
pane.addEventListener("transitionend", end, false); pane.addEventListener("transitionend", end, false);
})(); })();
@ -6303,19 +6330,23 @@ var Scrolling = function () {
/* Find all toggles and check which one is active */ /* Find all toggles and check which one is active */
var toggles = this.el_.querySelectorAll("[data-md-toggle]"); var toggles = this.el_.querySelectorAll("[data-md-toggle]");
Array.prototype.forEach.call(toggles, function (toggle) { Array.prototype.forEach.call(toggles, function (toggle) {
if (toggle.checked) { if (toggle instanceof HTMLInputElement && toggle.checked) {
/* Find corresponding navigational pane */ /* Find corresponding navigational pane */
var pane = toggle.nextElementSibling; var pane = toggle.nextElementSibling;
while (pane.tagName !== "NAV") { if (!(pane instanceof HTMLElement)) throw new ReferenceError();
while (pane.tagName !== "NAV" && pane.nextElementSibling) {
pane = pane.nextElementSibling; pane = pane.nextElementSibling;
} /* Find current and parent list elements */ } /* Check references */
if (!(toggle.parentNode instanceof HTMLElement) || !(toggle.parentNode.parentNode instanceof HTMLElement)) throw new ReferenceError();
/* Find parent and active panes */
var parent = toggle.parentNode.parentNode; var parent = toggle.parentNode.parentNode;
var target = pane.children[pane.children.length - 1]; var active = pane.children[pane.children.length - 1];
/* Always reset all lists when transitioning */ /* Always reset all lists when transitioning */
parent.style.webkitOverflowScrolling = ""; parent.style.webkitOverflowScrolling = "";
target.style.webkitOverflowScrolling = ""; active.style.webkitOverflowScrolling = "";
} }
}); });
} }
@ -6408,12 +6439,18 @@ var Lock = function () {
* Lock body for full-screen search modal * Lock body for full-screen search modal
* *
* @constructor * @constructor
*
* @property {HTMLInputElement} el_ - TODO
* @property {number} offset_ - TODO
*
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
*/ */
function Lock(el) { function Lock(el) {
_classCallCheck(this, Lock); _classCallCheck(this, Lock);
this.el_ = typeof el === "string" ? document.querySelector(el) : el; var ref = typeof el === "string" ? document.querySelector(el) : el;
if (!(ref instanceof HTMLInputElement)) throw new ReferenceError();
this.el_ = ref;
} }
/** /**
@ -6526,8 +6563,14 @@ var Result = function () {
* Perform search and update results on keyboard events * Perform search and update results on keyboard events
* *
* @constructor * @constructor
*
* @property {HTMLElement} el_ - TODO
* @property {(Object|Array<Object>|Function)} data_ - TODO (very dirty)
* @property {*} meta_ - TODO (must be done like this, as React$Component does not return the correct thing)
* @property {*} list_ - TODO (must be done like this, as React$Component does not return the correct thing)
*
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
* @param {(Array.<object>|Function)} data - Promise or array providing data * @param {(Array<Object>|Function)} data - Promise or array providing data // TODO ????
*/ */
function Result(el, data) { function Result(el, data) {
_classCallCheck(this, Result); _classCallCheck(this, Result);

View File

@ -25,6 +25,7 @@
"scripts": { "scripts": {
"build": "scripts/build", "build": "scripts/build",
"clean": "scripts/clean", "clean": "scripts/clean",
"flow": "scripts/flow",
"lint": "scripts/lint", "lint": "scripts/lint",
"start": "scripts/start", "start": "scripts/start",
"test:visual:run": "scripts/test/visual/run", "test:visual:run": "scripts/test/visual/run",
@ -39,7 +40,6 @@
"babel-loader": "^6.3.1", "babel-loader": "^6.3.1",
"babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-syntax-flow": "^6.18.0", "babel-plugin-syntax-flow": "^6.18.0",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-react-jsx": "^6.8.0", "babel-plugin-transform-react-jsx": "^6.8.0",
"babel-polyfill": "^6.20.0", "babel-polyfill": "^6.20.0",
"babel-preset-es2015": "^6.22.0", "babel-preset-es2015": "^6.22.0",
@ -52,6 +52,7 @@
"ecstatic": "^2.1.0", "ecstatic": "^2.1.0",
"eslint": "^3.14.0", "eslint": "^3.14.0",
"fastclick": "^1.0.6", "fastclick": "^1.0.6",
"flow-bin": "^0.39.0",
"flow-jsdoc": "^0.2.2", "flow-jsdoc": "^0.2.2",
"git-hooks": "^1.1.7", "git-hooks": "^1.1.7",
"gulp": "^3.9.1", "gulp": "^3.9.1",

44
scripts/flow Executable file
View File

@ -0,0 +1,44 @@
#!/bin/bash
# Copyright (c) 2016-2017 Martin Donath <martin.donath@squidfunk.com>
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.
# Check if "npm install" was executed
if [[ ! -d `npm bin` ]]; then
echo "\"node_modules\" not found:"
echo "npm install"
exit 1
fi
# Annotate source files
`npm bin`/gulp assets:javascripts:annotate "$@"
FLOW_JSDOC=$?
# Run flow typecheck
`npm bin`/flow check tmp
FLOW=$?
# If one command failed, exit with error
if [ $FLOW_JSDOC -gt 0 ] || [ $FLOW -gt 0 ]; then
exit 1
fi;
# Otherwise return with success
exit 0

View File

@ -36,9 +36,12 @@ export default class Collapse {
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
*/ */
constructor(el) { constructor(el) {
this.el_ = (typeof el === "string") const ref = (typeof el === "string")
? document.querySelector(el) ? document.querySelector(el)
: el : el
if (!(ref instanceof HTMLElement))
throw new ReferenceError
this.el_ = ref
} }
/** /**

View File

@ -36,9 +36,12 @@ export default class Scrolling {
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
*/ */
constructor(el) { constructor(el) {
this.el_ = (typeof el === "string") const ref = (typeof el === "string")
? document.querySelector(el) ? document.querySelector(el)
: el : el
if (!(ref instanceof HTMLElement))
throw new ReferenceError
this.el_ = ref
} }
/** /**
@ -52,13 +55,20 @@ export default class Scrolling {
/* Find all toggles and check which one is active */ /* Find all toggles and check which one is active */
const toggles = this.el_.querySelectorAll("[data-md-toggle]") const toggles = this.el_.querySelectorAll("[data-md-toggle]")
Array.prototype.forEach.call(toggles, toggle => { Array.prototype.forEach.call(toggles, toggle => {
if (toggle.checked) { if (toggle instanceof HTMLInputElement && toggle.checked) {
/* Find corresponding navigational pane */ /* Find corresponding navigational pane */
let pane = toggle.nextElementSibling let pane = toggle.nextElementSibling
while (pane.tagName !== "NAV") if (!(pane instanceof HTMLElement))
throw new ReferenceError
while (pane.tagName !== "NAV" && pane.nextElementSibling)
pane = pane.nextElementSibling pane = pane.nextElementSibling
/* Check references */
if (!(toggle.parentNode instanceof HTMLElement) ||
!(toggle.parentNode.parentNode instanceof HTMLElement))
throw new ReferenceError
/* Find current and parent list elements */ /* Find current and parent list elements */
const parent = toggle.parentNode.parentNode const parent = toggle.parentNode.parentNode
const target = pane.children[pane.children.length - 1] const target = pane.children[pane.children.length - 1]
@ -76,34 +86,48 @@ export default class Scrolling {
* @param {Event} ev - Change event * @param {Event} ev - Change event
*/ */
update(ev) { update(ev) {
const target = ev.target
if (!(target instanceof HTMLElement))
throw new ReferenceError
/* Find corresponding navigational pane */ /* Find corresponding navigational pane */
let pane = ev.target.nextElementSibling let pane = target.nextElementSibling
while (pane.tagName !== "NAV") if (!(pane instanceof HTMLElement))
throw new ReferenceError
while (pane.tagName !== "NAV" && pane.nextElementSibling)
pane = pane.nextElementSibling pane = pane.nextElementSibling
/* Find current and parent list elements */ /* Check references */
const parent = ev.target.parentNode.parentNode if (!(target.parentNode instanceof HTMLElement) ||
const target = pane.children[pane.children.length - 1] !(target.parentNode.parentNode instanceof HTMLElement))
throw new ReferenceError
/* Find parent and active panes */
const parent = target.parentNode.parentNode
const active = pane.children[pane.children.length - 1]
/* Always reset all lists when transitioning */ /* Always reset all lists when transitioning */
parent.style.webkitOverflowScrolling = "" parent.style.webkitOverflowScrolling = ""
target.style.webkitOverflowScrolling = "" active.style.webkitOverflowScrolling = ""
/* Set overflow scrolling on parent */ /* Set overflow scrolling on parent pane */
if (!ev.target.checked) { if (!target.checked) {
const end = () => { const end = () => {
if (pane instanceof HTMLElement) {
parent.style.webkitOverflowScrolling = "touch" parent.style.webkitOverflowScrolling = "touch"
pane.removeEventListener("transitionend", end) pane.removeEventListener("transitionend", end)
} }
}
pane.addEventListener("transitionend", end, false) pane.addEventListener("transitionend", end, false)
} }
/* Set overflow scrolling on target */ /* Set overflow scrolling on active pane */
if (ev.target.checked) { if (target.checked) {
const end = () => { const end = () => {
target.style.webkitOverflowScrolling = "touch" if (pane instanceof HTMLElement) {
pane.removeEventListener("transitionend", end, false) active.style.webkitOverflowScrolling = "touch"
pane.removeEventListener("transitionend", end)
}
} }
pane.addEventListener("transitionend", end, false) pane.addEventListener("transitionend", end, false)
} }
@ -120,20 +144,27 @@ export default class Scrolling {
/* Find all toggles and check which one is active */ /* Find all toggles and check which one is active */
const toggles = this.el_.querySelectorAll("[data-md-toggle]") const toggles = this.el_.querySelectorAll("[data-md-toggle]")
Array.prototype.forEach.call(toggles, toggle => { Array.prototype.forEach.call(toggles, toggle => {
if (toggle.checked) { if (toggle instanceof HTMLInputElement && toggle.checked) {
/* Find corresponding navigational pane */ /* Find corresponding navigational pane */
let pane = toggle.nextElementSibling let pane = toggle.nextElementSibling
while (pane.tagName !== "NAV") if (!(pane instanceof HTMLElement))
throw new ReferenceError
while (pane.tagName !== "NAV" && pane.nextElementSibling)
pane = pane.nextElementSibling pane = pane.nextElementSibling
/* Find current and parent list elements */ /* Check references */
if (!(toggle.parentNode instanceof HTMLElement) ||
!(toggle.parentNode.parentNode instanceof HTMLElement))
throw new ReferenceError
/* Find parent and active panes */
const parent = toggle.parentNode.parentNode const parent = toggle.parentNode.parentNode
const target = pane.children[pane.children.length - 1] const active = pane.children[pane.children.length - 1]
/* Always reset all lists when transitioning */ /* Always reset all lists when transitioning */
parent.style.webkitOverflowScrolling = "" parent.style.webkitOverflowScrolling = ""
target.style.webkitOverflowScrolling = "" active.style.webkitOverflowScrolling = ""
} }
}) })
} }

View File

@ -37,9 +37,12 @@ export default class Lock {
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
*/ */
constructor(el) { constructor(el) {
this.el_ = (typeof el === "string") const ref = (typeof el === "string")
? document.querySelector(el) ? document.querySelector(el)
: el : el
if (!(ref instanceof HTMLInputElement))
throw new ReferenceError
this.el_ = ref
} }
/** /**

View File

@ -35,7 +35,8 @@ export default class Result {
* *
* @property {HTMLElement} el_ - TODO * @property {HTMLElement} el_ - TODO
* @property {(Object|Array<Object>|Function)} data_ - TODO (very dirty) * @property {(Object|Array<Object>|Function)} data_ - TODO (very dirty)
* @property {React$Element|HTMLElement} meta_ - TODO * @property {*} meta_ - TODO (must be done like this, as React$Component does not return the correct thing)
* @property {*} list_ - TODO (must be done like this, as React$Component does not return the correct thing)
* *
* @param {(string|HTMLElement)} el - Selector or HTML element * @param {(string|HTMLElement)} el - Selector or HTML element
* @param {(Array<Object>|Function)} data - Promise or array providing data // TODO ???? * @param {(Array<Object>|Function)} data - Promise or array providing data // TODO ????