mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-06-14 11:52:32 +03:00
Integrated static type-checking via JSDoc and Flow
This commit is contained in:
parent
672a39b697
commit
22a2f084a1
@ -45,17 +45,25 @@ git checkout -- .
|
||||
FILES=$(git diff --cached --name-only --diff-filter=ACMR | \
|
||||
grep "\.\(js\|jsx\|scss\)$")
|
||||
|
||||
# Run the check and print indicator
|
||||
# Run check and print indicator
|
||||
if [ "$FILES" ]; then
|
||||
npm run lint --silent
|
||||
|
||||
# If we're on master, abort commit
|
||||
# If linter terminated with errors, abort commit
|
||||
if [ $? -gt 0 ]; then
|
||||
echo -e "\x1B[31m✗\x1B[0m Linter - \x1B[31m$MESSAGE\x1B[0m"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\x1B[32m✓\x1B[0m Linter"
|
||||
fi
|
||||
|
||||
# If flow terminated with errors, abort commit
|
||||
npm run flow --silent
|
||||
if [ $? -gt 0 ]; then
|
||||
echo -e "\x1B[31m✗\x1B[0m Flow - \x1B[31m$MESSAGE\x1B[0m"
|
||||
exit 1
|
||||
else
|
||||
echo -e "\x1B[32m✓\x1B[0m Flow"
|
||||
fi
|
||||
fi
|
||||
|
||||
# We're good
|
@ -26,9 +26,9 @@
|
||||
|
||||
declare module "fastclick" {
|
||||
|
||||
/* FastClick type */
|
||||
/* Type: FastClick */
|
||||
declare type FastClick = {
|
||||
attach(name: HTMLElement): null
|
||||
attach(name: HTMLElement): void
|
||||
}
|
||||
|
||||
/* Exports */
|
||||
|
@ -26,13 +26,13 @@
|
||||
|
||||
declare module "js-cookie" {
|
||||
|
||||
/* Options type for setting cookie values */
|
||||
/* Type: Options for setting cookie values */
|
||||
declare type Options = {
|
||||
path?: string,
|
||||
expires?: number | string
|
||||
}
|
||||
|
||||
/* Cookie type */
|
||||
/* Type: Cookie */
|
||||
declare type Cookie = {
|
||||
getJSON(json: string): Object,
|
||||
set(key: string, value: string, options?: Options): string
|
||||
|
@ -24,9 +24,11 @@
|
||||
* Declarations
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Currently, it's not possible to export a function that returns a class type,
|
||||
* as the imports just don't correctly work with flow. As a workaround we
|
||||
* export an object until this error is fixed.
|
||||
*/
|
||||
declare module "lunr" {
|
||||
declare class lunr {
|
||||
// TODO
|
||||
}
|
||||
declare function exports(): lunr
|
||||
declare function exports(name: () => void): Object
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
declare class Modernizr {
|
||||
static addTest(name: string, test: () => boolean): null
|
||||
static addTest(name: string, test: () => boolean): void
|
||||
}
|
||||
|
||||
/* Exports */
|
||||
|
@ -30,7 +30,7 @@ export default /* Jsx */ {
|
||||
* Create a native DOM node from JSX's intermediate representation
|
||||
*
|
||||
* @param {string} tag - Tag name
|
||||
* @param {Object} properties - Properties // TODO: nullable, as the second...
|
||||
* @param {?Object} properties - Properties
|
||||
* @param {...(string|number|Array)} children - Child nodes
|
||||
* @return {HTMLElement} Native DOM node
|
||||
*/
|
||||
|
File diff suppressed because one or more lines are too long
3
material/assets/javascripts/application-8dc3dfc020.js
Normal file
3
material/assets/javascripts/application-8dc3dfc020.js
Normal file
File diff suppressed because one or more lines are too long
@ -124,7 +124,7 @@
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% block scripts %}
|
||||
<script src="{{ base_url }}/assets/javascripts/application-e546393d04.js"></script>
|
||||
<script src="{{ base_url }}/assets/javascripts/application-3fa7d77989.js"></script>
|
||||
<script>app.initialize({url:{base:"{{ base_url }}"}})</script>
|
||||
{% for path in extra_javascript %}
|
||||
<script src="{{ path }}"></script>
|
||||
|
@ -3,7 +3,7 @@
|
||||
<div class="md-search__overlay"></div>
|
||||
<div class="md-search__inner">
|
||||
<form class="md-search__form" name="search">
|
||||
<input type="text" class="md-search__input" name="query" placeholder="{{ lang.t('search.placeholder') }}" accesskey="s" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false">
|
||||
<input type="text" class="md-search__input" name="query" placeholder="{{ lang.t('search.placeholder') }}" accesskey="s" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="query">
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
|
@ -96,14 +96,6 @@
|
||||
"chai": "^3.5.0",
|
||||
"eslint-plugin-mocha": "^4.8.0",
|
||||
"gemini": "^4.14.3",
|
||||
"karma": "^1.3.0",
|
||||
"karma-chrome-launcher": "^2.0.0",
|
||||
"karma-coverage": "^1.1.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-notify-reporter": "^1.0.1",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.26",
|
||||
"karma-webpack": "^2.0.1",
|
||||
"mocha": "^3.2.0",
|
||||
"moniker": "^0.1.2",
|
||||
"saucelabs": "^1.4.0",
|
||||
|
@ -4,7 +4,7 @@
|
||||
],
|
||||
"plugins": [
|
||||
["transform-react-jsx", {
|
||||
"pragma": "JSX.createElement"
|
||||
"pragma": "Jsx.createElement"
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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"))
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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 => {
|
||||
|
@ -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_)
|
||||
|
@ -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>)}
|
||||
|
@ -64,7 +64,7 @@
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
|
||||
// Hovered source information
|
||||
// Hovered source container
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
<input type="text" class="md-search__input" name="query"
|
||||
placeholder="{{ lang.t('search.placeholder') }}"
|
||||
accesskey="s" autocapitalize="off" autocorrect="off"
|
||||
autocomplete="off" spellcheck="false" />
|
||||
autocomplete="off" spellcheck="false" data-md-component="query" />
|
||||
<label class="md-icon md-search__icon" for="search"></label>
|
||||
</form>
|
||||
<div class="md-search__output">
|
||||
|
Loading…
Reference in New Issue
Block a user