Integrated static type-checking via JSDoc and Flow

This commit is contained in:
squidfunk
2017-02-25 17:13:50 +01:00
parent 672a39b697
commit 22a2f084a1
22 changed files with 114 additions and 83 deletions

View File

@@ -28,26 +28,25 @@ import Material from "./components/Material"
* ------------------------------------------------------------------------- */
/**
* [initialize description]
* Initialize Material for MkDocs
*
* @param {Object} config - TODO // TODO: define via type declaration!?
* @param {Object} config - Configuration
*/
export const initialize = config => {
function initialize(config) { // eslint-disable-line func-style
/* Initialize Modernizr and FastClick */
new Material.Event.Listener(document, "DOMContentLoaded", () => {
/* Test for iOS */
Modernizr.addTest("ios", () => {
return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g)
})
if (!(document.body instanceof HTMLElement))
throw new ReferenceError
/* Attach FastClick to mitigate 300ms delay on touch devices */
FastClick.attach(document.body)
/* Test for iOS */
Modernizr.addTest("ios", () => {
return !!navigator.userAgent.match(/(iPad|iPhone|iPod)/g)
})
/* Wrap all data tables for better overflow scrolling */
const tables = document.querySelectorAll("table:not([class])")
Array.prototype.forEach.call(tables, table => {
@@ -119,7 +118,7 @@ export const initialize = config => {
new Material.Search.Lock("[data-md-toggle=search]")))
/* Component: search results */
new Material.Event.Listener(document.forms.search.query, [
new Material.Event.Listener("[data-md-component=query]", [
"focus", "keyup"
], new Material.Search.Result("[data-md-component=result]", () => {
return fetch(`${config.url.base}/mkdocs/search_index.json`, {
@@ -143,7 +142,9 @@ export const initialize = config => {
new Material.Event.Listener("[data-md-component=navigation] [href^='#']",
"click", () => {
const toggle = document.querySelector("[data-md-toggle=drawer]")
if (toggle instanceof HTMLInputElement && toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
}
@@ -152,17 +153,24 @@ export const initialize = config => {
/* Listener: focus input after opening search */
new Material.Event.Listener("[data-md-toggle=search]", "change", ev => {
setTimeout(toggle => {
const query = document.forms.search.query
if (toggle instanceof HTMLInputElement && toggle.checked)
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
const query = document.querySelector("[data-md-component=query]")
if (!(query instanceof HTMLInputElement))
throw new ReferenceError
query.focus()
}
}, 400, ev.target)
}).listen()
/* Listener: open search on focus */
new Material.Event.MatchMedia("(min-width: 960px)",
new Material.Event.Listener(document.forms.search.query, "focus", () => {
new Material.Event.Listener("[data-md-component=query]", "focus", () => {
const toggle = document.querySelector("[data-md-toggle=search]")
if (toggle instanceof HTMLInputElement && !toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (!toggle.checked) {
toggle.checked = true
toggle.dispatchEvent(new CustomEvent("change"))
}
@@ -172,7 +180,9 @@ export const initialize = config => {
new Material.Event.MatchMedia("(min-width: 960px)",
new Material.Event.Listener(document.body, "click", () => {
const toggle = document.querySelector("[data-md-toggle=search]")
if (toggle instanceof HTMLInputElement && toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
}
@@ -183,10 +193,15 @@ export const initialize = config => {
const code = ev.keyCode || ev.which
if (code === 27) {
const toggle = document.querySelector("[data-md-toggle=search]")
if (toggle instanceof HTMLInputElement && toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
document.forms.search.query.blur()
const query = document.querySelector("[data-md-component=query]")
if (!(query instanceof HTMLInputElement))
throw new ReferenceError
query.focus()
}
}
}).listen()
@@ -213,7 +228,7 @@ export const initialize = config => {
default: return Promise.resolve([])
}
/* Render repository source information */
/* Render repository information */
})().then(facts => {
const sources = document.querySelectorAll("[data-md-source]")
Array.prototype.forEach.call(sources, source => {
@@ -222,3 +237,11 @@ export const initialize = config => {
})
})
}
/* ----------------------------------------------------------------------------
* Exports
* ------------------------------------------------------------------------- */
export {
initialize
}

View File

@@ -31,7 +31,7 @@ export default class Scrolling {
*
* @constructor
*
* @property {HTMLElement} el_ - Navigation
* @property {HTMLElement} el_ - Primary navigation
*
* @param {(string|HTMLElement)} el - Selector or HTML element
*/
@@ -55,7 +55,9 @@ export default class Scrolling {
/* Find all toggles and check which one is active */
const toggles = this.el_.querySelectorAll("[data-md-toggle]")
Array.prototype.forEach.call(toggles, toggle => {
if (toggle instanceof HTMLInputElement && toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
/* Find corresponding navigational pane */
let pane = toggle.nextElementSibling
@@ -144,7 +146,9 @@ export default class Scrolling {
/* Find all toggles and check which one is active */
const toggles = this.el_.querySelectorAll("[data-md-toggle]")
Array.prototype.forEach.call(toggles, toggle => {
if (toggle instanceof HTMLInputElement && toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
/* Find corresponding navigational pane */
let pane = toggle.nextElementSibling

View File

@@ -31,9 +31,9 @@ export default class Lock {
*
* @constructor
*
* @property {HTMLInputElement} el_ - TODO
* @property {HTMLElement} lock_ - Element to lock
* @property {number} offset_ - TODO
* @property {HTMLInputElement} el_ - Lock toggle
* @property {HTMLElement} lock_ - Element to lock (document body)
* @property {number} offset_ - Current page y-offset
*
* @param {(string|HTMLElement)} el - Selector or HTML element
*/

View File

@@ -33,14 +33,15 @@ export default class Result {
*
* @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) (React$Element<*>|Element)
* @property {*} list_ - // TODO (must be done like this, as React$Component does not return the correct thing)
* @property {Object} index_ - TODO
* @property {HTMLElement} el_ - Search result container
* @property {(Array<Object>|Function)} data_ - Raw document data
* @property {Object} docs_ - Indexed documents
* @property {HTMLElement} meta_ - Search meta information
* @property {HTMLElement} list_ - Search result list
* @property {Object} index_ - Search index
*
* @param {(string|HTMLElement)} el - Selector or HTML element
* @param {(Array<Object>|Function)} data - Promise or array providing data // TODO ????
* @param {(Array<Object>|Function)} data - Function providing data or array
*/
constructor(el, data) {
const ref = (typeof el === "string")
@@ -73,9 +74,9 @@ export default class Result {
* would be better to create something more intelligent, highlighting the
* search occurrences and making a better summary out of it
*
* @param {string} string - TODO
* @param {number} n - TODO
* @return {string} TODO
* @param {string} string - String to be truncated
* @param {number} n - Number of characters
* @return {string} Truncated string
*/
truncate_(string, n) {
let i = n
@@ -107,7 +108,7 @@ export default class Result {
})
/* Index documents */
this.data_ = data.reduce((docs, doc) => {
this.docs_ = data.reduce((docs, doc) => {
this.index_.add(doc)
docs[doc.location] = doc
return docs
@@ -132,10 +133,9 @@ export default class Result {
this.list_.removeChild(this.list_.firstChild)
/* Perform search on index and render documents */
let result = this.index_.search(target.value)
result += 3
const result = this.index_.search(target.value)
result.forEach(item => {
const doc = this.data_[item.ref]
const doc = this.docs_[item.ref]
/* Check if it's a anchor link on the current page */
let [pathname] = doc.location.split("#")
@@ -166,7 +166,9 @@ export default class Result {
Array.prototype.forEach.call(anchors, anchor => {
anchor.addEventListener("click", ev2 => {
const toggle = document.querySelector("[data-md-toggle=search]")
if (toggle instanceof HTMLInputElement && toggle.checked) {
if (!(toggle instanceof HTMLInputElement))
throw new ReferenceError
if (toggle.checked) {
toggle.checked = false
toggle.dispatchEvent(new CustomEvent("change"))
}

View File

@@ -31,10 +31,10 @@ export default class Position {
*
* @constructor
*
* @property {HTMLElement} el_ - TODO
* @property {HTMLElement} parent_ - TODO
* @property {number} height_ - TODO
* @property {number} offset_ - TODO
* @property {HTMLElement} el_ - Sidebar
* @property {HTMLElement} parent_ - Sidebar container
* @property {number} height_ - Current sidebar height
* @property {number} offset_ - Current page y-offset
*
* @param {(string|HTMLElement)} el - Selector or HTML element
*/

View File

@@ -29,13 +29,13 @@ import Cookies from "js-cookie"
export default class Abstract {
/**
* Retrieve source information
* Retrieve repository information
*
* @constructor
*
* @property {HTMLAnchorElement} el_ - TODO
* @property {string} base_ - TODO
* @property {number} salt_ - TODO
* @property {HTMLAnchorElement} el_ - Link to repository
* @property {string} base_ - API base URL
* @property {number} salt_ - Unique identifier
*
* @param {(string|HTMLAnchorElement)} el - Selector or HTML element
*/
@@ -56,7 +56,7 @@ export default class Abstract {
/**
* Retrieve data from Cookie or fetch from respective API
*
* @return {Promise<*>} Promise that returns an array of facts // TODO: @returns {Promise.<string, Error>}
* @return {Promise<Array<string>>} Promise that returns an array of facts
*/
fetch() {
return new Promise(resolve => {

View File

@@ -29,7 +29,7 @@ import Abstract from "./Abstract"
export default class GitHub extends Abstract {
/**
* Retrieve source information from GitHub
* Retrieve repository information from GitHub
*
* @constructor
* @param {(string|HTMLAnchorElement)} el - Selector or HTML element
@@ -42,9 +42,9 @@ export default class GitHub extends Abstract {
}
/**
* Fetch relevant source information from GitHub
* Fetch relevant repository information from GitHub
*
* @return {Promise<*>} Promise returning an array of facts
* @return {Promise<Array<string>>} Promise returning an array of facts
*/
fetch_() {
return fetch(this.base_)

View File

@@ -31,7 +31,7 @@ export default class Repository {
*
* @constructor
*
* @property {HTMLElement} el_ - TODO
* @property {HTMLElement} el_ - Repository information
*
* @param {(string|HTMLElement)} el - Selector or HTML element
*/
@@ -45,12 +45,12 @@ export default class Repository {
}
/**
* Initialize the source repository
* Initialize the repository
*
* @param {Array<string>} facts - Facts to be rendered
*/
initialize(facts) {
if (facts.length)
if (facts.length && this.el_.children.length)
this.el_.children[this.el_.children.length - 1].appendChild(
<ul class="md-source__facts">
{facts.map(fact => <li class="md-source__fact">{fact}</li>)}